prometeu-studio/docs/pbs/agendas/14.1. Name Resolution Workshop 1 - Scope, Lookup, and Imports.md
2026-03-24 13:42:18 +00:00

7.5 KiB

PBS Name Resolution Workshop 1

Status: Active

Purpose

Run the first focused discussion for 14. Name Resolution and Module Linking Specification.md on the smallest set of decisions that unlocks normative frontend work:

  • scope construction,
  • namespace-specific lookup order,
  • import visibility,
  • and ambiguity rejection.

Why This Slice First

This slice is the best first cut because it does not require full lowering closure, but it does unblock:

  • parser and binder architecture,
  • symbol-table modeling,
  • deterministic frontend diagnostics,
  • and the later discussion of overload visibility and reserved stdlib shells.

It should intentionally avoid trying to close every linking edge case in one meeting.

Proposed Meeting Order

  1. Confirm already-settled inputs that are not up for debate.
  2. Close scope-construction rules inside one module.
  3. Close lookup order by namespace.
  4. Close import visibility and alias rules.
  5. Close ambiguity and duplicate rejection rules.
  6. Record deferred items for a second workshop.

Already-Settled Inputs To Reconfirm

The meeting should start by explicitly reaffirming:

  • mod.barrel is the single source of module visibility.
  • Imports target modules, not files.
  • Only pub names are importable from another module.
  • PBS has distinct type, value, callable, and host-owner namespaces.
  • Builtin simple types int, float, bool, and str are always present in type position.
  • Reserved stdlib spaces resolve from the selected stdlib environment, not from ordinary dependencies.

These points already come from existing specs and should not be reopened in this workshop.

Decisions To Produce

  1. Scope construction inside a module.
  2. Lookup order in value, type, callable, and host-owner position.
  3. Import alias behavior and collisions.
  4. Ambiguity rules when multiple imports expose the same visible name.
  5. The phase boundary between syntax, static semantics, and linking for these failures.

Candidate Decisions

1. Scope Construction Inside One Module

Candidate direction:

  • File-local top-level declarations are collected first from all .pbs files in the module.
  • mod.barrel is then applied as a visibility filter over the already-collected top-level declarations.
  • Top-level declaration availability inside the same module does not depend on source-file order.
  • Local block scopes nest normally over module scope.

Rationale:

  • This matches the existing module model.
  • It prevents file-order-dependent lookup.
  • It keeps barrel as a visibility mechanism, not as the source of declaration existence.

2. Lookup Order By Namespace

Candidate direction:

Value position:

  • nearest local bindings,
  • parameters,
  • visible declare const,
  • visible imported values,
  • service singleton values introduced by visible service declarations.

Type position:

  • nearest type declarations visible in module scope,
  • visible imported type declarations,
  • builtin simple types.

Callable position:

  • nearest callable declarations visible in module scope,
  • then visible imported callable declarations,
  • with overload sets formed after visibility filtering.

Host-owner position:

  • visible host owners in module scope,
  • then visible imported host owners.

Open point for discussion:

  • whether builtin simple types should be treated as implicit outermost scope or as a final fallback outside ordinary visible declarations.

3. Import Alias Rules

Candidate direction:

  • import @project:mod; imports the module itself as a module-qualified reference surface only if another spec later defines such a surface.
  • For current v1 name resolution, named imports are the only source of imported visible names.
  • import { X } from ...; introduces X in the matching namespace of the exported declaration.
  • import { X as Y } from ...; introduces only Y locally.
  • Alias spelling affects only the local visible name, never canonical builtin or host identity.

Rationale:

  • Keeps current source behavior conservative.
  • Avoids inventing module-as-value semantics accidentally.
  • Matches the existing distinction between source-visible spelling and canonical metadata identity.

4. Collision And Ambiguity Rules

Candidate direction:

  • Two local declarations in the same namespace that produce the same non-overload identity are duplicates.
  • A local declaration and an imported declaration with the same visible name in the same namespace are a deterministic conflict unless one rule explicitly allows shadowing.
  • Two imported declarations with the same visible name in the same namespace are a deterministic ambiguity unless they are the same declaration reached through the same canonical module resolution.
  • Callable overload sets may merge only when their callable identities remain distinct after tuple-shape identity rules are applied.
  • Non-callable namespaces do not merge by name.

Open point for discussion:

  • whether local declarations should fully shadow imports in value, type, callable, and host-owner namespaces, or whether PBS should reject such shadowing to keep lookup simpler for beginners.

5. Diagnostic Phase Boundary

Candidate direction:

  • malformed import syntax remains syntax-phase.
  • unresolved module path remains manifest/import-resolution phase.
  • import of non-exported symbol remains linking-phase or manifest/import-resolution-adjacent phase, but not syntax-phase.
  • duplicate local declarations remain static-semantics phase.
  • ambiguous visible names after import resolution remain linking-phase unless the project later collapses linking into static semantics explicitly.

Rationale:

  • This preserves a clean split between parsing, declaration validity, and cross-module resolution.
  • It gives 11. Diagnostics Specification.md a concrete input rather than forcing that spec to invent phases in isolation.

Questions To Resolve In The Room

  1. Do local top-level declarations shadow imported names, or is any such collision rejected?
  2. Are parameters and local let bindings one combined nearest-scope value layer, or should parameters be modeled separately for diagnostics only?
  3. Can imported overloads and local overloads merge into one callable set, or must that be rejected?
  4. Is import @project:module; currently just side-effect-free validation, or should it create any usable source-visible surface in v1?
  5. Do builtin simple types behave like reserved final fallback names or like ordinary always-visible type declarations?

Expected Outputs

This workshop should produce:

  1. a decision record for scope and lookup order,
  2. a decision record for import alias and ambiguity policy,
  3. a concrete update plan for 14. Name Resolution and Module Linking Specification.md,
  4. and a list of deferred issues for Workshop 2.

Explicit Deferrals For Workshop 2

The following topics should be deferred unless they become unavoidable:

  • reserved stdlib shell priority versus ordinary imports,
  • member lookup on builtin receivers,
  • contract and method dispatch lookup details,
  • barrel matching of callable overload sets across module boundaries,
  • and whether linking is its own normative phase or is folded fully into static semantics.

Inputs

  • docs/pbs/specs/3. Core Syntax Specification.md
  • docs/pbs/specs/4. Static Semantics Specification.md
  • docs/pbs/specs/5. Manifest, Stdlib, and SDK Resolution Specification.md
  • docs/pbs/specs/14. Name Resolution and Module Linking Specification.md
  • docs/pbs/specs/18. Standard Library Surface Specification.md
  • docs/pbs/agendas/14. Name Resolution and Module Linking Agenda.md