Skip to content

Syntax summary

Every form of jihoo on one page, as an informal grammar. x? is optional, x* repeats zero or more times, x | y is either, and sep is a comma or a newline. The Syntax page explains the lexical rules.

file = attribute* item*
attribute = "#![" ("native" | "freestanding") "]"
item = "import" path ("as" NAME)?
| "pub"? "fn" NAME "(" params ")" ("->" type)? contract* block
| "pub"? "extern" "fn" NAME "(" params ("," "...")? ")" ("->" type)?
| "pub"? "export" "fn" NAME "(" params ")" ("->" type)? contract* block
| "pub"? "struct" NAME ("(" params ")")? "{" ("pub"? NAME ":" type) sep* "}"
| "pub"? "enum" NAME ("(" params ")")? "{" (NAME ("(" types ")")?) sep* "}"
| "pub"? "const" NAME (":" type)? "=" expr
| "pub"? "trait" NAME "{" ("fn" NAME "(" params ")" ("->" type)? block?)* "}"
| "impl" ("(" params ")")? path "for" type "{" ("fn" NAME "(" params ")" ("->" type)? block)* "}"
| "pub"? "macro" NAME "(" params ")" "->" ("expr" | "stmts" | "items") block
| path "!" "(" exprs ")" ; an item macro
params = (("comptime")? NAME ":" type ("+" path)*),* ; `+ path`: more traits
contract = ("requires" | "ensures") expr ; `ensures` may read `result`
| "nocopy" ; natively, copies nothing
| "replaces" expr ; a rewrite rule: a call, made of the parameters
path = NAME ("." NAME)*
type = "unit" | "bool" | "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64"
| "f32" | "f64" | "str" | "type" | "expr" | "stmts" | "items"
| path ("(" exprs ")")? ; struct or enum, maybe generic
| "[" type ";" expr "]" ; array
| "[" type "]" ; list (hosted)
| "(" type ("," type)+ ")" ; tuple
| "fn" "(" types ")" ("->" type)? ; function, `->` on the same line
| "*" type | "ref" type | "cell" type | "chan" type

A statement ends at a newline, ; or }.

block = "{" stmt* "}"
stmt = "let" NAME (":" type)? "=" expr
| "let" "(" pattern ("," pattern)+ ")" (":" type)? "=" expr ; a pattern for every value
| place "=" expr
| place ("+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^=" | "<<=" | ">>=") expr
| "if" expr block ("else" (block | if-stmt))?
| "while" expr block
| "for" (NAME ",")? NAME "in" expr block ; a list, array or str
| "for" NAME "in" expr ".." expr block ; integers, end excluded
| "break" | "continue" ; inside a loop
| "return" expr?
| "match" expr "{" (pattern ("if" expr)? "=>" (block | stmt)) sep* "}"
| "select" "{" select-arm sep* "}"
| "go" call
| path "!" "(" exprs ")" ; a statement macro
| expr
select-arm = ("let" NAME "=")? "recv" "(" expr ")" "=>" (block | stmt)
| "send" "(" expr "," expr ")" "=>" (block | stmt)
| "_" "=>" (block | stmt)
place = NAME | place "." NAME | place "." INT | place "[" expr "]" | "*" expr

From the loosest-binding form to the tightest; see Operators for the binary operators.

expr = expr binop expr
| expr "as" type
| ("-" | "!" | "*" | "&" | "ref" | "comptime") expr
| expr "(" exprs ")" ; call
| expr "[" expr "]" | expr "." NAME ; index, field
| expr "." INT ; a part of a tuple
| expr "[" expr? ":" expr? "]" ; slice of a str or list
| primary
primary = INT | FLOAT | STRING | "true" | "false"
| NAME | path ; variable, constant, module item
| path ("(" exprs ")")? "{" (NAME ":" expr) sep* "}" ; struct literal
| path "." NAME ("(" exprs ")")? ; enum variant: `Shape.Rect(1, 2)`
| "[" exprs "]" | "[" expr ";" expr "]" ; array (or list) literals
| "(" expr ")"
| "(" expr ("," expr)+ ","? ")" ; tuple
| block ; its last statement's value, if an expression
| "fn" "(" (NAME (":" type)?),* ")" ("->" type)? block ; anonymous function
| "match" expr "{" (pattern ("if" expr)? "=>" expr) sep* "}"
| path "!" "(" exprs ")" ; an expression macro
| "quote" ("(" expr ")" | block | "items" "{" item* "}")
| "$" NAME | "$" "(" expr ")" ; a hole, inside quote
| "size_of" "(" type ")" | "align_of" "(" type ")"
| "chan" "(" type ("," expr)? ")" | "cell" "(" expr ")"
; with more parts, a type: `cell (A, B)`
| "asm" "(" STRING* ("," asm-operand)* ")"
| type ; a type argument: `max(u8, a, b)`
asm-operand = "out" "(" (STRING | "reg") ")" type
| "in" "(" (STRING | "reg" | "out") ")" expr
| "clobber" "(" STRING,* ")"
pattern = single ("|" single)*
single = "_" | NAME | INT | "-" INT | "true" | "false"
| NAME "(" pattern,* ")" ; a variant with a payload
| NAME "{" (NAME (":" pattern)?) sep* ".."? "}" ; a struct, `..` for the rest
| "(" pattern ("," pattern)+ ")" ; a tuple
as asm break cell chan comptime const continue
else enum export extern false fn for go
if import let macro match pub quote ref
return select struct true while

requires, ensures and result are only special in a function’s contract, nocopy only where it marks a copy-free function, and replaces only where it makes a rewrite rule; elsewhere they are names.