81 lines
5.3 KiB
Markdown
81 lines
5.3 KiB
Markdown
---
|
|
id: LSN-0024
|
|
ticket: pbs-game-facing-asset-refs-and-call-result-discard
|
|
title: Addressable Surface, Host Metadata, and Ignored-Value Discipline
|
|
created: 2026-03-30
|
|
tags: [compiler, pbs, asset-surface, lowering, diagnostics, runtime, host-metadata, ergonomics]
|
|
---
|
|
|
|
## Context
|
|
|
|
PBS needed to close two related gaps at the boundary between ergonomic game code and executable lowering.
|
|
Asset references needed an author-facing symbolic surface that did not fall back to unstable `asset_name` lookup or couple the frontend directly to packer internals.
|
|
At the same time, expression statements that produce values needed an explicit discard rule so backend stack discipline would not leak into source authoring.
|
|
|
|
The resulting implementation spans specs, frontend API models, backend lowering metadata, stdlib host surfaces, and compiler diagnostics.
|
|
|
|
## Key Decisions
|
|
|
|
### Keep Asset Authoring Symbolic But Backend-Owned
|
|
|
|
**What:**
|
|
PBS now treats `assets...` as a hierarchical compile-time namespace whose terminal leaves are `Addressable` values supplied through a backend-owned `FESurfaceContext`.
|
|
The v1 surface carries `List<Addressable(address, asset_id)>`.
|
|
|
|
**Why:**
|
|
This preserves natural source authoring while keeping the backend as the owner of operational asset identity and final `address -> asset_id` lowering.
|
|
The frontend gets enough structure for semantics, typing, and tooling without querying packer services directly.
|
|
|
|
**Trade-offs:**
|
|
Rename or move operations now change the canonical symbolic address and can break compile-time references.
|
|
That is stricter than a loose name-based model, but the breakage is explicit and deterministic instead of becoming late runtime ambiguity.
|
|
|
|
### Put Asset-Aware Lowering On Host Metadata, Not Service Bodies
|
|
|
|
**What:**
|
|
Asset-aware host calls now declare `[AssetLowering(param = N)]`, and backend lowering uses that metadata to rewrite the selected `Addressable` argument into runtime-facing `asset_id`.
|
|
|
|
**Why:**
|
|
This keeps lowering ownership on the host-backed contract surface instead of burying special behavior in wrapper services or generic expression shortcuts.
|
|
The lowering path stays aligned with `LowAssets`, and the compiler knows exactly which parameter is asset-facing.
|
|
|
|
**Trade-offs:**
|
|
Host-backed signatures must be validated more strictly, and metadata propagation has to remain consistent across extraction, indexing, and lowering.
|
|
That adds infrastructure, but it prevents the normative path from becoming implicit or drifting between layers.
|
|
|
|
### Treat Ignored Materialized Values As A General Language Rule
|
|
|
|
**What:**
|
|
Any PBS expression statement that produces a materialized value now triggers two things: a warning diagnostic and explicit discard lowering.
|
|
|
|
**Why:**
|
|
This keeps authoring simple without silently relying on backend stack behavior.
|
|
The language remains honest about ignored results while still allowing expression statements to execute.
|
|
|
|
**Trade-offs:**
|
|
The compiler now distinguishes unit-like results from materialized values in both semantics and lowering.
|
|
That is more work than silently discarding everything, but it yields a stable, testable language rule instead of API-specific exceptions.
|
|
|
|
## Patterns and Algorithms
|
|
|
|
- Use a backend-to-frontend surface contract when the frontend needs semantic visibility but must not own operational truth. `FESurfaceContext` is intentionally small and deduplicated by canonical address.
|
|
- Model symbolic assets as a namespace tree with terminal leaves only. Intermediate namespaces are not values, and terminal paths cannot also behave as namespace prefixes.
|
|
- Carry executable special cases as reserved host metadata. `[AssetLowering(param = N)]` is the authoritative marker for backend callsite rewriting.
|
|
- Make lowering side effects explicit when a source form hides operational cost. Ignored expression results are not silently tolerated; they lower to discard behavior and emit a warning.
|
|
- Pin cross-layer contracts in specs, stdlib surfaces, and compiler tests together. That prevents the PBS surface, host metadata, and runtime lowering path from drifting apart.
|
|
|
|
## Pitfalls
|
|
|
|
- Do not reintroduce `asset_name` as the operational compile-time identity. The symbolic surface is the canonical address derived from the asset root.
|
|
- Do not let the frontend query packer services directly for visible assets. It must consume the backend-owned surface contract.
|
|
- Do not bypass host metadata with generic expression rewriting for asset-aware calls. The normative path is host-backed `AssetLowering`.
|
|
- Do not treat intermediate `assets...` namespaces as terminal values, and do not allow terminal-vs-namespace collisions in asset roots.
|
|
- Do not silently drop ignored materialized values. If the compiler materializes a value in statement position, the discard path and warning are both part of the language contract.
|
|
|
|
## Takeaways
|
|
|
|
- PBS asset authoring is symbolic and hierarchical, but operational asset identity remains backend-owned and runtime-aligned through `asset_id`.
|
|
- Asset-aware lowering belongs to the host contract through reserved metadata, not to ad hoc wrapper logic.
|
|
- Ignored values are now a general PBS language rule: warn in semantics, discard explicitly in lowering.
|
|
- The durable pattern is consistent boundary ownership: frontend surfaces stay ergonomic, backend lowering stays authoritative, and the runtime contract remains explicit.
|