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

304 lines
5.2 KiB
Markdown

# 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.
---