ALB Ada backend
The ALB Ada backend — ALBA — compiles AdaLogic BASIC into Ada: the language the entire toolchain itself is written in. Every other backend is a translation; this one is a homecoming. It produces real, idiomatic Ada — modular types, digits floats, SPARK annotations, a .gpr project — and it is the largest single emitter in the set at over twelve thousand lines.
Why Ada matters here
ALB's design DNA — sized types, ranges, contracts, the hardened runtime, refusal to corrupt onward — is Ada's design DNA. Every backend has to translate those guarantees: FASM hand-builds trap stubs, C lowers TRY/CATCH to setjmp. The Ada backend mostly just writes them down: range checks, strong typing, and explicit unchecked operations are things Ada already has words for.
The emitted program is a real package
An ALB program doesn't flatten into a main() — it becomes a named Ada package with SPARK mode declared:
pragma SPARK_Mode (On);
with ALBA_API; use ALBA_API;
package My_Program with SPARK_Mode => On is …
package body My_Program is …
pragma SPARK_Mode (On)on the emitted unit — the generated code participates in SPARK's analysis regime by defaultwith ALBA_API— it links the runtime library, not a copy of it:alba_api.adbplus thealba_*_implunits (audio, gc, graphics, io, logic, runtime) living beside the driver- Unsafe blocks stay fenced — when ALB source needs raw memory work, the emitter carves a named
ALBA_Unsafe_Block_Nprocedure and stampspragma SPARK_Mode (Off)inside it — the unsafe region is a labeled island, not a leaked privilege
Types the Ada way
The runtime defines ALB's type system in textbook Ada — not typedef int8_t, but the real things:
type U8 is mod 2 ** 8; for U8'Size use 8;
type S64 is range -(2 ** 63) .. (2 ** 63) - 1; for S64'Size use 64;
type F32 is digits 6; for F32'Size use 32;
And ALB's bitwise operators on signed types — and/or/xor/not — are emitted the honest Ada way: Ada.Unchecked_Conversion to the modular twin, the bitwise op, convert back. Unsafe, named, and confined — which is exactly how Ada thinks unsafe should work.
The | concat operator becomes overload resolution:
function ALB_CAT (Left : ALB_Text; Right : S32) return ALB_Text;
function ALB_CAT (Left : U64; Right : ALB_Text) return ALB_Text;
function ALB_CAT (Left : ALB_Text; Right : Pure_Rational) …
Every operand pairing gets a real overload — Pure_Rational included, as a first-class Ada type with ALB_PURE_ADD/SUB/MUL/DIV/POW and NUM/DEN accessors.
A different breed of emitter
Like the TypeScript backend, ALBA is an AST-walker, not a streaming emitter: Emit_Program receives the tokens, the tree, and the root, then analyzes the whole program — but the analysis here goes deep. Inside one procedure live full semantic tables:
- 16,384 symbols, 8,192 routines, 512 fields, 128 structs, 2,048 constants — with
Has_Range/Range_Low/Range_Highon every symbol, so declared ranges survive into the emitted type system - Static constants evaluated at emit time (
Has_Static_Value) - Temporal symbols, alias resolution, module scoping, struct serialization helpers
pragma Import (C, …)emission for foreign routines — the FFI is Ada's own import pragma
--build then writes a proper GNAT project (for Languages use ("Ada"), for Object_Dir use "obj") and invokes gprbuild — or gnatmake with --gnatmake. This backend doesn't borrow another toolchain's linker; it speaks Ada's own build system.
The runtime surface — including the learning layer
NEURAL TOPOLOGY, TRAIN NETWORK, INFER NETWORK, MARKOV MODEL, and PREDICT MARKOV are language-level statements, and ALBA implements them like every serious backend — but in its own dialect. The ALB FASM backend forges hand-written x86-64 ALB_NN_* labels, the ALB C backend emits static C twins, the ALB TypeScript backend emits typed-array functions — and ALBA emits them as readable Ada procedures: ALB_NN_CREATE (layer sizes + activation codes), ALB_NN_INFER (forward pass), ALB_NN_TRAIN (epochs against expected data), ALB_NN_SEED (deterministic weight init), ALB_NN_ACT (activation by code), and ALB_MARKOV_PREDICT. Same feature, same deterministic seeding — just visible as named, SPARK-scoped Ada instead of asm or generated C.
Around that shared core, the ALBA runtime adds its own territory:
- **
ALB_NET_*** — real sockets:DEFINE,LISTEN_SOCKET,RECEIVE,SEND,CLOSE ALBA_Save_State/ALBA_Load_State— whole-program state serializationALBA_Sync_Frame_To_VAS— frame output synced into the virtual address space: the framebuffer as memory, the pattern the TypeScript backend'salbVasmirrorsALB_SIN/ALB_COSin integer degrees,ALB_ROLrotate-left,ALB_COLLIDE_RECT— the helpers a BASIC-flavored language is expected to haveALB_Peek_Address/ALB_Poke_Address/ALBA_Deref_Address— and they're emitted as named functions, so every bare-metal access is findable in the generated source
The oracles
When parsing fails, alba doesn't say "syntax error" — it reports an oracle code (ALBA: oracle code <n>) from the lexer/parser diagnostics. The compiler tells you which oracle was offended.
Under the hood
Emit_Native_Ada (~12,300 lines, pragma SPARK_Mode (On) — even the emitter's spec is annotated) is driven by alba.adb: flags (-o, --outdir, --build, --gprbuild/--gnatmake), the .gpr writer, the runtime-directory staging, and the build invocation. It is the only backend whose output a SPARK prover could, in principle, read.
See also
- AdaLogic BASIC — the language
- ALB FASM backend · ALB C backend · ALB FASM16 backend · ALB TypeScript backend · ALB NASM backend
- Ada Lovelace — the namesake at the top of the tree
- History of Programming — where Ada (the language) sits in the arc
References
- ALB Handbook — alb-lang.org/handbook — the language reference for all backends.
- ALB Technology page — alb-lang.org/technology — the sixteen-backend matrix.
- ALB source — github.com/rockyoliver454/AdaLogic-BASIC-ALB-Programming-Language — the emitter sources are Apache 2.0.