15 KiB
PBS Manifest, Module, Stdlib, and SDK Resolution Specification
Status: Draft v2 (Normative)
Applies to: prometeu.json, project and module terminology, workspace dependency resolution, stdlib selection, reserved stdlib projects, interface-module loading, and compile-time SDK metadata
1. Purpose
This document defines the normative compile-time model for:
- project manifests,
- project and module identity,
- import resolution,
- stdlib selection,
- reserved stdlib project spaces,
- stdlib interface modules,
- and the compile-time lifecycle of SDK host-binding metadata.
This document is the authority for how the compiler discovers and loads:
- ordinary project modules,
- reserved stdlib modules such as
@sdk:gfx, - compile-time reserved metadata attached to those reserved modules,
- and interface-only service facades that wrap host surfaces for source ergonomics.
This document does not define runtime load behavior. PBX host-binding emission and loader-side syscall resolution are defined by the Host ABI Binding and Loader Resolution Specification.
2. Scope
This document defines:
- the role of
languageinprometeu.json, - the role of
stdlibinprometeu.json, - the distinction between projects, modules, and imports,
- the distinction between ordinary project dependencies and the stdlib environment,
- root-project ownership of the effective stdlib line of a build,
- reserved project spaces such as
@sdk:*and@core:*, - the source model for stdlib interface modules,
- the compile-time role of reserved attributes such as
[Host(...)].
This document does not define:
- PBX binary layout,
- loader-side syscall resolution,
- cartridge capability policy,
- package registry protocol details,
- runtime reflection over attributes.
3. Core Terms
3.1 Project
A project is the unit described by prometeu.json.
Rules:
- A project has a
name,version,language,stdlib, anddependencies. - A project is the unit resolved by the workspace dependency graph.
- A project is the unit selected by a dependency declaration.
- A project is the unit published and versioned by ordinary dependency resolution.
- A project contains one or more modules.
3.2 Module
A module is the unit of source import inside a project.
Rules:
- Every
.pbssource file belongs to exactly one module. - Every module belongs to exactly one project.
- Imports select modules, not whole projects.
- A module is addressed by a project name plus a module path.
3.3 Canonical module address
The canonical PBS module address format is:
@project:path/to/module
Rules:
projectidentifies the owning project space.path/to/moduleidentifies the module path inside that project.- Module path segments are directory-style segments separated by
/. - The syntax is Java-like in organization and JavaScript-like in import surface.
Examples:
@game:player/state@physics:collision/shapes@sdk:gfx@core:math/vector
3.4 Reserved project spaces
The following project spaces are reserved:
@sdk:*@core:*
Rules:
- Reserved project spaces belong to the selected stdlib environment.
- Ordinary user-authored projects MUST NOT publish modules into reserved project spaces.
- Ordinary dependency resolution MUST NOT satisfy
@sdk:*or@core:*imports from user projects. - Reserved project spaces are resolved only from the selected stdlib environment.
4. prometeu.json
4.1 Required fields
The manifest format relevant to this document is:
{
"name": "main",
"version": "1.0.0",
"language": "pbs",
"stdlib": "1",
"dependencies": [
{ "name": "dep1", "version": "1.0.0" }
]
}
Rules:
nameidentifies the project.versionidentifies the project version.languageidentifies the frontend language.stdlibidentifies the selected stdlib major line.dependenciesdeclare ordinary project dependencies only.
4.2 language
Rules:
languageselects the compiler frontend.- All projects in one resolved workspace MUST use the same
language. - Unknown
languagevalues are compile-time errors.
4.3 stdlib
Rules:
stdlibis required in every manifest.stdlibuses major-only version syntax in v1.- The manifest surface for
stdlibis a string containing a positive decimal integer. - Examples of valid values:
"1","2". - Examples of invalid values:
"0","01","1.0","v1","". - Implementations SHOULD normalize
stdlibinternally to an integer major version.
Diagnostics:
- Missing
stdlibis a manifest error. - Invalid major-only format is a manifest error.
5. Ordinary Dependencies vs Stdlib Environment
5.1 Ordinary dependencies
Rules:
dependenciesmodel ordinary project relationships only.- A dependency may be local or registry-based according to the compiler's dependency resolver.
- Dependencies contribute source projects, modules, and project-graph edges.
dependenciesdo not declare stdlib projects.
5.2 Stdlib environment
Rules:
- The stdlib environment is not declared through
dependencies. - The stdlib environment is selected through
stdlib. @sdk:*and@core:*imports resolve against the stdlib environment selected for the build.- The presence of stdlib modules does not imply automatic visibility in source.
- User code MUST still import stdlib modules explicitly through ordinary import syntax.
Example:
import { Gfx, color } from @sdk:gfx;
let c: color = color.red;
Gfx.draw_pixel(1, 1, c);
Rules:
Gfxis not implicitly in scope.Gfxbecomes visible only throughimport.- The compiler accepts that import because the selected stdlib environment exposes
@sdk:gfx.
6. Effective Stdlib of the Build
The root project owns the effective stdlib line of the build.
Rules:
- The resolved workspace has exactly one effective stdlib major version.
- The effective stdlib major version is taken from the root project manifest.
- All projects in the workspace compile under that same effective stdlib line.
- Dependency projects do not activate separate stdlib environments for themselves.
This means:
stdlibon a dependency is a compatibility declaration,- not an instruction to switch the compiler into another stdlib mode for that dependency.
7. Stdlib Compatibility Across Dependency Projects
Let:
Rbe the root project'sstdlibmajor,Dbe a dependency project'sstdlibmajor.
Rules:
- If
D > R, dependency resolution MUST fail with a deterministic compile-time error. - If
D <= R, dependency resolution MAY proceed. D <= Rdoes not guarantee semantic compatibility of all APIs used by the dependency; it only means the dependency is not asking for a newer stdlib line than the root selected.
Rationale:
- the build target is chosen by the root project,
- dependency projects may target the same or an older stdlib line,
- dependency projects must not force the build to silently adopt a newer stdlib than the root requested.
Example:
- root
stdlib = "1", dependencystdlib = "2": error. - root
stdlib = "2", dependencystdlib = "1": allowed. - root
stdlib = "1", dependencystdlib = "1": allowed.
8. Import Resolution
8.1 Resolution sources
The compiler resolves imports against exactly two sources:
- the selected stdlib environment,
- the resolved ordinary project dependency graph.
Rules:
@sdk:*and@core:*are resolved only against the stdlib environment,- all other
@project:*imports are resolved only against the ordinary dependency graph, - there is no fallback from reserved stdlib resolution to ordinary dependencies,
- there is no fallback from ordinary dependency resolution to reserved stdlib spaces.
8.2 Resolution algorithm
For an import:
import { X } from @project:path/to/module;
the compiler MUST:
- parse the project space and module path,
- determine whether the project space is reserved,
- if reserved, resolve the module from the selected stdlib environment,
- otherwise, resolve the module from the root project or its dependency graph,
- load the target module,
- resolve the requested exported names from that module.
Failure at any step is a deterministic compile-time error.
9. Stdlib Interface Modules
9.1 Interface-module model
The selected stdlib environment MUST provide its modules as PBS-like interface modules.
Rules:
- Stdlib modules are
.pbsmodules loaded by the compiler. - Stdlib interface modules use the same parser surface as ordinary PBS modules.
- Stdlib interface modules are interpreted in interface-module mode.
- Interface-module mode is non-executable and compile-time only.
- Interface modules participate in import resolution and type checking.
- Interface modules do not emit executable bytecode by themselves.
9.2 Allowed role
At minimum, an interface module may provide:
- exported names,
- types,
- enums,
- host owners,
- method signatures,
- compile-time metadata such as canonical host-binding attributes.
This list fixes the currently required declarative role of interface modules, but does not by itself freeze the final complete declaration set allowed in interface-module mode.
An interface module is not runtime code.
9.3 Interface-module restrictions
At minimum, an interface module MUST remain declarative.
Rules:
- Interface modules MUST NOT contain top-level executable statements.
- Interface modules MUST NOT require runtime initialization.
- Interface modules MUST NOT introduce executable method bodies that would emit bytecode.
declare hostis permitted only in reserved stdlib/toolchain interface modules.- Reserved attributes such as
[Host(...)]are permitted only where another specification explicitly allows them.
9.4 Example interface module
Illustrative stdlib interface module:
declare enum color(red, green, blue);
declare host Gfx {
[Host(module = "gfx", name = "draw_pixel", version = 1)]
fn draw_pixel(x: int, y: int, c: color);
}
Rules:
- This module is valid only in a reserved stdlib/interface-module context.
- It contributes compile-time symbols and metadata.
- It does not produce executable bytecode by itself.
10. Compiler Loading of the Stdlib Environment
The compiler loads the stdlib environment from the stdlib line selected by the root project.
Required model:
- Read the root
prometeu.json. - Determine the effective stdlib major line.
- Mount or select the matching stdlib environment.
- Expose its reserved project spaces such as
@sdk:*and@core:*. - Load interface modules from that environment on demand during import resolution.
- Parse those modules with the ordinary PBS parser.
- Validate them under interface-module semantic rules.
- Populate the compiler's symbol graph from their exported declarations and attributes.
Rules:
- The compiler MUST behave as if it were loading real modules, not hardcoded symbol tables.
- The physical storage format of the stdlib environment is an implementation detail.
- The compiler MAY load the stdlib environment from disk, embedded resources, a virtual filesystem, or another implementation-defined source with equivalent behavior.
- For the Studio PBS frontend, embedding stdlib interface modules under frontend
resourcesis a valid implementation strategy.
11. Reserved Attributes and Metadata Lifecycle
11.1 General rule
Attributes are compile-time metadata, not runtime objects.
Rules:
- Attributes are parsed as part of the source module.
- Attributes participate in declaration validation and compiler metadata extraction.
- Attributes are not exported as ordinary values, types, or runtime-reflectable objects.
- Attributes do not automatically survive into bytecode, PBX, or runtime metadata.
11.2 Host attribute
The canonical reserved host-binding attribute is:
[Host(module = "gfx", name = "draw_pixel", version = 1)]
Rules:
Hostis valid only on a host method signature declared directly inside a reserved stdlib/interface-moduledeclare hostbody.Hostprovides the canonical host primitive identity used by compiler lowering.moduleandnameare string literals.versionis a positive integer literal.- The attribute surface itself is compile-time only.
11.3 Lowering effect
Although the attribute syntax itself is compile-time only, its semantic effect may be lowered.
Rules:
- The compiler consumes
Hostmetadata while resolving host-backed SDK members. - The compiler uses that metadata to emit runtime-facing host-binding declarations as defined by the Host ABI Binding specification.
- The compiler does not export the raw
[Host(...)]syntax into runtime as a source-level attribute object.
In other words:
- the attribute is compile-time metadata,
- the lowered host-binding declaration is runtime-facing artifact metadata,
- they are not the same thing.
12. Relationship to declare host
Rules:
declare hostremains reserved to SDK/toolchain-controlled modules.- Ordinary user-authored project modules do not declare canonical host bindings directly.
- User code consumes SDK exports through normal imports.
- SDK-facing surfaces such as
Gfx.draw_pixel(...)are resolved by the compiler against the selected stdlib environment. - Canonical host identity comes from reserved host-binding metadata such as
[Host(...)], not from the source spelling of the imported owner.
13. Project Publication and Distribution
Rules:
- Ordinary publication and dependency resolution operate at project granularity.
- A published project version contains one or more modules.
- Imports consume modules from a resolved project.
- The stdlib environment is distributed separately from ordinary project dependencies.
- The stdlib environment is selected by
stdlib, not bydependencies.
14. Non-Goals
- Making stdlib modules implicitly visible without
import. - Treating the stdlib as an ordinary dependency in the workspace graph.
- Allowing each dependency project to activate its own stdlib line.
- Hardcoding stdlib symbols directly into the compiler without a module model.
- Runtime reflection over source-level attributes.
15. Open Items Deferred
The following remain intentionally deferred:
- Exact on-disk distribution format of stdlib environment packs.
- Registry/publication protocol details for ordinary projects.
- Final diagnostics catalog for all import-resolution failures.
- Full list of declarations allowed inside interface modules beyond the already-fixed reserved host surfaces.
16. Current Decision Summary
The current PBS design direction is:
prometeu.jsondeclareslanguageandstdlibseparately.- A project is the unit described by
prometeu.jsonand selected bydependencies. - A module is the unit selected by
import. - Canonical module addresses use
@project:path/to/module. @sdk:*and@core:*are reserved stdlib project spaces.- The root project selects the effective stdlib line for the whole build.
- Dependency projects with a higher stdlib requirement than the root are rejected.
- Stdlib modules are loaded as PBS-like interface modules, not as ordinary dependencies.
- Interface modules are compile-time-only in packaging terms: they may carry declarative service facades with method bodies for source-level API ergonomics, but they still do not emit executable bytecode as standalone modules.
declare hostremains reserved to stdlib/toolchain interface modules.- Reserved attributes such as
[Host(...)]are compile-time metadata, not runtime objects. - The compiler consumes
Hostmetadata to produce runtime-facing host-binding artifacts defined elsewhere.