AEL operators
For the complete documentation index see: llms.txt
All documentation pages available in markdown.
Reference page: part of the AEL reference. Covers all AEL operators and their precedence. See Applies to on the overview page for SDK and Database version requirements.
Comparison operators
$.age > 21$.status == 'active'$.price != 0| Operator | Operand types | Result |
|---|---|---|
==, !=, <, <=, >, >= | Same type both sides | TRILEAN |
expr in listExpr | Right side evaluates to LIST | TRILEAN |
stringExpr =~ /pattern/[/flags] | Left side STRING; Perl-compatible regex | TRILEAN |
Both sides can be bins. Comparing two bins with no literal on either side requires an explicit :TYPE suffix on at least one side:
$.binA:INT > $.binBComparisons are not chainable (a < b < c is a parse error). Literals may appear on either side.
The in operator
$.name in ["Bob", "Mary", "Richard"]"gold" in $.allowedTiersThe right-hand side must evaluate to a LIST; the operator tests whether the left-hand value equals any list element. It does not test map keys or map values directly — use selectors or exists() for that. The left operand’s type must be resolved by the ordinary strict-typing rules (see Type inference); for example, $.x in $.other with neither side pinned is a parse error.
Regex match
Regex match (left operand must be STRING). See Regex literals for the pattern/flag syntax:
$.email =~ /^[^@]+@[^@]+\.[^@]+$/$.sku.trim().upper() =~ /^[A-Z]{3}-\d{4}$/The =~ operator is the regex match form in AEL. The pattern must appear as a regex literal in the expression (/…/ or /…/flags); it cannot be taken from a bin or variable. For example: $.name =~ /Mike|Michael .*/ or @key =~ /pen.*/.
Logical operators
$.age > 21 and $.status == 'active'$.role == 'admin' or $.role == 'super'not($.age > 65)exclusive($.a > 10, $.b > 5)| Form | Operands | Result |
|---|---|---|
a and b | TRILEAN | TRILEAN |
a or b | TRILEAN | TRILEAN |
not(expr) | TRILEAN | TRILEAN |
exclusive(a, b, …) | TRILEAN (varargs) | TRILEAN — true iff exactly one operand is true |
and binds tighter than or. Use parentheses to clarify:
$.a > 1 and ($.b > 2 or $.c > 3)TRILEAN truth tables
Trilean AND operation truth table
AND | true | false | unknown |
|---|---|---|---|
true | true | false | unknown |
false | false | false | false |
unknown | unknown | false | unknown |
Trilean OR operation truth table
OR | true | false | unknown |
|---|---|---|---|
true | true | true | true |
false | true | false | unknown |
unknown | true | unknown | unknown |
not(a): true → false; false → true; unknown → unknown.
Arithmetic
($.price * $.qty) > 1000($.apples + 5) > 10abs($.score - 50) < 10max($.a, $.b, $.c) > 100$.value % 2 == 0$.base:FLOAT ** 2.0 > 100.0| Operator | Operands | Result | Notes |
|---|---|---|---|
+ | INT or FLOAT (matching) | Same numeric type | Numeric addition |
+ | STRING (matching) | STRING | String concatenation |
- | INT or FLOAT (matching) | Same numeric type | |
*, /, % | INT or FLOAT (matching) | Same numeric type | % integer only |
** | FLOAT | FLOAT | Right-associative |
Type-directed +: when both operands are numeric, + adds (12 + 13). When both operands are STRING, + concatenates ($.first + ' ' + $.last, "Mr. " + $.name). A string literal anywhere in a + chain pins the chain to STRING; an all-bin string chain with no anchor is a parse error. Mixing incompatible types (for example $.a:INT + "x") is a type error. There is no standalone concat(), append(), or prepend() string method; use + or splice() (see String path functions).
Both operands must be the same type. Use toInt() / toFloat() to convert
between numeric types, or to cast a numerically-valued bin before comparison.
toInt() / toFloat() need a resolved receiver: a bare bin path with no
:INT/:FLOAT pin, and a bare numeric literal, are both unresolved as
method receivers, so pin the bin or parenthesize the literal first:
$.intBin:INT + $.floatBin:FLOAT.toInt()$.count:INT.toFloat() > 3.14(3.14).toInt() == 3toInt() / toFloat() converts between the two numeric types (INT ↔ FLOAT) and also parses numeric text out of STRING bins. A bin stored as the string "42" can be compared numerically with .toInt().
Integer division and %: when both operands of / are INT bins, AEL
performs true integer division, truncating any remainder, the same as most
programming languages: 7 / 2 evaluates to 3 (an INT), not 3.5. %
(modulo) also requires INT operands on both sides and always returns an
INT remainder. To get a fractional result instead, cast at least one
operand with .toFloat() before dividing: $.a.toFloat() / $.b.
Integer bitwise
Integer bitwise operators apply to whole 64-bit INT values (not BLOB bit ranges):
$.flags & 0xFF == 0x01$.mask | $.extra~$.bits$.value << 2$.value >> 1$.value >>> 1| Operator | Operands | Result |
|---|---|---|
&, ^, | | INT | INT |
~expr | INT | INT |
<<, >>, >>> | INT | INT |
>> is arithmetic shift; >>> is logical (zero-fill). &, ^, and |
share a single precedence level and are left-associative, the same as the
operator precedence table shows: a | b & c
evaluates as (a | b) & c, not a | (b & c). Parenthesize explicitly when
you need & or ^ to bind tighter than |.
Operator precedence
Lowest to highest binding. &, ^, and | share one precedence level and are left-associative:
| Level | Operators / forms |
|---|---|
| 1 | or |
| 2 | and |
| 3 | ==, !=, <, <=, >, >=, in, =~ |
| 4 | &, |, ^ (bitwise, left-associative) |
| 5 | <<, >>, >>> |
| 6 | +, - |
| 7 | *, /, % |
| 8 | ** |
| 9 | Unary ~, not(…), unary -, unary + |
| 10 | Primary: literals, paths, calls, (…) |
Comparisons are not chainable (a < b < c is a parse error).
Next steps
- Functions and terminals — record metadata, standalone functions, and path terminals
- Control structures and postfix flags —
when,let, and write-policy flags - Type inference and limits — how AEL resolves operand types