bcgen-lang 0.2.0

Compiles HIR to LSB bytecode: the path from a forged language's meaning to code bvm-lang runs.
Documentation
# bcgen-lang - Roadmap


> Path from scaffold to a stable 1.0. Hard parts are front-loaded; each phase has hard exit criteria.
> Master plan: ../_lexersketch/ROADMAP.md and ../_lexersketch/NEW-LIBS.md
>
> **Anti-deferral rule:** no listed hard task moves to a later phase unless this file records the move and the reason.

## v0.1.0 - Scaffold (DONE)

Compiles, CI green, structure correct, no domain logic.
- [x] Manifest, README, CHANGELOG, REPS, dual license, CI, deny, clippy, rustfmt, DIRECTIVES, ROADMAP.

## v0.2.0 - Foundation (DONE)

- [x] Dynamic-profile compilation of the HIR core (functions, closures, locals, control flow, calls incl. named/default/variadic, maps/arrays/strings, dynamic ops with OPS policies, exceptions with finally), debug line tables, differential tests against a reference HIR interpreter in tests.
- [x] Wires hir-lang and bytecode-lang; bvm-lang as a dev-dependency for execution tests.

Delivered:
- `compile`, `Compiler`, `Options`, `ArraySemantics`, `KeyCoercion`,
  `BodyMode`, `Compiled`, `Locate`, `Location`, `LineIndex`, `CompileError`,
  `Unsupported`.
- Code generation as an explicit task stack (no recursion over the input),
  registers and call windows pooled per type and shape, binders freed at
  scope end, an instruction budget.
- Calling convention: direct calls arranged at compile time (a presence mask
  for defaults), an argument packet for every function value, unpacked by a
  prologue with the same binding rules; host calls through imports; method
  calls through `get_prop` with the receiver first.
- Closures (explicit, implicit, self-binder captures; by value or by cell),
  shared locals in cells, `global`/`static` (cells when shared by
  reference), by-reference parameters and reference assignment between
  variables.
- Control flow, sequential `match` over every pattern the dynamic profile can
  test, let-else; `throw`, `try`/`catch`/`finally` by the canonical lowering
  (LSB section 4.3), `defer`.
- Every OPS op on `dyn` values with its policy (`promote` included),
  conversions, casts; PHP arrays (value semantics, auto-vivification,
  separation on nested writes, key coercion) or shared references.
- Origins for every instruction, line tables through `Locate`, debug locals.
- Proof: a reference HIR interpreter and a random program generator
  (`tests/common`), the differential test under both array profiles (over a
  million programs before release, mutation-checked), properties (loads in
  bvm, encoding round-trip, origins, determinism), an end-to-end Mox program
  through resolve-lang, deep nesting on a 512 KiB stack, budgets, every
  `Unsupported`.

Dependency wiring (decided here, recorded per the anti-deferral rule):
- **hir-lang 0.3: wired** (the input). **bytecode-lang 0.2: wired** (the
  output, through `ModuleBuilder`/`FunctionBuilder` and labels).
- **intern-lang 1: wired** (symbol text through `Lookup`; hir-lang re-exports
  `Symbol` but not the interner). Same major version hir-lang uses.
- **bvm-lang =2.0.0-alpha.1: dev-dependency** (execution, differential and
  load tests, benches). **resolve-lang 0.2: dev-dependency** (end to end).
- **lower-lang: not wired.** It is not on crates.io; the end-to-end test
  lowers by hand into the HIR a lowering produces and resolves it with
  resolve-lang. A lowering-driven test moves to 0.5 (below).
- **match-lang: not wired** (decision trees are 0.5 scope).

Moved, or not possible on LSB 1 (with the reason):
- `FunctionBuilder::parallel_move` is not used: arguments are evaluated
  straight into call windows, so no move set ever forms a cycle.
- References into array elements and properties (a known by-reference
  parameter given `$a[0]`, `$x = &$a[0]`), `$$name`, a host function used as a
  value, and spread or named arguments to host functions: LSB has no
  reference to a map slot, no named frames, and fixed-arity imports. Each is
  a precise `Unsupported`; reported to the LSB spec owners.
- A place argument naming an element, passed to a function called
  dynamically, goes by value (the callee is unknown when it is sent), and a
  place argument to a dynamic call is read when the callee binds it (after
  every argument). Documented deviations from PHP pending an LSB mechanism.
- Nested writes into a copied array separate the inner array on every write
  (a `dup` plus a copy-on-write store copy each time), because LSB cannot ask
  whether an array is shared: correct, but O(inner size) per nested write. An
  LSB "separate if shared" instruction is requested.
- LSB verifier checks: the verifier lands in bytecode-lang 0.5; until then
  every module is checked by bvm-lang's load-time checks.

## v0.5.0 - Implementation

- [ ] Typed fast paths from typeck-lang; match-lang decision trees; coroutines (yield/await/spawn); classes, mixins, declared records and sums; register allocation quality and benchmarks.
- [ ] Moved from 0.2 A lowering-driven end-to-end test through lower-lang once it is published; verifier-checked output once bytecode-lang 0.5 ships the LSB verifier; references into map slots if LSB adds them.

## v0.9.0 - Hardening

- [ ] Differential fuzzing; scale benchmarks; audit with the LexerSketch Demo as the consumer.

## v1.0.0 - Stable

- [ ] Frozen after Mox runs through it in the LexerSketch Demo (D18).