Skip to content

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
OperatorOperand typesResult
==, !=, <, <=, >, >=Same type both sidesTRILEAN
expr in listExprRight side evaluates to LISTTRILEAN
stringExpr =~ /pattern/[/flags]Left side STRING; Perl-compatible regexTRILEAN

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 > $.binB

Comparisons 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 $.allowedTiers

The 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)
FormOperandsResult
a and bTRILEANTRILEAN
a or bTRILEANTRILEAN
not(expr)TRILEANTRILEAN
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

ANDtruefalseunknown
truetruefalseunknown
falsefalsefalsefalse
unknownunknownfalseunknown

Trilean OR operation truth table

ORtruefalseunknown
truetruetruetrue
falsetruefalseunknown
unknowntrueunknownunknown

not(a): true → false; false → true; unknown → unknown.

Arithmetic

($.price * $.qty) > 1000
($.apples + 5) > 10
abs($.score - 50) < 10
max($.a, $.b, $.c) > 100
$.value % 2 == 0
$.base:FLOAT ** 2.0 > 100.0
OperatorOperandsResultNotes
+INT or FLOAT (matching)Same numeric typeNumeric addition
+STRING (matching)STRINGString concatenation
-INT or FLOAT (matching)Same numeric type
*, /, %INT or FLOAT (matching)Same numeric type% integer only
**FLOATFLOATRight-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() == 3

toInt() / 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
OperatorOperandsResult
&, ^, |INTINT
~exprINTINT
<<, >>, >>>INTINT

>> 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:

LevelOperators / forms
1or
2and
3==, !=, <, <=, >, >=, in, =~
4&, |, ^ (bitwise, left-associative)
5<<, >>, >>>
6+, -
7*, /, %
8**
9Unary ~, not(…), unary -, unary +
10Primary: literals, paths, calls, (…)

Comparisons are not chainable (a < b < c is a parse error).

Next steps