304 lines
5.2 KiB
Markdown
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.
|
|
|
|
---
|
|
|