-
Notifications
You must be signed in to change notification settings - Fork 0
Language
Line comments start with #
and continue to the end of the line.
# This is a comment
x = a + b; # This is another comment
Block comments start with #!
and end with !#
.
Block comments can be nested.
#!
Multi-line comment
#!
Nested comment
!#
Back in the outer comment
!#
Integer literals can be specified in the following bases: binary, octal, decimal, and hexadecimal.
Binary, octal, and hexadecimal integers have the respective prefixes 0b
, 0o
, and 0x
.
Base | Prefix | Valid Characters |
---|---|---|
2 | 0b |
0 and 1
|
8 | 0o |
0 -7
|
10 | none |
0 -9
|
16 | 0x |
0 -9 , a -f , A -F
|
Also, an underscore (_
) may be used as a separator.
Examples:
0b101
0b_1101_0101
0o026
1783
12_345
0x1234_abcd
Floating-point literals can be specified by using a decimal point (.
), an exponent (after e
), or both.
An underscore (_
) may be used as a separator.
Examples:
1.23
2e-8
1_234.567_890
1e1_000
Variables are declared using the var
keyword followed by the variable name.
They must be defined when they are declared.
The variable's type may optionally follow its name.
Otherwise, the type will be inferred from the expression being assigned.
Note that the type must be specified when assigning an integer literal.
var <name> [type] = <expression>;
Below are several examples:
var x i32 = 10;
var y = x * 2;
var isEqual bool = (x == y);
Constants are declared using the const
keyword followed by the constant name.
They must be defined when they are declared.
The constant's type may optionally follow its name.
Otherwise, the type will be inferred from the expression being assigned.
Note that the type must be specified when assigning an integer literal.
const <name> [type] = <expression>;
The assigned expression must be a constant expression. Constant expressions are one of the following:
- A boolean literal (i.e.
true
orfalse
) - An integer literal (e.g.
123
,0xA5
) - A string literal (e.g.
"abc"
) - Another constant
- A struct initialization where all members are initialized to constant expressions
- The following unary operators with a constant operand:
-
,!
- The following binary operators with constant operands:
==
,!=
,<
,<=
,>
,>=
,+
,-
,*
,/
,%
,<<
,>>
,>>>
,&
,^
,|
,..
,..<
,[]
- A
cast
with a constant argument - A member expression where the struct expression is constant
- An array expression where all array element expressions are constant
Below are several examples:
const n1 i32 = 10;
const n2 = n1 * 2;
const b bool = true;
const s = "abc";
const a1 []i32 = [n1, n2, 30, 40, 50];
const a2 = a1[1..3];
String literals are surrounded in double quotes ("
) and may contain any valid UTF-8 code point.
A backslash (\
) is used to start an escape sequences. Escape sequences are listed below:
Escape Sequence | Description |
---|---|
\' |
single quote |
\" |
double quote |
\\ |
backslash |
\n |
new line |
\r |
carriage return |
\t |
horizontal tab |
\u{} |
unicode |
\x |
byte |
Examples:
"abc"
"$1.00 ÷ 2 = 50¢"
"line 1\nline 2\nline 3\n"
"\x41\x42\x43"
"\u{03c0} = 3.14159"
Note that, unlike C/C++, strings are not null terminated.
Individual bytes in a string can be accessed with the subscript ([]
) operator.
var s = "Hello!";
var b u8 = s[4]; # get byte "o" at index 4
Functions are defined with the fun
keyword followed by the function name,
an optional list of parameters in parenthesis, and the return type.
Each parameter must have its type specified after the name.
Function bodies are surrounded by curly braces ({
and }
).
A function's return value is the last expression in the function body and does not have a trailing semicolon.
Alternatively, the return
keyword can be used to return a value from a function.
fun add(num1 i32, num2 i32) i32
{
var sum = num1 + num2;
sum
}
fun sub(num1 i32, num2 i32) i32
{
var diff = num1 - num2;
return diff;
}
Note that functions need not be defined before they are called within a file. Thus, the following is valid:
fun calculate(num i32) i32
{
# function is called here...
add(num, 2)
}
# ...but not defined until here
fun add(num1 i32, num2 i32) i32
{
num1 + num2
}
Functions in C libraries may also be called by providing an extern
function declaration:
extern fun myCFunction(x i32) i32;
Function types start with the fun
keyword followed by
an optional list of parameters in parenthesis and the return type.
For example, a function pointer variable can be defined like so:
var funPtr fun(a i32, b i32) i32 = add;
Branches are created using the if
and else
keywords.
Branches are expressions that evaluate to the expression of the branch taken.
fun myFunction(x i32, y i32, z i32) i32
{
if x == 0
{
y + z
}
else
{
y - z
}
}
Multiple branches may be added by using elif
to specify more conditions.
fun myFunction(x i32, y i32, z i32) i32
{
if x == 0
{
y + z
}
elif x == 1
{
y - z
}
else
{
y * z
}
}
Notes:
- Each branch's body must be surrounded in curly braces (
{
and}
) - Each
if
andelif
condition must evaluate to a boolean (bool
) value
Since branches are expressions, they can be nested in other expressions:
var y i64 = 10 *
if x < 0 { -1 }
elif x == 0 { 0 }
else { 1 };
While loops are created using the while
keyword:
var num i32 = 1;
var i i32 = 0;
while i < 10
{
num *= 2;
i += 1;
}
Notes:
- Each loop's body must be surrounded in curly braces (
{
and}
) - Each
while
condition must evaluate to a boolean (bool
) value
For loops are created with the for
and in
keywords.
The iterator type can be explicitly specified.
Otherwise, it will be inferred from the iterable expression.
Note that the type must be specified when assigning a range or array of integer literals.
for
loop (closed interval range):
for i i32 in 0..3
{
# i is 0, 1, 2, and 3
}
for
loop (half-open interval range):
for i i32 in 0..<3
{
# i is 0, 1, and 2
}
for
loops can also be used to iterate over arrays:
var array []i32 = [10, 20, 30];
for x in array
{
# ...
}
An index variable can also be added to a for
loop:
var array []i32 = [10, 20, 30];
for x, i in array
{
# x will be 10, 20, 30
# i will be 0, 1, 2
}
Notes:
- Each loop's body must be surrounded in curly braces (
{
and}
) - For loops can iterate over ranges or arrays
The break
and continue
keywords can be used in both while
and for
loops.
break
terminates the loop.
continue
jumps back to the start of the loop.
A pointer type is created by prepending &
to the type it points to.
The &
operator is used to get the pointer to a value.
var x i32 = 123;
var ptr &i32 = &x; # create a pointer to x
A pointer is dereferenced with the *
operator.
*ptr = 10;
Structs are defined with the struct
keyword followed by the struct name.
The struct's members are defined in curly braces ({
and }
).
struct MyStruct
{
name str,
x i32,
y i32,
}
Structs are initialized as follows:
var t MyStruct =
MyStruct
{
name: "Al",
x: 42,
y: -17
};
All members must be initialized when initializing a struct.
Note that structs need not be defined before they are referenced within a file. Thus, the following is valid:
struct Line
{
# Point struct is used here...
p1 Point,
p2 Point,
}
# ...but not defined until here
struct Point
{
x i32,
y i32,
}
Struct members are accessed with the .
operator.
var point = Point { x: 1, y: 2 };
point.x += 3;
Note that .
also works with struct pointers.
var ptr = &point;
ptr.x += 3;
An array type is created by prepending the array element type with square brackets ([]
).
For example, []i32
is an array of i32
integers.
Arrays are initialized in one of two ways: a multi-value expression or a size-value expression.
var a1 []i32 = [10, 20, 30]; # 3-element multi-value expression with initial values 10, 20, and 30
var a2 []i32 = [5; 0]; # 5-element size-value expression with initial values of 0
The number of elements in an array can be accessed with the Size
property which has the type usize
.
var a1 []i32 = [100; 0];
var len usize = a1.Length; # len will be 100
Arrays have 0-based indexing. Examples of getting/setting array elements:
x = a1[2]; # get element at index 2
a1[4] = 123; # set element at index 4 to 123
Arrays may be sliced with the subscript operator ([]
) and a range.
A slice is, itself, an array.
var a1 []i32 = [0, 1, 2, 3, 4];
var a2 = a1[1..<3]; # a2 = [1, 2]
var a3 = a1[1..3]; # a3 = [1, 2, 3]
Use cast(<type>, <expression>)
to cast expressions.
Example:
var x i32 = 123;
var y i8 = cast(i8, x);
Casting rules:
- Boolean to an integer results in
0
if the boolean isfalse
, otherwise1
- Boolean to a float results in
0.0
if the boolean isfalse
, otherwise1.0
- Integer to a boolean results in
false
if the integer is0
, otherwisetrue
- Integer to a larger integer:
- If expression is signed: sign extension
- If expression is unsigned: zero extension
- Integer to a smaller integer: truncate
- Integer to another integer of the same size: no change
- Integer to float: truncate if necessary
- Float to a boolean results in
false
if the float is0.0
or-0.0
, otherwisetrue
- Float to integer: truncate
- Float to larger float: resize
- Float to smaller float: truncate
-
bool
- Boolean type -
break
- Break out of a loop -
cast
- Cast an expression -
const
- Declare a constant -
continue
- Jump to the start of a loop -
elif
- Start of else-if block -
else
- Start of else block -
extern
- External function declaration -
f32
- 32-bit floating-point type -
f64
- 64-bit floating-point type -
false
- Boolean false literal -
for
- Start of for loop -
fun
- Function definition -
i8
- Signed 8-bit integer type -
i16
- Signed 16-bit integer type -
i32
- Signed 32-bit integer type -
i64
- Signed 64-bit integer type -
if
- Start of if block -
in
- Used in for loops between the iterator variable and expression -
isize
- Signed pointer-size integer type -
return
- Return from a function -
str
- String literal type -
struct
- Struct definition -
true
- Boolean true literal -
type
- Type type -
u8
- Unsigned 8-bit integer type -
u16
- Unsigned 16-bit integer type -
u32
- Unsigned 32-bit integer type -
u64
- Unsigned 64-bit integer type -
usize
- Unsigned pointer-size integer type -
var
- Declare a variable -
while
- Start of while loop
Operator | Description | Example |
---|---|---|
- |
negation (2's complement) | -a |
! |
1's complement | !a |
& |
address of | &a |
* |
dereference | *a |
= |
assignment | a = b |
== |
equal | a == b |
!= |
not equal | a != b |
< |
less than | a < b |
<= |
less than or equal | a <= b |
> |
greater than | a > b |
>= |
greater than or equal | a >= b |
+ |
addition | a + b |
- |
subtraction | a - b |
* |
multiplication | a * b |
/ |
division | a / b |
% |
remainder | a % b |
<< |
shift left | a << b |
>> |
logical shift right | a >> b |
>>> |
arithmetic shift right | a >>> b |
& |
bitwise AND | a & b |
^ |
bitwise XOR | a ^ b |
| |
bitwise OR | a | b |
&& |
logical AND | a && b |
|| |
logical OR | a || b |
+= |
add and assign | a += b |
-= |
subtract and assign | a -= b |
*= |
multiply and assign | a *= b |
/= |
divide and assign | a /= b |
%= |
remainder and assign | a %= b |
<<= |
shift left and assign | a <<= b |
>>= |
logical shift right and assign | a >>= b |
>>>= |
arithmetic shift right and assign | a >>>= b |
&= |
bitwise AND and assign | a &= b |
^= |
bitwise XOR and assign | a ^= b |
|= |
bitwise OR and assign | a |= b |
.. |
closed interval range | a..b |
..< |
half-open interval range | a..<b |
. |
member access | a.b |
[] |
subscript | a[b] |