A basic statically typed systems-level programming language. The compiler is written in rust using LLVM as its backend. A simple unoptimized x86_64 backend is also on it's way.
- Runtime Speed: The language should make it possible to write code about as fast as C.
- Short syntax: Shorter code is more fun to write and easier to read.
- Type inference: Having to write less types makes the code shorter and refactoring easier.
- Compilation speed: Compilation speed over a few seconds makes debugging painfully slow.
- Simplicity: Syntax features are nice but too many of them make the language too complicated.
main :: fn {
std.println("Hello World")
x := 3
y := 2 * x + 3
y += 1
std.c.printf("X is %d and y is %d\n".ptr, x, y)
}
use std.c.printf
add_pointer_values :: fn(x *i32, y *i32) -> i32: x^ + y^
main :: fn {
x := 5
y := 7
printf("Result: %d\n".ptr, add_pointer_values(&x, &y))
}
add :: fn(x i64, y i64) -> i64: x + y
main :: fn {
x := 3 # x is inferred to have type i64
pointer := &x
std.c.printf("Result: %d\n".ptr, if 1 < 2: add(pointer^, 4) else -1)
}
# this constant doesn't have a specific integer type
A :: 42
main :: fn {
std.c.printf("%d\n".ptr, A) # prints 42
# can be assigned to any integer
x: u8 = A
y: i32 = A
# also works with floats
PI :: 3.14
pi: f32 = PI
pi_squared: f64 = PI*PI
}
use std.c
Vec3 :: struct { x f64, y f64, z f64 }
print_vec3 :: fn(v *Vec3) {
c.printf("Vec3: [%.1f, %.1f, %.1f]\n".ptr, v^.x, v^.y, v^.z)
}
main :: fn {
v := c.malloc(12) as *Vec3
v^ = Vec3(1.0, 2.0, 3.0)
print_vec3(v)
}
Enums can be used locally without a type definition.
main :: fn {
color := .NoColor
inp := std.input("Which color do you want? ")
if inp == "red": color = .Red
else if inp == "green": color = .Green
else if inp == "blue": color = .Blue
if .NoColor := color:
print("You didn't select a valid color")
else {
print("Your color is ")
# match exhaustively checks patterns on a value. Removing any of the
# arms would create an error (even though the enum is completely inferred!)
println(match color {
.Red: "Red",
.Green: "Green",
.Blue: "Blue",
.NoColor: std.panic("unreachable"),
})
}
}
Enum variants can also have arguments. This is known as sum types/algebraic data types in many other languages. Note that implicit enums can infer to explicitly typed enums without having to name the type.
use std.print
use std.println
Fruit :: enum { Apple(i32), Banana, Citrus }
main :: fn {
# f is of type Fruit here because it is passed to print_fruit
f := .Banana
f = .Apple(5)
# This would create a compilation error because Orange is not a valid variant of Fruit
# f = .Orange
print_fruit(f)
print_fruit(.Banana)
}
print_fruit :: fn(f Fruit): match f {
.Apple(radius) {
print("Apple with radius ")
println(std.int_to_str(radius))
}
.Banana: println("A Banana"),
.Citrus: println("A Lemon?")
}
You will need LLVM 15 to build this project. The environment variable LLVM_SYS_150_PREFIX
should be set to the path of your LLVM installation. Look at the llvm-sys crate
for detailed instructions on how to build llvm.
Nightly rust will also be required. I will try to stay mostly up to date with the newest nightly version.
To run a program, use cargo +nightly run -- run example.eye