This document describes the GEL Evaluator — a core component of the General Expression Language (GEL) runtime. It assumes familiarity with the GEL manual describing the lexer, parser, and abstract syntax tree (AST).
The GelEvaluator
class processes a parsed GEL AST and executes it against
a data record. It supports both strict and non-strict evaluation modes. In strict mode, missing
fields cause an exception; in non-strict mode, they are treated as "missing value" and evaluate
to false or undefined, depending on context.
This evaluator supports asynchronous function calls, enabling integration with external APIs or asynchronous computations.
Once an expression string is parsed (into an Expression
AST),
the GelEvaluator
traverses that AST to produce a final value. The evaluator:
field_reference
nodes against a data record.and
, or
, not
) and comparison (eq
,
lt
, etc.) operations.
[*]
subscripting, producing array outputs when appropriate.strictEval = false
.
Below is a summarized API reference for GelEvaluator
. For more detail, see
Section 4.
Method | Signature | Description |
---|---|---|
evaluateRule |
(expr, data, strictEval) => Promise<boolean> |
Evaluates an expression as a boolean rule. Returns true or false .strictEval controls error-handling for missing fields.
|
evaluateTransform |
(expr, data, strictEval) => Promise<unknown> |
Evaluates an expression as a transform. Returns any value ( number , string , boolean , array ,
etc.).Missing data in non-strict mode yields undefined .
|
evaluateExpressionAsValue |
(expr, data, strictEval) => Promise<unknown> |
Internal helper. Recursively evaluates the AST node, returning a single result or array result. |
evaluateSubscript |
(node, data, strictEval) => Promise<unknown> |
Evaluates arr[index] , obj[key] , or arr[*] patterns.Throws (strict mode) or returns missing sentinel (non-strict) if invalid. |
evaluateFunctionCall |
(node, data, strictEval) => Promise<unknown> |
Invokes the appropriate function from the config registry, passing in evaluated arguments. Supports element-wise mapping if an argument uses [*] subscript.
|
evaluateComparison |
(node, data, strictEval) => Promise<boolean|boolean[]> |
Evaluates operators like eq , in , has , etc.May produce a single boolean or an array of booleans for wildcard comparisons. |
evaluateLogical |
(node, data, strictEval) => Promise<boolean> |
Evaluates and , or , and possible not negation flags.Uses evaluateRule internally to get a boolean from sub-expressions.
|
The GelEvaluator
includes various methods to navigate and compute values from AST nodes.
Each node type from the GEL manual is handled in evaluateExpressionAsValue
via
a switch
statement:
private async evaluateExpressionAsValue(
expr: Expression,
data: Record<string, unknown>,
strictEval: boolean
): Promise<unknown> {
switch (expr.type) {
case "literal":
return expr.value;
case "field_reference":
return this.getFieldValue(expr, data, strictEval);
case "inset":
// Evaluate each item in the set
return Promise.all(expr.values.map(...));
case "subscript":
return this.evaluateSubscript(expr, data, strictEval);
case "function_call":
return this.evaluateFunctionCall(expr, data, strictEval);
case "comparison":
return this.evaluateComparison(expr, data, strictEval);
case "logical":
return this.evaluateLogical(expr, data, strictEval);
default:
throw new Error("Unknown expression type");
}
}
Many evaluation paths check strictEval
to decide how to respond to missing fields or
invalid indexes:
UndefinedFieldError
) so the caller
is aware of incomplete data.Symbol("MISSING_VALUE")
),
which eventually yields false
(for rules) or undefined
(for transforms).
arr[*]
)
[*]
patterns produce an array of results when indexing. If a function argument
has [*]
, the evaluator maps that function call over each element of the array. The
final returned value is an array of results.
The config
object defines available functions. evaluateFunctionCall
looks up
the function by name, then calls it asynchronously:
const fn = this.config.functions[node.functionName];
const argVals = await Promise.all(node.args.map(...));
const result = await fn.apply(null, argVals);
The GelEngine
is a higher-level utility class that combines parsing (from the other manual)
and evaluation in one object:
boolean
).{{ expr }}
placeholders in a text template,
substituting evaluated results.
Note: The GelParser
is documented in the main GEL Technical Manual. In
GelEngine
, we see how the parser and evaluator integrate:
public parse(input: string): Expression {
const parser = new GelParser(input, this.config);
return parser.parse();
}
public evaluate(
rule: Expression,
data: Record<string, unknown>,
strictMode: boolean
): Promise<boolean> {
return this.evaluator.evaluateRule(rule, data, strictMode);
}
// 1) Parse the expression into an AST
const parser = new GelParser("not user.is_admin eq true", config);
const ast = parser.parse();
// 2) Evaluate as boolean
const evaluator = new GelEvaluator(config);
const result = await evaluator.evaluateRule(ast, { user: { is_admin: false } }, false);
// => true
const expr = parser.parse("file.extension eq 'exe'");
const resultStrict = await evaluator.evaluateRule(expr, {}, true);
// => throws UndefinedFieldError
const resultNonStrict = await evaluator.evaluateRule(expr, {}, false);
// => false (missing => false in non-strict mode)
const expr = parser.parse("any(process.args[*] eq '--verbose')");
const data = {
process: { args: [ "--help", "--verbose", "--quiet" ] }
};
const result = await evaluator.evaluateRule(expr, data, false);
// => true (one of the elements matched eq '--verbose')
Errors thrown by the evaluator include:
UndefinedFieldError
: Thrown in strict mode if a required field is missing.Error
: Generic runtime issues, e.g. invalid array indexing or unknown function calls.In non-strict mode, the evaluator uses an internal missing value sentinel to avoid throwing. This sentinel eventually resolves to:
false
when evaluating boolean rules.undefined
when evaluating transforms.Reference | Description | Link |
---|---|---|
engine.ts | Higher-level GelEngine showcasing parsing + evaluation. |
View Code |