The stack VM

The engine that runs the language.

Shape

A chunk of bytecode per compiled unit, executed against a value stack, with a frame per call recording where to return and where its locals live.

Ecko's VM is not trying to be a JIT. It is a straightforward, carefully tuned bytecode interpreter, on the reasoning that most Ecko programs are dominated by IO - model calls, HTTP, SQL - and that a predictable interpreter is worth more than a complicated compiler.

Spans and call stacks

Instructions carry source positions, so a runtime error reports the expression that raised it and the chain of calls that reached it. This survives through pipelines, pmap and spawned tasks.

try/catch frames

try pushes a handler frame. Raising unwinds to the nearest one, running finally blocks on the way out. return, break and continue unwind through a try without being caught, because they are not errors.

Superinstructions

Common instruction sequences are fused into single operations. This is the main structural optimization: it removes dispatch overhead from the hot paths that appear in every program - field access, comparison-and-branch, local arithmetic.

The lesson from tuning it, worth passing on: micro-optimizations were noise and structural changes were real. Removing an allocation from a hot loop, or a whole layer of indirection from a call path, moved the numbers; shaving instructions did not.

Bounds

ECKO_MAX_DEPTH (default 2000) caps call depth, so runaway recursion is a catchable error rather than a process death. ECKO_MAX_STEPS is an opt-in step budget. See Resource limits.

Parity

Every VM change is checked against the AST evaluator on the same programs, and a compat suite of frozen programs with golden output guards against behaviour drift between releases. A golden file changes only through a deliberate, documented breaking decision.