sorted agendas e discussions generated.
This commit is contained in:
parent
9a46851791
commit
b865e2386e
@ -1,95 +0,0 @@
|
|||||||
# 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<E>`,
|
|
||||||
- `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<E>`.
|
|
||||||
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<E>`
|
|
||||||
|
|
||||||
- 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`
|
|
||||||
@ -1,86 +0,0 @@
|
|||||||
# Dynamic Semantics - Execution Model Agenda
|
|
||||||
|
|
||||||
Status: Working agenda (pre-spec)
|
|
||||||
Purpose: close the observable execution model for PBS before drafting the dynamic semantics spec
|
|
||||||
|
|
||||||
## 1. Context
|
|
||||||
|
|
||||||
Static semantics already fixes a large part of the source model, but several runtime-visible questions remain open:
|
|
||||||
|
|
||||||
- exact evaluation order,
|
|
||||||
- what counts as a trap versus an ordinary control-flow outcome,
|
|
||||||
- how `FRAME_SYNC` and deterministic safepoints constrain execution,
|
|
||||||
- what host calls are allowed to observe or perturb execution order.
|
|
||||||
|
|
||||||
These decisions should be closed before effect surfaces and memory/lifetime rules are written as normative dynamic semantics.
|
|
||||||
|
|
||||||
## 2. Decisions to Produce
|
|
||||||
|
|
||||||
This agenda must end with decisions for:
|
|
||||||
|
|
||||||
1. The observable sequencing model for expressions, statements, and blocks.
|
|
||||||
2. The normative evaluation order for arguments, receivers, selectors, and chained `apply`.
|
|
||||||
3. The abrupt-completion model: `return`, `break`, `continue`, result propagation, and traps.
|
|
||||||
4. The interaction between host calls, safepoints, and deterministic execution.
|
|
||||||
|
|
||||||
## 3. Core Questions
|
|
||||||
|
|
||||||
### Q1. Global execution model
|
|
||||||
|
|
||||||
- Is PBS execution defined as single-threaded per program instance in v1?
|
|
||||||
- Which execution steps are observable to user code, and which remain VM-internal?
|
|
||||||
|
|
||||||
### Q2. Expression evaluation order
|
|
||||||
|
|
||||||
- Is expression evaluation strictly left-to-right unless a construct says otherwise?
|
|
||||||
- For `f(a, b)` / `f apply (a, b)`, what is the order of evaluating callee, receiver, and argument expressions?
|
|
||||||
- For `f1 apply f2 apply x`, what is the runtime order implied by the right-associative parse?
|
|
||||||
|
|
||||||
### Q3. Single-evaluation guarantees
|
|
||||||
|
|
||||||
- Which constructs normatively evaluate subexpressions exactly once?
|
|
||||||
- Does that guarantee apply to `switch` selectors, `if` conditions, `opt else fallback`, `handle expr`, and `bind(context, fn_name)` context expressions?
|
|
||||||
|
|
||||||
### Q4. Blocks and control transfer
|
|
||||||
|
|
||||||
- How are statement sequencing and tail-expression evaluation defined inside blocks?
|
|
||||||
- At what point does `return`, `break`, or `continue` abort further evaluation in the current construct?
|
|
||||||
|
|
||||||
### Q5. Trap model
|
|
||||||
|
|
||||||
- Which runtime failures are traps rather than status values or compile-time rejection?
|
|
||||||
- Must trap categories be stable and named in the dynamic semantics spec?
|
|
||||||
- Are traps deterministic for the same program input and runtime capability set?
|
|
||||||
|
|
||||||
### Q6. Host interaction
|
|
||||||
|
|
||||||
- Can host calls introduce extra traps beyond ordinary PBS runtime failures?
|
|
||||||
- Where are safepoints guaranteed around host calls, allocation-heavy operations, and loop back-edges?
|
|
||||||
|
|
||||||
### Q7. Determinism boundary
|
|
||||||
|
|
||||||
- Which behaviors must be identical across conforming implementations?
|
|
||||||
- Which details may vary as implementation strategy without changing observable behavior?
|
|
||||||
|
|
||||||
## 4. Expected Spec Material
|
|
||||||
|
|
||||||
After discussion, this agenda should directly feed sections of `Dynamic Semantics Specification.md` covering:
|
|
||||||
|
|
||||||
1. execution state and step ordering,
|
|
||||||
2. evaluation order by construct,
|
|
||||||
3. abrupt completion and trap propagation,
|
|
||||||
4. host-call interaction constraints,
|
|
||||||
5. determinism requirements for conforming runtimes.
|
|
||||||
|
|
||||||
## 5. Non-Goals
|
|
||||||
|
|
||||||
- Revisiting grammar or typing unless the current surface is impossible to specify dynamically.
|
|
||||||
- Defining diagnostics wording in detail.
|
|
||||||
- Designing allocator APIs or collection libraries.
|
|
||||||
|
|
||||||
## 6. Inputs
|
|
||||||
|
|
||||||
- `1. Language Charter.md`
|
|
||||||
- `3. Core Syntax Specification.md`
|
|
||||||
- `4. Static Semantics Specification.md`
|
|
||||||
- `Heap Model - Agenda.md`
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
# PBS Heap Model - Agenda
|
|
||||||
|
|
||||||
Status: Working umbrella agenda (pre-spec)
|
|
||||||
Purpose: coordinate the PBS discussions that define runtime-visible allocation, lifetime, and heap/host boundaries
|
|
||||||
|
|
||||||
## 1. Context
|
|
||||||
|
|
||||||
Legacy PBS experiments used explicit RC/HIP syntax (`alloc`, `borrow`, `mutate`, `peek`, `take`, `weak`).
|
|
||||||
Current runtime authority is GC-based with deterministic safepoints.
|
|
||||||
|
|
||||||
The original heap agenda proved too broad because the open questions now span three different but coupled areas:
|
|
||||||
|
|
||||||
- observable execution behavior,
|
|
||||||
- effect/control surfaces (`optional`, `result`, `apply`, `bind`, `switch`),
|
|
||||||
- memory ownership, GC, and host-memory boundaries.
|
|
||||||
|
|
||||||
This file now acts as the umbrella agenda that keeps those discussions aligned instead of trying to close every detail in one pass.
|
|
||||||
|
|
||||||
## 2. Agenda Split
|
|
||||||
|
|
||||||
The work is split into the following dedicated agendas:
|
|
||||||
|
|
||||||
1. `Dynamic Semantics - Execution Model Agenda.md`
|
|
||||||
2. `Dynamic Semantics - Effect Surfaces Agenda.md`
|
|
||||||
3. `Memory and Lifetime - Agenda.md`
|
|
||||||
|
|
||||||
The heap model is still the cross-cutting reference because allocation visibility, traps, and host boundaries must line up across all three.
|
|
||||||
|
|
||||||
## 3. Cross-Agenda Decisions This Umbrella Owns
|
|
||||||
|
|
||||||
This umbrella must keep the following decisions coherent across the child agendas:
|
|
||||||
|
|
||||||
1. GC is the baseline runtime model for PBS core unless a future profile explicitly says otherwise.
|
|
||||||
2. Core v1 does not require explicit lifetime syntax for ordinary user code.
|
|
||||||
3. Deterministic execution and `FRAME_SYNC` constraints override ergonomics when the two conflict.
|
|
||||||
4. Runtime-visible costs must be surfaced through diagnostics/tooling when code allocates, copies, crosses the host boundary, or can trap.
|
|
||||||
5. The VM heap and host-owned memory must remain distinct in the user model even when APIs make the boundary feel ergonomic.
|
|
||||||
|
|
||||||
## 4. Questions That Must Stay Aligned
|
|
||||||
|
|
||||||
### Q1. Baseline runtime authority
|
|
||||||
|
|
||||||
- Is GC always the default execution model for PBS core? (expected: yes)
|
|
||||||
- Which safepoints are part of the observable contract versus implementation detail?
|
|
||||||
|
|
||||||
### Q2. Language vs library boundary
|
|
||||||
|
|
||||||
- Which old RC/HIP concepts stay reserved-only in core syntax?
|
|
||||||
- Which advanced workflows move to stdlib/tooling APIs rather than language keywords?
|
|
||||||
|
|
||||||
### Q3. Cost visibility contract
|
|
||||||
|
|
||||||
- Which allocations, copies, host transfers, and trap paths must be visible in diagnostics?
|
|
||||||
- Which cost facts are normative, and which remain profiler-quality best effort?
|
|
||||||
|
|
||||||
### Q4. Host boundary
|
|
||||||
|
|
||||||
- How does PBS communicate "VM heap vs host-owned memory" without exposing raw host pointers as ordinary user values?
|
|
||||||
- Which host operations are allowed to allocate or retain memory, and how must that appear to the user?
|
|
||||||
|
|
||||||
### Q5. Migration policy
|
|
||||||
|
|
||||||
- What is the official migration story from legacy RC/HIP concepts?
|
|
||||||
- What hard criteria must be met before any reserved lifetime keyword can be activated in a future profile?
|
|
||||||
|
|
||||||
## 5. Expected Output Documents
|
|
||||||
|
|
||||||
After the child agendas close, use their decisions to draft:
|
|
||||||
|
|
||||||
1. `Dynamic Semantics Specification.md`
|
|
||||||
2. `Memory and Lifetime Specification.md`
|
|
||||||
3. `Diagnostics Specification.md`
|
|
||||||
|
|
||||||
The existing `4. Static Semantics Specification.md` may receive follow-up clarifications where memory or effect rules need stronger static wording.
|
|
||||||
|
|
||||||
## 6. Non-Goals for This Umbrella Agenda
|
|
||||||
|
|
||||||
- Defining new VM opcodes.
|
|
||||||
- Reintroducing RC as mandatory runtime strategy.
|
|
||||||
- Designing full stdlib memory-management APIs in this pass.
|
|
||||||
- Settling backend/lowering internals that do not affect observable semantics.
|
|
||||||
|
|
||||||
## 7. Working Assumptions
|
|
||||||
|
|
||||||
1. GC remains baseline for PBS core.
|
|
||||||
2. Explicit heap control is opt-in and likely library/tooling-driven.
|
|
||||||
3. Deterministic behavior and frame-sync constraints are non-negotiable.
|
|
||||||
4. Language should expose cost signals without forcing expert-only syntax.
|
|
||||||
5. Child agendas may narrow terminology, but they must not conflict on runtime-observable behavior.
|
|
||||||
@ -1,94 +0,0 @@
|
|||||||
# Memory and Lifetime - Agenda
|
|
||||||
|
|
||||||
Status: Working agenda (pre-spec)
|
|
||||||
Purpose: define the authoritative PBS memory, ownership, and lifetime model for v1
|
|
||||||
|
|
||||||
## 1. Context
|
|
||||||
|
|
||||||
PBS no longer exposes the old RC/HIP syntax as active core language, but the language still needs a precise memory story.
|
|
||||||
That story must explain:
|
|
||||||
|
|
||||||
- what values live on the VM heap,
|
|
||||||
- what identity and aliasing mean,
|
|
||||||
- how baseline GC interacts with deterministic execution,
|
|
||||||
- where host-owned memory begins and ends,
|
|
||||||
- how allocation and copy costs become visible to advanced users.
|
|
||||||
|
|
||||||
Without this agenda, the future `Memory and Lifetime Specification.md` would not have a stable scope.
|
|
||||||
|
|
||||||
## 2. Decisions to Produce
|
|
||||||
|
|
||||||
This agenda must end with decisions for:
|
|
||||||
|
|
||||||
1. The value-category map: stack-like transient values, heap-backed values, callbacks, collections, and host-backed handles.
|
|
||||||
2. The lifetime and reachability model under baseline GC.
|
|
||||||
3. The VM heap vs host-memory boundary and the user-visible rules at that boundary.
|
|
||||||
4. The minimum cost/allocation visibility contract needed by diagnostics and profiling.
|
|
||||||
5. The migration and reservation policy for legacy RC/HIP concepts.
|
|
||||||
|
|
||||||
## 3. Core Questions
|
|
||||||
|
|
||||||
### Q1. Heap residency by value category
|
|
||||||
|
|
||||||
- Which core values are heap-backed in v1: structs, callbacks, collections, tuples, `optional`, `result`, or only some of them?
|
|
||||||
- When a value is assigned, passed, or returned, what is copied versus what aliases the same heap identity?
|
|
||||||
|
|
||||||
### Q2. Identity and aliasing
|
|
||||||
|
|
||||||
- Which user-visible value kinds have stable identity?
|
|
||||||
- Are struct values always reference-like at runtime even when their fields are small and copyable?
|
|
||||||
- How should aliasing be described for beginner-facing semantics without hiding performance consequences?
|
|
||||||
|
|
||||||
### Q3. Baseline GC contract
|
|
||||||
|
|
||||||
- Which GC properties are normative: reachability, eventual reclamation, safepoints, no user finalizers?
|
|
||||||
- Which GC timing details remain non-normative implementation choices?
|
|
||||||
- Can user code observe reclamation directly, or only via indirect performance/diagnostic signals?
|
|
||||||
|
|
||||||
### Q4. Host memory boundary
|
|
||||||
|
|
||||||
- How are host-backed resources represented in PBS user space: opaque handles, nominal structs, services, or reserved host-bound values?
|
|
||||||
- Can host memory outlive PBS references, and if yes, what runtime contract prevents unsoundness?
|
|
||||||
- Is pinning, borrowing, or zero-copy transfer exposed in v1 at all?
|
|
||||||
|
|
||||||
### Q5. Allocation visibility
|
|
||||||
|
|
||||||
- Which operations are allowed to allocate on the VM heap?
|
|
||||||
- Which host calls may allocate host memory or retain VM-reachable references?
|
|
||||||
- What must tooling report as allocation, retention, copy, or escape risk?
|
|
||||||
|
|
||||||
### Q6. Lifetime-related traps and safety
|
|
||||||
|
|
||||||
- Which memory problems are impossible by construction in v1 core?
|
|
||||||
- Which remaining failures become traps, capability rejection, or host-defined status outcomes?
|
|
||||||
|
|
||||||
### Q7. Future explicit control
|
|
||||||
|
|
||||||
- Should pools, arenas, object reuse, or weak-reference patterns exist only as stdlib/tooling surfaces?
|
|
||||||
- What criteria must be met before reserved keywords like `alloc`, `borrow`, `take`, or `weak` can become active in a future profile?
|
|
||||||
|
|
||||||
## 4. Expected Spec Material
|
|
||||||
|
|
||||||
After discussion, this agenda should directly feed sections of `Memory and Lifetime Specification.md` covering:
|
|
||||||
|
|
||||||
1. runtime memory spaces,
|
|
||||||
2. value representation classes,
|
|
||||||
3. identity, aliasing, and copy rules,
|
|
||||||
4. GC and safepoint guarantees,
|
|
||||||
5. host-memory boundary rules,
|
|
||||||
6. cost visibility hooks for `Diagnostics Specification.md`.
|
|
||||||
|
|
||||||
## 5. Non-Goals
|
|
||||||
|
|
||||||
- Defining exact GC algorithm internals.
|
|
||||||
- Designing complete stdlib pool/arena APIs.
|
|
||||||
- Reintroducing mandatory user-authored lifetime syntax in core v1.
|
|
||||||
|
|
||||||
## 6. Inputs
|
|
||||||
|
|
||||||
- `1. Language Charter.md`
|
|
||||||
- `3. Core Syntax Specification.md`
|
|
||||||
- `4. Static Semantics Specification.md`
|
|
||||||
- `Heap Model - Agenda.md`
|
|
||||||
- `Dynamic Semantics - Execution Model Agenda.md`
|
|
||||||
- `Dynamic Semantics - Effect Surfaces Agenda.md`
|
|
||||||
154
docs/pbs/decisions/Allocation and Cost Visibility Decision.md
Normal file
154
docs/pbs/decisions/Allocation and Cost Visibility Decision.md
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
# Allocation and Cost Visibility Decision
|
||||||
|
|
||||||
|
Status: Accepted
|
||||||
|
Cycle: Initial allocation-and-cost closure pass
|
||||||
|
|
||||||
|
## 1. Context
|
||||||
|
|
||||||
|
PBS v1 needs a minimal but explicit contract for which runtime cost facts matter semantically and which belong only to diagnostics/profiling quality.
|
||||||
|
|
||||||
|
Earlier decisions already fixed important inputs:
|
||||||
|
|
||||||
|
- `bind(context, fn_name)` has real retention/storage consequences,
|
||||||
|
- `optional`, `result`, `handle`, `!`, `if`, and `switch` are not intended to hide implicit allocation semantics,
|
||||||
|
- host/userland interaction is stack-only across the boundary,
|
||||||
|
- and value categories already distinguish copied payload from preserved aliasing.
|
||||||
|
|
||||||
|
## 2. Decision
|
||||||
|
|
||||||
|
PBS v1 adopts the following cost-visibility baseline:
|
||||||
|
|
||||||
|
1. The normatively relevant cost facts are:
|
||||||
|
- whether an operation may allocate VM-owned runtime storage,
|
||||||
|
- whether an operation retains state beyond the current evaluation,
|
||||||
|
- whether an operation copies payload versus preserves aliasing,
|
||||||
|
- whether an operation crosses the host boundary,
|
||||||
|
- and whether an operation may trap.
|
||||||
|
2. `bind(context, fn_name)` is normatively retention-bearing and requires runtime storage sufficient to keep the callback target and captured context alive.
|
||||||
|
3. `apply` is not allocation-bearing by itself.
|
||||||
|
4. `optional`, `result`, `handle`, `!`, `if`, and `switch` are not allocation-bearing by themselves.
|
||||||
|
5. Host-boundary crossing is a normatively relevant cost fact, but concrete host-side allocation details belong to subsystem-specific contracts rather than to a general PBS rule.
|
||||||
|
6. Quantitative reporting such as exact byte counts, exact object counts, or precise collector timing is not a normative language guarantee in v1.
|
||||||
|
|
||||||
|
## 3. Normatively Relevant Cost Facts
|
||||||
|
|
||||||
|
The following cost facts are part of the PBS semantic model and may be relied on by later tooling/spec work:
|
||||||
|
|
||||||
|
- VM allocation-bearing versus non-allocation-bearing behavior,
|
||||||
|
- retention-bearing versus non-retention-bearing behavior,
|
||||||
|
- copy versus aliasing preservation,
|
||||||
|
- host-boundary crossing,
|
||||||
|
- trap possibility.
|
||||||
|
|
||||||
|
These facts matter because they affect how advanced tooling, diagnostics, and performance reasoning should interpret a construct.
|
||||||
|
|
||||||
|
## 4. `bind`
|
||||||
|
|
||||||
|
`bind(context, fn_name)` is the strongest closed cost case in the current PBS core.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `bind` is not semantically free,
|
||||||
|
- `bind` is retention-bearing,
|
||||||
|
- `bind` requires runtime storage sufficient to preserve the callback target and captured context,
|
||||||
|
- the captured context remains alive while the callback value remains alive.
|
||||||
|
|
||||||
|
This decision does not require the spec to freeze the exact runtime layout used to implement that storage.
|
||||||
|
|
||||||
|
## 5. Non-Allocation-Bearing Surfaces
|
||||||
|
|
||||||
|
The following constructs are not allocation-bearing by themselves in PBS v1:
|
||||||
|
|
||||||
|
- `optional`
|
||||||
|
- `result`
|
||||||
|
- `handle`
|
||||||
|
- `!`
|
||||||
|
- `if`
|
||||||
|
- `switch`
|
||||||
|
- `apply`
|
||||||
|
|
||||||
|
If allocation or retention occurs while evaluating one of these constructs, that cost arises from:
|
||||||
|
|
||||||
|
- subexpression evaluation,
|
||||||
|
- called targets,
|
||||||
|
- payload formation already defined elsewhere,
|
||||||
|
- or runtime behavior outside the surface itself.
|
||||||
|
|
||||||
|
## 6. Copy Versus Aliasing
|
||||||
|
|
||||||
|
Copy versus aliasing is a normatively relevant cost fact.
|
||||||
|
|
||||||
|
The language already distinguishes:
|
||||||
|
|
||||||
|
- pure values copied by value,
|
||||||
|
- identity-bearing values passed by preserved aliasing,
|
||||||
|
- carriers that preserve the semantics of their contained values.
|
||||||
|
|
||||||
|
Tooling and later specs may rely on these distinctions even if PBS v1 does not require a warning at every such site.
|
||||||
|
|
||||||
|
## 7. Host Boundary
|
||||||
|
|
||||||
|
Crossing the host boundary is a normatively relevant cost fact.
|
||||||
|
|
||||||
|
However, this decision does not impose a universal rule for:
|
||||||
|
|
||||||
|
- host-side allocation volume,
|
||||||
|
- host-side object count,
|
||||||
|
- or host-side retention internals.
|
||||||
|
|
||||||
|
Those details belong to subsystem-specific contracts when and if they become relevant.
|
||||||
|
|
||||||
|
## 8. Normative Versus Best-Effort Reporting
|
||||||
|
|
||||||
|
### 8.1 Normative facts
|
||||||
|
|
||||||
|
The following facts are normative and may be surfaced by diagnostics/tooling:
|
||||||
|
|
||||||
|
- whether a construct is retention-bearing,
|
||||||
|
- whether a construct crosses the host boundary,
|
||||||
|
- whether semantics preserve aliasing or copy payload,
|
||||||
|
- whether a construct may trap.
|
||||||
|
|
||||||
|
### 8.2 Best-effort facts
|
||||||
|
|
||||||
|
The following facts are not normative language guarantees in v1:
|
||||||
|
|
||||||
|
- exact byte counts,
|
||||||
|
- exact object counts,
|
||||||
|
- exact collector timing,
|
||||||
|
- exact host-side allocation volume,
|
||||||
|
- precise performance ranking beyond the semantic facts above.
|
||||||
|
|
||||||
|
These may be surfaced by implementations as profiling or tooling enrichment, but they are not part of the core language contract.
|
||||||
|
|
||||||
|
## 9. Invariants
|
||||||
|
|
||||||
|
- The language must not imply hidden allocation semantics where none were intentionally specified.
|
||||||
|
- `bind` remains the canonical retention-bearing callback-forming construct in v1.
|
||||||
|
- Cost visibility must be strong enough for advanced tooling without forcing exact runtime accounting into the language spec.
|
||||||
|
- Host-boundary cost reporting must not pretend to know subsystem-specific runtime internals unless those are explicitly specified.
|
||||||
|
|
||||||
|
## 10. Explicit Non-Decisions
|
||||||
|
|
||||||
|
This decision record does not yet close:
|
||||||
|
|
||||||
|
- the final diagnostics wording for warnings or notes,
|
||||||
|
- subsystem-specific host cost contracts,
|
||||||
|
- precise collection/profiling metrics,
|
||||||
|
- optimizer-facing reporting policy.
|
||||||
|
|
||||||
|
## 11. Spec Impact
|
||||||
|
|
||||||
|
This decision should feed at least:
|
||||||
|
|
||||||
|
- `docs/pbs/specs/10. Memory and Lifetime Specification.md`
|
||||||
|
- `docs/pbs/specs/11. Diagnostics Specification.md`
|
||||||
|
|
||||||
|
## 12. Validation Notes
|
||||||
|
|
||||||
|
The intended split is:
|
||||||
|
|
||||||
|
- semantic cost facts are explicit,
|
||||||
|
- `bind` is the main retained-storage construct already closed,
|
||||||
|
- most other core surfaces are not allocation-bearing by themselves,
|
||||||
|
- and quantitative performance reporting remains tooling-quality rather than normative language behavior.
|
||||||
@ -0,0 +1,128 @@
|
|||||||
|
# Dynamic Semantics - Branch Selection Decision
|
||||||
|
|
||||||
|
Status: Accepted
|
||||||
|
Cycle: Initial branch-selection closure pass
|
||||||
|
|
||||||
|
## 1. Context
|
||||||
|
|
||||||
|
PBS v1 needs a closed runtime contract for `if` and `switch` before the dynamic semantics spec can be completed.
|
||||||
|
|
||||||
|
The remaining questions were:
|
||||||
|
|
||||||
|
- whether conditions and selectors are evaluated once,
|
||||||
|
- whether non-selected branches evaluate at all,
|
||||||
|
- which selector categories are admitted for `switch`,
|
||||||
|
- and whether branch selection itself may trap.
|
||||||
|
|
||||||
|
## 2. Decision
|
||||||
|
|
||||||
|
PBS v1 adopts the following branch-selection rules:
|
||||||
|
|
||||||
|
1. `if` evaluates its condition exactly once.
|
||||||
|
2. `switch` evaluates its selector exactly once.
|
||||||
|
3. Only the selected branch or arm executes.
|
||||||
|
4. Non-selected branches and arms perform no evaluation.
|
||||||
|
5. `if` and `switch` are trap-free by themselves; only selected subexpressions may trap.
|
||||||
|
6. `switch` is limited to statically discriminable selector categories.
|
||||||
|
7. `switch` does not accept `result`, `error`, structs, string objects, or heap-backed types as selectors in v1.
|
||||||
|
|
||||||
|
## 3. `if`
|
||||||
|
|
||||||
|
For:
|
||||||
|
|
||||||
|
```text
|
||||||
|
if cond { then_block } else { else_block }
|
||||||
|
```
|
||||||
|
|
||||||
|
the runtime behaves as follows:
|
||||||
|
|
||||||
|
1. evaluate `cond` exactly once,
|
||||||
|
2. if it yields `true`, execute only `then_block`,
|
||||||
|
3. if it yields `false`, execute only `else_block`.
|
||||||
|
|
||||||
|
The non-selected branch is not evaluated, even partially.
|
||||||
|
|
||||||
|
Any trap associated with `if` arises only from:
|
||||||
|
|
||||||
|
- evaluating `cond`,
|
||||||
|
- or executing the selected branch.
|
||||||
|
|
||||||
|
## 4. `switch`
|
||||||
|
|
||||||
|
### 4.1 Selector evaluation
|
||||||
|
|
||||||
|
For:
|
||||||
|
|
||||||
|
```text
|
||||||
|
switch selector { ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
the runtime:
|
||||||
|
|
||||||
|
1. evaluates `selector` exactly once,
|
||||||
|
2. determines the matching arm using the canonical matching rule for the selector category,
|
||||||
|
3. executes exactly one selected arm.
|
||||||
|
|
||||||
|
No non-selected arm is evaluated.
|
||||||
|
|
||||||
|
### 4.2 Admitted selector categories
|
||||||
|
|
||||||
|
In v1, `switch` is restricted to selector categories with static, deterministic matching behavior.
|
||||||
|
|
||||||
|
These include:
|
||||||
|
|
||||||
|
- literal-comparable scalar values,
|
||||||
|
- enum values,
|
||||||
|
- `str` values with canonical static identity,
|
||||||
|
- and other compile-time-constant-compatible selector categories only if explicitly admitted elsewhere.
|
||||||
|
|
||||||
|
`switch` does not accept:
|
||||||
|
|
||||||
|
- `result` values,
|
||||||
|
- `error` values,
|
||||||
|
- structs,
|
||||||
|
- string object/reference types distinct from canonical `str`,
|
||||||
|
- or heap-backed selector categories.
|
||||||
|
|
||||||
|
Dynamic or structural matching belongs to a future `match`-style construct rather than to `switch`.
|
||||||
|
|
||||||
|
### 4.3 Matching rule
|
||||||
|
|
||||||
|
`switch` arm selection is exact and deterministic for the admitted selector type.
|
||||||
|
|
||||||
|
- Enum selectors match by canonical enum-case identity.
|
||||||
|
- Scalar selectors match by the exact equality rule already defined for that scalar category.
|
||||||
|
- `str` selectors match by canonical static string identity rather than by heap-object comparison.
|
||||||
|
|
||||||
|
`switch` does not perform structural matching, guard evaluation, or user-defined equality dispatch.
|
||||||
|
|
||||||
|
## 5. Invariants
|
||||||
|
|
||||||
|
- `if` and `switch` never evaluate more than one branch or arm.
|
||||||
|
- Branch selection is deterministic for the same selector value.
|
||||||
|
- `switch` remains a static discriminant-selection construct, not a result/error-processing construct.
|
||||||
|
- Error processing with logic belongs to `handle`, not to `switch`.
|
||||||
|
|
||||||
|
## 6. Explicit Non-Decisions
|
||||||
|
|
||||||
|
This decision record does not yet close:
|
||||||
|
|
||||||
|
- the final future design of `match`,
|
||||||
|
- whether additional scalar-like selector categories will be admitted later,
|
||||||
|
- the complete memory/cost wording associated with selector evaluation.
|
||||||
|
|
||||||
|
## 7. Spec Impact
|
||||||
|
|
||||||
|
This decision should feed at least:
|
||||||
|
|
||||||
|
- `docs/pbs/specs/9. Dynamic Semantics Specification.md`
|
||||||
|
- `docs/pbs/specs/4. Static Semantics Specification.md`
|
||||||
|
- `docs/pbs/specs/3. Core Syntax Specification.md`
|
||||||
|
|
||||||
|
## 8. Validation Notes
|
||||||
|
|
||||||
|
The intended split is:
|
||||||
|
|
||||||
|
- `if` and `switch` perform static, deterministic branch selection,
|
||||||
|
- `handle` processes modeled `result` errors,
|
||||||
|
- future dynamic or structural branching belongs to `match`, not to `switch`.
|
||||||
@ -0,0 +1,355 @@
|
|||||||
|
# Dynamic Semantics - Effect Surfaces Decision
|
||||||
|
|
||||||
|
Status: Accepted
|
||||||
|
Cycle: Initial effect-surfaces closure pass
|
||||||
|
|
||||||
|
## 1. Context
|
||||||
|
|
||||||
|
PBS v1 already commits to several effect and control surfaces in syntax and static semantics, but their runtime behavior must be closed before normative dynamic semantics can be written.
|
||||||
|
|
||||||
|
This decision record captures the first closed subset of that work:
|
||||||
|
|
||||||
|
- `optional`,
|
||||||
|
- `result<E>`,
|
||||||
|
- `!` propagation,
|
||||||
|
- `handle` processing.
|
||||||
|
|
||||||
|
Allocation, retention, copy visibility, and heap-facing cost wording are delegated to the memory and heap decision track.
|
||||||
|
|
||||||
|
## 2. Decision
|
||||||
|
|
||||||
|
PBS v1 adopts the following baseline runtime rules for `optional` and `result<E>` surfaces:
|
||||||
|
|
||||||
|
1. `optional` is a runtime presence/absence carrier with canonical `some(payload)` and `none` states.
|
||||||
|
2. `some(expr)` evaluates `expr` eagerly and exactly once before forming the `some` carrier.
|
||||||
|
3. `opt else fallback` evaluates the left operand exactly once and evaluates `fallback` only when the left operand is `none`.
|
||||||
|
4. `optional` is trap-free by itself; only subexpression evaluation may trap.
|
||||||
|
5. `result<E>` is the runtime carrier for expected, modelable failure in function return flow.
|
||||||
|
6. `expr!` evaluates `expr` exactly once and performs immediate enclosing-function error propagation on failure.
|
||||||
|
7. `handle expr { ... }` evaluates `expr` exactly once and, on error, executes exactly one matching arm.
|
||||||
|
8. A `handle` arm may execute user-defined logic.
|
||||||
|
9. A `handle` arm must terminate with either `ok(payload)` or `err(E2.case)`.
|
||||||
|
10. `ok(payload)` in a `handle` arm recovers locally and yields the payload as the value of the `handle` expression.
|
||||||
|
11. `err(E2.case)` in a `handle` arm performs immediate enclosing-function return with that error.
|
||||||
|
12. `handle` supports a short remap form `E1.case -> E2.case` as sugar for a block that returns `err(E2.case)`.
|
||||||
|
13. Neither `!` nor `handle` intercepts or converts traps.
|
||||||
|
14. `apply` is the canonical universal call surface for PBS v1 across all callable categories.
|
||||||
|
15. `apply` chains parse right-associatively but preserve the already-closed left-to-right observable evaluation model.
|
||||||
|
16. `apply` does not introduce implicit composition of `optional` or `result` surfaces.
|
||||||
|
17. `bind(context, fn_name)` forms a nominal callback value by attaching a struct context to a top-level function target.
|
||||||
|
18. `bind` evaluates its context expression exactly once, captures the same runtime context identity without copying it, and injects that context as the first argument when the callback is invoked.
|
||||||
|
19. `bind` is not a general closure mechanism and is trap-free at the language level.
|
||||||
|
|
||||||
|
## 3. `optional`
|
||||||
|
|
||||||
|
### 3.1 Runtime model
|
||||||
|
|
||||||
|
`optional` has exactly two runtime states:
|
||||||
|
|
||||||
|
- `some(payload)`
|
||||||
|
- `none`
|
||||||
|
|
||||||
|
`none` is the canonical absence of payload.
|
||||||
|
|
||||||
|
### 3.2 Construction
|
||||||
|
|
||||||
|
`some(expr)`:
|
||||||
|
|
||||||
|
- evaluates `expr` eagerly,
|
||||||
|
- evaluates it exactly once,
|
||||||
|
- then forms the `some(payload)` carrier from the produced payload.
|
||||||
|
|
||||||
|
### 3.3 Extraction
|
||||||
|
|
||||||
|
`opt else fallback`:
|
||||||
|
|
||||||
|
1. evaluates `opt` exactly once,
|
||||||
|
2. if the result is `some(payload)`, yields the extracted payload and does not evaluate `fallback`,
|
||||||
|
3. if the result is `none`, evaluates `fallback` and yields that value.
|
||||||
|
|
||||||
|
`else` is extraction with fallback, not error handling.
|
||||||
|
|
||||||
|
### 3.4 Trap behavior
|
||||||
|
|
||||||
|
`optional` itself does not trap.
|
||||||
|
|
||||||
|
Any trap associated with `some(expr)` or `opt else fallback` arises only from:
|
||||||
|
|
||||||
|
- evaluating `expr`,
|
||||||
|
- evaluating the left operand,
|
||||||
|
- or evaluating the fallback when it is needed.
|
||||||
|
|
||||||
|
## 4. `result<E>`
|
||||||
|
|
||||||
|
### 4.1 Runtime role
|
||||||
|
|
||||||
|
`result<E>` is the runtime carrier for success-or-modeled-failure at function boundaries and in expressions whose static type is `result<E> P`.
|
||||||
|
|
||||||
|
In v1, `ok(...)` and `err(...)` are special result-flow forms.
|
||||||
|
|
||||||
|
They are not general-purpose first-class userland constructors for arbitrary data modeling.
|
||||||
|
|
||||||
|
They are valid in:
|
||||||
|
|
||||||
|
- function return flow for `result<E>`,
|
||||||
|
- and `handle` arms, where they control recovery or propagation.
|
||||||
|
|
||||||
|
### 4.2 `!` propagation
|
||||||
|
|
||||||
|
`expr!`:
|
||||||
|
|
||||||
|
1. evaluates `expr` exactly once,
|
||||||
|
2. if `expr` yields success, yields the extracted success payload as the value of the expression,
|
||||||
|
3. if `expr` yields error, performs immediate enclosing-function return with the same `err(...)`.
|
||||||
|
|
||||||
|
`!` does not:
|
||||||
|
|
||||||
|
- remap the error,
|
||||||
|
- intercept traps,
|
||||||
|
- or continue ordinary evaluation after the propagated error path is chosen.
|
||||||
|
|
||||||
|
### 4.3 `handle`
|
||||||
|
|
||||||
|
`handle expr { ... }`:
|
||||||
|
|
||||||
|
1. evaluates `expr` exactly once,
|
||||||
|
2. if `expr` yields success, yields the extracted success payload directly,
|
||||||
|
3. if `expr` yields error, selects exactly one matching handle arm,
|
||||||
|
4. executes the selected arm,
|
||||||
|
5. requires that arm to terminate with either `ok(payload)` or `err(E2.case)`.
|
||||||
|
|
||||||
|
### 4.4 `handle` arm results
|
||||||
|
|
||||||
|
The selected `handle` arm has two admissible result forms:
|
||||||
|
|
||||||
|
- `ok(payload)`
|
||||||
|
- `err(E2.case)`
|
||||||
|
|
||||||
|
Their semantics are:
|
||||||
|
|
||||||
|
- `ok(payload)` recovers locally and makes the `handle` expression yield `payload`,
|
||||||
|
- `err(E2.case)` performs immediate enclosing-function return with `err(E2.case)`.
|
||||||
|
|
||||||
|
The `payload` in `ok(payload)` must be compatible with the success payload shape produced by the surrounding `handle` expression.
|
||||||
|
|
||||||
|
The `E2.case` in `err(E2.case)` must belong to the target error type required by the enclosing context.
|
||||||
|
|
||||||
|
### 4.5 `handle` sugar
|
||||||
|
|
||||||
|
For the common remap-only case, `handle` supports a short arm form:
|
||||||
|
|
||||||
|
```text
|
||||||
|
E1.case -> E2.case
|
||||||
|
```
|
||||||
|
|
||||||
|
This is sugar for:
|
||||||
|
|
||||||
|
```text
|
||||||
|
E1.case -> { err(E2.case) }
|
||||||
|
```
|
||||||
|
|
||||||
|
Recovery with `ok(payload)` requires the explicit block form.
|
||||||
|
|
||||||
|
### 4.6 `handle` scope
|
||||||
|
|
||||||
|
`handle` may execute user-defined logic inside an arm, but it remains specific to modeled `result` errors.
|
||||||
|
|
||||||
|
It does not provide:
|
||||||
|
|
||||||
|
- trap interception,
|
||||||
|
- arbitrary processing of non-`result` failure channels,
|
||||||
|
- or a general-purpose exception system.
|
||||||
|
|
||||||
|
## 5. Invariants
|
||||||
|
|
||||||
|
- `optional` models absence, not failure.
|
||||||
|
- Expected recoverable failure remains in `result<E>`, not in `optional`.
|
||||||
|
- `!` is an early-return propagation surface.
|
||||||
|
- `handle` is a typed result-processing surface with controlled recovery or propagation.
|
||||||
|
- Success paths produce payload values directly.
|
||||||
|
- Error paths in `result<E>` remain explicit and typed.
|
||||||
|
- Trap remains outside ordinary recoverable error flow.
|
||||||
|
- `apply` remains the single semantic call surface even when user code uses direct-call sugar.
|
||||||
|
- Callable-specific dispatch differences do not change the user-visible call pipeline.
|
||||||
|
- Effect boundaries remain explicit; `apply` does not auto-lift through `optional` or `result`.
|
||||||
|
|
||||||
|
## 6. `apply`
|
||||||
|
|
||||||
|
### 6.1 Canonical role
|
||||||
|
|
||||||
|
`apply` is the canonical universal call surface in PBS v1.
|
||||||
|
|
||||||
|
Direct call syntax is only sugar over `apply` and does not define separate runtime semantics.
|
||||||
|
|
||||||
|
The same observable call model applies to:
|
||||||
|
|
||||||
|
- top-level functions,
|
||||||
|
- struct methods,
|
||||||
|
- service methods,
|
||||||
|
- contract calls,
|
||||||
|
- callback calls,
|
||||||
|
- host-backed calls.
|
||||||
|
|
||||||
|
### 6.2 Shared observable pipeline
|
||||||
|
|
||||||
|
For `lhs apply rhs`, the shared observable runtime pipeline is:
|
||||||
|
|
||||||
|
1. form the call target from `lhs`,
|
||||||
|
2. evaluate any receiver or callable artifact needed for target formation exactly once,
|
||||||
|
3. evaluate `rhs` exactly once,
|
||||||
|
4. invoke the resolved target,
|
||||||
|
5. produce one of:
|
||||||
|
- normal return,
|
||||||
|
- explicit `result<Error>` propagation,
|
||||||
|
- or `trap`.
|
||||||
|
|
||||||
|
Callable-specific dispatch strategy may differ internally, but it does not change this user-visible sequencing model.
|
||||||
|
|
||||||
|
### 6.3 Chained `apply`
|
||||||
|
|
||||||
|
`apply` chains are parsed right-associatively.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```text
|
||||||
|
f1 apply f2 apply f3 apply params
|
||||||
|
```
|
||||||
|
|
||||||
|
parses as:
|
||||||
|
|
||||||
|
```text
|
||||||
|
f1 apply (f2 apply (f3 apply params))
|
||||||
|
```
|
||||||
|
|
||||||
|
The observable evaluation order still follows the already-closed left-to-right model:
|
||||||
|
|
||||||
|
1. form the target of `f1`,
|
||||||
|
2. evaluate the argument expression for `f1`,
|
||||||
|
3. within that argument expression, form the target of `f2`,
|
||||||
|
4. evaluate the argument expression for `f2`,
|
||||||
|
5. within that argument expression, form the target of `f3`,
|
||||||
|
6. evaluate `params`,
|
||||||
|
7. invoke `f3`,
|
||||||
|
8. invoke `f2`,
|
||||||
|
9. invoke `f1`.
|
||||||
|
|
||||||
|
### 6.4 Effect boundaries
|
||||||
|
|
||||||
|
`apply` does not introduce implicit effect composition.
|
||||||
|
|
||||||
|
If a callable returns:
|
||||||
|
|
||||||
|
- `optional<P>`, extraction remains explicit through `else`,
|
||||||
|
- `result<E> P`, propagation or remapping remains explicit through `!` or `handle`.
|
||||||
|
|
||||||
|
PBS v1 does not auto-lift ordinary call chains through `optional` or `result` boundaries.
|
||||||
|
|
||||||
|
## 7. `bind`
|
||||||
|
|
||||||
|
### 7.1 Role
|
||||||
|
|
||||||
|
`bind(context, fn_name)` is the explicit callback-formation mechanism in PBS v1.
|
||||||
|
|
||||||
|
It exists to attach a struct context to a compatible top-level function without introducing general lexical closures.
|
||||||
|
|
||||||
|
### 7.2 Context and target
|
||||||
|
|
||||||
|
`bind` requires:
|
||||||
|
|
||||||
|
- a context expression whose runtime value is a struct instance,
|
||||||
|
- a top-level function target whose first parameter is compatible with that struct type,
|
||||||
|
- and an expected callback type already validated by static semantics.
|
||||||
|
|
||||||
|
### 7.3 Runtime artifact
|
||||||
|
|
||||||
|
`bind(context, fn_name)` produces a nominal callback value that stores:
|
||||||
|
|
||||||
|
- the resolved top-level function target,
|
||||||
|
- the captured runtime identity of the context value.
|
||||||
|
|
||||||
|
The context is not copied or rematerialized during binding.
|
||||||
|
|
||||||
|
When the callback is later invoked, the runtime behaves as if it calls:
|
||||||
|
|
||||||
|
```text
|
||||||
|
fn_name(context, ...)
|
||||||
|
```
|
||||||
|
|
||||||
|
where `context` is the same captured runtime instance.
|
||||||
|
|
||||||
|
### 7.4 Evaluation and identity
|
||||||
|
|
||||||
|
The context expression is evaluated exactly once at bind time.
|
||||||
|
|
||||||
|
That evaluation exists only to obtain the struct instance that will be attached to the callback.
|
||||||
|
|
||||||
|
After capture:
|
||||||
|
|
||||||
|
- the same runtime context identity remains attached,
|
||||||
|
- mutations performed through the callback observe and affect that same context instance,
|
||||||
|
- `bind` does not create a detached copy of the context.
|
||||||
|
|
||||||
|
### 7.5 Storage and retention
|
||||||
|
|
||||||
|
`bind` is not semantically free.
|
||||||
|
|
||||||
|
Forming a callback through `bind` requires runtime storage sufficient to keep:
|
||||||
|
|
||||||
|
- the callback target identity,
|
||||||
|
- and the captured context alive while the callback value remains alive.
|
||||||
|
|
||||||
|
For the purposes of PBS v1 semantics, `bind` should be treated as a callback-forming operation with real retention and heap-facing consequences, even though the final memory/lifetime wording belongs in the dedicated memory specification.
|
||||||
|
|
||||||
|
### 7.6 Trap behavior
|
||||||
|
|
||||||
|
At the language-semantics level, `bind` is trap-free.
|
||||||
|
|
||||||
|
Incompatible context type, incompatible function target, or invalid callback shape are compile-time errors rather than runtime traps.
|
||||||
|
|
||||||
|
`bind` introduces no ordinary recoverable error surface and no bind-specific trap surface.
|
||||||
|
|
||||||
|
### 7.7 Non-goal
|
||||||
|
|
||||||
|
`bind` is not:
|
||||||
|
|
||||||
|
- general closure capture,
|
||||||
|
- arbitrary local-environment capture,
|
||||||
|
- or a promise that future closure features must behave identically.
|
||||||
|
|
||||||
|
It is the explicit v1 callback-binding mechanism only.
|
||||||
|
|
||||||
|
## 8. Explicit Non-Decisions
|
||||||
|
|
||||||
|
This decision record does not yet close:
|
||||||
|
|
||||||
|
- the final memory/lifetime wording for allocation, copy, and retention visibility,
|
||||||
|
- the final catalog of trap sources that may arise from subexpression evaluation.
|
||||||
|
|
||||||
|
## 9. Spec Impact
|
||||||
|
|
||||||
|
This decision should feed at least:
|
||||||
|
|
||||||
|
- `docs/pbs/specs/9. Dynamic Semantics Specification.md`
|
||||||
|
- `docs/pbs/specs/10. Memory and Lifetime Specification.md`
|
||||||
|
- `docs/pbs/specs/11. Diagnostics Specification.md`
|
||||||
|
|
||||||
|
The unresolved cost and retention wording for these surfaces should be completed through:
|
||||||
|
|
||||||
|
- `docs/pbs/agendas/Memory and Lifetime - Agenda.md`
|
||||||
|
- `docs/pbs/agendas/Heap Model - Agenda.md`
|
||||||
|
|
||||||
|
## 10. Validation Notes
|
||||||
|
|
||||||
|
The intended behavior is:
|
||||||
|
|
||||||
|
- `some(expr)` is eager,
|
||||||
|
- `opt else fallback` is short-circuit on `some`,
|
||||||
|
- `!` propagates the same typed error unchanged,
|
||||||
|
- `handle` remaps typed errors without introducing custom logic,
|
||||||
|
- `apply` remains the universal call surface across callable kinds,
|
||||||
|
- chained `apply` does not create implicit optional/result composition,
|
||||||
|
- `bind` captures a struct context identity without copying it,
|
||||||
|
- `bind` forms a callback with real retention/storage consequences,
|
||||||
|
- `handle` may recover with `ok(payload)` or propagate with `err(E2.case)`,
|
||||||
|
- short-form `handle` arms are sugar for propagation-only remap blocks,
|
||||||
|
- `trap` remains outside both `!` and `handle`.
|
||||||
@ -0,0 +1,131 @@
|
|||||||
|
# Dynamic Semantics - Execution Model Decision
|
||||||
|
|
||||||
|
Status: Accepted
|
||||||
|
Cycle: Initial execution-model closure pass
|
||||||
|
|
||||||
|
## 1. Context
|
||||||
|
|
||||||
|
PBS needs a closed execution-model baseline before effect surfaces and memory/lifetime semantics can be specified normatively.
|
||||||
|
|
||||||
|
The key open questions were:
|
||||||
|
|
||||||
|
- whether execution is single-threaded per program instance,
|
||||||
|
- which runtime effects are observable to user code,
|
||||||
|
- what the default evaluation order is,
|
||||||
|
- which constructs guarantee single evaluation,
|
||||||
|
- how abrupt completion behaves,
|
||||||
|
- how `result<Error>` differs from `trap`,
|
||||||
|
- and how host calls interact with `FRAME_SYNC` without perturbing user-visible sequencing.
|
||||||
|
|
||||||
|
## 2. Decision
|
||||||
|
|
||||||
|
PBS v1 adopts the following execution-model baseline:
|
||||||
|
|
||||||
|
1. Execution is single-threaded per program instance.
|
||||||
|
2. User-visible execution is deterministic and does not expose concurrent interleaving.
|
||||||
|
3. The default evaluation rule is strict left-to-right unless a construct explicitly states otherwise.
|
||||||
|
4. Call evaluation proceeds by forming the call target first, then evaluating arguments left-to-right, then invoking the target.
|
||||||
|
5. Abrupt completion terminates the current construct immediately and prevents later sibling evaluation.
|
||||||
|
6. Recoverable, expected failures belong to `result<Error>`, not to `trap`.
|
||||||
|
7. `trap` is reserved for non-recoverable runtime failures outside ordinary userland error flow.
|
||||||
|
8. Any trap aborts the current PBS program execution rather than returning control to ordinary userland flow.
|
||||||
|
9. `FRAME_SYNC` is the only normative safepoint in PBS v1.
|
||||||
|
10. `FRAME_SYNC` remains the execution boundary for userland progress; host-side work during that boundary must not reorder PBS-observable semantics.
|
||||||
|
|
||||||
|
## 3. Invariants
|
||||||
|
|
||||||
|
- PBS v1 does not expose a user-visible concurrent execution model.
|
||||||
|
- User-visible sequencing is defined by evaluation order, branch selection, abrupt completion, result propagation, trap propagation, and host-call boundaries.
|
||||||
|
- Traps are not recoverable in userland and do not resume PBS execution.
|
||||||
|
- VM-internal frame layout, temporary storage, and lowering steps are not observable unless they change the semantic effects above.
|
||||||
|
- Unless a construct states otherwise, subexpressions are evaluated once and in left-to-right order.
|
||||||
|
- `return`, `break`, `continue`, result propagation via `!`, and `trap` abort further evaluation in the current construct.
|
||||||
|
- Host calls must not introduce user-visible reordering of already-defined PBS evaluation order.
|
||||||
|
- No normative safepoint exists in v1 other than `FRAME_SYNC`.
|
||||||
|
|
||||||
|
## 4. Call Evaluation Rule
|
||||||
|
|
||||||
|
The runtime call rule for v1 is:
|
||||||
|
|
||||||
|
1. Form the call target.
|
||||||
|
2. Evaluate any receiver that participates in target formation.
|
||||||
|
3. Evaluate arguments in source order from left to right.
|
||||||
|
4. Invoke the resolved target.
|
||||||
|
5. Produce one of:
|
||||||
|
- normal return,
|
||||||
|
- explicit `result<Error>` propagation,
|
||||||
|
- or `trap`.
|
||||||
|
|
||||||
|
This rule applies to canonical `apply` and to ordinary call sugar that desugars to `apply`.
|
||||||
|
|
||||||
|
## 5. Error Boundary
|
||||||
|
|
||||||
|
`result<Error>` and `trap` are distinct runtime categories.
|
||||||
|
|
||||||
|
### 5.1 `result<Error>`
|
||||||
|
|
||||||
|
`result<Error>` is the required mechanism for failures that are:
|
||||||
|
|
||||||
|
- expected by the API contract,
|
||||||
|
- recoverable in ordinary userland control flow,
|
||||||
|
- modelable through an explicit PBS error type.
|
||||||
|
|
||||||
|
Such failures may be:
|
||||||
|
|
||||||
|
- processed with `handle`,
|
||||||
|
- propagated with `!`,
|
||||||
|
- and discussed as part of ordinary function contract design.
|
||||||
|
|
||||||
|
### 5.2 `trap`
|
||||||
|
|
||||||
|
`trap` is reserved for failures that are:
|
||||||
|
|
||||||
|
- outside the ordinary userland contract,
|
||||||
|
- not suitably representable as the declared `result<Error>` surface,
|
||||||
|
- caused by runtime or host invariant failure,
|
||||||
|
- or severe enough that ordinary userland recovery is not part of the v1 language model.
|
||||||
|
|
||||||
|
PBS v1 does not define `try/catch` for traps.
|
||||||
|
Traps are not part of ordinary recoverable control flow.
|
||||||
|
Once a trap is raised, PBS userland execution aborts and control transfers to runtime or firmware crash handling outside the ordinary language model.
|
||||||
|
|
||||||
|
## 6. Consequences
|
||||||
|
|
||||||
|
- User-authored code does not explicitly throw traps as part of ordinary PBS semantics.
|
||||||
|
- API surfaces must not use trap as a substitute for a modelable `result<Error>` failure.
|
||||||
|
- Host-backed operations must expose predictable operational failures through `result<Error>` when those failures are part of the callable contract.
|
||||||
|
- Residual host or runtime failures that cannot be represented by the declared PBS contract may still trap.
|
||||||
|
- The language-level consequence of trap is program abort rather than catchable failure handling.
|
||||||
|
- In v1, no safepoint inventory is normative beyond `FRAME_SYNC`.
|
||||||
|
|
||||||
|
## 7. Explicit Non-Decisions
|
||||||
|
|
||||||
|
This decision does not yet close:
|
||||||
|
|
||||||
|
- the exact list of constructs with explicit single-evaluation wording as finally integrated into the dynamic-semantics spec,
|
||||||
|
- the final wording split between dynamic semantics and runtime-initialization for trap/crash handoff.
|
||||||
|
|
||||||
|
Those points must be integrated by the remaining dynamic-semantics and memory/lifetime decisions.
|
||||||
|
|
||||||
|
## 8. Spec Impact
|
||||||
|
|
||||||
|
This decision should feed at least:
|
||||||
|
|
||||||
|
- `docs/pbs/specs/9. Dynamic Semantics Specification.md`
|
||||||
|
- `docs/pbs/specs/10. Memory and Lifetime Specification.md`
|
||||||
|
- `docs/pbs/specs/16. Runtime Execution and Initialization Specification.md`
|
||||||
|
|
||||||
|
It should also constrain future work in:
|
||||||
|
|
||||||
|
- `docs/pbs/specs/11. Diagnostics Specification.md`
|
||||||
|
- `docs/pbs/specs/13. Conformance Test Specification.md`
|
||||||
|
|
||||||
|
## 9. Validation Notes
|
||||||
|
|
||||||
|
The intended rule is:
|
||||||
|
|
||||||
|
- expected domain failure: `result<Error>`
|
||||||
|
- remappable, processable, or propagatable failure: `result<Error>`
|
||||||
|
- runtime invariant breakage or non-contract catastrophic failure: `trap`
|
||||||
|
|
||||||
|
In practical terms, a host-backed API must not rely on trap for ordinary operational failures if those failures can be declared and modeled explicitly in PBS. The only normative safepoint in v1 is `FRAME_SYNC`, and any trap aborts PBS userland execution rather than returning through an in-language recovery path.
|
||||||
130
docs/pbs/decisions/GC and Reachability Decision.md
Normal file
130
docs/pbs/decisions/GC and Reachability Decision.md
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# GC and Reachability Decision
|
||||||
|
|
||||||
|
Status: Accepted
|
||||||
|
Cycle: Initial GC-and-reachability closure pass
|
||||||
|
|
||||||
|
## 1. Context
|
||||||
|
|
||||||
|
PBS v1 uses GC as the baseline runtime model, but the language still needs a precise statement of:
|
||||||
|
|
||||||
|
- what reachability guarantees are normative,
|
||||||
|
- what reclamation guarantees are normative,
|
||||||
|
- what remains implementation-defined,
|
||||||
|
- how GC interacts with the single normative safepoint at `FRAME_SYNC`,
|
||||||
|
- and what user code may or may not observe.
|
||||||
|
|
||||||
|
## 2. Decision
|
||||||
|
|
||||||
|
PBS v1 adopts the following GC-and-reachability baseline:
|
||||||
|
|
||||||
|
1. GC is the baseline runtime model for VM-owned memory in PBS core.
|
||||||
|
2. Reachability is the normative liveness criterion for GC-managed values.
|
||||||
|
3. Eventual reclamation is the strongest reclamation guarantee in v1.
|
||||||
|
4. `FRAME_SYNC` is the only normative safepoint relevant to GC-observable behavior.
|
||||||
|
5. User code cannot observe reclamation directly.
|
||||||
|
6. PBS v1 defines no user-authored finalizers, destructors, or reclamation callbacks.
|
||||||
|
7. Implementations may perform internal GC work outside `FRAME_SYNC` only if doing so creates no additional user-visible semantic effects.
|
||||||
|
|
||||||
|
## 3. Normative Reachability Contract
|
||||||
|
|
||||||
|
For GC-managed VM-owned values, liveness is defined by reachability from the runtime roots that matter to PBS semantics.
|
||||||
|
|
||||||
|
At minimum, these roots include:
|
||||||
|
|
||||||
|
- currently active local/frame state,
|
||||||
|
- reachable fields of reachable struct instances,
|
||||||
|
- service singleton roots,
|
||||||
|
- retained callback state that remains reachable,
|
||||||
|
- and any other runtime roots required to preserve already-observable PBS behavior.
|
||||||
|
|
||||||
|
If a GC-managed value remains reachable through the normative runtime state, the implementation must preserve its continued semantic availability.
|
||||||
|
|
||||||
|
If a value becomes unreachable, user code must not rely on when reclamation occurs.
|
||||||
|
|
||||||
|
## 4. Reclamation Guarantee
|
||||||
|
|
||||||
|
PBS v1 guarantees eventual reclamation, not prompt reclamation.
|
||||||
|
|
||||||
|
This means:
|
||||||
|
|
||||||
|
- unreachable GC-managed memory may be reclaimed later,
|
||||||
|
- the language does not promise immediate reclamation,
|
||||||
|
- the language does not promise reclamation at a specific frame boundary,
|
||||||
|
- and the language does not expose a semantic event when reclamation occurs.
|
||||||
|
|
||||||
|
## 5. Safepoint Relationship
|
||||||
|
|
||||||
|
`FRAME_SYNC` is the only normative safepoint in PBS v1.
|
||||||
|
|
||||||
|
For GC semantics, this means:
|
||||||
|
|
||||||
|
- the language does not promise any additional observable GC safepoints,
|
||||||
|
- no user-visible program rule may depend on another safepoint existing,
|
||||||
|
- and any internal collector work outside `FRAME_SYNC` must remain semantically invisible to PBS userland.
|
||||||
|
|
||||||
|
The spec does not require a specific collector architecture.
|
||||||
|
It only constrains what may become observable.
|
||||||
|
|
||||||
|
## 6. Observability
|
||||||
|
|
||||||
|
User code cannot observe reclamation directly.
|
||||||
|
|
||||||
|
PBS v1 provides no user-visible mechanism for:
|
||||||
|
|
||||||
|
- detecting that a value was collected,
|
||||||
|
- registering a callback on reclamation,
|
||||||
|
- forcing immediate collection,
|
||||||
|
- or sequencing user code against GC timing.
|
||||||
|
|
||||||
|
GC-related information may appear in diagnostics, profiling, or runtime tooling, but those surfaces are not ordinary language semantics.
|
||||||
|
|
||||||
|
## 7. Finalization and Cleanup
|
||||||
|
|
||||||
|
PBS v1 forbids user-authored finalizers and destructor-like reclamation hooks.
|
||||||
|
|
||||||
|
GC reclamation of pure VM-owned values does not trigger user code.
|
||||||
|
|
||||||
|
Host-backed cleanup policy is not defined by GC finalization semantics in this decision.
|
||||||
|
If host-backed resources require explicit or contract-specific cleanup rules, those belong to the host-boundary decision track rather than to GC finalization in userland.
|
||||||
|
|
||||||
|
## 8. Invariants
|
||||||
|
|
||||||
|
- Reachability, not timing, is the normative semantic axis.
|
||||||
|
- Reclamation timing remains implementation-defined.
|
||||||
|
- No direct user-visible behavior is allowed to depend on collector timing.
|
||||||
|
- The only normative safepoint is `FRAME_SYNC`.
|
||||||
|
- GC must not create extra user-visible sequencing effects outside the already-closed execution model.
|
||||||
|
|
||||||
|
## 9. Beginner-Facing Model
|
||||||
|
|
||||||
|
The user-facing explanation should be:
|
||||||
|
|
||||||
|
- if a value can still be reached by the program, it remains alive,
|
||||||
|
- once it can no longer be reached, the runtime may clean it up later,
|
||||||
|
- the program does not control or directly observe that cleanup moment.
|
||||||
|
|
||||||
|
## 10. Explicit Non-Decisions
|
||||||
|
|
||||||
|
This decision record does not yet close:
|
||||||
|
|
||||||
|
- the exact collector algorithm,
|
||||||
|
- host-backed resource cleanup semantics,
|
||||||
|
- diagnostics wording for GC-related tooling surfaces,
|
||||||
|
- the full root-set wording as finally integrated into the memory specification.
|
||||||
|
|
||||||
|
## 11. Spec Impact
|
||||||
|
|
||||||
|
This decision should feed at least:
|
||||||
|
|
||||||
|
- `docs/pbs/specs/10. Memory and Lifetime Specification.md`
|
||||||
|
- `docs/pbs/specs/11. Diagnostics Specification.md`
|
||||||
|
- `docs/pbs/specs/16. Runtime Execution and Initialization Specification.md`
|
||||||
|
|
||||||
|
## 12. Validation Notes
|
||||||
|
|
||||||
|
The intended split is:
|
||||||
|
|
||||||
|
- GC defines reachability and eventual reclamation,
|
||||||
|
- `FRAME_SYNC` is the only normative safepoint,
|
||||||
|
- reclamation timing is not user-observable,
|
||||||
|
- host-backed cleanup is a separate boundary question rather than a user finalization feature.
|
||||||
115
docs/pbs/decisions/Host Memory Boundary Decision.md
Normal file
115
docs/pbs/decisions/Host Memory Boundary Decision.md
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
# Host Memory Boundary Decision
|
||||||
|
|
||||||
|
Status: Accepted
|
||||||
|
Cycle: Initial host-boundary closure pass
|
||||||
|
|
||||||
|
## 1. Context
|
||||||
|
|
||||||
|
PBS needs a user-visible contract for the boundary between VM-owned semantics and host-provided runtime services.
|
||||||
|
|
||||||
|
At the current stage of the language, userland does not expose complex host-owned resource models.
|
||||||
|
The runtime offers features and the frontend consumes them; PBS should be careful not to project unnecessary language-level memory abstractions into runtime internals too early.
|
||||||
|
|
||||||
|
## 2. Decision
|
||||||
|
|
||||||
|
PBS v1 adopts the following host-memory boundary baseline:
|
||||||
|
|
||||||
|
1. Cross-boundary interaction between host and PBS userland is restricted to stack-only values.
|
||||||
|
2. PBS userland does not expose host memory as ordinary language values.
|
||||||
|
3. Raw pointers are not exposed in PBS userland.
|
||||||
|
4. Borrowed host-memory views are not exposed in PBS userland.
|
||||||
|
5. Pinning is not exposed in PBS v1.
|
||||||
|
6. Zero-copy transfer is not exposed in PBS v1.
|
||||||
|
7. Heap-shared boundary values between host and PBS userland are not part of the v1 model.
|
||||||
|
8. Long-lived host resources, if later exposed, must be specified explicitly by subsystem contract rather than inferred from a general host-memory model.
|
||||||
|
|
||||||
|
## 3. Boundary Rule
|
||||||
|
|
||||||
|
The host/userland boundary in PBS v1 is value-based rather than memory-sharing-based.
|
||||||
|
|
||||||
|
This means:
|
||||||
|
|
||||||
|
- host-backed interaction happens through explicit call boundaries,
|
||||||
|
- data crossing that boundary is limited to stack-only value forms,
|
||||||
|
- and userland never receives direct access to host-owned memory regions.
|
||||||
|
|
||||||
|
PBS therefore does not model host memory as something the language can directly hold, borrow, pin, or traverse.
|
||||||
|
|
||||||
|
## 4. What Is Not Exposed
|
||||||
|
|
||||||
|
PBS v1 does not expose any general userland model for:
|
||||||
|
|
||||||
|
- raw host pointers,
|
||||||
|
- borrowed host slices or views,
|
||||||
|
- pinned host memory,
|
||||||
|
- zero-copy host/userland transfer,
|
||||||
|
- shared heap objects spanning host memory and VM memory.
|
||||||
|
|
||||||
|
These features are out of scope for the v1 language model.
|
||||||
|
|
||||||
|
## 5. Role of Syscalls
|
||||||
|
|
||||||
|
At the current stage, host interaction should be understood primarily through syscall-style host-backed contracts.
|
||||||
|
|
||||||
|
Those contracts may accept and return stack-only values, but they do not imply that PBS userland owns, borrows, or directly manipulates host memory.
|
||||||
|
|
||||||
|
## 6. Long-Lived Host Resources
|
||||||
|
|
||||||
|
PBS v1 does not yet define a general-purpose language model for long-lived host-owned resources such as:
|
||||||
|
|
||||||
|
- banks,
|
||||||
|
- mixers,
|
||||||
|
- or other subsystem-specific retained resources.
|
||||||
|
|
||||||
|
If such resources are exposed later, they must be specified by explicit subsystem contract rather than by assuming a general host-memory-handle model in core PBS.
|
||||||
|
|
||||||
|
## 7. Failure Model Scope
|
||||||
|
|
||||||
|
This decision does not force a universal language-level error projection for all runtime-internal host behavior.
|
||||||
|
|
||||||
|
It only closes the memory-boundary side of the question:
|
||||||
|
|
||||||
|
- PBS userland does not directly manipulate host memory,
|
||||||
|
- and cross-boundary interaction remains stack-value-based.
|
||||||
|
|
||||||
|
Concrete error modeling for particular host-backed surfaces belongs to the contract of those surfaces rather than to a general raw-memory boundary rule.
|
||||||
|
|
||||||
|
## 8. Invariants
|
||||||
|
|
||||||
|
- The host/runtime may own internal memory and resource lifetimes that PBS userland never sees directly.
|
||||||
|
- PBS userland remains insulated from host-memory unsoundness by not exposing raw memory access at the language level.
|
||||||
|
- The absence of pointers and borrowed host views is a core v1 safety property.
|
||||||
|
- Boundary simplicity takes priority over premature expressiveness in this area.
|
||||||
|
|
||||||
|
## 9. Beginner-Facing Model
|
||||||
|
|
||||||
|
The user-facing explanation should be:
|
||||||
|
|
||||||
|
- the runtime can provide services to PBS programs,
|
||||||
|
- programs pass ordinary values into those services and receive ordinary values back,
|
||||||
|
- but programs do not directly hold or manipulate host memory.
|
||||||
|
|
||||||
|
## 10. Explicit Non-Decisions
|
||||||
|
|
||||||
|
This decision record does not yet close:
|
||||||
|
|
||||||
|
- the future design of subsystem-specific long-lived host resources,
|
||||||
|
- the future design of any explicit resource-release APIs,
|
||||||
|
- the concrete error contract of each host-backed surface,
|
||||||
|
- the final wording of host-boundary diagnostics.
|
||||||
|
|
||||||
|
## 11. Spec Impact
|
||||||
|
|
||||||
|
This decision should feed at least:
|
||||||
|
|
||||||
|
- `docs/pbs/specs/10. Memory and Lifetime Specification.md`
|
||||||
|
- `docs/pbs/specs/6. VM-owned vs Host-backed.md`
|
||||||
|
- `docs/pbs/specs/6.2. Host ABI Binding and Loader Resolution Specification.md`
|
||||||
|
|
||||||
|
## 12. Validation Notes
|
||||||
|
|
||||||
|
The intended split is:
|
||||||
|
|
||||||
|
- runtime and host internals may remain complex,
|
||||||
|
- PBS userland sees only stack-only value exchange across the boundary,
|
||||||
|
- and any richer host-resource model must be introduced later by explicit subsystem contract.
|
||||||
@ -0,0 +1,121 @@
|
|||||||
|
# Lifetime Control and Future Profiles Decision
|
||||||
|
|
||||||
|
Status: Accepted
|
||||||
|
Cycle: Initial lifetime-control policy closure pass
|
||||||
|
|
||||||
|
## 1. Context
|
||||||
|
|
||||||
|
PBS v1 no longer uses the old RC/HIP model as an active core-language direction.
|
||||||
|
|
||||||
|
The remaining question is not how to design explicit lifetime control now, but how the project should treat legacy concepts and what policy should govern any future reintroduction of lifetime-oriented language features.
|
||||||
|
|
||||||
|
## 2. Decision
|
||||||
|
|
||||||
|
PBS v1 adopts the following lifetime-control policy baseline:
|
||||||
|
|
||||||
|
1. No lifetime-control keyword is reserved in core PBS merely for possible future use.
|
||||||
|
2. If a lifetime-control surface is not active in v1, it should not remain in the language as a reserved future-only keyword on that basis alone.
|
||||||
|
3. Advanced memory workflows should default to library/tooling-first exploration rather than syntax-first activation.
|
||||||
|
4. GC remains the default core model; future explicit lifetime control, if ever introduced, must be profile-gated rather than silently folded into the default language.
|
||||||
|
5. Future lifetime-oriented syntax may be introduced only when there is concrete evidence that library/tooling approaches are insufficient.
|
||||||
|
|
||||||
|
## 3. Legacy RC/HIP Concepts
|
||||||
|
|
||||||
|
Legacy concepts such as:
|
||||||
|
|
||||||
|
- `alloc`
|
||||||
|
- `borrow`
|
||||||
|
- `take`
|
||||||
|
- `weak`
|
||||||
|
- pool-style and arena-style control patterns
|
||||||
|
- object reuse patterns
|
||||||
|
|
||||||
|
do not remain active merely by historical inertia.
|
||||||
|
|
||||||
|
For PBS v1 policy:
|
||||||
|
|
||||||
|
- legacy concepts may survive as historical or design-reference material,
|
||||||
|
- but they do not imply reserved syntax commitment,
|
||||||
|
- and they do not imply a roadmap promise of later activation.
|
||||||
|
|
||||||
|
## 4. Language Versus Library Boundary
|
||||||
|
|
||||||
|
The default policy is:
|
||||||
|
|
||||||
|
- library first,
|
||||||
|
- tooling first,
|
||||||
|
- profile later only if justified,
|
||||||
|
- syntax last.
|
||||||
|
|
||||||
|
This means advanced workflows should first be explored through:
|
||||||
|
|
||||||
|
- stdlib APIs,
|
||||||
|
- tooling support,
|
||||||
|
- diagnostics,
|
||||||
|
- profiling guidance,
|
||||||
|
- subsystem-specific contracts where needed.
|
||||||
|
|
||||||
|
The language should not absorb explicit lifetime syntax simply because a legacy concept existed before.
|
||||||
|
|
||||||
|
## 5. Migration Narrative
|
||||||
|
|
||||||
|
The official migration narrative is:
|
||||||
|
|
||||||
|
- PBS v1 moves away from RC/HIP-style user-authored lifetime control as the core user model,
|
||||||
|
- GC plus deterministic execution is the baseline,
|
||||||
|
- performance-sensitive reasoning remains important,
|
||||||
|
- but performance and memory control should rise through explicit APIs and tooling before new syntax is considered.
|
||||||
|
|
||||||
|
This is a deliberate simplification, not a temporary placeholder awaiting automatic return to explicit ownership syntax.
|
||||||
|
|
||||||
|
## 6. Future Activation Criteria
|
||||||
|
|
||||||
|
Any future lifetime-oriented language/profile work must satisfy all of the following:
|
||||||
|
|
||||||
|
1. Real implementation and product evidence shows that library/tooling-first approaches are insufficient.
|
||||||
|
2. The proposed feature has a coherent semantic model that does not break the GC baseline by accident.
|
||||||
|
3. The feature can be isolated behind an explicit profile or equivalent opt-in boundary.
|
||||||
|
4. Diagnostics, conformance, and migration obligations are clear.
|
||||||
|
5. The feature does not degrade the beginner-facing default language without strong justification.
|
||||||
|
|
||||||
|
Future activation must be justified by present need and validated design, not by preserving speculative syntax in the current language.
|
||||||
|
|
||||||
|
## 7. Invariants
|
||||||
|
|
||||||
|
- GC remains the default core runtime model.
|
||||||
|
- Core PBS v1 does not promise future activation of legacy lifetime syntax.
|
||||||
|
- Absence of reserved lifetime keywords is a deliberate policy choice.
|
||||||
|
- Future explicit control must be explicit, justified, and profile-gated.
|
||||||
|
|
||||||
|
## 8. Beginner-Facing Model
|
||||||
|
|
||||||
|
The user-facing explanation should be:
|
||||||
|
|
||||||
|
- PBS v1 does not require ownership or lifetime syntax in ordinary code,
|
||||||
|
- advanced control is not removed as a future possibility,
|
||||||
|
- but it will be introduced only if it proves necessary and only through explicit design, not through dormant keywords left in the language.
|
||||||
|
|
||||||
|
## 9. Explicit Non-Decisions
|
||||||
|
|
||||||
|
This decision record does not yet close:
|
||||||
|
|
||||||
|
- the exact shape of any future profile mechanism,
|
||||||
|
- the exact syntax of any future explicit lifetime feature,
|
||||||
|
- the future stdlib design for pools, arenas, or weak-reference-like patterns.
|
||||||
|
|
||||||
|
## 10. Spec Impact
|
||||||
|
|
||||||
|
This decision should feed at least:
|
||||||
|
|
||||||
|
- `docs/pbs/specs/10. Memory and Lifetime Specification.md`
|
||||||
|
- `docs/pbs/specs/17. Compatibility and Evolution Policy.md`
|
||||||
|
- `docs/pbs/specs/3. Core Syntax Specification.md`
|
||||||
|
|
||||||
|
## 11. Validation Notes
|
||||||
|
|
||||||
|
The intended policy is:
|
||||||
|
|
||||||
|
- no dormant lifetime keywords in core v1,
|
||||||
|
- no nostalgia-based reservation policy,
|
||||||
|
- library/tooling first,
|
||||||
|
- profile-gated language activation only when clearly justified.
|
||||||
190
docs/pbs/decisions/Value Representation and Identity Decision.md
Normal file
190
docs/pbs/decisions/Value Representation and Identity Decision.md
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
# Value Representation and Identity Decision
|
||||||
|
|
||||||
|
Status: Accepted
|
||||||
|
Cycle: Initial value-representation closure pass
|
||||||
|
|
||||||
|
## 1. Context
|
||||||
|
|
||||||
|
PBS v1 needs a stable user-visible model for:
|
||||||
|
|
||||||
|
- which values are pure copied payloads,
|
||||||
|
- which values preserve shared runtime identity,
|
||||||
|
- which carriers merely wrap other values,
|
||||||
|
- and how callback values fit into the language without exposing general first-class functions or closures.
|
||||||
|
|
||||||
|
Earlier decisions already fixed important inputs:
|
||||||
|
|
||||||
|
- structs are reference-like in ordinary use,
|
||||||
|
- services are canonical singleton values,
|
||||||
|
- `bind(context, fn_name)` captures the same struct identity without copying it,
|
||||||
|
- `optional` and `result` remain explicit carriers rather than implicit effect-lifting mechanisms.
|
||||||
|
|
||||||
|
## 2. Decision
|
||||||
|
|
||||||
|
PBS v1 adopts the following value-representation baseline:
|
||||||
|
|
||||||
|
1. Pure scalar-like values are copied by value and do not carry user-visible identity.
|
||||||
|
2. Struct values are identity-bearing, heap-backed reference values.
|
||||||
|
3. Service values are identity-bearing canonical singleton values.
|
||||||
|
4. Host-backed resource values are identity-bearing values on the PBS side, even though their backing authority remains host-owned.
|
||||||
|
5. Tuple, `optional`, and `result` carriers do not introduce identity of their own.
|
||||||
|
6. Contract values do not introduce a new user-visible identity distinct from the underlying struct or service value.
|
||||||
|
7. Callback values are first-class callable values in PBS v1, but callback identity is not promoted as a user-visible identity concept.
|
||||||
|
8. Assignment, parameter passing, and return preserve aliasing for identity-bearing values and copy payload for pure value kinds.
|
||||||
|
|
||||||
|
## 3. Value Categories
|
||||||
|
|
||||||
|
### 3.1 Pure copied values
|
||||||
|
|
||||||
|
The following value kinds are pure copied values in the user model:
|
||||||
|
|
||||||
|
- `int`
|
||||||
|
- `float`
|
||||||
|
- `bool`
|
||||||
|
- enum values
|
||||||
|
- canonical `str`
|
||||||
|
|
||||||
|
Assignment, parameter passing, and return of these values copy the value itself.
|
||||||
|
|
||||||
|
### 3.2 Identity-bearing values
|
||||||
|
|
||||||
|
The following value kinds carry stable user-visible identity:
|
||||||
|
|
||||||
|
- struct values
|
||||||
|
- service values
|
||||||
|
- host-backed resource/handle values
|
||||||
|
|
||||||
|
Assignment, parameter passing, and return of these values preserve aliasing to the same runtime entity rather than copying an independent underlying object.
|
||||||
|
|
||||||
|
### 3.3 Carrier-only values
|
||||||
|
|
||||||
|
The following value kinds are carriers and do not create identity of their own:
|
||||||
|
|
||||||
|
- tuples
|
||||||
|
- `optional`
|
||||||
|
- `result`
|
||||||
|
|
||||||
|
They preserve the semantics of the values they contain.
|
||||||
|
|
||||||
|
If a carrier contains an identity-bearing payload, the carrier transports that same payload identity rather than inventing a new one.
|
||||||
|
|
||||||
|
## 4. Structs
|
||||||
|
|
||||||
|
Struct values are always reference-like in PBS v1.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `new Struct(...)` produces a fresh struct identity.
|
||||||
|
- Assignment of a struct value copies the reference, not the underlying field storage.
|
||||||
|
- Passing or returning a struct value preserves aliasing to the same struct instance.
|
||||||
|
- Mutation through one alias is observable through other aliases to that same struct instance.
|
||||||
|
|
||||||
|
## 5. Services
|
||||||
|
|
||||||
|
Service values are canonical module-owned singleton values.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- A service value denotes the same singleton identity wherever it is used in the same resolved program.
|
||||||
|
- Assignment, parameter passing, and return preserve that same singleton identity.
|
||||||
|
- Service use does not create fresh service instances.
|
||||||
|
|
||||||
|
## 6. Contract Values
|
||||||
|
|
||||||
|
Contract values do not introduce a new user-visible entity.
|
||||||
|
|
||||||
|
A contract value is a runtime view over:
|
||||||
|
|
||||||
|
- an underlying struct identity or service singleton identity,
|
||||||
|
- together with the selected contract implementation used for dispatch.
|
||||||
|
|
||||||
|
For user-facing semantics:
|
||||||
|
|
||||||
|
- aliasing is defined by the underlying struct or service value,
|
||||||
|
- not by treating the contract wrapper as a separate identity-bearing object.
|
||||||
|
|
||||||
|
## 7. Callback Values
|
||||||
|
|
||||||
|
Callback values are first-class callable values in PBS v1.
|
||||||
|
|
||||||
|
This means they may be:
|
||||||
|
|
||||||
|
- assigned to variables,
|
||||||
|
- passed as arguments,
|
||||||
|
- and returned from functions.
|
||||||
|
|
||||||
|
However, PBS v1 does not promote callback identity as an explicit user-visible identity concept.
|
||||||
|
|
||||||
|
### 7.1 Plain callback values
|
||||||
|
|
||||||
|
When a callback value is formed from a compatible top-level `fn`, it denotes a callable value over that target function.
|
||||||
|
|
||||||
|
### 7.2 Bound callback values
|
||||||
|
|
||||||
|
When a callback value is formed through `bind(context, fn_name)`:
|
||||||
|
|
||||||
|
- the same struct context identity is captured,
|
||||||
|
- the context is not copied,
|
||||||
|
- the callback retains the target function together with that captured context,
|
||||||
|
- and invoking the callback behaves as if the target function is called with the captured context as its first argument.
|
||||||
|
|
||||||
|
### 7.3 User model
|
||||||
|
|
||||||
|
The language must explain callback behavior without requiring the user to reason about callback identity as if callbacks were ordinary heap objects.
|
||||||
|
|
||||||
|
It is sufficient to state that:
|
||||||
|
|
||||||
|
- callbacks are first-class callable values,
|
||||||
|
- bound callbacks retain their captured context,
|
||||||
|
- and copies of a callback value preserve the same callable meaning and retained context.
|
||||||
|
|
||||||
|
## 8. Copy Versus Aliasing Rule
|
||||||
|
|
||||||
|
The general rule for PBS v1 is:
|
||||||
|
|
||||||
|
- pure value kinds are copied by value,
|
||||||
|
- identity-bearing kinds preserve aliasing,
|
||||||
|
- carrier kinds preserve the semantics of their contained values and do not create identity of their own.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- assigning an `int` copies the integer value,
|
||||||
|
- assigning a `Struct` value copies the reference to the same struct instance,
|
||||||
|
- assigning an `optional<Player>` that contains `some(player)` preserves the same `Player` identity inside the carrier,
|
||||||
|
- assigning a `result<E> Player` success payload preserves the same `Player` identity inside the carrier.
|
||||||
|
|
||||||
|
## 9. Beginner-Facing Model
|
||||||
|
|
||||||
|
The user-facing explanation should be:
|
||||||
|
|
||||||
|
- some values are plain data, so passing them passes the value,
|
||||||
|
- structs and services are shared entities, so passing them passes access to the same entity,
|
||||||
|
- tuples, `optional`, and `result` only package values and do not become new entities by themselves,
|
||||||
|
- callbacks are callable values, and bound callbacks keep the same captured context rather than copying it.
|
||||||
|
|
||||||
|
This wording is simple enough for beginners while still preserving the performance-relevant truth about aliasing and mutation.
|
||||||
|
|
||||||
|
## 10. Explicit Non-Decisions
|
||||||
|
|
||||||
|
This decision record does not yet close:
|
||||||
|
|
||||||
|
- the exact runtime layout of any heap object,
|
||||||
|
- collection value categories in detail,
|
||||||
|
- the final host-backed handle representation syntax,
|
||||||
|
- the final diagnostics wording for aliasing/copy visibility.
|
||||||
|
|
||||||
|
## 11. Spec Impact
|
||||||
|
|
||||||
|
This decision should feed at least:
|
||||||
|
|
||||||
|
- `docs/pbs/specs/10. Memory and Lifetime Specification.md`
|
||||||
|
- `docs/pbs/specs/4. Static Semantics Specification.md`
|
||||||
|
- `docs/pbs/specs/11. Diagnostics Specification.md`
|
||||||
|
|
||||||
|
## 12. Validation Notes
|
||||||
|
|
||||||
|
The intended split is:
|
||||||
|
|
||||||
|
- structs, services, and host-backed resources behave like identity-bearing entities,
|
||||||
|
- tuples, `optional`, and `result` are carriers,
|
||||||
|
- callbacks are first-class callable values without promoted callback identity in the user model.
|
||||||
Loading…
x
Reference in New Issue
Block a user