Language Specification
Version 0.2.0 β Complete reference for the AXON language grammar, type system, and semantics.
Design Philosophy
AXON is built on four core principles that distinguish it from every human-facing language.
AI-Native
Designed for language models to emit deterministically β no ambiguous syntax, no formatting choices, no implicit conversions.
Performance-First
Zero-cost abstractions, no garbage collector, no runtime overhead. Compiles to native code via QBE or LLVM.
Explicit Everything
Every type annotation, every cast, every conversion is explicit. Nothing is inferred, nothing is implicit, nothing is hidden.
Minimal Surface
Small, orthogonal feature set. Each construct does one thing. No operator overloading, no macros, no variadic functions.
EBNF Grammar
The complete grammar for AXON's S-expression syntax. All source files use this notation.
(* ββ Top Level ββ *) module = "(" "module" { top_decl } ")" ; top_decl = fn_decl | extern_decl | struct_decl | const_decl | global_decl | enum_decl | sum_decl ; (* ββ Declarations ββ *) fn_decl = "(" "fn" IDENT "(" { param } ")" type expr ")" ; extern_decl = "(" "extern" IDENT "(" { param } ")" type ")" ; struct_decl = "(" "struct" IDENT "(" { field } ")" ")" ; const_decl = "(" "const" IDENT type literal ")" ; global_decl = "(" "global" IDENT type expr ")" ; enum_decl = "(" "enum" IDENT int_type "(" { enum_variant } ")" ")" ; enum_variant = "(" IDENT INT_LIT ")" ; sum_decl = "(" "sum" IDENT "(" { sum_variant } ")" ")" ; sum_variant = "(" IDENT { type } ")" ; param = "(" IDENT type ")" ; field = "(" IDENT type ")" ; (* ββ Types ββ *) type = prim_type | ptr_type | array_type | struct_type | enum_type | sum_type | fnptr_type ; prim_type = "i8" | "i16" | "i32" | "i64" | "f32" | "f64" | "bool" | "void" ; ptr_type = "(" "ptr" type ")" ; array_type = "(" "array" type INT_LIT ")" ; struct_type = IDENT ; enum_type = IDENT ; sum_type = IDENT ; fnptr_type = "(" "fnptr" "(" { type } ")" type ")" ; (* ββ Expressions ββ *) expr = literal | var_ref | binop | unop | call | block | if_expr | let_expr | set_expr | while_expr | cast_expr | deref_expr | addr_expr | field_expr | index_expr | struct_lit | match_expr | enum_lit | sum_lit ; literal = "(" type ( INT_LIT | FLOAT_LIT | "true" | "false" ) ")" ; var_ref = IDENT ; binop = "(" BIN_OP expr expr ")" ; call = "(" "call" expr { expr } ")" ; block = "(" "block" { expr } ")" ; if_expr = "(" "if" expr expr [ expr ] ")" ; let_expr = "(" "let" IDENT type expr ")" ; set_expr = "(" "set" IDENT expr ")" ; while_expr = "(" "while" expr expr ")" ; cast_expr = "(" "cast" type expr ")" ; deref_expr = "(" "deref" expr ")" ; addr_expr = "(" "addr" IDENT ")" ; field_expr = "(" "field" expr IDENT ")" ; index_expr = "(" "index" expr expr ")" ; struct_lit = "(" "struct" IDENT { "(" IDENT expr ")" } ")" ; enum_lit = "(" IDENT IDENT ")" ; (* (Color Red) *) sum_lit = "(" IDENT "." IDENT { expr } ")" ; (* (Option.Some (i64 42)) *) match_expr = "(" "match" expr { match_arm } ")" ; match_arm = "(" pattern expr ")" ; pattern = literal | enum_lit | sum_pat | "_" | "true" | "false" ; sum_pat = "(" IDENT "." IDENT { IDENT } ")" ; (* (Option.Some val) *)
Primitive Types
| Type | Size (bytes) | Description |
|---|---|---|
i8 | 1 | Signed 8-bit integer |
i16 | 2 | Signed 16-bit integer |
i32 | 4 | Signed 32-bit integer |
i64 | 8 | Signed 64-bit integer |
f32 | 4 | IEEE 754 single-precision float |
f64 | 8 | IEEE 754 double-precision float |
bool | 1 | Boolean (true / false) |
void | 0 | Unit type (no value) |
Compound Types
| Type | Syntax | Description |
|---|---|---|
| Pointer | (ptr T) | Typed pointer to a value of type T |
| Array | (array T N) | Fixed-size array of N elements of type T |
| Struct | (struct Name ((f1 T1) ...)) | Named product type with ordered fields |
| Enum | (enum Name iN ((V1 0) ...)) | Nominal enum with explicit integer backing |
| Sum Type | (sum Name ((V1 T1...) ...)) | Tagged union with per-variant payloads |
| Function Pointer | (fnptr (T1 T2) Ret) | Pointer to a function with given param/return types |
Cast Rules
All type conversions in AXON are explicit via the (cast T expr) form. The following casts are allowed:
| From | To | Semantics |
|---|---|---|
int | int | Sign-extend or truncate to target width |
int | float | Signed integer to floating-point conversion |
float | int | Floating-point to signed integer (truncate toward zero) |
ptr | ptr | Reinterpret pointer type (no runtime cost) |
enum | int | Extract underlying integer value from enum |
int | enum | Wrap integer as enum (value must be valid variant) |
Operators
All operators use prefix notation: (op lhs rhs). No operator overloading.
| Category | Operators | Operand Types |
|---|---|---|
| Arithmetic | + - * / % | int Γ int, float Γ float |
| Comparison | == != < <= > >= | int Γ int, float Γ float, enum Γ enum (== != only) |
| Logical | && || ! | bool Γ bool (! is unary) |
| Bitwise | & | ^ ~ << >> | int Γ int (~ is unary) |
Enum Types
Enums are nominal integer-backed types with named variants. Each variant has an explicit integer value.
;; Declaration (enum EnumName backing_int_type ((Variant1 0) (Variant2 1) ...)) ;; Construction (enum literal) (EnumName VariantName) ;; Cast to integer (cast i32 (Color Red)) ;; β 0 ;; Comparison (== c (Color Blue)) ;; enum == enum β bool
Example
(module (extern print_i64 ((n i64)) void) (enum Dir i32 ((North 0) (South 1) (East 2) (West 3))) (fn main () i32 (block (let d Dir (Dir East)) (call print_i64 (cast i64 d)) ;; prints 2 (i32 0))))
Rules
- Backing type must be an integer type (
i8,i16,i32,i64) - All variant values must be explicit integer literals
- Variant values must be unique within the enum
- Enums support
==and!=comparison - Cast to/from backing int type via
(cast ...) - Enums are type-safe: cannot assign one enum to another
Sum Types (Tagged Unions)
Sum types are algebraic data types where each variant can carry a different payload. The compiler auto-assigns sequential tag values and enforces exhaustive pattern matching.
;; Declaration: auto-assigned tags 0, 1, 2, ... (sum TypeName ((Variant1 type1 type2) (Variant2) (Variant3 type1))) ;; Construction (dot notation) (TypeName.Variant1 expr1 expr2) (TypeName.Variant2) ;; Pattern match with payload binding (match value ((TypeName.Variant1 a b) ;; a, b bound to payload fields (add a b)) ((TypeName.Variant2) (i64 0)))
Example
(module (extern print_i64 ((n i64)) void) (sum Option ((None) (Some i64))) (fn unwrap_or ((opt Option) (default i64)) i64 (match opt ((Option.Some val) val) ((Option.None) default))) (fn main () i32 (block (call print_i64 (call unwrap_or (Option.Some (i64 42)) (i64 0))) ;; 42 (call print_i64 (call unwrap_or (Option.None) (i64 -1))) ;; -1 (i32 0))))
Rules
- Layout:
i32tag + aligned payload region (max variant size) - Tag values are auto-assigned: 0, 1, 2, ...
- Variants may carry zero or more payload fields (positional, not named)
- Construction uses dot notation:
(Type.Variant payload...) - Payload count and types are checked at compile time
- Sum types are nominal: different sum types with identical layouts are distinct
- Pattern matching with binding introduces local variables scoped to the arm body
Match Expressions
Pattern matching with exhaustiveness checking. Returns a value β every arm must produce the same type.
(match scrutinee (patternβ resultβ) (patternβ resultβ) ... (_ default))
Exhaustiveness Rules
- Enum: Must cover all variants, or include a wildcard
_arm - Sum: Must cover all variants, or include a wildcard
_arm β payload bindings scoped to arm body - Bool: Must cover both
trueandfalse, or include_ - Integer: Must include a wildcard
_arm (infinite domain)
Enum Match
(enum Color i32 ((Red 0) (Green 1) (Blue 2))) (match c ((Color Red) (i64 10)) ((Color Green) (i64 20)) ((Color Blue) (i64 30))) ;; exhaustive: all 3 variants covered
Integer Match (wildcard required)
(match x ((i32 0) (i64 100)) ((i32 1) (i64 200)) (_ (i64 999))) ;; wildcard required for int
Bool Match
(match flag (true (i64 1)) (false (i64 0))) ;; exhaustive: both values covered
Function Pointers
First-class function pointers with explicit type annotation and auto-coercion from named functions.
Type Syntax
;; Type: pointer to function (i64, i64) β i64 (fnptr (i64 i64) i64) ;; Declare a local with fnptr type (let fp (fnptr (i64 i64) i64) add) ;; auto-coerce fn β fnptr ;; Call via fnptr (call fp (i64 3) (i64 4)) ;; β 7
Auto-Coercion
When a named function is used where a fnptr is expected, the compiler automatically coerces it.
No explicit cast is needed β just use the function name as an expression.
(fn double ((x i64)) i64 (* x (i64 2))) (fn triple ((x i64)) i64 (* x (i64 3))) (fn apply ((f (fnptr (i64) i64)) (val i64)) i64 (call f val)) ;; Usage: auto-coerces 'double' and 'triple' to fnptr (call apply double (i64 5)) ;; β 10 (call apply triple (i64 5)) ;; β 15