Skip to content

Engines ​

Handl engines are pluggable implementations of the language operations — lex, parse, transform, typecheck and eval. A language definition is data; an engine interprets that data. Swapping an engine therefore changes how a language runs, not what it means.

Every operation follows the same shape: a small abstraction crate owns the contract (§ marker type, request, trait, shared helpers) and one or more engine crates implement it. The kit decides which engine fills each slot.

The five operations ​

operationcontractengines
lexengine-lexengine-lex-pattern — data-driven rules
parseengine-parseengine-parse-pratt — Pratt, grammar rows
transformengine-transformengine-transform-rewrite — rule-interpreting
typecheckengine-typecheckengine-typecheck-nbe (NBE; private) + bootstrap in the contract crate
evalengine-execengine-exec-tree-walk — reference; engine-exec-bytecode — stack VM

Shared substrate ​

  • engine — Term, Model, and the arena view every engine uses.

Tools ​

These are engine-* repos that are not operation slots — they are rule-based tools over the same Language data:

toolwhat it does
engine-fmtdata-driven AST formatter (FormattingRule / PostProcessRule seams)
engine-lintrule-based linter (lang.lints + named native checks)
engine-exec-craneliftCranelift eval backend (JIT / object file)

engine-test is the test runner; it stays private while its corpus harness depends on the private kit closure.

How to read a crate here ​

Each engine repo publishes the same four quadrants: an overview (what it is), reference (the public API), how-to (task recipes) and explanation (why it is shaped that way). They carry no tutorials — end-to-end walkthroughs belong to the product that composes them, the Handl platform.

Design invariant ​

The reference interpreter is the oracle: engine-exec-bytecode must produce results identical to engine-exec-tree-walk, and its conformance suite enforces that. Optimisation is allowed to change speed, never meaning. The same rule holds for the other operations — a data-driven engine must not become a second definition of the language.