Skip to content
ALB Wiki

Diff — ALB Ada backend

Comparing rev 4 → rev 5

{{infobox
| title = ALB Ada backend
| tool = `alba.exe` ("ALBA — AdaLogic BASIC for Ada")
| produces = Ada source (.adb) + generated .gpr project
| builds_with = `gprbuild` (default) · `gnatmake`
| emitter_unit = `Emit_Native_Ada` (emit_native_ada.adb) — ~12,300 lines
| runtime = `ALBA_API` package + `alba_*_impl` units
| status = The native-tongue backend — the toolchain's own language
}}
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.
```alb One-liner
alba tool.alb --build
→ tool.adb + alba.gpr + ALBA_API units → gprbuild → tool.exe
```
# 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:
```ada
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:
```ada
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:
```ada
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 [[ALB TypeScript backend|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
```fact The lineage joke that isn't a joke
Ada was named for [[Ada Lovelace]]; ALB's toolchain is written in Ada; ALBA turns ALB back into Ada. Three generations of "write it down so the machine checks it" — from the Analytical Engine's notes to `pragma SPARK_Mode`.
```
# 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
-
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.
+
1. ALB Handbook — [alb-lang.org/handbook](https://alb-lang.org/handbook) — the language reference for all backends.
+
2. ALB Technology page — [alb-lang.org/technology](https://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.
[[Category:Backends]]
[[Category:AdaLogic BASIC]]