Language Specification
Formal specification of Hew v0.5.0 — grammar, types, expressions, actors, concurrency, wire types, and FFI.
Contents
1. Program Structure
A Hew program is a sequence of items. Each .hew file is a module.
Program = { Item } ;
Item = Attribute* Visibility? ( Import | ConstDecl | LetDecl | VarDecl
| TypeDecl | TraitDecl | ImplDecl | WireDecl | FnDecl
| ExternBlock | ActorDecl | SupervisorDecl ) ;Items may be prefixed with attributes and visibility modifiers:
Attribute = "#[" AttrContent "]" ;
AttrContent = Ident ( "(" AttrArgs ")" )? ;
Visibility = "pub" ( "(" VisScope ")" )? ;
VisScope = "package" | "super" ;Visibility levels: pub (public to all), pub(package) (package-private), pub(super) (parent module only), or no modifier (module-private).
2. Module System
Hew uses a file-based module system. Each .hew file is a module named after the file. Directories create nested namespaces. All declarations are private by default.
Import = "import" ModulePath ( "::" ImportSpec )? ";" ;
ModulePath = Ident { "::" Ident } ;
ImportSpec = Ident
| "{" Ident { "," Ident } "}"
| "*" ;import network::tcp; // Import moduleimport network::tcp::Connection; // Import specific symbolimport network::tcp::{Connection, connect}; // Import multipleimport network::tcp::*; // Import all public symbols3. Declarations
Bindings
let creates immutable bindings, var creates mutable bindings, and const declares compile-time constants. These are binding modes, not ownership annotations.
LetDecl = "let" Ident ( ":" Type )? "=" Expr ";" ;
VarDecl = "var" Ident ( ":" Type )? "=" Expr ";" ;
ConstDecl = "const" Ident ":" Type "=" Expr ";" ;let x = 5; // immutable — cannot reassignvar y = 5; // mutable — can reassignconst MAX: i32 = 100; // compile-time constanty = 10; // ok// x = 10; // compile errorFunctions
FnDecl = "async"? "fn" Ident TypeParams? "(" Params? ")" RetType? WhereClause? Block ;
Params = Param { "," Param } ;
Param = Ident ":" Type ;
RetType = "->" Type ;fn add(a: i32, b: i32) -> i32 { a + b}fn max<T: Ord>(a: T, b: T) -> T { if a > b { a } else { b }}Structs and Enums
TypeDecl = ("struct" | "enum") Ident TypeParams? WhereClause? TypeBody ;
TypeBody = "{" { FieldDecl | VariantDecl | FnDecl } "}" ;
FieldDecl = ("let" | "var") Ident ":" Type ("=" Expr)? ";" ;
VariantDecl = Ident ( "(" TypeList ")" | "{" { FieldDecl } "}" )? ";" ;struct Point { x: f64, y: f64 }struct Config { let name: String; // immutable field var retries: i32 = 3; // mutable field with default}enum Shape { Circle(f64); Rectangle { width: f64, height: f64 }; Unit;}Generics and Where Clauses
TypeParams = "<" TypeParam { "," TypeParam } ">" ;
TypeParam = Ident ( ":" TraitBounds )? ;
TraitBounds = TraitBound { "+" TraitBound } ;
WhereClause = "where" WherePredicate { "," WherePredicate } ;
WherePredicate = Type ":" TraitBounds | AssociatedTypeBound ;fn merge<K, V>(a: Map<K, V>, b: Map<K, V>) -> Map<K, V>where K: Hash + Eq + Send, V: Clone + Send,{ // implementation}4. Type System
Hew is statically typed with bidirectional type inference. All types are known at compile time.
Built-in Numeric Types
| Type | Size | Description |
|---|---|---|
i8, i16, i32, i64 | 1/2/4/8 bytes | Signed integers |
u8, u16, u32, u64 | 1/2/4/8 bytes | Unsigned integers |
isize, usize | platform | Pointer-sized integers |
f32, f64 | 4/8 bytes | IEEE 754 floating point |
bool | 1 byte | Boolean (true/false) |
char | 4 bytes | Unicode scalar value |
All numeric types support explicit conversion methods: .to_i32(), .to_f64(), .to_usize(), etc.
Composite and Reference Types
Type = Ident TypeArgs?
| "Task" "<" Type ">" // Async task
| "Scope" // Structured concurrency scope
| "ActorRef" "<" Type ">" // Actor reference
| "Actor" "<" Type ("," Type)? ">" // Lambda actor type
| "Arc" "<" Type ">" // Atomic refcount (cross-actor sharing)
| "Rc" "<" Type ">" // Single-actor refcount
| "Weak" "<" Type ">" // Weak reference
| "Result" "<" Type "," Type ">"
| "Option" "<" Type ">"
| "Vec" "<" Type ">" // Growable array
| "HashMap" "<" Type "," Type ">" // Hash map
| "(" TypeList? ")" // Tuple / Unit
| "[" Type ";" IntLit "]" // Fixed array
| "[" Type "]" // Slice
| "fn" "(" TypeList? ")" RetType? // Function type
| "*" "const"? Type // Immutable raw pointer
| "*" "mut" Type // Mutable raw pointer
| "dyn" TraitBound // Trait object
| "dyn" "(" TraitBounds ")" ;Type Categories
- Value types (copy): integers, floats, bool, char, small fixed aggregates
- Owned heap types:
String,Vec<T>,Map<K,V>, userstruct - Shared immutable:
Arc<T>whereT: Frozen - Actor references:
ActorRef<A>— always sendable
Sendability Rule
A value may cross an actor boundary only if it satisfies Send. Send is satisfied if the value is a value type, is owned and transferred (move), is Frozen (deeply immutable), or is an actor reference. This is Hew's central compile-time guarantee: no data races without locks.
| Context | Aliasing | Mutation | Borrow Checking |
|---|---|---|---|
| Within actor | Unrestricted | Unrestricted | None |
| Across actors | Not allowed | N/A | Move required |
5. Traits
TraitDecl = "trait" Ident TypeParams? TraitSuper? WhereClause?
"{" { TraitItem } "}" ;
TraitSuper = ":" TraitBounds ;
TraitItem = FnSig ";" | AssociatedType ;
AssociatedType = "type" Ident ( ":" TraitBounds )? ( "=" Type )? ";" ;
ImplDecl = "impl" TypeParams? TraitBound "for" Type WhereClause?
"{" { FnDecl | AssociatedTypeImpl } "}" ;trait Display { fn display(self) -> String;}trait Iterator { type Item; fn next(self) -> Option<Self::Item>;}struct Point { x: f64, y: f64 }impl Display for Point { fn display(self) -> String { f"({self.x}, {self.y})" }}Built-in Marker Traits
Send— Type can safely cross actor boundariesFrozen— Deeply immutable and safely shareable. ImpliesSendCopy— Copied on assignment rather than moved (value types only)
Trait Objects
For dynamic dispatch, use dyn Trait. Trait objects are fat pointers (data pointer + vtable pointer). Object-safe traits require self receiver, no Self in return position, and no generic methods.
fn log_anything(item: dyn Display) { print(item.display());}// Multiple trait boundsfn process(item: dyn(Display + Clone)) { // ...}6. Expressions & Operators
Operator Precedence
From highest to lowest:
| Precedence | Operators | Description |
|---|---|---|
| 1 (highest) | ? .field (args) [index] | Postfix |
| 2 | ! - await | Unary prefix |
| 3 | * / % | Multiplicative |
| 4 | + - | Additive |
| 5 | .. ..= | Range |
| 6 | < <= > >= | Relational |
| 7 | == != | Equality |
| 8 | and / && | Logical AND |
| 9 | or / || | Logical OR |
| 10 | | after | Timeout combinator |
| 11 | <- | Send |
| 12 (lowest) | = += -= *= /= %= | Assignment |
Expression Grammar
Expr = TryExpr | UnsafeExpr | SendExpr ;
TryExpr = "try" Block ;
UnsafeExpr = "unsafe" Block ;
SendExpr = TimeoutExpr ( "<-" Expr )? ;
TimeoutExpr = OrExpr ( "|" "after" Expr )? ;
OrExpr = AndExpr { ("or" | "||") AndExpr } ;
AndExpr = EqExpr { ("and" | "&&") EqExpr } ;
EqExpr = RelExpr { ("==" | "!=") RelExpr } ;
RelExpr = RangeExpr { ("<" | "<=" | ">" | ">=") RangeExpr } ;
RangeExpr = AddExpr ( (".." | "..=") AddExpr )? ;
AddExpr = MulExpr { ("+" | "-") MulExpr } ;
MulExpr = UnaryExpr { ("*" | "/" | "%") UnaryExpr } ;
UnaryExpr = ("!" | "-" | "await") UnaryExpr | PostfixExpr ;
PostfixExpr = Primary { "?" | "." Ident | "(" Args? ")" | "[" Expr "]" } ;Primary Expressions
Primary = Literal
| InterpolatedStr
| Ident ( "{" FieldInitList "}" )? // struct init
| "[" ExprList? "]" // array literal
| "[" Expr ";" Expr "]" // array repeat: [0; 256]
| "(" Expr ")" // grouping
| "(" ExprList ")" // tuple
| IfExpr | MatchExpr | Lambda | Spawn
| SelectExpr | RaceExpr | JoinExpr
| ScopeSpawn | ScopeCancel | ScopeCheck | Scope
| YieldExpr ;Closures (Lambda Expressions)
Two equivalent syntaxes — pipe and arrow:
Lambda = "move"? ( PipeLambda | ArrowLambda ) ;
PipeLambda = "|" LambdaParams? "|" RetType? (Expr | Block) ;
ArrowLambda = "(" LambdaParams? ")" "=>" (Expr | Block) ;
LambdaParam = Ident ( ":" Type )? ;// Arrow syntaxlet doubled = numbers.map((x) => x * 2);// Pipe syntax (equivalent)let doubled = numbers.map(|x| x * 2);// With type annotationslet f: fn(i32, i32) -> i32 = (x, y) => x + y;// Move capturelet config = load_config();let worker = spawn move (msg: Msg) => { use(config); };Try and Error Propagation
The ? operator propagates errors from Result types. The try expression catches errors within a scope:
fn read_file(path: String) -> Result<String, IoError> { let handle = open(path)?; // propagate on error let content = read(handle)?; Ok(content)}let result = try { dangerous_operation()?; Ok(value)};7. Statements & Control Flow
Block = "{" { Stmt } Expr? "}" ;
Stmt = LetStmt | VarStmt | AssignStmt | IfStmt | MatchStmt
| LoopStmt | ForStmt | WhileStmt
| BreakStmt | ContinueStmt | ReturnStmt | ExprStmt
| UnsafeBlock ;Assignments
AssignStmt = LValue AssignOp Expr ";" ;
AssignOp = "=" | "+=" | "-=" | "*=" | "/=" | "%=" ;
LValue = Ident { "." Ident | "[" Expr "]" } ;Control Flow
IfStmt = "if" Expr Block ( "else" (IfStmt | Block) )? ;
MatchStmt = "match" Expr "{" { MatchArm } "}" ;
MatchArm = Pattern Guard? "=>" (Expr "," | Block) ;
Guard = "if" Expr ;
LoopStmt = ("'" Ident ":")? "loop" Block ;
ForStmt = "for" Pattern "in" Expr Block ;
WhileStmt = "while" Expr Block ;
BreakStmt = "break" ("'" Ident)? Expr? ";" ;
ContinueStmt = "continue" ("'" Ident)? ";" ;
ReturnStmt = "return" Expr? ";" ;Both if and match are expressions — they return values. Loops support labeled breaks with 'label: syntax.
// If expressionlet status = if count > 0 { "active" } else { "idle" };// Match expressionmatch shape { Circle(r) => 3.14 * r * r, Rectangle { width, height } => width * height, Unit => 0.0,}// Labeled loop'outer: loop { for item in items { if item.done { break 'outer; } }}8. Pattern Matching
Pattern = "_" // wildcard
| LiteralPattern // literal value
| Ident // binding
| Ident "(" PatternList? ")" // constructor
| Ident "{" PatternFieldList? "}" // struct destructuring
| "(" PatternList ")" // tuple
| Pattern "|" Pattern ; // or-pattern
PatternField = Ident ( ":" Pattern )? ;
Guard = "if" Expr ;match value { 0 | 1 => println("zero or one"), n if n < 0 => println("negative"), n => println(f"positive: {n}"),}// Struct destructuringmatch point { Point { x: 0, y } => println(f"on y-axis at {y}"), Point { x, y: 0 } => println(f"on x-axis at {x}"), Point { x, y } => println(f"({x}, {y})"),}// Nested constructor patternsmatch result { Ok(Some(value)) => use(value), Ok(None) => println("empty"), Err(e) => println(f"error: {e}"),}9. Actors & Supervisors
Actor Declaration
ActorDecl = "actor" Ident TypeParams? TraitSuper? WhereClause? "{"
ActorInit?
MailboxDecl?
{ FieldDecl | ReceiveFnDecl | FnDecl }
"}" ;
ActorInit = "init" "(" Params? ")" Block ;
MailboxDecl = "mailbox" IntLit ";" ;
ReceiveFnDecl = "receive" "fn" Ident TypeParams? "(" Params? ")" RetType?
WhereClause? Block ;receive fn declares a message handler. Without a return type, it is fire-and-forget. With a return type, it is request-response (caller must await). fn declares a private internal method.
actor Counter { var count: i32 = 0; mailbox 256; // Fire-and-forget: no return type, no await needed receive fn increment(n: i32) { self.count += n; } // Request-response: has return type, caller must await receive fn get() -> i32 { self.count } fn validate(n: i32) -> bool { n >= 0 }}let counter = spawn Counter { count: 0 };counter.increment(10); // fire-and-forgetlet n = await counter.get(); // request-responseLambda Actors
Spawn = "spawn" ( LambdaActor | Primary "(" Args? ")" ) ;
LambdaActor = "move"? "(" LambdaParams? ")" RetType? "=>" (Expr | Block) ;Lambda actors handle a single message type. Use <- to send messages. Captured values must implement Send; use move for ownership transfer.
// Fire-and-forget lambda actorlet worker = spawn (msg: i32) => { println(msg * 2); };worker <- 42;// Request-response lambda actorlet calc = spawn (x: i32) -> i32 => { x * x };let result = await calc <- 5;// With move capturelet factor = 2;let multiplier = spawn move (x: i32) -> i32 => { x * factor };Supervisor Declaration
SupervisorDecl = "supervisor" Ident "{" { ChildSpec } "}" ;
ChildSpec = "child" Ident ":" Ident RestartSpec? ";" ;
RestartSpec = "restart" "(" ("permanent" | "transient" | "temporary") ")"
("budget" "(" IntLit "," DurationLit ")")?
("strategy" "(" ("one_for_one" | "one_for_all"
| "rest_for_one") ")")? ;Restart classification: permanent (always restart), transient (restart on abnormal exit), temporary (never restart). Exceeding the restart budget escalates failure to the parent supervisor.
supervisor AppSupervisor { child db: DatabaseActor restart(permanent) budget(5, 30.s) strategy(one_for_one); child cache: CacheActor restart(transient); child logger: LogActor restart(temporary);}10. Structured Concurrency
Scope
Scope = "scope" Block ;
ScopeSpawn = "scope" "." "spawn" Block ;
ScopeCancel = "scope" "." "cancel" "(" ")" ;
ScopeCheck = "scope" "." ("is_cancelled" | "check_cancelled") "(" ")" ;
YieldExpr = "yield" ;A scope block creates a structured concurrency boundary. All tasks spawned within it must complete before the scope exits. Tasks are cooperatively scheduled within the actor's single thread.
scope { let a = scope.spawn { fetch_user(id1) }; let b = scope.spawn { fetch_user(id2) }; // Both run concurrently let user1 = await a; let user2 = await b; merge_users(user1, user2)}Select Expression
Waits for the first of several async operations to complete. Remaining operations are cancelled.
SelectExpr = "select" "{" SelectArm { SelectArm } "}" ;
SelectArm = Ident "from" Expr "=>" Expr ","
| "after" Expr "=>" Expr "," ;let result = select { count from counter.get_count() => count * 2, data from worker.get_data() => data.len, after 1.seconds => -1,};Race Expression
Spawns all branches concurrently and returns the first to complete. All expressions must have the same type.
RaceExpr = "race" "{" (Expr ",")+ ("after" Expr "=>" Expr ",")? "}" ;let fastest = race { server1.fetch(key), server2.fetch(key), server3.fetch(key), after 5.seconds => Err(Timeout),};Join Expression
Runs all branches concurrently and waits for all to complete. Result is a tuple. Each branch may have a different type.
JoinExpr = "join" "{" Expr { "," Expr } ","? "}" ;let (users, posts, stats) = join { db.fetch_users(), db.fetch_posts(), analytics.get_stats(),};Timeout Combinator
The | after combinator wraps an individual await in a Result<T, Timeout>:
let result = await counter.get_count() | after 1.seconds;// result: Result<i32, Timeout>11. Wire Types
Wire types define network-serializable data with stable field tags, explicit optionality, and forward/backward compatibility guarantees.
WireDecl = "wire" ("struct" | "enum") Ident WireBody ;
WireBody = "{" { WireFieldDecl | VariantDecl } "}" ;
WireFieldDecl = Ident ":" WireType "@" IntLit WireAttr* ";" ;
WireAttr = "optional" | "deprecated"
| "default" "(" Expr ")" | ReservedDecl ;
ReservedDecl = "reserved" "(" IntLit { "," IntLit } ")" ;
WireType = "u8" | "u16" | "u32" | "u64"
| "i8" | "i16" | "i32" | "i64"
| "f32" | "f64"
| "bool" | "bytes" | "string"
| Ident | "list" "[" WireType "]" ;wire struct User { name: string @1; email: string @2; age: u32 @3 optional; role: Role @4 default(Role::Member); reserved(5, 6); // deleted fields}wire enum Role { Admin; Member; Guest;}Compatibility rules: field tag numbers must never be reused. Deleted fields must have their tags reserved. Wire types support Hew Binary Format (HBF) and JSON encoding.
12. Foreign Function Interface
ExternBlock = ("foreign" | "extern") StringLit "{" { ExternFnDecl } "}" ;
ExternFnDecl = "fn" Ident "(" ExternParams? ")" RetType? Variadic? ";" ;
Variadic = "..." ;
ExternFnExport = "#[" "export" ( "(" StringLit ")" )? "]" ExternFnDef ;
ExternFnDef = "foreign" StringLit "fn" Ident "(" Params? ")" RetType? Block ;
UnsafeBlock = "unsafe" Block ;All FFI calls are unsafe. Use safe wrapper patterns to expose a safe public API. C-compatible struct layout is specified with #[repr(C)].
foreign "C" { fn malloc(size: usize) -> *mut u8; fn free(ptr: *mut u8); fn printf(fmt: *const u8, ...) -> i32;}fn allocate(size: usize) -> *mut u8 { unsafe { malloc(size) }}#[export("hew_process")]foreign "C" fn process(data: *const u8, len: usize) -> i32 { // callable from C as hew_process()}Type Mapping: Hew to C
| Hew Type | C Type |
|---|---|
i8...i64 | int8_t...int64_t |
u8...u64 | uint8_t...uint64_t |
isize / usize | ssize_t / size_t |
f32 / f64 | float / double |
bool | _Bool |
*T / *mut T | const T* / T* |
fn(...) -> T | Function pointer |
13. Literals & Lexical Elements
Comments
Comment = LineComment | BlockComment | DocComment ;
LineComment = "//" { AnyChar } Newline ;
BlockComment = "/*" { AnyChar } "*/" ;
DocComment = "///" { AnyChar } Newline ;Literals
Literal = IntLit | FloatLit | StringLit | "true" | "false" ;
DurationLit = IntLit ("ns" | "us" | "ms" | "s" | "m" | "h") ;
IntLit = Digit { Digit | "_" }
| "0x" HexDigit { HexDigit | "_" }
| "0b" BinDigit { BinDigit | "_" } ;
FloatLit = Digit { Digit } "." Digit { Digit }
( ("e"|"E") ("+"|"-")? Digit { Digit } )? ;
StringLit = '"' { Char | EscapeSeq } '"'
| 'r"' { AnyChar } '"' ;
InterpolatedStr = 'f"' { Char | "{" Expr "}" } '"' ;
EscapeSeq = "\\" ( "n" | "r" | "t" | "\\" | '"' | "0"
| "x" HexDigit HexDigit ) ;// Integerslet dec = 1_000_000;let hex = 0xFF;let bin = 0b1010;// Floatslet pi = 3.14;let sci = 1.5e10;// Stringslet s = "hello\nworld";let raw = r"no escapes here";let interp = f"count is {count + 1}";// Durationslet timeout = 500.ms;let interval = 1.s;let budget = 30.s;Identifiers
Ident = Letter { Letter | Digit | "_" } ;
Letter = "a".."z" | "A".."Z" ;
Digit = "0".."9" ;
HexDigit = Digit | "a".."f" | "A".."F" ;
BinDigit = "0" | "1" ;14. Full EBNF Grammar
The complete v0.5.0 EBNF grammar for reference. This covers the full Hew syntax including modules, traits, closures, pattern matching, control flow, structured concurrency, actor messaging, concurrency expressions, FFI, and where clauses.
(* Comments *)
Comment = LineComment | BlockComment | DocComment ;
LineComment = "//" { AnyChar } Newline ;
BlockComment = "/*" { AnyChar } "*/" ;
DocComment = "///" { AnyChar } Newline ;
(* Program structure *)
Program = { Item } ;
Item = Attribute* Visibility? ( Import
| ConstDecl
| LetDecl
| VarDecl
| TypeDecl
| TraitDecl
| ImplDecl
| WireDecl
| FnDecl
| ExternBlock
| ActorDecl
| SupervisorDecl ) ;
(* Module-level bindings *)
LetDecl = "let" Ident ( ":" Type )? "=" Expr ";" ;
VarDecl = "var" Ident ( ":" Type )? "=" Expr ";" ;
Visibility = "pub" ( "(" VisScope ")" )? ;
VisScope = "package" | "super" ;
(* Attributes *)
Attribute = "#[" AttrContent "]" ;
AttrContent = Ident ( "(" AttrArgs ")" )? ;
AttrArgs = AttrArg { "," AttrArg } ;
AttrArg = Ident | StringLit | Ident "=" (StringLit | Ident) ;
(* Module system *)
Import = "import" ModulePath ( "::" ImportSpec )? ";" ;
ModulePath = Ident { "::" Ident } ;
ImportSpec = Ident
| "{" Ident { "," Ident } "}"
| "*" ;
(* Constants and types *)
ConstDecl = "const" Ident ":" Type "=" Expr ";" ;
TypeDecl = ("struct" | "enum") Ident TypeParams? WhereClause? TypeBody ;
WireDecl = "wire" ("struct" | "enum") Ident WireBody ;
TypeParams = "<" TypeParam { "," TypeParam } ">" ;
TypeParam = Ident ( ":" TraitBounds )? ;
TraitBounds = TraitBound { "+" TraitBound } ;
TraitBound = Ident TypeArgs? ;
WhereClause = "where" WherePredicate { "," WherePredicate } ;
WherePredicate = Type ":" TraitBounds
| AssociatedTypeBound ;
AssociatedTypeBound = Type "::" Ident ":" TraitBounds ;
TypeBody = "{" { FieldDecl | VariantDecl | FnDecl } "}" ;
WireBody = "{" { WireFieldDecl | VariantDecl } "}" ;
FieldDecl = ("let" | "var") Ident ":" Type ("=" Expr)? ";" ;
WireFieldDecl = Ident ":" WireType "@" IntLit WireAttr* ";" ;
WireAttr = "optional" | "deprecated"
| ("default" "(" Expr ")") | ReservedDecl ;
ReservedDecl = "reserved" "(" IntLit { "," IntLit } ")" ;
VariantDecl = Ident ( "(" TypeList ")" | "{" { FieldDecl } "}" )? ";" ;
TypeList = Type { "," Type } ;
(* Traits *)
TraitDecl = "trait" Ident TypeParams? TraitSuper? WhereClause?
"{" { TraitItem } "}" ;
TraitSuper = ":" TraitBounds ;
TraitItem = FnSig ";"
| AssociatedType ;
AssociatedType = "type" Ident ( ":" TraitBounds )? ( "=" Type )? ";" ;
FnSig = "fn" Ident TypeParams? "(" Params? ")" RetType? WhereClause? ;
ImplDecl = "impl" TypeParams? TraitBound "for" Type WhereClause?
"{" { FnDecl | AssociatedTypeImpl } "}" ;
AssociatedTypeImpl = "type" Ident "=" Type ";" ;
(* Actors *)
ActorDecl = "actor" Ident TypeParams? TraitSuper? WhereClause? "{"
ActorInit?
MailboxDecl?
{ FieldDecl | ReceiveFnDecl | FnDecl }
"}" ;
ActorInit = "init" "(" Params? ")" Block ;
MailboxDecl = "mailbox" IntLit ";" ;
ReceiveFnDecl = "receive" "fn" Ident TypeParams? "(" Params? ")"
RetType? WhereClause? Block ;
(* Supervisors *)
SupervisorDecl = "supervisor" Ident "{" { ChildSpec } "}" ;
ChildSpec = "child" Ident ":" Ident RestartSpec? ";" ;
RestartSpec = "restart" "(" ("permanent" | "transient" | "temporary") ")"
("budget" "(" IntLit "," DurationLit ")")?
("strategy" "(" ("one_for_one" | "one_for_all"
| "rest_for_one") ")")? ;
(* FFI / Extern declarations *)
ExternBlock = ("foreign" | "extern") StringLit "{" { ExternFnDecl } "}" ;
ExternFnDecl = "fn" Ident "(" ExternParams? ")" RetType? Variadic? ";" ;
ExternParams = ExternParam { "," ExternParam } ;
ExternParam = Ident ":" Type ;
Variadic = "..." ;
ExternFnExport = "#[" "export" ( "(" StringLit ")" )? "]" ExternFnDef ;
ExternFnDef = "foreign" StringLit "fn" Ident "(" Params? ")" RetType? Block ;
(* Functions *)
FnDecl = "async"? "fn" Ident TypeParams? "(" Params? ")"
RetType? WhereClause? Block ;
Params = Param { "," Param } ;
Param = Ident ":" Type ;
RetType = "->" Type ;
(* Unsafe blocks *)
UnsafeBlock = "unsafe" Block ;
(* Statements *)
Block = "{" { Stmt } Expr? "}" ;
Stmt = LetStmt | VarStmt | AssignStmt | IfStmt | MatchStmt
| LoopStmt | ForStmt | WhileStmt
| BreakStmt | ContinueStmt | ReturnStmt | ExprStmt
| UnsafeBlock ;
LetStmt = "let" Pattern ( ":" Type )? "=" Expr ";" ;
VarStmt = "var" Ident ( ":" Type )? "=" Expr ";" ;
AssignStmt = LValue AssignOp Expr ";" ;
AssignOp = "=" | "+=" | "-=" | "*=" | "/=" | "%=" ;
LValue = Ident { "." Ident | "[" Expr "]" } ;
IfStmt = "if" Expr Block ( "else" (IfStmt | Block) )? ;
MatchStmt = "match" Expr "{" { MatchArm } "}" ;
MatchArm = Pattern Guard? "=>" (Expr "," | Block) ;
Guard = "if" Expr ;
LoopStmt = ("'" Ident ":")? "loop" Block ;
ForStmt = "for" Pattern "in" Expr Block ;
WhileStmt = "while" Expr Block ;
BreakStmt = "break" ("'" Ident)? Expr? ";" ;
ContinueStmt = "continue" ("'" Ident)? ";" ;
ReturnStmt = "return" Expr? ";" ;
ExprStmt = Expr ";" ;
(* Expressions *)
Expr = TryExpr | UnsafeExpr | SendExpr ;
TryExpr = "try" Block ;
UnsafeExpr = "unsafe" Block ;
SendExpr = TimeoutExpr ( "<-" Expr )? ;
TimeoutExpr = OrExpr ( "|" "after" Expr )? ;
OrExpr = AndExpr { ("or" | "||") AndExpr } ;
AndExpr = EqExpr { ("and" | "&&") EqExpr } ;
EqExpr = RelExpr { ("==" | "!=") RelExpr } ;
RelExpr = RangeExpr { ("<" | "<=" | ">" | ">=") RangeExpr } ;
RangeExpr = AddExpr ( (".." | "..=") AddExpr )? ;
AddExpr = MulExpr { ("+" | "-") MulExpr } ;
MulExpr = UnaryExpr { ("*" | "/" | "%") UnaryExpr } ;
UnaryExpr = ("!" | "-" | "await") UnaryExpr | PostfixExpr ;
PostfixExpr = Primary { "?" | "." Ident | "(" Args? ")" | "[" Expr "]" } ;
Primary = Literal
| InterpolatedStr
| Ident ( "{" FieldInitList "}" )?
| "[" ExprList? "]"
| "[" Expr ";" Expr "]"
| "(" Expr ")"
| "(" ExprList ")"
| IfExpr
| MatchExpr
| Lambda
| Spawn
| SelectExpr
| RaceExpr
| JoinExpr
| ScopeSpawn
| ScopeCancel
| ScopeCheck
| Scope
| YieldExpr ;
FieldInitList = FieldInit { "," FieldInit } ","? ;
FieldInit = Ident ":" Expr ;
IfExpr = "if" Expr Block ( "else" (IfExpr | Block) )? ;
MatchExpr = "match" Expr "{" { MatchArm } "}" ;
Literal = IntLit | FloatLit | StringLit | "true" | "false" ;
ExprList = Expr { "," Expr } ;
Args = Expr { "," Expr } ;
(* Closures *)
Lambda = "move"? ( PipeLambda | ArrowLambda ) ;
PipeLambda = "|" LambdaParams? "|" RetType? (Expr | Block) ;
ArrowLambda = "(" LambdaParams? ")" "=>" (Expr | Block) ;
LambdaParams = LambdaParam { "," LambdaParam } ;
LambdaParam = Ident ( ":" Type )? ;
(* Actor operations *)
Spawn = "spawn" ( LambdaActor | (Primary "(" Args? ")") ) ;
LambdaActor = "move"? "(" LambdaParams? ")" RetType? "=>" (Expr | Block) ;
(* Concurrency expressions *)
SelectExpr = "select" "{" SelectArm { SelectArm } "}" ;
SelectArm = Ident "from" Expr "=>" Expr ","
| "after" Expr "=>" Expr "," ;
RaceExpr = "race" "{" (Expr ",")+ ("after" Expr "=>" Expr ",")? "}" ;
JoinExpr = "join" "{" Expr { "," Expr } ","? "}" ;
(* Structured concurrency *)
Scope = "scope" Block ;
ScopeSpawn = "scope" "." "spawn" Block ;
ScopeCancel = "scope" "." "cancel" "(" ")" ;
ScopeCheck = "scope" "." ("is_cancelled" | "check_cancelled") "(" ")" ;
YieldExpr = "yield" ;
(* Types *)
Type = Ident TypeArgs?
| "Task" "<" Type ">"
| "Scope"
| "ActorRef" "<" Type ">"
| "Actor" "<" Type ("," Type)? ">"
| "Arc" "<" Type ">"
| "Rc" "<" Type ">"
| "Weak" "<" Type ">"
| "Result" "<" Type "," Type ">"
| "Option" "<" Type ">"
| "Vec" "<" Type ">"
| "HashMap" "<" Type "," Type ">"
| "(" TypeList? ")"
| "[" Type ";" IntLit "]"
| "[" Type "]"
| "fn" "(" TypeList? ")" RetType?
| "*" "const"? Type
| "*" "mut" Type
| "dyn" TraitBound
| "dyn" "(" TraitBounds ")" ;
TypeArgs = "<" Type { "," Type } ">" ;
(* Wire types *)
WireType = "u8" | "u16" | "u32" | "u64"
| "i8" | "i16" | "i32" | "i64"
| "f32" | "f64"
| "bool" | "bytes" | "string"
| Ident | ("list" "[" WireType "]") ;
(* Pattern matching *)
Pattern = "_"
| LiteralPattern
| Ident
| Ident "(" PatternList? ")"
| Ident "{" PatternFieldList? "}"
| "(" PatternList ")"
| Pattern "|" Pattern ;
LiteralPattern = IntLit | FloatLit | StringLit | "true" | "false" ;
PatternList = Pattern { "," Pattern } ;
PatternFieldList = PatternField { "," PatternField } ;
PatternField = Ident ( ":" Pattern )? ;
(* Literals *)
DurationLit = IntLit ("ns" | "us" | "ms" | "s" | "m" | "h") ;
IntLit = Digit { Digit | "_" }
| "0x" HexDigit { HexDigit | "_" }
| "0b" BinDigit { BinDigit | "_" } ;
FloatLit = Digit { Digit } "." Digit { Digit }
( ("e" | "E") ("+" | "-")? Digit { Digit } )? ;
StringLit = '"' { Char | EscapeSeq } '"'
| 'r"' { AnyChar } '"' ;
InterpolatedStr = 'f"' { Char | "{" Expr "}" } '"' ;
Ident = Letter { Letter | Digit | "_" } ;
Letter = "a".."z" | "A".."Z" ;
Digit = "0".."9" ;
HexDigit = Digit | "a".."f" | "A".."F" ;
BinDigit = "0" | "1" ;
EscapeSeq = "\\" ( "n" | "r" | "t" | "\\" | '"' | "0"
| "x" HexDigit HexDigit ) ;