| | {{infobox |
| | | title = ALB TypeScript backend |
| | | tool = `albw.exe` ("ALBW — AdaLogic BASIC for the Web") |
| | | produces = TypeScript (.ts) → JavaScript + index.html + tsconfig |
| | | runs_on = Any modern browser · Node.js |
| | | output_dir = `web_<name>/` |
| | | emitter_unit = `Emit_Native_TypeScript` (emit_native_typescript.adb) |
| | | status = Full web backend — games, documents, ES/WASM libraries |
| | }} |
| | |
| | The **ALB TypeScript backend** — **ALBW** — compiles [[AdaLogic BASIC]] into a self-contained TypeScript program that runs in any browser or under Node.js. It is the backend that makes an ALB game a *web page*: canvas graphics, a real console, chiptune audio, files, and the full logic engine — all inside a single emitted `.ts` file. |
| | |
| | ```alb One-liner |
| | albw game.alb --build |
| | → web_game/game.ts → tsc → game.js + index.html + tsconfig.json |
| | ``` |
| | |
| | # The pipeline |
| | |
| | Unlike the streaming emitters behind [[ALB FASM backend|FASM]] and [[ALB C backend|C]], ALBW's emitter takes the **whole AST** in one call — `Compile_To_File (Root : AST_Node)` — and walks it directly: it owns a symbol table, scopes names (`Safe_JS_Name`, `Scoped_Name`), evaluates constants at emit time, and emits TypeScript source. Different architecture, same language. |
| | |
| | | Flag | What it does | |
| | | --- | --- | |
| | | `-o <file>` | Output .ts path (default: derived from input name) | |
| | | `--outdir <dir>` | Output directory | |
| | | `--tsc` | Also run tsc — .ts → .js | |
| | | `--target <ver>` | TypeScript target: `es5`, `es2020` (default), `esnext` | |
| | | `--build`, `-b` | Full build: transpile + tsc + index.html shell | |
| | | `--library`, `-l` | Shared module build — no HTML shell (for `EXPORT_ES`/`EXPORT_WASM`) | |
| | | `--metrics`, `-m` · `--walker`, `-w` · `--quiet`, `-q` | Metrics · AST dump · silence | |
| | |
| | A `--build` folder is a complete, openable website: the emitted `.ts`, a generated `tsconfig.json` (`strict: false`, `noCheck: true` — the generated code is already correct; the checker just gets in the way), and an `index.html` that loads the script — as a plain script or an ES module, depending on the program. |
| | |
| | # A computer inside a file |
| | |
| | The generated file is not a thin translation — it emits an entire **runtime machine**, expressed as typed arrays so the JIT keeps it fast: |
| | |
| | ```ts |
| | const albKeys = new Uint8Array(512); // keyboard state |
| | const albMouseButtons = new Uint8Array(8); |
| | const albVas = new Int32Array(65536); // virtual address space |
| | const albGcAlive = new Uint8Array(1024); // object grid, alive flags |
| | const albGcRefs = new Uint16Array(1024); // refcounts |
| | const albGcChildA … albGcChildD // four child links per node |
| | ``` |
| | |
| | It is the same architecture as the [[ALB C backend|C]] and [[ALB FASM16 backend|FASM16]] Dumptruck — same node grid, same refcount contract — ported to the substrate JavaScript gives you: `Uint8Array` and `Int32Array` instead of structs. |
| | |
| | - **Sized integers, emulated** — `albU8`/`albU16`/`albU32` mask; `albI8`/`albI16`/`albI32` sign-extend. ALB's sized type system behaves correctly on a language with only `number` |
| | - **PURE, packed into one f64** — `albPurePack` encodes an exact rational (numerator+denominator, gcd-reduced, graceful shrink on overflow) into a single JavaScript number |
| | - **Division semantics** — `albDiv`/`albMod` truncate like integer division should; divide-by-zero yields 0 rather than crashing a browser tab |
| | - **Integer powers** — `albPowInt` does exponentiation by squaring, the way you teach it |
| | - **A working logic engine** — `albFact*` fact store plus `albRel*` relation tables and `albRule*` **rule records with bodies** (head predicate, body length, body terms, arg modes) — Prolog, in the browser |
| | |
| | # The console overlay |
| | |
| | `PRINT` in a browser has nowhere to go — so ALBW builds one. The emitted runtime injects a console: a `<div>` containing a `<pre>`, monospace on `#050511`, that pins itself to the bottom 40% of the viewport when a canvas is active (fullscreen otherwise): |
| | |
| | ```ts |
| | function albWriteText(text) { … albTextRows[row] = |
| | padded.slice(0, col) + ch + padded.slice(col + 1) … } |
| | ``` |
| | |
| | Underneath the div is a **character-grid text model** — `albTextRows`, an x/y cursor, `padEnd` for sparse writes — so `LOCATE`-style text behaves like a real terminal, not like `console.log`. `MODE NO CONSOLE` or the `--no-console` path disables it for programs that want only graphics. |
| | |
| | # The frame loop — events are real |
| | |
| | ALB's event-driven model maps directly onto the browser's: |
| | |
| | ```ts |
| | function ALB_RunFrame(now) { |
| | if (!albRunning) { ALB_ProgramShutdown(); return; } |
| | requestAnimationFrame(ALB_RunFrame); |
| | if (now < albDelayUntil) return; |
| | if (now - albLastFrame < albFrameInterval) return; |
| | try { ALB_PREPARE_FRAME(); ALB_ON_TICK(); ALB_ON_PAINT(); } |
| | catch (err) { ALB_FATAL(err); } |
| | } |
| | ``` |
| | |
| | `requestAnimationFrame` drives the loop; `ON TICK` and `ON PAINT` become literal emitted functions; `DELAY` is a deadline check; frame-rate throttling is a comparison. A BASIC event loop and a browser event loop turn out to be the same idea wearing different clothes. |
| | |
| | # Graphics and sound |
| | |
| | - **Canvas** — `HTMLCanvasElement` + `CanvasRenderingContext2D`, base framebuffer **320×200** (yes, the classic resolution), scaled to the window with correct mouse-coordinate transform, and a color LUT (palette entries evaluated at compile time) |
| | - **Colors** — `albColorToCss` unpacks a packed RGBA `u32` into `rgba(r,g,b,a)` — the same 0xAABBGGRR value every backend understands |
| | - **PC speaker chiptune** — `albPcSpeakerTone` drives a WebAudio **square-wave oscillator** with an attack-hold-release gain envelope: real retro beeps, polyphonic via `albActiveMusicVoices` (live `[OscillatorNode, GainNode]` pairs, reaped on `ended`) |
| | - **Music** — `ALB_PLAY_MUSIC_FROM` fetches an ALB score file and plays it — the notation survives the journey to the web |
| | |
| | # Files in a browser (and Node) |
| | |
| | Browsers can't open files — so the backend emits a **virtual file table**: 64 handles (`albFileLive`, `albFileName`, `albFileBuffer`, `albFileCursor`) over a `albSaveStore` object, with real `ALB_Open`/`Read`/`Write`/`Seek`/`Close` semantics. Writes persist into the store on close. |
| | |
| | Then the clever bit — the *same emitted file* detects Node.js: |
| | |
| | ```ts |
| | const nodeProcess = globalThis.process; |
| | if (nodeProcess?.versions?.node) |
| | buf = eval('require')('fs').readFileSync(path, 'latin1'); |
| | ``` |
| | |
| | In a browser, files are virtual. Under `node game.js`, they're real — one source, two worlds, literally. |
| | |
| | # The serious machinery |
| | |
| | ```fact Not a toy |
| | **A capability firewall** — `albFirewallStack` with per-frame read/write allow tables on file names; **a network sniffer** — `ALB_SNIFFER_DEFINE` builds live objects with protocol, port, buffer size, and an error cell for `AST_Network_Sniffer_Decl`; **sockets** — channel keys like `ALB_NET_<proto>_<port>`; **fetch()** wired into the runtime; **`albPromptContext`** — the last 18 console lines assembled as context for AI-prompt features. |
| | ``` |
| | |
| | # It even learns |
| | |
| | The language-level learning statements work here too: `ALB_NN_CREATE`, `ALB_NN_SEED`, `ALB_NN_INFER`, `ALB_NN_TRAIN`, `ALB_NN_ACT`, and `ALB_MARKOV_PREDICT` are emitted as TypeScript functions for `NEURAL TOPOLOGY`, `TRAIN NETWORK`, `INFER NETWORK`, `MARKOV MODEL`, and `PREDICT MARKOV`. Deterministic weight seeding means a program's net starts identically in a typed-array browser runtime as it does in the [[ALB FASM backend|x86-64 asm]] or [[ALB C backend|C]] builds — train a model on the desktop, deploy it to a page. (One learning feature stays native: `EMOTION` is FASM-only.) |
| | |
| | # Modes and library exports |
| | |
| | - **`MODE DOCUMENT`** in the source flips the generated `index.html` from the dark game shell to a light document shell — the same language emits *games* or *pages* |
| | - **`EXPORT_ES` / `EXPORT_WASM`** with `--library` emit a module-aware build (no HTML shell, `module: es2020` tsconfig) — ALB programs compiled into importable web libraries; the foreign-export table is sized to match `albt`'s `Max_Foreign_Exports` so even the full-engine `libgamedeck` façade fits one weave |
| | |
| | # Under the hood |
| | |
| | `Emit_Native_TypeScript` is ~7,000 lines of SPARK-annotated Ada — second in size only to the [[ALB Ada backend|Ada emitter]] — driven by `albw.adb`, which handles flags, the tsconfig writer, the HTML shell writer, and the tsc/package dance. Where the native backends stream tokens into buffers, this one is an **AST interpreter that prints TypeScript**: it sees the whole program before it writes a line. |
| | |
| | # See also |
| | |
| | - [[AdaLogic BASIC]] — the language |
| | - [[ALB C backend]] · [[ALB FASM backend]] · [[ALB FASM16 backend]] — the native siblings |
| | - [[History of Programming]] — JavaScript's chapter in the arc |
| | - [[Z3]] · [[Manchester Baby]] — the web page as a machine, then and now |
| | |
| | # 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]] |
| | |