# 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` that contains `some(player)` preserves the same `Player` identity inside the carrier, - assigning a `result 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.