Grammar & Syntax

Turn is a process-centric language. The grammar is designed so that every program defines the behavior 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 | UseStmt | SpawnStmt | SuspendStmt
        | TurnStmt | LetStmt | ContextAppend | RememberStmt
        | CallStmt | ReturnStmt | IfStmt | WhileStmt | ExprStmt

StructDef     := "struct" Id "{" FieldDef* "}" ";"
UseStmt       := "let" Id "=" "use" String ";"
SpawnStmt     := "spawn" TurnExpr ";"
SuspendStmt   := "suspend" ";"
TurnStmt      := "turn" Block
LetStmt       := "let" Id "=" Expr ";"
ContextAppend := "context" "." "append" "(" Expr ")" ";"
RememberStmt  := "remember" "(" Expr "," Expr ")" ";"
CallStmt      := "call" "(" Expr "," Expr ")" ";"
ReturnStmt    := "return" Expr ";"
IfStmt        := "if" Expr Block ( "else" Block )?
WhileStmt     := "while" Expr Block
ExprStmt      := Expr ";"

Block         := "{" Stmt* "}"}

Each statement form maps to a domain concept. StructDef introduces a typed schema for inference. UseStmt imports a module. SpawnStmt creates an actor. TurnStmt defines a turn boundary. The remaining forms handle bindings, effects, control flow, and expressions.


Expressions and Precedence

Expressions follow a standard precedence hierarchy. Lower rows in the grammar bind more tightly — postfix operations (indexing, member access, function calls) have the highest precedence, while logical or has the lowest.

BNF — expressions
Expr     := OrExpr
OrExpr   := AndExpr ( "or" AndExpr )*
AndExpr  := EqExpr ( "and" EqExpr )*
EqExpr   := CmpExpr ( ( "==" | "!=" ) CmpExpr )*
CmpExpr  := AddExpr ( ( "<" | ">" | "<=" | ">=" ) AddExpr )*
AddExpr  := Unary ( "+" Unary )*
Unary    := ( "!" )* Postfix

Postfix  := Primary ( Index | Member | CallArgs )*
Primary  := Literal | Id | RecallExpr | InferExpr | TurnExpr | "(" Expr ")"

RecallExpr := "recall" "(" Expr ")"
InferExpr  := "infer" Type "{" Expr ";" "}"
TurnExpr   := "turn" "(" ParamList? ")" ( "->" Type )? Block

Precedence summary (highest to lowest): postfix (., [], ()) → unary (!) → arithmetic (+) → comparison (<, >, <=, >=) → equality (==, !=) → logical and → logical or.


Keywords and Terminals

The language reserves the following identifiers as keywords. They cannot be used as variable names, struct field names, or module identifiers.

Keywords: struct, use, turn, spawn, suspend, infer, let, context, append, remember, recall, call, return, if, else, while, and, or, true, false, null.

Operators: +, ==, !=, <, >, <=, >=, !, ->, :.

Comments: Line comments begin with // and extend to the end of the line. Block comments are enclosed in /* ... */ and may be nested.


Operator Semantics

OperatorBehavior
+String concatenation when either operand is a string, numeric addition when both are numbers. Mixed types coerce to string: "x" + 1 evaluates to "x1".
==, !=Structural value equality. No type coercion is performed — 1 == "1" evaluates to false.
and, orShort-circuit evaluation. Returns the determining operand, not a boolean cast. 0 or "default" evaluates to "default".

Truthiness: The values false, null, "" (empty string), 0, and 0.0 are falsy. Every other value, including empty lists and empty maps, is truthy.

NOTE

Semicolons are required after every statement. There is no automatic semicolon insertion. Writing one statement per line is a style convention, not a syntactic requirement.