Skip to main content

core.script — Verum as its own scripting language

A host Verum program can compile and run Verum scripts at runtime, in-process, on the same VBC interpreter the host itself runs on.

This is the capability a game engine gets from embedding Lua — user content that ships after the binary does — with one difference that shapes the whole design: there is no second virtual machine, heap, or sandbox. Script and host are the same execution model, so the boundary that usually costs marshalling costs nothing to cross.

mount core.script.{Engine, ScriptValue, ScriptResult};

let engine = Engine.new();
match engine.eval(user_script) {
ScriptResult.Ok(ScriptValue.Int(n)) => use_result(n),
ScriptResult.Err => report_failure(),
_ => {},
};

Layout​

FileLinesWhat's in it
engine.vr431Engine, Session, World, ScriptValue, ScriptResult, ErrorKind
mod.vr44Re-exports; declares public module engine

The three affine handles​

Engine, Session and World are all declared affine, which is what makes lifetime management disappear from the caller's code: a handle is used at most once along any path, so the compiler knows exactly where it dies.

Engine is the compile-and-run surface. It owns the interpreter handle and is freed automatically when it goes out of scope — no explicit teardown, no leak on an early return.

Session is obtained from Engine.link2 and holds state across calls. Globals and heap written by an earlier call are visible to later ones, shared by reference rather than copied. This is the shape you want for a REPL, a modding API, or anything where scripts accumulate context.

World carries the shared environment scripts observe.

Why sharing works here and not elsewhere​

Because host and script run on one interpreter, values cross the boundary by reference. Boundary-crossing engines — Wasm, BEAM, V8 — cannot offer this: their guest heap is a separate address space, so every value is copied or proxied.

The source notes that scalars and Text share correctly today through the World table. That qualifier matters: it describes the shared environment, not every boundary crossing. Passing arguments to a call is a separate path — Engine.call_args currently carries self-contained scalar values, and Text, List and Map arguments need reconstruction on the script side that is not wired yet. So a Text visible through the shared world is not the same as a Text handed over as a call argument.

Richer structures generally are the area to check against the sources before relying on them, which the status above already implies: with no core-tests/script/ suite, the guarantee is what the implementation does, not what a conformance run has confirmed.

Status​

There is no conformance suite for this module. The public surface above is read from the sources; runtime behaviour across tiers has not been validated the way regression-only and partial modules have. Treat the API as documented-but-unpinned until a core-tests/script/ suite lands.