Keyboard shortcuts

Press ← or β†’ to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Expressions

This chapter describes the expression grammar designed for Fiducia and the subset that today’s parser actually accepts. Expressions appear as:

  • the right-hand side of assignments inside event bodies and the constructor block;
  • the payload of a channel send (c!e);
  • the body of a guard ([b]);
  • arguments to sub-process calls and computation-event references.

The grammar is divided into four sub-languages: arithmetic (integer- valued), logical (boolean / relational), boolean (lifted), and call expressions. Only call expressions are fully implemented today. The others are flagged 🚧 below.

Expr  ::= AExpr | LExpr | BExpr | CExpr

Call expressions (CExpr)

CExpr ::= ident '.' ident '(' (Expr (',' Expr)*)? ')'

A call expression invokes a function defined in an imported .c / .rs file, prefixed with the import alias chosen at the import declaration. The alias is required β€” there are no local callables in Fiducia, only externally-implemented functions reached through an alias.

The first ident is the alias; the second is the function name. No whitespace is permitted around the . or before the (:

eth.send_frame()                  // OK
drv.start()                       // OK
drv .start()                      // rejected β€” whitespace before '.'
drv. start()                      // rejected β€” whitespace after '.'
drv.start ()                      // rejected β€” whitespace before '('

Argument lists

Argument parsing is currently a stub: the parser accepts an empty (...) argument list and stores Vec::new() for the args. Once the rest of the expression grammar lands, arguments will be Vec<Expr> and the call site shape (eth.send_frame(pkt)) will parse as expected.

🚧 Argument parsing for call expressions is gated on the broader expression grammar β€” see #105. Today, only () is accepted; calls with arguments parse only inside places that do their own identifier-list handling (sub-process calls, computation-event carriers).

Arithmetic expressions (AExpr)

🚧 Not yet implemented β€” see #105.

The designed grammar covers integer literals, variables, unary negation, and the standard binary arithmetic operators (+, -, *, /, %). Until the grammar lands, integer values appear in source only as literals at fixed positions (IRQ numbers, page sizes, sizes / phys-addrs in MemoryRegion).

Logical expressions (LExpr)

🚧 Not yet implemented β€” see #105.

The designed grammar covers comparison (==, !=, <, <=, >, >=) and boolean composition (&&, ||, !). Until the grammar lands, guards accept only [var] and [!var].

Boolean expressions (BExpr)

🚧 Not yet implemented β€” see #105.

A lifted boolean form for use as a payload type, distinct from LExpr which composes other relations. Likely to merge into LExpr in the final grammar β€” tracked under #105.

Stand-ins for unimplemented forms

Where the grammar currently lacks a construct, the surrounding parser accepts a narrow stand-in so existing fixtures continue to parse:

PositionStand-in accepted
MemoryRegion size / page / physhex literal only
Mapping vaddrhex literal only
c!e send payloadidentifier
irq?N / irq!N IRQ numberinteger literal
Computation-event carrier argsidentifier
Sub-process call argsidentifier
Constructor RHSmapping.field or opaque text to ;
Guard expressionvar or !var

These accept-narrow / reject-everything-else windows keep the parser honest: every position where an expression should go either has a fully-typed Expr (via CExpr) today, or accepts a clearly-restricted shape that surfaces an error if you reach for an un-implemented form.