Skip to content
ALB Wiki

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 default
  • with ALBA_API — it links the runtime library, not a copy of it: alba_api.adb plus the alba_*_impl units (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_N procedure and stamps pragma 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_High on 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 serialization
  • ALBA_Sync_Frame_To_VAS — frame output synced into the virtual address space: the framebuffer as memory, the pattern the TypeScript backend's albVas mirrors
  • ALB_SIN/ALB_COS in integer degrees, ALB_ROL rotate-left, ALB_COLLIDE_RECT — the helpers a BASIC-flavored language is expected to have
  • ALB_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

References

  1. ALB Handbook — alb-lang.org/handbook — the language reference for all backends.
  2. ALB Technology page — alb-lang.org/technology — the sixteen-backend matrix.
  3. ALB source — github.com/rockyoliver454/AdaLogic-BASIC-ALB-Programming-Language — the emitter sources are Apache 2.0.
Categories: AdaLogic BASIC · Backends
This page was last edited 2026-10-20 13:00:48 UTC by ALB Team. What links here