sorted agendas e discussions generated.

This commit is contained in:
bQUARKz 2026-03-03 09:47:29 +00:00
parent 9a46851791
commit b865e2386e
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
12 changed files with 1324 additions and 364 deletions

View File

@ -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`

View File

@ -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`

View File

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

View File

@ -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`

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

View File

@ -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`.

View File

@ -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`.

View File

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

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

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

View File

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

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