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.jda

Import 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 constant

Types

TypeDescription
i6464-bit signed integer (default)
i3232-bit signed integer
i88-bit signed integer (byte)
f6464-bit floating point
&TPointer/reference to type T
&i8Byte buffer / string pointer
boolBoolean (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 0

Booleans 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, 6

Break / 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, 3

Operators

CategoryOperators
Arithmetic+, -, *, /, %
Comparison==, !=, <, >, <=, >=
Logicaland, 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 = 20

Arrays 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")
}