prometeu-runtime/docs/specs/02b-vm-function-values-and-closures.md

71 lines
2.1 KiB
Markdown

# VM Function Values and Closures
Domain: VM closures and function values
Function: normative
This chapter defines how the PVM models first-class function values.
## 1 First-Class Function Model
The PVM treats user function values as closures.
This means:
- functions can be stored in variables;
- functions can be passed as arguments;
- functions can be returned from other functions;
- function values carry explicit runtime representation.
Even functions without captures may be represented as closures with an empty capture set.
## 2 Closure Layout
Closures are heap objects.
Conceptual layout:
```
Closure {
func_id
captures[]
}
```
Captures may be:
- copied values;
- handles to heap objects.
Closure environments are part of the GC root graph as long as the closure remains reachable.
## 3 Direct and Indirect Calls
The PVM supports two forms of invocation:
| Opcode | Description |
| -------------- | -------------------------------------- |
| `CALL` | Direct call by function id |
| `CALL_CLOSURE` | Indirect call through a closure handle |
For `CALL_CLOSURE`:
1. the closure handle is read from the stack;
2. the VM resolves the target function;
3. captured environment state becomes available to the callee according to the closure calling convention.
## 4 Verification and Safety
The verifier ensures, at minimum:
- closure call sites have coherent arity;
- invalid closure call shapes are rejected or trapped according to the verifier/runtime boundary;
- return-slot contracts remain valid.
Handle validity, heap reachability, and dynamic misuse remain subject to runtime checks where static proof is not possible.
## 5 Relationship to Memory and GC
- Closure objects live in heap memory, so their object model is constrained by [`03-memory-stack-heap-and-allocation.md`](03-memory-stack-heap-and-allocation.md).
- Captured heap references participate in the GC root graph.
- Closures are function values, not syscalls; syscall calls remain a separate non-first-class boundary defined in [`16-host-abi-and-syscalls.md`](16-host-abi-and-syscalls.md).