Skip to content

Keep Expr non-generic; record checked facts in side tables - #71

Open
wtholliday wants to merge 3 commits into
mainfrom
refactor/checked-side-tables
Open

Keep Expr non-generic; record checked facts in side tables#71
wtholliday wants to merge 3 commits into
mainfrom
refactor/checked-side-tables

Conversation

@wtholliday

Copy link
Copy Markdown
Collaborator

Stacked on #70: this branch contains #70's commits plus one commit on top (1c7294e). #70's head lives on a fork, so the PR cannot target it directly; review the last commit only, and merge after #70.

#70 made Expr generic over its reference, binder and parameter payloads (Expr<R, B, P>) so checked bodies could carry Reference/LocalId in place of names. The repository's established pattern is to keep derived facts in tables indexed by ExprID, and the checker already built exactly those tables before transcribing them into the generic form. This PR returns to that pattern.

  • Expr is a single non-generic enum again.
  • CheckedBody owns the source ExprArena plus parallel tables: solved type, the recorded Reference of each Id/TypeApp node, and the LocalIds each declaration or lambda introduces. CheckedNode and CheckedExpr are removed.
  • Consumers read identity through reference(id), binder(id) and binders(id). Node construction goes through add_id, add_local_read, add_let, add_var, add_binding, set_reference and set_binders; replace keeps recorded facts only when they still apply to the new expression.
  • The checker's publication step hands its existing reference/binder tables straight to the body; the 35-arm transcription and the duplicated checked pretty printer are gone.
  • Validation checks that references are recorded exactly on Id/TypeApp nodes and that binder counts match the expression kind, so the publication boundary still enforces what the generic type used to.
  • Specialization, safety checking, hoisting, copy elision, and the Cranelift, LLVM, register VM and stack backends are migrated mechanically with unchanged behavior. Docs updated.

CheckedFunction.params still uses CheckedParam { local }; it is no longer required by Expr but is referenced widely in the backends, so it was left alone to keep the diff focused.

Validated on macOS ARM64: cargo test --workspace (default features, including golden CLI and LSP tests) and cargo test --features llvm with LLVM 18 both pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BcyQEVKmy98VkZhAnx13Tk

izaak and others added 3 commits September 9, 2026 03:08
Record lexical bindings, solved types, and source locations in owned checked
bodies. Specialization produces explicit concrete function/global instances
consumed by safety, hoisting, copy elision, Cranelift, LLVM, register VM, and
Stack lowering.

Replace repeated name lookup, shadowing bookkeeping, and separate capture
walkers with recorded identities and shared capture discovery.

Retain templates across entry-point changes and specialization retries,
validate publication boundaries, and keep partial editor facts separate from
executable programs. Check concrete requirements in every retained function
body before code motion.

Preserve existing syntax and overload/coercion policies. Share borrowed-call
classification and add ownership, lifecycle, safety, editor recovery, DSP state,
and cancellation regressions. Document the contract in docs/CHECKED_PROGRAM.md.

Validated on macOS ARM64 with LLVM 18: default and LLVM workspace
builds/tests, backend golden suites, AOT integration tests, and a library
check without default features all passed.
The Ubuntu LLVM job builds without the Clang-only C Stack interpreter.
Three unguarded references to stack_interp_bridge prevented its library
tests from compiling.

Gate the C Stack portions of the hoisting and VM codegen regressions with
has_stack_interp while keeping register VM coverage active on every build.

Validation: reproduced all three original errors with has_stack_interp
disabled locally; all 439 LLVM library tests now pass in that configuration.
All 13 affected hoisting and VM codegen tests also pass with the C Stack
interpreter enabled. git diff --check passes.
The checked-program boundary made `Expr` generic over its reference,
binder and parameter payloads so checked bodies could carry `Reference`
and `LocalId` in place of names. The repository already records derived
facts in tables indexed by `ExprID`, and the checker itself built those
tables before transcribing them into the generic form.

`Expr` is a single non-generic type again. `CheckedBody` owns the source
expression tree plus parallel tables for the solved type, the recorded
`Reference` of each identifier/type application, and the `LocalId`s each
declaration or lambda introduces. Consumers read identity through
`reference(id)`, `binder(id)` and `binders(id)`; the checked pretty
printer delegates to the source printer instead of duplicating it.

Specialization, safety checking, hoisting, copy elision, Cranelift, LLVM,
register VM and stack lowering read the tables. Validation checks that
references and binders are recorded exactly where the expression kind
requires them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BcyQEVKmy98VkZhAnx13Tk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants