# Dynamic Semantics - Effect Surfaces Agenda Status: Working agenda (pre-spec) Purpose: close the runtime behavior of PBS effect and control surfaces before drafting the dynamic semantics spec ## 1. Context PBS v1 already commits to several user-visible effect surfaces: - `optional`, - `result`, - `apply`, - `bind`, - `switch`, - `if`, - `else`, - `handle`, - `!` result propagation. Static semantics explains where these forms are legal. What is still missing is the runtime contract: evaluation timing, payload extraction behavior, propagation order, and interaction with traps and allocation. ## 2. Decisions to Produce This agenda must end with decisions for: 1. The runtime value model of `optional` and `result`. 2. The evaluation and propagation semantics of `apply`, `bind`, `else`, `!`, and `handle`. 3. The runtime branch-selection model for `if` and `switch`. 4. The exact boundary between explicit status values and true runtime traps. ## 3. Core Questions ### Q1. `optional` - Is `some(expr)` evaluated eagerly before container construction? - Does `opt else fallback` evaluate `fallback` only on `none`? - Is `optional` guaranteed trap-free at runtime except for traps produced by evaluating its subexpressions? ### Q2. `result` - Is `ok(...)` / `err(...)` purely a return-flow construct with no standalone runtime value form in v1? - How exactly does `expr!` propagate failure through the enclosing function? - Does `handle expr { ... }` first evaluate `expr`, then dispatch exactly one remapping arm, or are there any hidden intermediate forms? ### Q3. `apply` - Is direct-call sugar defined entirely through canonical `apply`, including runtime order? - When `apply` resolves to a callback, method, contract implementation, or host-backed callable, what runtime steps are shared and what remains callable-specific? - Must `apply` preserve a single common trap model regardless of callable kind? ### Q4. `bind` - What runtime artifact does `bind(context, fn_name)` produce: a nominal callback pair, hidden object, or other VM-level value category? - Is the `context` expression always evaluated exactly once at bind time? - Does `bind` itself allocate, and if yes, must that be part of the visible cost contract? ### Q5. `switch` and `if` - Is the selector/condition evaluated exactly once before branch selection? - Does `switch` compare enum cases and scalar literals via a single equality model, or are there construct-specific rules? - Are non-selected arm blocks guaranteed not to evaluate at all? ### Q6. Status values vs traps - Which user-visible failures must stay in `optional` / `result` space instead of trapping? - Are there any operations over these surfaces that may still trap despite their explicit effect model? ### Q7. Allocation and copy visibility - Which of these constructs may allocate, copy, or retain heap state as part of normal execution? - Which of those costs must be reflected later by the diagnostics spec? ## 4. Expected Spec Material After discussion, this agenda should directly feed sections of `Dynamic Semantics Specification.md` covering: 1. runtime values and carrier forms, 2. call and callback execution, 3. effect propagation and remapping, 4. conditional and branching execution, 5. trap versus status-value behavior for effect-bearing constructs. ## 5. Non-Goals - Revisiting the static typing surface already settled in `4. Static Semantics Specification.md`. - Designing collection APIs or general async/error subsystems. - Reopening reserved syntax such as future `match`. ## 6. Inputs - `3. Core Syntax Specification.md` - `4. Static Semantics Specification.md` - `Heap Model - Agenda.md` - `Dynamic Semantics - Execution Model Agenda.md`