Every Tenor contract uses these symbols in predicates, transitions, and quantifiers. The parser accepts both Unicode and ASCII forms. Unicode is conventional in docs and examples. ASCII works everywhere.
Logical Operators
| Symbol | ASCII | Name | Meaning | Example |
|---|---|---|---|---|
∧ | and | Conjunction | Both sides must be true | payment_ok = true ∧ dispute_filed = false |
∨ | or | Disjunction | Either side can be true | status = "cancelled" ∨ status = "expired" |
¬ | not | Negation | Inverts the condition | ¬ verdict_present(override_approved) |
Quantifiers
| Symbol | ASCII | Name | Meaning | Example |
|---|---|---|---|---|
∀ | forall | Universal | True for every element in a list | ∀ item in line_items . item.amount > 0 |
∃ | exists | Existential | True for at least one element | ∃ doc in documents . doc.status = "verified" |
Quantifiers bind over List-typed facts or List-typed Record fields. The . after the list reference introduces the body predicate — it is NOT the field access operator in this position.
Comparison Operators
| Symbol | ASCII | Meaning | Applies to |
|---|---|---|---|
= | = | Equal | All types |
≠ | != | Not equal | All types |
< | < | Less than | Int, Decimal, Money, Date, DateTime |
≤ | <= | Less or equal | Int, Decimal, Money, Date, DateTime |
> | > | Greater than | Int, Decimal, Money, Date, DateTime |
≥ | >= | Greater or equal | Int, Decimal, Money, Date, DateTime |
Not available on: Bool (only = ≠), Text (only = ≠), Enum (only = ≠). Attempting < on a Bool is an elaboration error.
Money comparison: both sides must be the same currency. Money(USD) < Money(EUR) is a type error.
Arithmetic Operators
| Symbol | Meaning | Restriction | Example |
|---|---|---|---|
+ | Addition | Int, Decimal, Money | base_amount + surcharge |
- | Subtraction | Int, Decimal, Money; also DateTime - DateTime → Duration | total - discount |
* | Multiplication | Literal only — fact * 3 is allowed, fact1 * fact2 is forbidden | unit_price * 100 |
The multiplication restriction is deliberate. Variable × variable would require unbounded range analysis. Literal multiplication keeps ranges statically checkable.
Field Access
| Symbol | Name | Meaning | Example |
|---|---|---|---|
. | Dot | Access a field on a Record-typed fact | plan_features.max_seats |
When a fact has type Record(fields), the . operator accesses a named field. Chaining is supported for nested records: order.billing_address.zip_code.
Inside quantifiers: The . after ∀ item in list introduces the body predicate — this is syntactically distinct from field access. ∀ item in line_items . item.amount > 0 has two dots: the first separates the binding from the body, the second accesses the amount field on item.
Transition Arrow
| Symbol | ASCII | Meaning | Example |
|---|---|---|---|
→ | -> | State transition | (EscrowAccount, held, released) in effects; (held, released) in entity transitions |
Used in entity transition declarations and operation effects. Both forms are identical to the parser.
Special Functions
| Function | Meaning | Example |
|---|---|---|
verdict_present(id) | True if the named verdict was produced by rule evaluation | verdict_present(payment_verified) |
len(list) | Length of a List-typed value (operator on ground term, not a built-in function) | len(line_items) > 0 |
verdict_present is the bridge between strata — a stratum 1 rule checks whether stratum 0 produced a verdict.
There are no other built-in functions. No now(), no abs(), no sqrt(), no string functions. All time-varying values enter as Facts.
Precedence
From highest to lowest:
.(field access)¬/not*(multiplication)+,-=,≠,<,≤,>,≥∧/and∨/or∀,∃(quantifiers bind loosest)
Parentheses override precedence as expected.