# PBS Stdlib Environment Packaging and Loading Specification Status: Draft v1 (Temporary) Applies to: Studio PBS frontend stdlib packaging, stdlib environment discovery, reserved stdlib project spaces, and compiler-side stdlib loading abstractions ## 1. Purpose This document defines a practical packaging and loading model for the PBS stdlib environment inside the Studio compiler frontend. Its purpose is to make the stdlib: - available to the compiler without hardcoded symbol tables, - structured as real PBS interface modules, - versioned by stdlib major line, - and loadable through explicit compiler abstractions. This document complements the normative language-level model in: - [5. Manifest, Stdlib, and SDK Resolution Specification.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/pbs/5.%20Manifest,%20Stdlib,%20and%20SDK%20Resolution%20Specification.md) ## 2. Scope This document defines: - the recommended Studio packaging layout for stdlib interface modules, - the logical mapping between stdlib line, reserved project space, and module path, - the minimum compiler abstractions required to load stdlib modules, - the relationship between `resources` packaging and the logical stdlib environment. This document does not define: - runtime loader behavior, - PBX emission, - registry publication of stdlib packs, - final external distribution of stdlib outside Studio. ## 3. Core Model The compiler must load stdlib modules as real interface modules, not as hardcoded built-ins. Rules: - the stdlib is selected by the root project's `stdlib` major, - each stdlib line defines one stdlib environment, - a stdlib environment exposes reserved project spaces such as `@sdk:*` and `@core:*`, - each reserved project space contains one or more modules, - each module is represented as PBS source plus `mod.barrel`. ## 4. Recommended Studio Packaging Layout The recommended Studio layout is: ```text prometeu-compiler/frontends/prometeu-frontend-pbs/ src/main/resources/ stdlib/ 1/ sdk/ composer/ main.pbs mod.barrel gfx/ main.pbs mod.barrel asset/ main.pbs mod.barrel audio/ main.pbs mod.barrel core/ math/ main.pbs mod.barrel ``` Interpretation: - `stdlib/1` selects stdlib major line `1`, - `sdk` and `core` are reserved project spaces, - `composer`, `gfx`, `audio`, `math` are module paths within those reserved spaces, - `main.pbs` and `mod.barrel` form the interface module contents. ## 5. Logical Mapping The compiler must treat the physical layout as a logical stdlib environment. Required mapping: - `stdlib//sdk/gfx` -> `@sdk:gfx` - `stdlib//sdk/composer` -> `@sdk:composer` - `stdlib//sdk/asset` -> `@sdk:asset` - `stdlib//sdk/audio` -> `@sdk:audio` - `stdlib//core/math` -> `@core:math` - `stdlib//core/math/vector` -> `@core:math/vector` Rules: - physical storage is an implementation detail, - logical module identity is authoritative, - callers of the resolver should work with logical addresses such as `@sdk:gfx` and `@sdk:composer`, not resource paths. ## 6. Module File Convention For the Studio implementation, each stdlib module should follow the same structural convention as ordinary PBS modules: - one or more `.pbs` files, - exactly one `mod.barrel`. Recommended minimum convention: - `main.pbs` - `mod.barrel` Rules: - `main.pbs` is a convention, not a language-level requirement, - the module remains an ordinary PBS module from the parser's perspective, - it is interpreted under interface-module semantics because it lives in a reserved stdlib project space. ## 7. Required Compiler Abstractions The compiler should not reach directly into `resources` paths throughout the frontend. At minimum, the PBS frontend should define abstractions equivalent to: ### 7.1 `StdlibEnvironment` Responsibility: - represent the selected stdlib line for one compilation, - expose reserved project spaces, - provide access to interface modules by logical module address. Minimum operations: - select stdlib major line, - answer whether a reserved project space exists, - open a module by logical address. ### 7.2 `StdlibModuleResolver` Responsibility: - resolve logical imports in reserved project spaces, - map `@sdk:*` and `@core:*` imports to concrete interface module sources, - reject unknown stdlib modules deterministically. Minimum operations: - `resolve(@sdk:gfx)` - `resolve(@sdk:composer)` - `resolve(@core:math/vector)` ### 7.3 `StdlibModuleSource` Responsibility: - represent the source files of one stdlib module, - provide access to the module's `.pbs` files and `mod.barrel`, - hide whether content came from disk, `resources`, or another source. Minimum contents: - module address - list of `.pbs` source texts or streams - `mod.barrel` source text or stream ### 7.4 `InterfaceModuleLoader` Responsibility: - parse a stdlib module source using the normal PBS parser, - validate it in interface-module mode, - return compiler-facing symbols and metadata. Minimum outputs: - exported symbols - declared types - host owners - host method signatures - reserved attribute metadata such as `[Host(...)]` ## 8. Loading Algorithm The recommended Studio compiler flow is: 1. read the root `prometeu.json`, 2. parse and normalize `stdlib`, 3. construct `StdlibEnvironment` for that stdlib major, 4. create a `StdlibModuleResolver`, 5. when an import targets a reserved project space, resolve it through the stdlib resolver, 6. obtain a `StdlibModuleSource`, 7. parse the module with the standard PBS parser, 8. validate it under interface-module semantic rules, 9. cache the resulting interface module graph for the duration of the compilation. Rules: - reserved stdlib modules must not be handled through ordinary dependency resolution, - ordinary dependency modules must not be handled through the stdlib resolver, - a failed stdlib import is a deterministic compile-time error. ## 9. Attributes and Interface Metadata Stdlib interface modules may contain reserved compile-time attributes such as: ```pbs declare host Gfx { [Host(module = "gfx", name = "draw_pixel", version = 1)] fn draw_pixel(x: int, y: int, c: color); } ``` or: ```pbs declare host LowAssets { [Host(module = "asset", name = "load", version = 1)] [Capability(name = "asset")] [AssetLowering(param = 0)] fn load(addressable: Addressable, slot: int) -> (status: int, loading_handle: int); } ``` or: ```pbs declare host LowComposer { [Host(module = "composer", name = "emit_sprite", version = 1)] [Capability(name = "gfx")] fn emit_sprite( glyph_id: int, palette_id: int, x: int, y: int, layer: int, bank_id: int, flip_x: bool, flip_y: bool, priority: int ) -> int; } ``` Rules: - the parser reads the attribute as part of the interface module source, - the interface-module loader validates that the attribute is legal in that position, - the compiler stores the extracted metadata in its interface graph, - the raw attribute surface is not treated as a runtime object, - later lowering stages may consume the extracted metadata to produce PBX host-binding declarations. - stdlib line `1` MUST expose the sprite-composition interface module at `@sdk:composer`, - that module MUST declare `LowComposer` and public service `Composer`, - that module MUST use runtime module `composer` and capability `gfx`, - that module MUST expose `emit_sprite(glyph_id: int, palette_id: int, x: int, y: int, layer: int, bank_id: int, flip_x: bool, flip_y: bool, priority: int) -> int`, - stdlib line `1` MUST NOT expose `Gfx.set_sprite`, - stdlib line `1` MUST expose the low-level asset interface module at `@sdk:asset`, - that module MUST declare `LowAssets`, - that module MUST use runtime module `asset` and capability `asset`, - that module MUST use the runtime-aligned signatures and reserved lowering metadata: - `load(addressable: Addressable, slot: int) -> (status: int, loading_handle: int)` together with `[AssetLowering(param = 0)]` - `status(loading_handle: int) -> int` - `commit(loading_handle: int) -> int` - `cancel(loading_handle: int) -> int` ## 10. Resources as an Implementation Strategy For the Studio PBS frontend, packaging stdlib interface modules in frontend `resources` is a valid implementation strategy. Rules: - `resources` packaging is implementation-level, not language-level, - the compiler should still access stdlib modules through `StdlibEnvironment` and related abstractions, - code outside the stdlib loader should not depend on resource path layout directly. Rationale: - `resources` gives a simple bootstrap path, - stdlib evolves as real source artifacts, - the frontend avoids hardcoded built-ins, - the implementation remains replaceable later. ## 11. Caching and Reuse The compiler may cache stdlib interface modules within one compilation or across compilations. Rules: - caching must not change observable semantics, - cache keys should include at least the stdlib major line and logical module address, - cached modules must preserve the same parsed declarations and attribute metadata as uncached loads. ## 12. Current Decision Summary The current Studio direction is: 1. the stdlib environment is loaded as real PBS interface modules, 2. the initial implementation may live under frontend `resources`, 3. the logical model remains `stdlib line -> reserved project space -> module path`, 4. the compiler should use explicit abstractions such as `StdlibEnvironment` and `StdlibModuleResolver`, 5. stdlib interface modules are parsed with the normal PBS parser and validated in interface-module mode, 6. reserved attributes such as `[Host(...)]` are extracted as compile-time metadata for later lowering.