prometeu-studio/docs/specs/compiler-languages/pbs/8. Stdlib Environment Packaging and Loading Specification.md
2026-04-18 17:01:31 +01:00

305 lines
9.7 KiB
Markdown

# 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/<N>/sdk/gfx` -> `@sdk:gfx`
- `stdlib/<N>/sdk/composer` -> `@sdk:composer`
- `stdlib/<N>/sdk/asset` -> `@sdk:asset`
- `stdlib/<N>/sdk/audio` -> `@sdk:audio`
- `stdlib/<N>/core/math` -> `@core:math`
- `stdlib/<N>/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.