Syntax Reference
Comments
// Single-line comment
;; Documentation comment (extracted by jda-doc)
/* Multi-line comment */
/*
* Block comment
* spanning multiple lines
*/Imports
import "math" // imports stdlib/math.jda
import "vec" // imports stdlib/vec.jda
import "net/http" // imports stdlib/net/http.jdaImport statements must appear at the top of the file. The compiler resolves import "name" to stdlib/<name>.jda. Duplicate imports are automatically skipped.
Variables
let x = 42 // mutable variable
let name = "hello" // string literal (&i8 pointer)
let flag = true // boolean (true=1, false=0)
let ch = 'A' // char literal (ASCII value 65)
const MAX = 100 // compile-time constantTypes
| Type | Description |
|---|---|
i64 | 64-bit signed integer (default) |
i32 | 32-bit signed integer |
i8 | 8-bit signed integer (byte) |
f64 | 64-bit floating point |
&T | Pointer/reference to type T |
&i8 | Byte buffer / string pointer |
bool | Boolean (true / false) |
Boolean and Character Literals
let a = true // compiles to i64 1
let b = false // compiles to i64 0
if a and not b { print("ok\n") }
let ch = 'A' // char literal -> i64 65
let nl = '\n' // escape -> i64 10
let tab = '\t' // tab -> i64 9
let zero = '\0' // null -> i64 0Booleans are syntactic sugar for i64 values. Char literals produce the ASCII integer value.
Functions
fn add(a: i64, b: i64) -> i64 {
ret a + b
}
fn greet() {
print("hello\n")
}Functions without a return type annotation return void. ret is the return keyword.
Generic Functions
fn max<T>(a: T, b: T) -> T {
if a > b { ret a }
ret b
}
fn identity<T>(x: T) -> T {
ret x
}The compiler generates specialized versions at each call site (monomorphization).
Const Generics
fn zeros<const N>() -> [i64; N] {
let arr: [i64; N]
for i in range(N) { arr[i] = 0 }
ret arr
}Compile-time integer parameters for array sizes and loop bounds.
Closures
fn make_adder(n: i64) -> fn(i64) -> i64 {
let captured = n
ret fn(x: i64) -> i64 {
ret x + captured
}
}Closures capture variables from their enclosing scope.
Control Flow
If / Else
if x > 0 {
print("positive\n")
} else if x == 0 {
print("zero\n")
} else {
print("negative\n")
}Loops
// Conditional loop
let i = 0
loop i < 10 {
print_i64(i)
i = i + 1
}
// For-in loop
for i in range(10) { ... } // i = 0, 1, ..., 9
for i in range(3, 7) { ... } // i = 3, 4, 5, 6Break / Continue
let i = 0
loop i < 100 {
if i == 10 { break }
i = i + 1
}
let sum = 0
for i in range(10) {
if i % 2 != 0 { continue }
sum += i
}Defer
fn process_file(path: &i8) -> i64 {
let fd = file_open(path, 0)
defer file_close(fd) // runs when process_file returns
let data = file_read_all(fd)
ret str_len(data)
}Multiple defers execute in LIFO (last-in, first-out) order:
fn do_work() {
defer print("3\n")
defer print("2\n")
defer print("1\n")
print("working\n")
}
// Output: working, 1, 2, 3Operators
| Category | Operators |
|---|---|
| Arithmetic | +, -, *, /, % |
| Comparison | ==, !=, <, >, <=, >= |
| Logical | and, or, not |
| Bitwise | &, |, ^, ~, <<, >> |
| Compound assignment | +=, -=, *=, /= |
| Address-of | & (prefix) |
| Index | [] |
| Field access | . |
| Error propagation | ? |
Structs
struct Point {
x: i64
y: i64
}
let p = Point{}
p.x = 10
p.y = 20Arrays in Structs
struct Buffer {
data: i64[256]
len: i64
}Enums
enum Direction {
North,
South,
East,
West,
}Pattern Matching
match value {
0 => print("zero\n"),
1 => print("one\n"),
_ => print("other\n"),
}Unsafe Blocks
unsafe {
// raw pointer arithmetic, inline assembly, etc.
}Compile with --safe to enforce unsafe block boundaries.
Inline Assembly
unsafe {
asm("mov rax, 60; xor rdi, rdi; syscall")
}