Variables
Local bindings, outputs, and the input object
Nodora has three kinds of names you can use inside a rule:
- Locals — named results of an expression, scoped to the rule.
- Outputs — locals also exposed in the evaluation result.
input— the implicit, read-only object passed at evaluation time.
Local bindings
rule Example {
is_adult = input.age >= 18
in_us = input.country == "us"
eligible = is_adult && in_us
}Each name is bound by a single = assignment. Names must be declared
before use — forward references are rejected by the semantic analyzer.
Bindings are immutable. Reassigning a name is a compile-time error:
rule Bad {
x = 1
x = 2 // error: duplicate definition
}There are no let, var, or const keywords — every assignment is a
fresh, immutable binding.
Outputs
Prefixing an assignment with out adds it to the rule's result map under
the same name:
rule Approval {
eligible = input.age >= 18 && input.email_verified
out approved = eligible
}Output names must be unique. The value of an output can still be referenced by later statements just like a local.
A rule with no out statements is valid — it simply returns an empty
outputs map and is only useful for its emitted signals.
The input object
input is reserved. It always has type object and is provided by the
caller of the evaluator:
rule Demo {
name = input.user.name // dot access
role = input["user"]["role"] // bracket access
first = input.tags[0] // array index
}Reading a missing field returns undefined. undefined propagates
through arithmetic, comparison and most built-ins, so partial inputs
generally do not produce evaluation errors — they produce undefined
outputs, which are omitted from the result.
Scope
Every rule has its own scope. Names declared inside one rule are not visible in another:
rule A { x = 1 }
rule B { y = x } // error: 'x' is not definedNaming
Identifiers start with a letter or underscore and contain letters,
digits, or underscores. The keywords listed in
Basics cannot be used as
names, and input is reserved.