| | {{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. |
| + | 3. ALB source — github.com/rockyoliver454/AdaLogic-BASIC-ALB-Programming-Language — the emitter sources are Apache 2.0. |
| + | |
| | [[Category:Backends]] |
| | [[Category:AdaLogic BASIC]] |
| | |