169 lines
7.5 KiB
Markdown
169 lines
7.5 KiB
Markdown
# Name Resolution - Builtin Shells and Host Owners Decision
|
|
|
|
Status: Accepted (Implemented)
|
|
Cycle: Initial name-resolution closure pass
|
|
|
|
## 1. Context
|
|
|
|
PBS v1 needs a deterministic rule for how reserved stdlib shells participate in source-level name resolution.
|
|
|
|
The open questions were:
|
|
|
|
- whether builtin shells and host owners enter lookup as ordinary imported declarations or as special compiler-only names,
|
|
- whether builtin intrinsic methods participate in free callable lookup,
|
|
- whether reserved shells receive special collision priority,
|
|
- whether builtin shells belong under `@core:*` or `@sdk:*` by policy,
|
|
- and which phase owns failures related to builtin member lookup and canonical identity duplication.
|
|
|
|
Important fixed inputs already existed:
|
|
|
|
- reserved stdlib project spaces are resolved from the selected stdlib environment,
|
|
- source-visible builtin names resolve through imported builtin shell declarations,
|
|
- canonical builtin and host identities come from metadata rather than local spelling,
|
|
- builtin intrinsic methods are not imported as free functions,
|
|
- and host-owner namespace remains distinct from type, value, and callable namespaces.
|
|
|
|
## 2. Decision
|
|
|
|
PBS v1 adopts the following baseline for builtin shells and host-owner resolution:
|
|
|
|
1. Source-visible declarations exposed by reserved builtin shells are imported into their ordinary corresponding namespaces.
|
|
2. This means builtin-exposed types enter type lookup as imported type declarations, builtin-exposed constants enter value lookup as imported values, and host owners enter host-owner lookup as imported host-owner declarations.
|
|
3. `declare builtin type` itself remains a reserved stdlib/toolchain declaration form rather than ordinary user-authored source syntax.
|
|
4. Reserved-shell metadata exists to drive canonical identity and later lowering, not to create special source-level lookup priority.
|
|
5. Builtin simple types `int`, `float`, `bool`, and `str` remain separate always-available reserved type names and are not treated as ordinary imported builtin shells.
|
|
6. Builtin intrinsic methods never participate in free lookup.
|
|
7. Builtin intrinsic methods are resolved only through member lookup on a receiver already known to have the corresponding builtin type.
|
|
8. Reserved builtin shells and host owners follow the same collision policy as ordinary imported declarations: same visible name in the same namespace is an error unless another already-closed rule explicitly permits otherwise.
|
|
9. By policy, builtin shells are preferred under `@core:*`.
|
|
10. Member lookup failure on an already-typed builtin receiver belongs to static semantics.
|
|
11. Duplicate canonical builtin identities or duplicate canonical host identities in one resolved environment belong normatively to linking rather than to syntax or ordinary static semantics.
|
|
|
|
## 3. Reserved Shells As Imported Declarations
|
|
|
|
Reserved shells are source-visible through ordinary import and visibility rules.
|
|
|
|
This means:
|
|
|
|
- the user imports the shell from a reserved stdlib module,
|
|
- the imported shell becomes visible in the matching namespace,
|
|
- and source-level lookup treats that visible declaration like other imported declarations of the same namespace.
|
|
|
|
The compiler still recognizes the reserved metadata attached to those declarations, but that metadata does not create a parallel hidden namespace.
|
|
|
|
## 4. Builtin Simple Types Versus Imported Builtin Shells
|
|
|
|
PBS distinguishes:
|
|
|
|
- the tiny predeclared builtin simple-type set: `int`, `float`, `bool`, `str`,
|
|
- and imported builtin shells such as `Vec2`, `Color`, or similar stdlib-exposed types.
|
|
|
|
Rules:
|
|
|
|
- builtin simple types remain always available without import,
|
|
- imported builtin shells are not promoted to that same status,
|
|
- and the two categories must not be conflated in source-level lookup.
|
|
|
|
## 5. Intrinsic Member Lookup
|
|
|
|
Builtin intrinsic members are resolved only through receiver-member lookup.
|
|
|
|
Rules:
|
|
|
|
- they do not appear in top-level callable lookup,
|
|
- they are not introduced by import as free functions,
|
|
- and aliasing the owner builtin type changes only the local visible owner spelling, not the intrinsic's canonical identity.
|
|
|
|
This keeps member semantics uniform and avoids special free-function treatment for reserved surfaces.
|
|
|
|
## 6. Collision Policy
|
|
|
|
Reserved shells receive no special collision privilege.
|
|
|
|
Rules:
|
|
|
|
- if an imported builtin shell declaration and another visible declaration produce the same visible name in the same namespace, the program is rejected under the ordinary collision rules already chosen,
|
|
- if a host owner shares a spelling with a type or value, that alone is not a conflict because host-owner namespace remains distinct,
|
|
- and reserved-shell status does not authorize silent shadowing.
|
|
|
|
## 7. Reserved Project-Space Policy
|
|
|
|
For source-level policy:
|
|
|
|
- builtin shells are preferred under `@core:*`,
|
|
- host-facing capability surfaces remain the natural fit for `@sdk:*`.
|
|
|
|
This is a policy direction for clarity and separation of concerns.
|
|
It does not change the underlying ownership model governed by other specs.
|
|
|
|
## 8. Failure Ownership Baseline
|
|
|
|
The current baseline is:
|
|
|
|
- failure to resolve a reserved stdlib module remains manifest/import resolution,
|
|
- import of a non-exported reserved shell remains linking,
|
|
- member lookup failure on an already-typed builtin receiver remains static semantics,
|
|
- duplicate canonical builtin or host identities in one resolved environment remain linking failures.
|
|
|
|
Implementations may internally perform some of these checks during environment validation, but the normative external phase ownership is linking where the linking-phase decision assigns it.
|
|
|
|
## 9. Invariants
|
|
|
|
- Reserved-shell metadata does not create special source-level lookup priority.
|
|
- Builtin intrinsic methods are never free functions in source-level lookup.
|
|
- Builtin simple types remain separate from stdlib-delivered builtin shells.
|
|
- Host owners remain in the host-owner namespace only.
|
|
- Ordinary collision rules apply to reserved-shell imports unless a later explicit rule says otherwise.
|
|
- Canonical identity conflicts are linking problems, not syntax problems.
|
|
|
|
## 10. Explicit Non-Decisions
|
|
|
|
This decision record does not yet close:
|
|
|
|
- the full stdlib-surface policy of `18. Standard Library Surface Specification.md`,
|
|
- and the final lowering consequences in `13. Lowering IRBackend Specification.md`.
|
|
|
|
## 11. Spec Impact
|
|
|
|
This decision should feed at least:
|
|
|
|
- `docs/general/specs/14. Name Resolution and Module Linking Specification.md`
|
|
- `docs/general/specs/18. Standard Library Surface Specification.md`
|
|
- `docs/pbs/specs/12. Diagnostics Specification.md`
|
|
|
|
It should also constrain future work in:
|
|
|
|
- `docs/pbs/specs/13. Lowering IRBackend Specification.md`
|
|
|
|
## 12. Validation Notes
|
|
|
|
The intended baseline is:
|
|
|
|
- reserved builtin shells are imported like ordinary declarations into the matching namespace,
|
|
- builtin methods are found only through receiver-member lookup,
|
|
- builtin simple types remain always available without import,
|
|
- `@core:*` is the preferred home for builtin shells,
|
|
- and duplicate canonical builtin or host identities are rejected at linking time.
|
|
|
|
Illustrative examples:
|
|
|
|
```pbs
|
|
import { Vec2 } from @core:math;
|
|
```
|
|
|
|
`Vec2` becomes an imported visible type declaration with builtin metadata.
|
|
|
|
```pbs
|
|
import { Vec2 } from @core:math;
|
|
Vec2.zero()
|
|
```
|
|
|
|
If `zero` is a builtin intrinsic member, it resolves through builtin member lookup on `Vec2`-typed receiver use and not through free callable lookup by the name `zero`.
|
|
|
|
```pbs
|
|
import { Vec2 } from @core:math;
|
|
declare const Vec2: int = 1;
|
|
```
|
|
|
|
This is rejected as an ordinary same-namespace collision rather than resolved by reserved-shell priority.
|