Jexata is the public facade. compile/2 checks source limits, tokenizes, parses, and returns an immutable Jexata.Expression containing an AST. evaluate/2 walks that AST against the supplied Elixir value. There is no global process or cache.
The tokenizer emits tokens with byte offsets. The parser uses precedence climbing for operators and builds tuple AST nodes. The optimizer prepares constant values and path and lambda metadata. The evaluator walks those nodes with a per-call context containing the root value and lexical bindings. It carries ancestry only for expressions that use parent navigation. Closures capture bindings for anonymous functions. Operators, higher-order functions, transforms, grouping, joins, ancestry, constructors, path selection, and regex callbacks live in focused evaluator modules. The built-in dispatcher delegates to small function groups.
The runtime value layer distinguishes undefined from JSON null (nil), and sequences from explicit arrays. At the public boundary, undefined becomes :undefined, a sequence of multiple values becomes a list, and an explicit array remains a list. public_root/1 collapses a top-level singleton sequence, while nested sequences inside $map retain their array boundary; this preserves $match results returned by callbacks. The semantics module owns boolean conversion, path selection, and basic comparison rules.
The implementation is pure Elixir and does not compile or evaluate user expressions as Elixir code. Compiled expressions are immutable and can be shared between BEAM processes. evaluate_bounded/3 runs a worker with time, heap, regex, result-size, optional AST-visit, collection-size, and reduction limits; ordinary evaluate/2 has no general step budget. CI enforces a 1,300-physical-line ceiling for every Elixir source file in lib/.