Download a prebuilt binary, write your first program, and run it. A few minutes start to finish, with no toolchain to assemble.
Grab the build for your platform. The standard library ships inside the tarball, so imports work the moment it's unpacked.
Windows is experimental: the compiler runs and emits object files, but end-to-end linking, exceptions, and networking are still being ported across the 0.7.x releases.
Unpack it into /usr/local and check the version:
# macOS (Apple Silicon)
tar -xzf eskiuc-macos-arm64.tar.gz -C /usr/local
# Linux (x86-64)
tar -xzf eskiuc-linux-x86_64.tar.gz -C /usr/local
# Windows (x86-64): unzip, then add the bin\ folder to PATH
Expand-Archive eskiuc-windows-x86_64.zip -DestinationPath C:\eskiu
eskiuc --version
Eskiu 0.7.0 (LLVM ...)
The tarball installs:
bin/eskiuc: the compilerlib/eskiu/stdlib/: the standard library
Linking needs a C toolchain on your machine (clang or
gcc), the same one Rust and Clang call to produce a binary.
macOS has it via the Xcode command-line tools; on Linux, install
build-essential (or gcc).
Create hello.esk:
extern int printf(string fmt, ...);
int add(int a, int b) {
return a + b;
}
int main() {
int result = add(5, 3);
printf("Hello from Eskiu!\n");
printf("Result: %d\n", result);
return 0;
}
Compile and run it in one step. eskiuc run builds a temporary
native binary, runs it, and cleans up:
eskiuc run hello.esk
Hello from Eskiu!
Result: 8
Or keep the binary. When the -o name has no .o
extension, eskiuc links it into an executable for you:
eskiuc hello.esk -o hello && ./hello
Want just the object file? Use a .o name, then link it yourself:
eskiuc hello.esk -o hello.o && clang hello.o -o hello && ./hello
Structs hold data. Methods are plain functions that take a pointer to the struct as their first argument.
extern int printf(string fmt, ...);
struct Point {
int x;
int y;
}
int Point_sum(Point* self) {
return self.x + self.y;
}
int main() {
let p: Point;
p.x = 3;
p.y = 7;
int s = Point_sum(&p);
printf("sum = %d\n", s); // sum = 10
return 0;
}
alloc<T>(n) (from the <mem> stdlib)
allocates n elements of type T and returns a typed
pointer. Index with []. Call free when you're done. The memory is yours to account for.
import <mem>;
extern int printf(string fmt, ...);
int main() {
*int buf = alloc<int>(4);
buf[0] = 10;
buf[1] = 20;
buf[2] = 30;
buf[3] = 40;
int sum = buf[0] + buf[1] + buf[2] + buf[3];
printf("sum = %d\n", sum); // sum = 100
free(buf);
return 0;
}
Functions are first-class values. Write a lambda with the same syntax as a regular function, minus the name:
extern int printf(string fmt, ...);
int apply(fn(int)->int f, int x) {
return f(x);
}
int main() {
let double_it: fn(int)->int = int(int x) { return x * 2; };
printf("%d\n", double_it(5)); // 10
printf("%d\n", apply(double_it, 4)); // 8
return 0;
}
fn(int)->int is the function-pointer type. The lambda
int(int x) { ... } produces a value of that type.