Orb Concepts in Zorb

Copy Markdown View Source

Zorb uses the Orb DSL to compile Z-machine stories into WebAssembly. This document covers the Orb concepts the codebase relies on.

1. Module Composition

A capsule is assembled from three pieces:

  • Interpreter engine: lib/zorb/interpreter.ex, read and quoted at build time by the assembler in lib/zorb/capsule/assembler.ex.
  • Host imports: lib/zorb/capsule/host.ex declares the zio namespace and is attached to the generated module with Orb.Import.register/1.
  • Story data: header fields, dictionary hash tables, and story memory, injected as literals into the module.

Version-specific interpreter branches are pruned from the quoted AST before the story data is added, so each capsule only contains code its version can reach.

2. Elixir Compiler Integration

Zorb transforms the interpreter AST with ordinary Elixir metaprogramming (quote, pattern matching, Macro) — there is no source-code round trip. Assembler.assemble/2 returns a final AST that is evaluated with Code.eval_quoted/3, which means dictionary hashing, version pruning, and story-data embedding all run while the capsule module is being compiled.

3. Custom Types

Orb allows defining custom types via the Orb.CustomType behaviour. These types map to underlying WebAssembly primitives (like :i32) but provide Elixir-side type safety and clarity. In Zorb, we use these for:

  • T.Address: Ensuring memory offsets are correctly handled.
  • T.Variable: Clarifying when an integer represents a Z-machine variable index.
  • T.Object: Distinguishing object IDs from raw numbers.

These types exist only at compile-time and do not introduce any runtime overhead in the final WebAssembly binary.