Variable Declarations
VarDecl ::= ident ':' Type ';'
Type ::= BaseType ('[' ArrayLen ']')?
BaseType ::= PrimitiveType | StructName
A variable declaration introduces one named value at PD-global scope or
inside an event body. The ident: Type; form is
the only shape supported today; an initialiser (ident: Type = expr;) is
reserved but not yet parsed.
🚧 Initialiser syntax (
= expr) is reserved but unparsed — see #105. For now, initialise locals from inside the body, and globals from the imported source’sinit()function (see Boot Initialisation).
Scopes
Variables can appear in two positions inside a .fi file:
- Global — at the top level of the file, alongside
Mappingandimportdeclarations. Globals are visible everywhere in the PD, read/write inside event bodies. - Local — inside a computation event body. Locals
shadow globals of the same name. Their scope ends where the enclosing
event’s body ends — implicitly, at the next top-level item (
evt,proc,import,Mapping), since there is no explicit terminator keyword.
Process bodies cannot declare variables; any state needed by guards or process expressions must be promoted to a global.
The full scope-resolution order inside an event body is:
local → carrier → global
Carriers are the read-only inputs declared in the event header — see Event Declarations.
Primitive types
The primitive types accepted in declarations are:
| Group | Tokens |
|---|---|
| Signed integers | int, int8, int16, int32, int64 |
| Unsigned integers | uint, uint8, uint16, uint32, uint64 |
| Boolean | bool |
| Byte alias | byte (8-bit) |
| Address | Address |
int and uint without a width default to 32-bit. byte is an alias
for uint8. There is no void type — every declared variable has a
concrete, storable type.
Struct types and arrays
pkt: Slot // user-defined struct — declared in the .fis data layer
buf: uint8[16] // fixed-size array — length is a literal or const name
Any identifier that isn’t a recognised primitive keyword is treated as a
struct type name, resolved against the .fis struct declarations during
name resolution (unknown names are rejected there, not at parse time).
Fiducia has no pointer types — there is no ptr<T> syntax.
Examples
// Global declarations, top of a .fi file.
counter: int;
ready: bool;
last_irq_ts: uint64;
// Local declarations inside an event body.
evt handle_packet.|size: int|:
local_buf: uint8[64]; // local
ok: bool; // local
local_buf = eth.alloc(); // assignment uses globals/locals/carriers
Validation
- A variable name is unique within its enclosing scope (multiple globals with the same name are rejected; a local may legally shadow a global).
- The type must be a recognised primitive,
Address, a fixed-size array of one, or a struct name that resolves to a real.fisstruct declaration.