2026-03-24 13:40:40 +00:00

5.2 KiB

PR-6.2 — Closure Capture Materialization

Briefing

Closures must capture values from the current stack frame into a heap-allocated environment.

This PR defines:

  • How captured values are materialized.
  • How the environment layout is constructed.

No CALL_CLOSURE yet.


Target

Define bytecode semantics for closure creation:

Introduce instruction (placeholder name):

MAKE_CLOSURE fn_id, capture_count

Semantics:

  • Pop capture_count values from stack (top-first).
  • Allocate closure object with those values stored in-order.
  • Push resulting HeapRef to stack.

Work Items

  1. Define new opcode MAKE_CLOSURE.
  2. Implement stack semantics.
  3. Ensure captured values are copied (not borrowed).
  4. Update interpreter to support opcode.

Acceptance Checklist

  • MAKE_CLOSURE opcode exists.
  • Stack pops correct number of values.
  • Closure allocated correctly.
  • Closure ref pushed to stack.

Tests

  1. Create closure capturing 0 values.
  2. Create closure capturing 2 values.
  3. Validate env order correctness.

Junie Instructions

You MAY:

  • Add opcode.
  • Modify interpreter dispatch.
  • Add tests.

You MUST NOT:

  • Implement CALL_CLOSURE yet.
  • Modify GC behavior.
  • Change verifier in this PR.

If capture order semantics unclear, STOP and ask.


Definition of Done

Closures can be created with captured environment and exist as heap values.


PR-6.3 — CALL_CLOSURE Instruction

Briefing

Closures must be invokable at runtime. This PR introduces dynamic invocation semantics for closures.


Target

Introduce opcode:

CALL_CLOSURE arg_count

Semantics:

  • Stack layout before call:

    [... args..., closure_ref]
    
  • Pop closure_ref.

  • Validate it is ObjectKind::Closure.

  • Pop arg_count arguments.

  • Create new call frame:

    • Locals initialized with captured env first (design choice below).
    • Arguments appended after captures.
  • Jump to function entry (fn_id).


Work Items

  1. Add CALL_CLOSURE opcode.
  2. Validate closure_ref type.
  3. Integrate into call frame creation logic.
  4. Respect function signature for ret_slots.

Acceptance Checklist

  • CALL_CLOSURE implemented.
  • Correct stack consumption.
  • Correct frame initialization.
  • Error on non-closure value.

Tests

  1. Simple closure returning constant.
  2. Closure capturing value and using it.
  3. Error when calling non-closure.

Junie Instructions

You MAY:

  • Add opcode and dispatch.
  • Modify call frame initialization.
  • Add tests.

You MUST NOT:

  • Redesign stack model.
  • Introduce coroutine behavior here.
  • Change GC.

If frame layout decision is ambiguous, STOP and ask before choosing ordering.


Definition of Done

Closures can be invoked dynamically and execute correctly.


PR-6.4 — GC Traversal for Closures

Briefing

Closures introduce heap-to-heap references through their captured environments.

The GC must traverse:

closure -> env -> inner HeapRefs

This PR updates the GC mark phase to correctly traverse closure environments.


Target

Extend GC mark logic:

  • When encountering ObjectKind::Closure:

    • Iterate over env values.
    • If a value contains HeapRef → mark referenced object.

Work Items

  1. Update mark traversal switch for Closure.
  2. Ensure no panics on malformed env.
  3. Add tests for nested closure references.

Acceptance Checklist

  • GC marks env HeapRefs.
  • No regression in existing GC tests.
  • Nested closures retained correctly.

Tests

  1. Closure capturing another closure.
  2. Closure capturing heap object.
  3. Unreferenced closure collected.

Junie Instructions

You MAY:

  • Modify mark traversal.
  • Add GC tests.

You MUST NOT:

  • Implement compaction.
  • Change sweep policy.

If unsure whether env values may contain non-heap values, ask before assuming.


Definition of Done

GC correctly traverses closure environments.


PR-6.5 — Verifier Support for Closures

Briefing

The verifier must understand closure values as a distinct type and validate dynamic calls safely.

Closures are heap objects but semantically represent callable values.


Target

Extend verifier to:

  • Introduce a stack type: ClosureValue.
  • Validate MAKE_CLOSURE stack effects.
  • Validate CALL_CLOSURE argument counts.
  • Validate ret_slots against function signature.

Work Items

  1. Add closure type to verifier type lattice.
  2. Define stack transitions for MAKE_CLOSURE.
  3. Define stack transitions for CALL_CLOSURE.
  4. Ensure deterministic failure on misuse.

Acceptance Checklist

  • Verifier understands closure values.
  • Invalid CALL_CLOSURE rejected.
  • ret_slots validated.
  • All tests pass.

Tests

  1. Valid closure call passes verification.
  2. CALL_CLOSURE with wrong arg count fails.
  3. CALL_CLOSURE on non-closure fails.

Junie Instructions

You MAY:

  • Extend verifier type model.
  • Add tests.

You MUST NOT:

  • Weaken verification rules.
  • Introduce runtime-only checks instead of verifier checks.

If closure typing conflicts with current stack model, STOP and ask.


Definition of Done

Verifier fully supports closure creation and invocation.