prometeu-studio/docs/compiler/pbs/decisions/Value Representation and Identity Decision.md
2026-03-24 13:42:37 +00:00

191 lines
6.8 KiB
Markdown

# Value Representation and Identity Decision
Status: Accepted (Implemented)
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/12. 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.