Grammar & Syntax
Turn is a process-centric language. The grammar is designed so that every program defines the behaviour of a Turn process with runtime-managed context and memory. This document specifies the complete BNF grammar, operator precedence, keyword set, and design rationale.
Program Structure and Statements
A Turn program is a sequence of statements. There is no top-level main function: the program executes from top to bottom, and turn { ... } blocks define the boundaries of agent execution cycles.
Program := Stmt*
Stmt := StructDef | ImplDef | TypeAlias
| UseStmt | UseSchemaStmt | GrantStmt | LetStmt
| SpawnStmt | SuspendStmt | TurnStmt
| ContextAppend | ContextSystem
| RememberStmt | SendStmt | ThrowStmt
| TryCatchStmt | CallStmt | ReturnStmt
| IfStmt | WhileStmt | ExprStmt
StructDef := "struct" Id "{" ( Id ":" Type ( "," Id ":" Type )* )? "}" ";"
ImplDef := "impl" Id "{" Stmt* "}"
TypeAlias := "type" Id "=" Type ";"
UseStmt := "let" Id "=" "use" String ";"
UseSchemaStmt := "use" Id "::" Id "(" Expr ")" ";"
GrantStmt := "grant" Id "::" Id "(" Expr ")" ";"
LetStmt := "let" Id ( ":" Type )? "=" Expr ";"
SpawnStmt := ( "spawn" | "spawn_link" | "spawn_each" ) TurnExpr ( "," TurnExpr )? ";"
SuspendStmt := "suspend" ";"
TurnStmt := "turn" Block
ContextAppend := "context" "." "append" "(" Expr ")" ";"
ContextSystem := "context" "." "system" "(" Expr ")" ";"
RememberStmt := "remember" "(" Expr "," Expr ")" ";"
SendStmt := "send" Expr "," Expr ";"
ThrowStmt := "throw" Expr ";"
TryCatchStmt := "try" Block "catch" "(" Id ")" Block
CallStmt := "call" "(" Expr ( "," Expr )* ")" ";"
ReturnStmt := "return" Expr ";"
IfStmt := "if" Expr Block ( "else" Block )?
WhileStmt := "while" Expr Block
ExprStmt := Expr ";"
Block := "{" Stmt* "}"Expressions and Precedence
Expressions follow a standard precedence hierarchy. Postfix operations (indexing, member access, function calls) have the highest precedence. Logical or has the lowest.
Expr := OrExpr
OrExpr := AndExpr ( "or" AndExpr )*
AndExpr := EqExpr ( "and" EqExpr )*
EqExpr := CmpExpr ( ( "==" | "!=" ) CmpExpr )*
CmpExpr := AddExpr ( ( "<" | ">" | "<=" | ">=" | "~>" ) AddExpr )*
AddExpr := MulExpr ( ( "+" | "-" ) MulExpr )*
MulExpr := Unary ( ( "*" | "/" ) Unary )*
Unary := ( "!" | "-" )* Postfix
Postfix := Primary ( Index | Member | MethodCall )*
Index := "[" Expr "]"
Member := "." Id
MethodCall := "." Id "(" Expr? ")"
Primary := Literal | Id | ListLiteral | MapLiteral | VecLiteral
| StructInit | RecallExpr
| InferExpr | TurnExpr | MapExpr | FilterExpr
| SpawnExpr | SendExpr | ReceiveExpr
| ConfidenceExpr | CallExpr | IfExpr
| "(" Expr ")"
Literal := Num | String | "true" | "false" | "null"
ListLiteral := "[" ( Expr ( "," Expr )* )? "]"
MapLiteral := "{" ( String ":" Expr ( "," String ":" Expr )* )? "}"
VecLiteral := "vec" "[" ( Expr ( "," Expr )* )? "]"
StructInit := Id "{" ( Id ":" Expr ( "," Id ":" Expr )* )? ( ".." Expr )? "}"
RecallExpr := "recall" "(" Expr ")"
InferExpr := "infer" Type Block
TurnExpr := "turn" "(" ParamList? ")" ( "->" Type )? Block
MapExpr := "map" "(" Expr "," TurnExpr ")"
FilterExpr := "filter" "(" Expr "," TurnExpr ")"
SpawnExpr := ( "spawn" | "spawn_link" ) TurnExpr
ReceiveExpr := "receive"
SendExpr := "send" Expr "," Expr
ConfidenceExpr := "confidence" Expr
CallExpr := "call" "(" Expr ( "," Expr )* ")"
IfExpr := "if" Expr Block "else" Block
ParamList := Param ( "," Param )*
Param := Id ":" TypeNOTE
if/else can be used as an expression when both branches are present and the last statement in each block is an expression (no trailing semicolon). When used as a statement, the trailing semicolon is required.
Struct Spread Syntax
The ..base spread operator creates a new struct epoch by copying all fields from base and overriding the specified fields:
struct AgentState { cycle: Num, status: Str, confidence_floor: Num };
let state = AgentState { cycle: 1, status: "running", confidence_floor: 0.85 };
// Only override the fields that changed. All others are copied from state
let next_state = AgentState { cycle: state.cycle + 1, ..state };
call("echo", next_state.status); // "running" carried from baseKeywords and Terminals
The language reserves the following identifiers as keywords. They cannot be used as variable names or struct field names.
Core keywords: struct, impl, type, use, grant, turn, let, return, if, else, while, and, or, true, false, null, try, catch, throw.
Agent primitives: spawn, spawn_link, spawn_each, send, receive, suspend, context, append, system, remember, recall, call, infer, confidence, map, filter, vec, self.
Type keywords: Num, Str, Bool, List, Map, Any, Void, Pid, Vec, Identity.
Operators: +, -, *, /, ==, !=, <, >, <=, >=, ~> (semantic similarity on Vec), ! (logical not), -> (return type annotation), : (type annotation), .. (struct spread).
Comments: Line comments begin with // and extend to the end of the line. Block comments use /* ... */ and can span multiple lines.
Operator Semantics
| Operator | Behaviour |
|---|---|
+ | String concatenation when either operand is a string. Numeric addition when both are numbers. "x" + 1 evaluates to "x1". |
-, *, / | Standard arithmetic. Both operands must be numeric. |
==, != | Structural value equality. No type coercion: 1 == "1" is false. |
<, >, <=, >= | Numeric comparison. |
~> | Semantic similarity. Returns a confidence score between 0.0 and 1.0 comparing two Vec values. |
and, or | Short-circuit evaluation. Returns the determining operand. 0 or "default" evaluates to "default". |
! | Logical negation. |
.. | Struct spread. Copies all fields from the right-hand struct into the new struct literal, with named fields overriding. |
Truthiness: The values false, null, "" (empty string), 0, and 0.0 are falsy. Every other value is truthy.
NOTE
Semicolons are required after every statement. There is no automatic semicolon insertion.
Type System
| Type | Description |
|---|---|
Num | 64-bit floating-point number |
Str | UTF-8 string |
Bool | true or false |
List | Heterogeneous ordered list [a, b, c] |
Map | String-keyed map {"key": value} |
Any | Accepts any value. Use for untyped inference results. |
Void | No return value |
Pid | Process identifier (returned by spawn / spawn_link) |
Vec | Embedding vector for semantic similarity (~>) |
Identity | Cryptographic identity capability (requested via grant identity::oauth(...)) |
| Named struct | Defined with struct Name { field: Type, ... } |