TODO

Multiple return values

get_numbers fn() -> (i32, i32) {
    return 1, 2
}

Right now I am not planning to add tuples as a first class citizen (that may change of course) which means the returned values will have to get destructured during assignment.

a, b : i32, i32 = get_numbers()
_, b : i32, i32 = get_numbers() // Only assign the second value
a, b := get_numbers()

I do not really like this syntax because the declaration (the : symbol) is not applied specifically to the variables you want to declare but to all the variables on the left side of the assignment.

get_numbers fn() -> (i32, i32) {
    return 1, 2
}

a : f32

a, b : i32, i32 = get_numbers() // a gets redeclared to a i32

In this example I want to use the preexisting variable a and declare a new variable b. a is a f32 and it is getting assigned a i32 so an error is expected. Instead, a new variable a of type i32 gets declared instead and shadows the previous one. Languages like Go and Rust also have this problem. Maybe it is not that important, especially since Rawr is strongly typed with few implicit conversions making that kind of bug probably easy to spot.

My other issue is extracting a value from a multiple return values function to use in an expression. Go doesn’t seem to support that but on Rust i can use the . operator. It may be weird to only allow that in function calls, it would feel like Rawr supports tuples but doesn’t let you use them (which is kinda true).

get_numbers fn() -> (i32, i32) {
    return 50, 8
}

a := get_result().1 + 93  // Extract the first value (50) and discard the others

Automatic C bindings

Making bindings is painful so I am planning to add a binding command to the Rawr compiler.

$ rawr binding gl.h

It would produce a .rawr file with all the declarations in a module. If no files are specified, the compiler would convert C functions wrote in stdin and print the result so you could just copy and paste declarations and quickly get a binding out of it. While parsing C is notoriously painful, I expect this feature to be very useful even if it only supports a subset of the language. The language Zig takes this idea further by supporting including C headers directly from Zig code.

Better type inference

In Rawr, literals have a special untyped type: 1 is an untyped integer and 1.0 is an untyped float. Literals get implicitly cast when they interact with a compatible type.

a : i8 = 1
b := a + 2  // 2 gets implicitly cast to i8

However, when no type is provided, integer literals default to i32 and float literals to f32.

a := 1    // a i32
b := 1.0  // a f32

This behavior mostly work but forces the user to add type annotation in situation where the type is obvious.

value := 1
print_i8(value)  // Error: expected a i8 and got a i32

I used to have a better type inference system mostly working in the compiler but it made the typechecking code more complex for not a lot of added value so I removed it. I want to give it another shot when I add generics in Rawr.