Skip to content
ALB Wiki

ALB Lua backend

This is an old revision of this page — revision 1 (2026-10-10 21:11:22 UTC). It may differ from the current revision.

The ALB Lua backend — ALBL — compiles AdaLogic BASIC into one self-contained .lua file: program, runtime, and all. No compiler is needed where it lands — drop it next to alb_sdl3.dll and SDL3.dll, run lua program.lua (or luajit), and a BASIC program with a Prolog engine and a framebuffer comes alive inside the most embeddable scripting runtime ever made.

Why Lua, and why it works

Lua's proposition is unique among the backends: the emitted file is portable source that runs anywhere a Lua interpreter lives — game engines with Lua scripting, mods, tools, embedded hosts. The emitted header says it plainly: "self-contained Lua 5.1+/LuaJIT runtime" — the file doesn't even insist on LuaJIT; plain Lua 5.1 and up will do.

The catch — that Lua is a small language — is exactly where the emitter earns its keep. Everything ALB needs that Lua doesn't have gets built out of Lua tables.

A computer inside a script

The runtime reconstructs ALB's machinery the way the TypeScript backend does it in typed arrays — here, in plain tables:

  • albVas — the virtual address space: framebuffer and memory-mapped state as a Lua table
  • albGcAlive / albGcRefs / albGcChildA–D — the Dumptruck claim-grid, running inside Lua's own garbage collector (two collectors, one process)
  • albTextRows + a cursor — the console-overlay model: PRINT writes to a character grid, LOCATE positions the cursor — a terminal inside the window, killed only by MODE NO CONSOLE in source
  • albSaveStore + ALB_serialize_state/ALB_deserialize_state — whole-program SAVE STATE/LOAD STATE, Lua-side
  • PURE arithmetic, for real — albPureGcd reduces rationals properly; PURE_ADD/SUB/MUL/DIV/POW keep numerator and denominator separate so ⅓ stays exactly ⅓
  • 64-bit-safe math shims — albDiv, albMod, albPowInt, ALB_shl/shr — because Lua numbers are doubles and precision past 2^53 is a cliff, the emitter implements sized-integer ops as algorithms instead of trusting the operators
  • The capability firewall — ALB_FIREWALL_ENTER/LEAVE/READ/WRITE/TOUCH with per-frame allow tables — in a scripting language, where sandboxing is the whole point
  • ALB_KNOWS_GET/HAS/SET — the Knows store
  • INI files, PPM export, ALB_FILE_XOR, bitmap/system fonts — the file-and-format suite didn't get left behind either

The Logic pillar, with rules

This backend doesn't ship a toy Prolog — it ships the rule engine:

local albRelPred = {}; local albRelArity = {}
local albRelArg1 = {}; local albRelArg4 = {}
local albRuleHeadPred = {}; local albRuleBodyLen = {}
local albRuleBodyPred = {}; local albRuleBodyArgMode = {}

Facts live in one table family (albRel*), rules in another — albRuleHeadPred (the rule's head predicate), albRuleBodyLen and albRuleBodyPred/ArgMode (the body, with per-argument modes). ALB_INIT_LOGIC wires it up; AST_Logic_Var handles real unification variables; watch nodes re-evaluate when the KB changes. The Logic in AdaLogic BASIC, running in a language that fits in a few hundred kilobytes.

The alb_sdl3 bridge

Graphics and input don't use LuaJIT's FFI at all — both script backends share one design: alb_sdl3.dll, a Lua C-module loaded by name:

local ok, mod = pcall(require, "alb_sdl3")
if not ok then ALB_FATAL("ALBL requires alb_sdl3.dll next to the .lua (and Lua 5.4).") end
albSDL = mod
albSDL.init()

One bridge, one call surface — create_window, prepare_frame, color, clear, plot, draw_rect, fill_rect, draw_line, ticks — behind which SDL3.dll does the actual work. Lazy-loaded via albEnsureSDL() so programs that never draw never pay for it, and pcall wraps the load so the failure message is friendly.

The game loop

ON TICK / ON PAINT / ON KEY blocks become literal Lua functions wired into a while ALB_Running loop that pumps the bridge's event queue — the same frame model as every other backend, expressed in local functions and tables.

Flags and output

-o, --outdir, --metrics, --walker, --quiet; --build stages SDL3.dll + a run.bat beside the .lua in lua_<name>/; --run finds luajit.exe (deps tree or PATH) and runs it in place.

Under the hood

Emit_Native_Lua (~8,500 lines, SPARK-annotated) is the AST-walker architecture: Compile_To_File(Root, Output_Filename) receives the whole tree and walks it top-down — the same shape as the TypeScript and Ada emitters, and literally mirrored by the MoonScript sibling, which shares the runtime design, the bridge, and most of its source structure.

See also

Categories: AdaLogic BASIC · Backends
This page was last edited 2026-10-10 21:11:22 UTC by Anonymous. What links here