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.

BNF: statements
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.

BNF: expressions
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 ":" Type

NOTE

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_spread.tn
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 base

Keywords 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

OperatorBehaviour
+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, orShort-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

TypeDescription
Num64-bit floating-point number
StrUTF-8 string
Booltrue or false
ListHeterogeneous ordered list [a, b, c]
MapString-keyed map {"key": value}
AnyAccepts any value. Use for untyped inference results.
VoidNo return value
PidProcess identifier (returned by spawn / spawn_link)
VecEmbedding vector for semantic similarity (~>)
IdentityCryptographic identity capability (requested via grant identity::oauth(...))
Named structDefined with struct Name { field: Type, ... }

Next Steps