Referensi Sintaks

Sintaks lengkap AHA! — kata kunci, operator, literal, dan grammar, terverifikasi dari source compiler

Referensi Sintaks

Sintaks lengkap AHA! Lang, terverifikasi dari compiler. Setiap konstruksi di sini diperiksa langsung terhadap lexer dan parser di src/.

Kata Kunci

Ada tepat 13 kata kunci reserved:

Kata KunciFungsi
fnDefinisi fungsi
letBinding variabel
structDefinisi struct
if / elsePercabangan kondisional
returnKembali dari fungsi
whileLoop berbasis kondisi
for / inLoop rentang (range)
breakKeluar dari loop lebih awal
continueLewati ke iterasi berikutnya
true / falseLiteral boolean

Kata kunci ini reserved — tidak bisa dipakai sebagai nama variabel atau fungsi.

Identifier

  • Diawali huruf (a-z, A-Z) atau garis bawah (_)
  • Dilanjutkan huruf, angka, atau garis bawah (my_var2, _private)
  • Tidak boleh sama dengan kata kunci
let valid_name = 1;
let _private = 2;
let myVar2 = 3;

Literal

LiteralContohTipe
Integer42Int (64-bit)
Booleantrue, falseBool
String"hello"String ({i8*, i64})

Urutan escape string

EscapeArti
\nBaris baru
\tTab
\\Backslash
\"Tanda kutip ganda
\rCarriage return
\0Null byte

Tipe

TipeCatatan
IntInteger 64-bit — tipe numerik universal
Booltrue / false; dihasilkan oleh ! dan perbandingan
String"..." — disimpan sebagai struct {pointer, length}
voidType hint untuk fungsi tanpa return (hanya hint)
StructNameStruct buatan user (hint tipe field: name: string, age: int)

Type hint di deklarasi field dan anotasi masa depan memakai bentuk huruf kecil: int, i64, bool, string, str, void.

Operator

Aritmetika

+ - * / %

Perbandingan (→ Int 0/1)

== != < > <= >=

Logika (→ Int 0/1)

&& ||

Prefix

-x (negasi), !x (not)

Penugasan

x = value, p.x = value

Precedence (rendah → tinggi)

PrecedenceOperator
Terendah= (penugasan)
||
&&
== !=
< > <= >=
+ -
* / %
Tertinggiprefix - !, call, field access, index

Statement

let (binding variabel)

let count = 0;

Binding tidak mengizinkan redeklarasi nama yang sama; mutasi dilakukan via penugasan =.

Variabel dapat membawa anotasi tipe eksplisit — nilai diperiksa tipenya saat kompilasi:

let x: int = 5;
let s: string = "hello";
let b: bool = true;
let p: Point = Point { x: 1, y: 2 };

Anotasi yang tidak cocok dengan tipe nilai adalah error kompilasi:

let x: int = "hi";  // Type mismatch: variable 'x' annotated as 'int' but value has type 'String'

Expression statement

Ekspresi apa pun di baris sendiri adalah statement:

print(42);
x + y;

return

fn add(a, b) {
    return a + b;
}

Fungsi juga bisa mengembalikan ekspresi terakhirnya secara implisit (lihat bawah).

Fungsi generik

Fungsi dapat memiliki tipe parameter generik — tipe konkret di-infer dari call site:

fn id<T>(x: T) -> T { x }
fn pick<T>(a: T, b: T) -> T { if a > b { a } else { b } }
fn first<A, B>(a: A, b: B) -> A { a }
  • Tipe parameter ditulis dalam kurung sudut <T, U> setelah nama fungsi
  • Parameter bisa memakai hint tipe: fn max<T>(a: T, b: T) -> T
  • Anotasi return type memakai -> T atau tipe konkret -> int
  • Setiap kombinasi unik (nama, tipe konkret) menjadi fungsi LLVM terpisah saat kompilasi — nol biaya runtime

Definisi struct

struct Point {
    x,
    y,
}

Definisi struct mendukung hint tipe field opsional:

struct Person {
    name: string,
    age: int,
}

Tipe field diperiksa saat kompilasi: menugaskan literal string ke field int adalah error kompilasi.

Ekspresi

Struct literal

let p = Point { x: 3, y: 4 };
  • Urutan field tidak tergantung urutan deklarasi
  • Field yang tidak diisi default ke 0 (int) / string kosong (string)
  • Tipe diperiksa terhadap deklarasi

Akses field

let sum = p.x + p.y;
let name_len = len(p.name);

Akses field mempertahankan tipe yang dideklarasikan, sehingga p.first + p.last (concat string) dan len(p.name) bekerja.

Panggilan fungsi

print(42);
abs(-5);
sum(Point { x: 1, y: 2 });

Fungsi

fn greet(name) {
    print_str("Hello, ");
    print_str(name);
}

fn add(a, b) {
    a + b // return implisit ekspresi terakhir
}

fn make_point(x, y) {
    Point { x: x, y: y } // return value struct
}
  • Tipe parameter diinferensikan dari call site (default Int; String/struct saat teramati)
  • Struct bisa dioper by-value dan dikembalikan sebagai nilai
  • Ekspresi terakhir adalah nilai return implisit
  • return keluar lebih awal

Alur Kontrol

if / else

if adalah ekspresi — ekspresi terakhir tiap cabang adalah nilainya:

let m = if a > b { a } else { b };

while

let i = 0;
while i < 5 {
    i = i + 1;
}

for (range loop)

let sum = 0;
for i in 0..10 {
    sum = sum + i;
}

Rentang a..b eksklusif b (menghasilkan a, a+1, ..., b-1).

break / continue

let total = 0;
for i in 0..100 {
    if i == 5 {
        break;      // keluar dari loop
    }
    if i % 2 == 0 {
        continue;   // lewati ke iterasi berikutnya
    }
    total = total + i;
}

Komentar

// komentar satu baris

/* komentar blok
   beberapa baris */

Builtin

BuiltinDeskripsi
print(int)Cetak integer
print_str(string)Cetak string
len(string)Panjang string O(1)
abs(x)Nilai absolut
min(a, b)Angka terkecil dari dua
max(a, b)Angka terbesar dari dua

Ringkasan Grammar

program     := statement*
statement   := let-stmt | struct-def | return-stmt | expr-stmt
let-stmt    := 'let' IDENT '=' expression ';'
struct-def  := 'struct' IDENT '{' (IDENT (':' type-hint)? (',' IDENT (':' type-hint)?)*)? '}'
return-stmt := 'return' expression
expr-stmt   := expression ';'? (ekspresi terakhir di blok boleh tanpa ';')

expression  := assignment
assignment  := unary '=' expression | infix
infix       := unary (operator unary)*
unary       := ('-' | '!') unary | primary
primary     := literal | IDENT | call | field-access | index | struct-literal
             | '(' expression ')' | if-expr | while-expr | for-expr
             | array-literal | function-literal
call        := primary '(' (expression (',' expression)*)? ')'
field-access:= primary '.' IDENT
index       := primary '[' expression ']'
struct-lit  := IDENT '{' (IDENT ':' expression (',' IDENT ':' expression)*)? '}'
if-expr     := 'if' expression block ('else' (block | if-expr))?
while-expr  := 'while' expression block
for-expr    := 'for' IDENT 'in' expression block
block       := '{' statement* '}'