Syntax & grammar
The annotated grammar reference: every Bynk construct, with its production, what it means, the diagnostics that govern it, and an example. The verbatim machine grammar — every production in one block — is the complete grammar appendix.
Notation & conventions
Section titled “Notation & conventions”Productions are written in EBNF:
"x" a literal token · /x/ a regular expression · ( … )? optional ·
( … )* zero or more · ( … )+ one or more · a | b choice · ε empty.
- Nonterminals are the unquoted names; each is defined by its own entry on this page. Names are the display names of the grammar rules: a leading underscore (an internal helper rule) is dropped and trivial wrappers are collapsed, so productions read as language rather than parser internals. The raw rules and the byte-exact grammar live in the appendix.
- Every production on this page is generated from the
tree-sitter-bynkgrammar, so it cannot drift from the parser. - A production says what parses. A Static semantics block lists the
bynk.*diagnostics that constrain a construct beyond parsing; each links by code to the diagnostic index. A construct with no such diagnostics says so.
Lexical grammar
Section titled “Lexical grammar”The terminals: identifiers, literals, comments, and the trivia ignored between tokens.
identifier
Section titled “identifier”identifier ::= /[A-Za-z][A-Za-z0-9_]*/A name: a letter followed by letters, digits, or underscores. Used for declarations, parameters, fields, and bindings.
Static semantics. {{#grammar-semantics identifier}}
constant_name
Section titled “constant_name”constant_name ::= /[A-Z][A-Za-z0-9_]*/An upper-case-initial name, used for sum-type variants and enum constants.
number_literal
Section titled “number_literal”number_literal ::= /[0-9]+/A non-negative integer literal.
Static semantics. {{#grammar-semantics number_literal}}
float_literal
Section titled “float_literal”float_literal ::= /[0-9]+\.[0-9]+([eE][+-]?[0-9]+)?|[0-9]+[eE][+-]?[0-9]+/A Float literal: a fraction with a digit required on both sides of the .
(1.0, 0.5 — 1. and .5 are rejected), an exponent (1e10, 1.5e-3),
or both. A literal that does not fit a finite 64-bit float (1e999) is
rejected at lex time.
Static semantics. {{#grammar-semantics float_literal}}
string_literal
Section titled “string_literal”string_literal ::= """ (/[^"\\\n]/ | /\\[nt"\\]/ | string_interpolation)* """A double-quoted string. The escapes \n, \t, \", and \\ are recognised.
A string may also contain \(expr) interpolation holes (v0.43); see
string_interpolation.
Static semantics. {{#grammar-semantics string_literal}}
string_interpolation
Section titled “string_interpolation”string_interpolation ::= "\(" expression ")"An interpolation hole \(expr) inside a string literal (v0.43). The body is an
ordinary expression; the hole’s parentheses balance, so \(f(x)) takes f(x).
A bare \( was previously an invalid escape, so this is backward-compatible
(\\( is an escaped backslash followed by a literal (). The hole-typing rule
is in §5.2 well-typedness.
boolean_literal
Section titled “boolean_literal”boolean_literal ::= "true" | "false"The two Bool values, true and false.
unit_literal
Section titled “unit_literal”unit_literal ::= "(" ")"The unit value () — the single value of the unit type.
line_comment
Section titled “line_comment”line_comment ::= "--" /[^\n]*/A comment from -- to end of line. Bynk uses --, never //. Comments are
trivia: ignored between tokens.
A --- … --- doc-block is an external token attached to the following
declaration; it, whitespace, and line comments are the trivia ignored between
tokens (see the appendix’s Tokens & trivia).
See also. Keywords.
Top-level & modules
Section titled “Top-level & modules”A source file is a commons (pure, shareable code) or a context (an isolated
bounded context), or test declarations. The helper fragment rules are entry
points the tooling uses to parse incomplete input; they are not written
directly.
source_file
Section titled “source_file”source_file ::= (commons_decl | context_decl | adapter_decl | integration_decl | test_decl)+ | item_fragment+ | expr_fragmentA whole file: one or more top-level declarations, or a fragment (used by editor tooling).
Example.
commons shop { type Status = | Pending | Shipped(tracking: String) | Cancelled(reason: String)
fn describe(s: Status) -> String { match s { Pending => "awaiting shipment" Shipped(tracking: t) => t Cancelled(reason: r) => r } }}See also. How a Bynk program is shaped · Lay out a project.
item_fragment
Section titled “item_fragment”item_fragment ::= context_body_item | handler | store_field | key_declA tooling entry point: a single body item parsed in isolation. Not written by hand.
expr_fragment
Section titled “expr_fragment”expr_fragment ::= statement+ expression? | expressionA tooling entry point: statements and/or an expression parsed in isolation. Not written by hand.
commons_decl
Section titled “commons_decl”commons_decl ::= "commons" qualified_name ("{" commons_body_item* "}" | commons_body_item*)A commons module: pure, dependency-free declarations (types, functions,
capabilities) shareable across contexts. Body braces are optional at file scope.
context_decl
Section titled “context_decl”context_decl ::= "context" qualified_name ("{" context_body_item* "}" | context_body_item*)A context: a bounded context with its own services, agents, and provided
capabilities, isolated behind its boundary.
Example.
context reaper
service sweeper from cron { on schedule("*/5 * * * *") (at: Int) -> Effect[Result[(), String]] { Ok(()) }}Static semantics. {{#grammar-semantics context_decl}}
See also. How a Bynk program is shaped.
adapter_decl
Section titled “adapter_decl”adapter_decl ::= "adapter" qualified_name ("{" adapter_body_item* "}" | adapter_body_item*)An adapter: the host boundary. It co-locates a capability contract with a
non-Bynk binding, declaring capabilities, boundary types, inline pure helpers,
and external (bodiless) providers. The only place host code may enter a program.
Example.
adapter tokens { binding "./tokens.binding.ts" requires { "jose": "^5" } exports capability { Jwt } exports transparent { Claims } type Claims = { sub: String, exp: Int } capability Jwt { fn sign(claims: Claims, secret: String) -> Effect[String] } provides Jwt = JoseJwt}Static semantics. {{#grammar-semantics adapter_decl}}
See also. Adapters · Wrap a library as an adapter.
test_decl
Section titled “test_decl”test_decl ::= "test" qualified_name ("{" test_body_item* "}" | test_body_item*)A test block targeting a commons or context, holding its test cases and
mocks.
Static semantics. {{#grammar-semantics test_decl}}
See also. Testing · Write tests and mock collaborators.
integration_decl
Section titled “integration_decl”integration_decl ::= "test" "integration" string_literal ("{" wires_decl integration_body_item* "}" | wires_decl integration_body_item*)A test integration block that wires several contexts together and exercises a
flow across their boundaries.
Static semantics. {{#grammar-semantics integration_decl}}
See also. Test a flow across Workers.
wires_decl
Section titled “wires_decl”wires_decl ::= "wires" qualified_name ("," qualified_name)*Lists the contexts an integration test wires together.
Static semantics. {{#grammar-semantics wires_decl}}
integration_body_item
Section titled “integration_body_item”integration_body_item ::= uses_decl | test_caseWhat may appear in an integration test: uses declarations and test cases.
commons_body_item
Section titled “commons_body_item”commons_body_item ::= uses_decl | type_decl | fn_decl | capability_decl | provider_decl | service_decl | agent_decl | actor_declThe declarations allowed in a commons (no consumes, exports, or mocks).
context_body_item
Section titled “context_body_item”context_body_item ::= uses_decl | consumes_decl | exports_decl | type_decl | fn_decl | capability_decl | provider_decl | service_decl | agent_decl | actor_declThe declarations allowed in a context, including consumes and exports.
adapter_body_item
Section titled “adapter_body_item”adapter_body_item ::= binding_decl | uses_decl | consumes_decl | exports_decl | type_decl | fn_decl | capability_decl | provider_decl | service_decl | agent_decl | actor_declThe declarations allowed in an adapter: a binding clause, capabilities,
boundary types, inline pure helpers and uses, external providers, and
exports (no consumes).
test_body_item
Section titled “test_body_item”test_body_item ::= uses_decl | consumes_decl | mocks_decl | test_caseThe declarations allowed in a test block, including mocks and test cases.
qualified_name
Section titled “qualified_name”qualified_name ::= identifier ("." identifier)*A dotted name, e.g. shop.orders — used to name modules and reference them.
uses_decl
Section titled “uses_decl”uses_decl ::= "uses" qualified_nameImports a commons so its public names are in scope.
Static semantics. {{#grammar-semantics uses_decl}}
See also. Define sum, record, and opaque types.
consumes_decl
Section titled “consumes_decl”consumes_decl ::= "consumes" qualified_name ("as" identifier | "{" (identifier ("," identifier)*)? ","? "}")?Declares that a context depends on another context’s (or adapter’s) services or
capabilities — whole and qualified, aliased (as), or with selected
capabilities flattened to bare names ({ Cap, … }).
Static semantics. {{#grammar-semantics consumes_decl}}
See also. Consume another context’s services.
binding_decl
Section titled “binding_decl”binding_decl ::= "binding" string_literal ("requires" "{" (binding_requirement ("," binding_requirement)*)? ","? "}")?Names an adapter’s TypeScript binding module (resolved relative to the adapter’s source file) and, optionally, the npm dependencies it requires. Pinned version ranges only.
Static semantics. {{#grammar-semantics binding_decl}}
See also. Adapters.
binding_requirement
Section titled “binding_requirement”binding_requirement ::= string_literal ":" string_literalOne "package": "range" entry in a binding’s requires { … } map; folded into
the generated package.json.
exports_decl
Section titled “exports_decl”exports_decl ::= "exports" ("opaque" | "transparent" | "capability") "{" (identifier ("," identifier)*)? ","? "}"Controls a context’s boundary: which types are exported opaquely or transparently, and which capabilities are exported.
Static semantics. {{#grammar-semantics exports_decl}}
See also. Share a capability across contexts.
Types & refinements
Section titled “Types & refinements”Type declarations and the type references that appear in signatures.
type_decl
Section titled “type_decl”type_decl ::= "type" identifier "=" type_bodyNames a type as a record, sum, enum, opaque, or refined type.
Example.
type Status = | Pending | Shipped(tracking: String) | Cancelled(reason: String)Static semantics. {{#grammar-semantics type_decl}}
See also. Type system · Define sum, record, and opaque types · The type-system philosophy.
type_body
Section titled “type_body”type_body ::= opaque_type | refined_type | record_type | sum_type | enum_typeThe right-hand side of a type declaration: one of the five type forms.
opaque_type
Section titled “opaque_type”opaque_type ::= "opaque" base_type ("where" refinement)?A type whose representation is hidden outside its defining module; constructed and inspected only through its API.
See also. Define sum, record, and opaque types.
refined_type
Section titled “refined_type”refined_type ::= base_type ("where" refinement)?A base or named type narrowed by a where refinement, e.g. Int where Positive.
Example.
type Quantity = Int where InRange(1, 100)Static semantics. {{#grammar-semantics refined_type}}
See also. Refined-type API · Define and validate untrusted input.
record_type
Section titled “record_type”record_type ::= "{" (record_field ("," record_field)*)? ","? "}"A product type: named fields, each with a type and optional refinement and default.
Static semantics. {{#grammar-semantics record_type}}
record_field
Section titled “record_field”record_field ::= identifier ":" type_ref ("where" refinement)? ("=" expression)?One field of a record: a name, a type, an optional inline refinement, and an optional default value.
Static semantics. {{#grammar-semantics record_field}}
sum_type
Section titled “sum_type”sum_type ::= sum_variant+A tagged union of variants, each optionally carrying a payload.
Static semantics. {{#grammar-semantics sum_type}}
See also. Type system.
sum_variant
Section titled “sum_variant”sum_variant ::= "|" constant_name ("(" (variant_payload_field ("," variant_payload_field)*)? ","? ")")?One variant of a sum type: a constant name with an optional payload.
variant_payload_field
Section titled “variant_payload_field”variant_payload_field ::= identifier ":" type_refA named field in a sum-variant payload.
enum_type
Section titled “enum_type”enum_type ::= "enum" "{" (constant_name ("," constant_name)*)? ","? "}"A sum type whose variants all have no payload.
refinement
Section titled “refinement”refinement ::= refinement_pred ("and" refinement_pred)*One or more predicates joined by and, narrowing a type to the values that
satisfy them.
Static semantics. {{#grammar-semantics refinement}}
See also. The refined-literal admission model.
refinement_pred
Section titled “refinement_pred”refinement_pred ::= pred_call | predicate_nameA single refinement predicate: a predicate call or a bare predicate.
pred_call
Section titled “pred_call”pred_call ::= predicate_name "(" (pred_arg ("," pred_arg)*)? ")"A predicate with arguments, e.g. InRange(1, 100) or Matches("…").
predicate_name
Section titled “predicate_name”predicate_name ::= "Matches" | "InRange" | "MinLength" | "MaxLength" | "Length" | "NonNegative" | "Positive" | "NonEmpty"The built-in refinement predicates.
Static semantics. {{#grammar-semantics predicate_name}}
pred_arg
Section titled “pred_arg”pred_arg ::= number_literal | float_literal | string_literalAn argument to a predicate: a number or string literal.
base_type
Section titled “base_type”base_type ::= "Int" | "String" | "Bool" | "Float" | "Duration" | "Instant"The primitive types Int, String, Bool, Float, and Duration. Duration
(v0.86, ADR 0112) is a span of time in milliseconds, written with a literal
<int>.<unit> (5.minutes, 30.days); its closed unit set is milliseconds,
seconds, minutes, hours, days.
Static semantics. {{#grammar-semantics base_type}}
type_ref
Section titled “type_ref”type_ref ::= function_type_ref | base_type | unit_type | validation_error_type | generic_type_ref | identifierA type as it appears in a signature: a base type, a unit, a validation-error type, a generic application, or a named type.
unit_type
Section titled “unit_type”unit_type ::= "(" ")"The unit type ().
validation_error_type
Section titled “validation_error_type”validation_error_type ::= "ValidationError"ValidationError — the error produced when refined-type validation fails.
generic_type_ref
Section titled “generic_type_ref”generic_type_ref ::= ("Result" | "Option" | "Effect" | "HttpResult" | "List" | "Map" | "Stream" | "Query" | "Connection") "[" type_ref ("," type_ref)* "]"A generic type applied to arguments: Result[T, E], Option[T], Effect[T],
HttpResult[T], or Stream[T].
Static semantics. {{#grammar-semantics generic_type_ref}}
See also. Work with Result and optional values.
function_type_ref
Section titled “function_type_ref”function_type_ref ::= (base_type | unit_type | validation_error_type | generic_type_ref | identifier | "(" type_ref ("," type_ref)* ","? ")") "->" type_refA function type (v0.20a): Int -> Int, (Int, String) -> Bool, () -> Int.
The arrow is right-associative (A -> B -> C is A -> (B -> C)), and a
function type is effectful exactly when its return type is Effect[_] — the
same structural rule that classifies function declarations. Function types are
confined to non-boundary positions: fn/lambda parameters, returns, and
locals; they are rejected in record fields, sum payloads, handler and
capability signatures, agent state, and anything else that would serialise or
cross a boundary.
Static semantics. {{#grammar-semantics function_type_ref}}
Functions, capabilities & providers
Section titled “Functions, capabilities & providers”Pure functions and methods, the capability interfaces an effectful program depends on, and the providers that implement them.
fn_decl
Section titled “fn_decl”fn_decl ::= "fn" (method_name | identifier) ("[" identifier ("," identifier)* "]")? "(" params? ")" "->" type_ref blockA function or method: a name, parameters, a return type, and a block body.
Example.
commons demo { type Id = Int
fn add(a: Int, b: Int) -> Int { a + b }}Static semantics. {{#grammar-semantics fn_decl}}
See also. Operators & built-ins.
method_name
Section titled “method_name”method_name ::= identifier "." identifierA method name, Type.method, defining a method on a named type.
params
Section titled “params”params ::= (self_param | param) ("," param)* ","?A parameter list: an optional self parameter followed by named parameters.
self_param
Section titled “self_param”self_param ::= "self"The self receiver of a method or handler.
param ::= identifier ":" type_refOne parameter: a name and a type.
Static semantics. {{#grammar-semantics param}}
capability_decl
Section titled “capability_decl”capability_decl ::= "capability" identifier "{" capability_op* "}"A capability: an interface of effectful operations a context can depend on.
Example.
context demo
capability Logger { fn info(message: String) -> Effect[()] }capability Greeter { fn greet() -> Effect[()] }
provides Logger = ConsoleLogger { fn info(message: String) -> Effect[()] { Effect.pure(()) }}
provides Greeter = PoliteGreeter given Logger { fn greet() -> Effect[()] { let _ <- Logger.info("hello") Effect.pure(()) }}Static semantics. {{#grammar-semantics capability_decl}}
See also. Capabilities & providers.
capability_op
Section titled “capability_op”capability_op ::= "fn" identifier "(" (param ("," param)*)? ","? ")" "->" type_refOne operation in a capability: a name, parameters, and a return type (no body).
Static semantics. {{#grammar-semantics capability_op}}
provider_decl
Section titled “provider_decl”provider_decl ::= "provides" identifier "=" identifier given_clause? ("{" provider_op* "}")?A provides block implementing a capability, optionally given other
capabilities it depends on.
Static semantics. {{#grammar-semantics provider_decl}}
See also. Compose a provider from other capabilities.
provider_op
Section titled “provider_op”provider_op ::= "fn" identifier "(" (param ("," param)*)? ","? ")" "->" type_ref blockOne operation implementation in a provider: a capability operation with a body.
Static semantics. {{#grammar-semantics provider_op}}
given_clause
Section titled “given_clause”given_clause ::= "given" qualified_name ("," qualified_name)*Declares the capabilities a handler or provider may use.
Static semantics. {{#grammar-semantics given_clause}}
Actors (v0.45)
Section titled “Actors (v0.45)”An actor is a nominal boundary contract — a closed, compiler-known
authentication scheme plus an optional sealed identity. A handler consumes one
on its by clause; the boundary verifies the scheme and mints the identity
before the body runs.
actor_decl
Section titled “actor_decl”actor_decl ::= "actor" identifier ("{" "auth" "=" scheme scheme_config? ("," "identity" "=" type_ref)? "}" | "=" identifier "where" refinement)A boundary contract: actor Name { auth = <Scheme> }, optionally
, identity = <Type> (a context-ownable, sealed identity type). The reserved
refinement form actor Admin = Base where <predicate> is parsed and rejected in
Foundations (bynk.actor.refinement_unsupported). Actors are context-only.
scheme
Section titled “scheme”scheme ::= "None" | "Internal" | "Bearer" | "Signature"The closed authentication-scheme set: None (anonymous; identity ()),
Internal (in-system/platform trust), Bearer (a JWT in Authorization, v0.47),
and Signature (an HMAC over the request body, for webhooks, v0.51). The
authenticated schemes carry a scheme_config.
scheme_config
Section titled “scheme_config”scheme_config ::= "(" scheme_arg ("," scheme_arg)* ")"The keyed-args config an authenticated scheme carries — Bearer(secret = "<ENV>")
or Signature(secret = "<ENV>", header = "<Header>", (timestamp = "<Header>", tolerance = <seconds>)?). The checker validates which keys each scheme admits.
scheme_arg
Section titled “scheme_arg”scheme_arg ::= identifier "=" (string_literal | number_literal)One key = value pair in a scheme_config; the value is a
string or integer literal (e.g. an integer tolerance in seconds).
by_clause
Section titled “by_clause”by_clause ::= "by" (identifier ":")? identifier ("|" identifier)*by <binder>: <Actor> on a handler, after the protocol config and before the
parameters. The verified actor binds to <binder>; its identity is
<binder>.identity. The binder is optional (v0.50): by <Actor> verifies the
contract fail-closed but captures no identity (anonymous / verify-and-discard) —
the canonical form for an identity-less scheme like Signature (by Webhook (body: T)). Omitting by entirely inherits the protocol’s default actor — except
on HTTP, where by is required (bynk.actor.missing_by_on_http).
Services & handlers
Section titled “Services & handlers”A service groups the handlers that respond to calls and external triggers.
service_decl
Section titled “service_decl”service_decl ::= "service" identifier service_protocol? "{" handler* "}"A service: a named group of handlers inside a context.
Example.
context notes
service api from http { on GET("/ping") by Visitor () -> Effect[HttpResult[String]] { Ok("pong") }
on GET("/notes/:id") by Visitor (id: String) -> Effect[HttpResult[String]] { NotFound }}Static semantics. {{#grammar-semantics service_decl}}
service_protocol
Section titled “service_protocol”service_protocol ::= "from" ("http" | "cron" | "queue" "(" string_literal ")" | "WebSocket" "(" "in" ":" type_ref "," "out" ":" type_ref ","? ")")The from <protocol> header clause (v0.44): from http, from cron,
from queue("<name>"), or from WebSocket(in: I, out: O) (v0.103, binding the
inbound/outbound frame types). Absent ⇒ a contract-mediated, on call-only
service.
handler
Section titled “handler”handler ::= call_handler | http_handler | cron_handler | queue_handler | ws_open_handler | ws_close_handlerA handler: a call, HTTP, cron, queue, or WebSocket (on open/on close, with
on message shared with the queue form) entry point.
Static semantics. {{#grammar-semantics handler}}
call_handler
Section titled “call_handler”call_handler ::= "on" "call" identifier? by_clause? "(" (param ("," param)*)? ","? ")" "->" type_ref given_clause? blockon call — an in-process entry point, optionally named, callable across
contexts.
http_handler
Section titled “http_handler”http_handler ::= "on" http_method "(" string_literal ")" by_clause? "(" (param ("," param)*)? ","? ")" "->" type_ref given_clause? blockfrom http — an HTTP route handler returning Effect[HttpResult[T]].
Static semantics. {{#grammar-semantics http_handler}}
See also. HTTP · Handle an HTTP request.
http_method
Section titled “http_method”http_method ::= "GET" | "POST" | "PUT" | "PATCH" | "DELETE"The HTTP methods a route may handle.
Static semantics. {{#grammar-semantics http_method}}
cron_handler
Section titled “cron_handler”cron_handler ::= "on" "schedule" "(" string_literal ")" by_clause? "(" (param ("," param)*)? ","? ")" "->" type_ref given_clause? blockfrom cron — a scheduled handler returning Effect[Result[(), E]].
Static semantics. {{#grammar-semantics cron_handler}}
See also. Cron · Run a task on a schedule.
queue_handler
Section titled “queue_handler”queue_handler ::= "on" "message" by_clause? "(" (param ("," param)*)? ","? ")" "->" type_ref given_clause? blockfrom queue — a queue-message handler returning Effect[Result[(), E]].
Static semantics. {{#grammar-semantics queue_handler}}
See also. Queue · Process a queued message.
ws_open_handler
Section titled “ws_open_handler”ws_open_handler ::= "on" "open" by_clause? "(" (param ("," param)*)? ","? ")" "->" type_ref given_clause? blockfrom WebSocket — the upgrade handshake (v0.103). Exactly one per service; it
names its actor with by and receives an owned connection: Connection[out] it
must dispose. The inbound-frame handler reuses the on message (queue) form.
ws_close_handler
Section titled “ws_close_handler”ws_close_handler ::= "on" "close" by_clause? "(" (param ("," param)*)? ","? ")" "->" type_ref given_clause? blockfrom WebSocket — fires when the connection ends (v0.106); disposes the stored
connection.
See also. WebSocket · Handle a WebSocket connection.
Agents
Section titled “Agents”An agent is a keyed, stateful entity: its state lives in store fields that
handlers read by name and write with :=.
agent_decl
Section titled “agent_decl”agent_decl ::= "agent" identifier "{" key_decl store_field* invariant_decl* handler* "}"An agent: a key, store fields, and handlers that read and write them (writes
commit atomically at handler end).
Example.
context counters
type CounterId = opaque String
agent Counter { key id: CounterId
store count: Cell[Int]
on call current() -> Effect[Int] { count }
on call increment() -> Effect[Int] { let next = count + 1 count := next next }}Static semantics. {{#grammar-semantics agent_decl}}
See also. Agents · Build a stateful agent · The agent model.
key_decl
Section titled “key_decl”key_decl ::= "key" identifier ":" type_refThe agent’s identity: a key field whose value names an instance.
store_field
Section titled “store_field”store_field ::= "store" identifier ":" store_kind store_annotation* ("=" expression)?A store field (storage track): store <name>: <Kind>[…] [@annotations] [= <init>]
— an access-pattern slot of a declared storage kind. store is a contextual
keyword (also a valid identifier elsewhere). It is the agent’s sole state surface
(ADR 0108); the legacy state { } block was removed at the parity slice.
Cell,Map,Set,Cache, andLogare functional. ACell[T](v0.82) reads by bare name (implicit deref) and writes with:=; aMap[K, V](v0.83, ADR 0110) is a storage map with effectful entry methods (put/get/update/upsert/remove/contains/size); aSet[T](v0.84, ADR 0110) is a storage set with effectful membership methods (add/remove/contains/size); aCache[K, V](v0.87, ADR 0113) is aMapwith per-entry TTL expiry, requiring@ttl(<duration>)andgiven Clockon its handlers (eviction reads the clock); aLog[T](v0.95, ADR 0121) is an append-only, time-indexed sequence whoseappendstampsClock.now()(given Clock) and whose reads are lazyQuery[T]time-window builders (since/before/between/recent/reversed), with an optional@retain(<duration>). All write ops are awaited with<-and commit atomically at handler end with the invariant gate (ADR 0109). The storage-kind catalogue is closed at these five — there is noQueuestorage kind: a queue is a delivery concern reached through thefrom queueprotocol, not agent state (ADR 0122).
store_kind
Section titled “store_kind”store_kind ::= identifier ("[" type_ref ("," type_ref)* "]")?A storage kind applied to its element type(s): Cell[Int], Map[K, V]. The head
is the kind name; the checker restricts it to the storage-kind catalogue.
store_annotation
Section titled “store_annotation”store_annotation ::= "@" identifier ("(" (annotation_arg ("," annotation_arg)*)? ","? ")")?A storage-field annotation (v0.85, ADR 0111): @<name> or @<name>(<args>),
between the kind and the initialiser — @ttl(5.minutes), @indexed(by: orderId).
The name is matched against the closed registry (@indexed/@ttl/@retain/
@bounded); an unknown name, a wrong-kind use, or an annotation whose slice has
not landed is a checker diagnostic. v0.85 (slice 3a) lands the grammar and
registry; each annotation becomes functional with its kind’s slice.
annotation_arg
Section titled “annotation_arg”annotation_arg ::= (identifier ":")? expressionOne annotation argument: an optional label: then a value expression — by: id
(labelled, as in @indexed) or 5.minutes (positional, as in @ttl). Arguments
are compile-time metadata, restricted to literals (and the @indexed field-name
labels) by the checker (ADR 0111 D4).
invariant_decl
Section titled “invariant_decl”invariant_decl ::= "invariant" identifier ":" expressionAn agent invariant: invariant <name>: <predicate>. A universally-quantified,
pure Bool predicate over the agent’s store fields, runtime-checked at each
commit boundary. Invariants form a phase between the store fields and the
handlers.
See also. Agent invariants.
Expressions
Section titled “Expressions”Bynk is expression-oriented: a block’s value is its final expression. Operators follow the usual precedence (see Operators & built-ins).
expression
Section titled “expression”expression ::= if_expr | match_expr | is_expr | assert_expr | binary_expr | unary_expr | primaryAny expression: control flow, refinement checks, operators, or a primary.
primary
Section titled “primary”primary ::= lambda_expr | paren_expr | method_call | field_access | call | record_construction | record_spread | question_expr | ok_expr | err_expr | some_expr | none_expr | effect_pure_expr | mock_expr | list_literal | block | number_literal | float_literal | string_literal | boolean_literal | unit_literal | self_expr | identifierThe atomic and postfix expressions: literals, names, calls, field and method access, constructors, and parenthesised expressions.
if_expr
Section titled “if_expr”if_expr ::= "if" expression block "else" (if_expr | block)A conditional expression; both branches must have the same type.
Static semantics. {{#grammar-semantics if_expr}}
match_expr
Section titled “match_expr”match_expr ::= "match" expression "{" match_arm* "}"Pattern-matches a value against variants; must be exhaustive.
Example.
match s { Pending => "awaiting shipment" Shipped(tracking: t) => t Cancelled(reason: r) => r}Static semantics. {{#grammar-semantics match_expr}}
See also. Pattern-match with match.
is_expr
Section titled “is_expr”is_expr ::= expression "is" patternA refinement/variant check that also narrows the value’s type in the true
branch.
Static semantics. {{#grammar-semantics is_expr}}
See also. Narrow and bind with is.
binary_expr
Section titled “binary_expr”binary_expr ::= expression "implies" expression | expression "||" expression | expression "&&" expression | expression ("==" | "!=") expression | expression ("<" | "<=" | ">" | ">=") expression | expression ("+" | "-") expression | expression ("*" | "/") expressionThe binary operators, in precedence order from || to *//.
Static semantics. {{#grammar-semantics binary_expr}}
See also. Operators & built-ins.
unary_expr
Section titled “unary_expr”unary_expr ::= ("!" | "-") expressionLogical negation ! and numeric negation -.
method_call
Section titled “method_call”method_call ::= primary "." identifier ("[" type_ref ("," type_ref)* "]")? "(" (expression ("," expression)*)? ","? ")"Calls a method on a value: receiver.method(args).
Static semantics. {{#grammar-semantics method_call}}
field_access
Section titled “field_access”field_access ::= primary "." identifierReads a field of a record or agent state: value.field.
Static semantics. {{#grammar-semantics field_access}}
call ::= identifier ("[" type_ref ("," type_ref)* "]")? "(" (expression ("," expression)*)? ","? ")"Calls a function or constructs a variant: name(args).
Static semantics. {{#grammar-semantics call}}
record_construction
Section titled “record_construction”record_construction ::= identifier "{" (field_init ("," field_init)*)? ","? "}"Builds a record value: Type { field: value, … }.
Static semantics. {{#grammar-semantics record_construction}}
field_init
Section titled “field_init”field_init ::= identifier ":" expression | identifierOne field in a record construction: name: value, or shorthand name.
record_spread
Section titled “record_spread”record_spread ::= identifier "{" "..." expression ("," field_init)* ","? "}" | "{" "..." expression ("," field_init)* ","? "}"Builds a record from an existing one, overriding some fields: { ...base, field: value }.
Static semantics. {{#grammar-semantics record_spread}}
question_expr
Section titled “question_expr”question_expr ::= expression "?"The ? operator: unwraps a Result, propagating the error on failure.
Static semantics. {{#grammar-semantics question_expr}}
See also. Work with Result and optional values.
ok_expr
Section titled “ok_expr”ok_expr ::= "Ok" "(" expression ")"The Ok constructor of Result (or HttpResult).
Static semantics. {{#grammar-semantics ok_expr}}
err_expr
Section titled “err_expr”err_expr ::= "Err" "(" expression ")"The Err constructor of Result.
Static semantics. {{#grammar-semantics err_expr}}
some_expr
Section titled “some_expr”some_expr ::= "Some" "(" expression ")"The Some constructor of Option.
Static semantics. {{#grammar-semantics some_expr}}
none_expr
Section titled “none_expr”none_expr ::= "None"The None constructor of Option.
Static semantics. {{#grammar-semantics none_expr}}
effect_pure_expr
Section titled “effect_pure_expr”effect_pure_expr ::= "Effect" "." "pure" "(" expression ")"Effect.pure(x) — lifts a pure value into an Effect.
mock_expr
Section titled “mock_expr”mock_expr ::= "Mock" "[" type_ref "]" mock_arg?Mock[T] — fabricates a test value of type T, optionally pinned. Valid only
in test bodies.
Static semantics. {{#grammar-semantics mock_expr}}
See also. Write tests and mock collaborators.
mock_arg
Section titled “mock_arg”mock_arg ::= "(" expression ("," expression)* ","? ")" | "{" (field_init ("," field_init)*)? ","? "}"The pin arguments to a Mock[T]: positional values or a record of field pins.
lambda_expr
Section titled “lambda_expr”lambda_expr ::= "(" (lambda_param ("," lambda_param)*)? ")" "=>" (expression | block)A lambda (v0.20a): (o) => o.paid, (acc, t) => acc + t, () => 0, or with a
block body (o) => { … }. Always parenthesised; => is the value arrow
(shared with match arms), -> stays the type arrow. Parameter annotations
are optional where an expected function type supplies them — and required
otherwise. A lambda may close over and call a given capability; its
effectfulness is read off its body (an effect operation makes it effectful,
wrapping the result in Effect).
Static semantics. {{#grammar-semantics lambda_expr}}
lambda_param
Section titled “lambda_param”lambda_param ::= identifier (":" type_ref)?One lambda parameter, with an optional type annotation.
Static semantics. {{#grammar-semantics lambda_param}}
list_literal
Section titled “list_literal”list_literal ::= "[" (expression ("," expression)* ","?)? "]"A List literal (v0.20b): [1, 2, 3], with an optional trailing comma. A
leading [ only — type application (name[T](…)) stays a postfix form on
a callee identifier, and its [ must sit on the same line as the callee.
Elements check against the expected element type when one is supplied; an
empty [] needs an expected type to infer its element type from.
Static semantics. {{#grammar-semantics list_literal}}
paren_expr
Section titled “paren_expr”paren_expr ::= "(" expression ")"A parenthesised expression, for grouping.
self_expr
Section titled “self_expr”self_expr ::= "self"self — the receiver inside a method or agent handler.
Static semantics. {{#grammar-semantics self_expr}}
Patterns & matching
Section titled “Patterns & matching”The patterns used in match arms and is checks.
match_arm
Section titled “match_arm”match_arm ::= pattern "=>" expression ","?One arm of a match: a pattern, =>, and a result expression.
Static semantics. {{#grammar-semantics match_arm}}
See also. Pattern-match with match.
pattern
Section titled “pattern”pattern ::= wildcard_pattern | variant_patternA pattern: a wildcard or a variant pattern.
variant_pattern
Section titled “variant_pattern”variant_pattern ::= (identifier ".")? identifier ("(" (pattern_binding ("," pattern_binding)*)? ","? ")")?Matches a sum-type variant, optionally binding its payload fields.
Static semantics. {{#grammar-semantics variant_pattern}}
wildcard_pattern
Section titled “wildcard_pattern”wildcard_pattern ::= "_"_ — matches anything, binding nothing.
pattern_binding
Section titled “pattern_binding”pattern_binding ::= named_binding | positional_bindingA binding in a variant pattern: named or positional.
named_binding
Section titled “named_binding”named_binding ::= identifier ":" (identifier | "_")Binds a payload field by name: field: name (or field: _ to ignore).
positional_binding
Section titled “positional_binding”positional_binding ::= identifier | "_"Binds a payload field by position, or _ to ignore it.
Statements
Section titled “Statements”A block is a sequence of statements ending in an optional value expression.
block ::= "{" statement* expression? "}"A braced sequence of statements with an optional trailing expression, which is the block’s value.
statement
Section titled “statement”statement ::= let_stmt | effect_let_stmt | effect_send_stmt | assign_stmt | assert_exprA statement: a let, an effectful let, a := store write, an async send, or
an assertion.
let_stmt
Section titled “let_stmt”let_stmt ::= "let" binding_name (":" type_ref)? "=" expressionBinds a pure value: let name = expr.
Static semantics. {{#grammar-semantics let_stmt}}
effect_let_stmt
Section titled “effect_let_stmt”effect_let_stmt ::= "let" binding_name (":" type_ref)? "<-" expressionBinds the result of an effect: let name <- effect.
Static semantics. {{#grammar-semantics effect_let_stmt}}
effect_send_stmt
Section titled “effect_send_stmt”effect_send_stmt ::= "~>" expressionSends an effect asynchronously without awaiting its reply: ~> effect. The
caller does not wait and binds nothing; legal only when the reply is Effect[()]
(see the error gate below). Contrast let _ <- effect, which awaits the reply
and discards it.
Static semantics. {{#grammar-semantics effect_send_stmt}}
assign_stmt
Section titled “assign_stmt”assign_stmt ::= identifier ":=" expressionname := expr (v0.81, storage track) — a Cell store write. The unconditional
write form; .update(fn) is the read-modify-write form. ADR 0108.
assert_expr
Section titled “assert_expr”assert_expr ::= "assert" expressionassert — checks a Bool condition in a test case.
Static semantics. {{#grammar-semantics assert_expr}}
binding_name
Section titled “binding_name”binding_name ::= identifier | "_"The name bound by a let: an identifier, or _ to discard.
Testing constructs
Section titled “Testing constructs”Test cases, mocks, and integration wiring. See also the top-level
test_decl and integration_decl.
test_case
Section titled “test_case”test_case ::= "test" string_literal blockA single named test case with a block body, typically ending in asserts.
Example.
test "a fresh counter starts at zero" { let n <- Counter(CounterId.unsafe("fresh")).current() assert n == 0}Static semantics. {{#grammar-semantics test_case}}
See also. Testing · Write tests and mock collaborators.
mocks_decl
Section titled “mocks_decl”mocks_decl ::= "mocks" identifier "=" identifier "{" provider_op* "}"mocks — supplies a test implementation of a capability for the cases in a
test block.
Static semantics. {{#grammar-semantics mocks_decl}}
See also. Write tests and mock collaborators.