added specs for linkage model
This commit is contained in:
parent
239d7251c3
commit
7f831d8d37
@ -1,167 +1,321 @@
|
||||
# PBS v0 — Module & Linking Model (Self‑Contained Blob)
|
||||
# Prometeu PBS v0 — Unified Project, Module, Linking & Execution Specification
|
||||
|
||||
## Status
|
||||
|
||||
**Accepted (v0)** — This specification defines the authoritative execution and linking model for PBS v0.
|
||||
> **Status:** Canonical / Replaces all previous module & linking specs
|
||||
>
|
||||
> This document **fully replaces**:
|
||||
>
|
||||
> * "PBS – Module and Linking Model"
|
||||
> * Any partial or implicit module/linking descriptions in earlier PBS documents
|
||||
>
|
||||
> After this document, there must be **no parallel or competing spec** describing project structure, modules, imports, or linking for PBS v0.
|
||||
|
||||
---
|
||||
|
||||
## 1. Motivation
|
||||
## 1. Purpose
|
||||
|
||||
PBS is designed to be executed by a small, deterministic virtual machine embedded in PrometeuOS. To keep the VM **simple, secure, and optimizable**, all *semantic linking* must happen **before runtime**, in the compiler/tooling layer.
|
||||
This specification defines the **single authoritative model** for how a Prometeu PBS v0 program is:
|
||||
|
||||
The VM is **not a linker**. It is an executor with validation guarantees.
|
||||
1. Organized as a project
|
||||
2. Structured into modules
|
||||
3. Resolved and linked at compile time
|
||||
4. Emitted as one executable bytecode blob
|
||||
5. Loaded and executed by the Prometeu Virtual Machine
|
||||
|
||||
The primary objective is to **eliminate ambiguity** by enforcing a strict separation of responsibilities:
|
||||
|
||||
* **Compiler / Tooling**: all symbolic, structural, and linking work
|
||||
* **Runtime / VM**: verification and execution only
|
||||
|
||||
---
|
||||
|
||||
## 2. Core Principle
|
||||
## 2. Core Principles
|
||||
|
||||
> **A PBS module must be fully self‑contained and executable as a single blob.**
|
||||
### 2.1 Compiler Finality Principle
|
||||
|
||||
There is **no runtime linking** in PBS v0.
|
||||
All operations involving **names, symbols, structure, or intent** must be completed at compile time.
|
||||
|
||||
The VM only performs:
|
||||
The VM **never**:
|
||||
|
||||
```
|
||||
load → verify → execute
|
||||
* Resolves symbols or names
|
||||
* Loads or links multiple modules
|
||||
* Applies relocations or fixups
|
||||
* Interprets imports or dependencies
|
||||
|
||||
### 2.2 Single-Blob Execution Principle
|
||||
|
||||
A PBS v0 program is executed as **one fully linked, self-contained bytecode blob**.
|
||||
|
||||
At runtime there is no concept of:
|
||||
|
||||
* Projects
|
||||
* Modules
|
||||
* Imports
|
||||
* Dependencies
|
||||
|
||||
These concepts exist **only in the compiler**.
|
||||
|
||||
---
|
||||
|
||||
## 3. Project Model
|
||||
|
||||
### 3.1 Project Root
|
||||
|
||||
A Prometeu project is defined by a directory containing:
|
||||
|
||||
* `prometeu.json` — project manifest (required)
|
||||
* One or more module directories
|
||||
|
||||
### 3.2 `prometeu.json` Manifest
|
||||
|
||||
The project manifest is mandatory and must define:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "example_project",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"core": "../core",
|
||||
"input": "../input"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
#### Fields
|
||||
|
||||
## 3. What “Linking” Means in PBS
|
||||
* `name` (string, required)
|
||||
|
||||
In PBS, *linking* refers to resolving all symbolic or relative references into a **final, index‑based layout**.
|
||||
* Canonical project identifier
|
||||
* `version` (string, required)
|
||||
* `dependencies` (map, optional)
|
||||
|
||||
This includes:
|
||||
* Key: dependency project name
|
||||
* Value: filesystem path or resolver hint
|
||||
|
||||
* Function call resolution
|
||||
* Control‑flow targets (JMP / conditional branches)
|
||||
* Constant pool indexing
|
||||
* Syscall signature binding
|
||||
|
||||
All of this must be **fully resolved by the compiler/toolchain**.
|
||||
Dependency resolution is **purely a compiler concern**.
|
||||
|
||||
---
|
||||
|
||||
## 4. PBS v0 Module Structure
|
||||
## 4. Module Model (Compile-Time Only)
|
||||
|
||||
A PBS v0 module consists of:
|
||||
### 4.1 Module Definition
|
||||
|
||||
* `code: [u8]` — final bytecode stream
|
||||
* `functions: [FunctionMeta]` — function table
|
||||
* `const_pool: [Const]` — constant pool
|
||||
* (optional) metadata (build id, debug info, hashes)
|
||||
* A module is a directory inside a project
|
||||
* Each module contains one or more `.pbs` source files
|
||||
|
||||
The module is **self‑contained**: no external symbols, imports, or relocations.
|
||||
### 4.2 Visibility Rules
|
||||
|
||||
Visibility is enforced **exclusively at compile time**:
|
||||
|
||||
* `file`: visible only within the same source file
|
||||
* `mod`: visible within the same module
|
||||
* `pub`: visible to importing modules or projects
|
||||
|
||||
The VM has **zero awareness** of visibility.
|
||||
|
||||
---
|
||||
|
||||
## 5. Function Table and CALL Semantics
|
||||
## 5. Imports & Dependency Resolution
|
||||
|
||||
### 5.1 Function Identification
|
||||
### 5.1 Import Syntax
|
||||
|
||||
Functions are identified **by index** in the function table.
|
||||
Imports reference **projects and modules**, never files:
|
||||
|
||||
```
|
||||
import @core:math
|
||||
import @input:pad
|
||||
```
|
||||
|
||||
### 5.2 Resolution Pipeline
|
||||
|
||||
The compiler performs the following phases:
|
||||
|
||||
1. Project dependency graph resolution (via `prometeu.json`)
|
||||
2. Module discovery
|
||||
3. Symbol table construction
|
||||
4. Name and visibility resolution
|
||||
5. Type checking
|
||||
|
||||
Any failure aborts compilation and **never reaches the VM**.
|
||||
|
||||
---
|
||||
|
||||
## 6. Linking Model (Compiler Responsibility)
|
||||
|
||||
### 6.1 Link Stage
|
||||
|
||||
After semantic validation, the compiler executes a **mandatory link stage**.
|
||||
|
||||
The linker:
|
||||
|
||||
* Assigns final `func_id` indices
|
||||
* Assigns constant pool indices
|
||||
* Computes final `code_offset` and `code_len`
|
||||
* Resolves all jumps and calls
|
||||
* Merges all module bytecode into one contiguous code segment
|
||||
|
||||
### 6.2 Link Output Format
|
||||
|
||||
The output of linking is a **Linked PBS Program** with the following layout:
|
||||
|
||||
```text
|
||||
CALL <u32 func_id>
|
||||
[ Header ]
|
||||
[ Constant Pool ]
|
||||
[ Function Table ]
|
||||
[ Code Segment ]
|
||||
```
|
||||
|
||||
There are **no address‑based calls** in PBS v0.
|
||||
All references are:
|
||||
|
||||
### 5.2 FunctionMeta
|
||||
* Absolute
|
||||
* Final
|
||||
* Fully resolved
|
||||
|
||||
Each function is described by `FunctionMeta`:
|
||||
|
||||
* `code_offset`
|
||||
* `code_len`
|
||||
* `param_slots`
|
||||
* `local_slots`
|
||||
* `return_slots`
|
||||
* (optional) `max_stack_slots` (precomputed)
|
||||
|
||||
The compiler is responsible for emitting **correct metadata**.
|
||||
No relocations or fixups remain.
|
||||
|
||||
---
|
||||
|
||||
## 6. Control Flow (JMP / Branches)
|
||||
## 7. Runtime Execution Contract
|
||||
|
||||
* All jump targets are **relative to the start of the current function**.
|
||||
* Targets must land on **valid instruction boundaries**.
|
||||
### 7.1 VM Input Requirements
|
||||
|
||||
This eliminates the need for global relocations.
|
||||
The Prometeu VM accepts **only linked PBS blobs**.
|
||||
|
||||
It assumes:
|
||||
|
||||
* All function references are valid
|
||||
* All jumps target instruction boundaries
|
||||
* No unresolved imports exist
|
||||
|
||||
### 7.2 VM Responsibilities
|
||||
|
||||
The VM is responsible for:
|
||||
|
||||
1. Loading the bytecode blob
|
||||
2. Structural and control-flow verification
|
||||
3. Stack discipline verification
|
||||
4. Deterministic execution
|
||||
|
||||
The VM **must not**:
|
||||
|
||||
* Perform linking
|
||||
* Resolve symbols
|
||||
* Modify code offsets
|
||||
* Load multiple modules
|
||||
|
||||
---
|
||||
|
||||
## 7. Role of the Compiler / Tooling
|
||||
## 8. Errors and Runtime Traps
|
||||
|
||||
The compiler (or offline tooling) is responsible for:
|
||||
### 8.1 Compile-Time Errors
|
||||
|
||||
* Resolving all calls to `func_id`
|
||||
* Emitting the final function table
|
||||
* Laying out code contiguously
|
||||
* Emitting valid jump targets
|
||||
* Computing stack effects (optionally embedding `max_stack_slots`)
|
||||
* Ensuring ABI‑correct syscall usage
|
||||
Handled exclusively by the compiler:
|
||||
|
||||
The output must be a **ready‑to‑run PBS module**.
|
||||
* Unresolved imports
|
||||
* Visibility violations
|
||||
* Type errors
|
||||
* Circular dependencies
|
||||
|
||||
These errors **never produce bytecode**.
|
||||
|
||||
### 8.2 Runtime Traps
|
||||
|
||||
Runtime traps represent **deterministic execution faults**, such as:
|
||||
|
||||
* Stack underflow
|
||||
* Invalid local access
|
||||
* Invalid syscall invocation
|
||||
* Explicit `TRAP` opcode
|
||||
|
||||
Traps are part of the **execution model**, not debugging.
|
||||
|
||||
---
|
||||
|
||||
## 8. Role of the VM
|
||||
## 9. Versioning and Scope
|
||||
|
||||
The VM **does not perform linking**.
|
||||
### 9.1 PBS v0 Guarantees
|
||||
|
||||
It is responsible for:
|
||||
PBS v0 guarantees:
|
||||
|
||||
* Parsing the module
|
||||
* Verifying structural and semantic correctness
|
||||
* Executing bytecode deterministically
|
||||
* Single-blob execution
|
||||
* No runtime linking
|
||||
* Deterministic behavior
|
||||
|
||||
### 8.1 Mandatory Runtime Verification
|
||||
### 9.2 Out of Scope for v0
|
||||
|
||||
The VM must always verify:
|
||||
The following are explicitly excluded from PBS v0:
|
||||
|
||||
* Bytecode truncation / corruption
|
||||
* Stack underflow / overflow
|
||||
* Invalid `func_id`
|
||||
* Invalid jump targets
|
||||
* Syscall signature mismatches
|
||||
|
||||
These checks exist for **safety and determinism**, not for late binding.
|
||||
* Dynamic module loading
|
||||
* Runtime imports
|
||||
* Hot reloading
|
||||
* Partial linking
|
||||
|
||||
---
|
||||
|
||||
## 9. Legacy and Compatibility Policies
|
||||
## 10. Canonical Ownership Summary
|
||||
|
||||
Legacy formats (e.g. PPBC) may be supported behind explicit policies.
|
||||
| Concern | Owner |
|
||||
| ----------------- | ------------- |
|
||||
| Project structure | Compiler |
|
||||
| Dependencies | Compiler |
|
||||
| Modules & imports | Compiler |
|
||||
| Linking | Compiler |
|
||||
| Bytecode format | Bytecode spec |
|
||||
| Verification | VM |
|
||||
| Execution | VM |
|
||||
|
||||
Example:
|
||||
|
||||
* Legacy `CALL addr` encodings are **rejected** under Policy (A)
|
||||
* Only `CALL func_id` is valid in PBS v0
|
||||
|
||||
Compatibility handling is **orthogonal** to the linking model.
|
||||
> **Rule of thumb:**
|
||||
> If it requires names, symbols, or intent → compiler.
|
||||
> If it requires bytes, slots, or PCs → VM.
|
||||
|
||||
---
|
||||
|
||||
## 10. Future Evolution (Non‑Goals for v0)
|
||||
## 11. Final Note
|
||||
|
||||
PBS v0 explicitly does **not** define:
|
||||
After adoption of this document:
|
||||
|
||||
* Multi‑module linking
|
||||
* Dynamic imports
|
||||
* Runtime symbol resolution
|
||||
* Relocation tables
|
||||
|
||||
These may appear in future versions (v1+), but **v0 is closed and static by design**.
|
||||
* Any existing or future document describing PBS modules or linking **must defer to this spec**
|
||||
* Any behavior conflicting with this spec is considered **non-compliant**
|
||||
* The Prometeu VM is formally defined as a **pure executor**, not a linker
|
||||
|
||||
---
|
||||
|
||||
## 11. Summary
|
||||
## Addendum — `prometeu.json` and Dependency Management
|
||||
|
||||
* PBS modules are **single, self‑contained blobs**
|
||||
* All linking happens **before runtime**
|
||||
* The VM is a **verifying executor**, not a linker
|
||||
* This model enables aggressive optimization, predictability, and simplicity
|
||||
This specification intentionally **does not standardize the full dependency resolution algorithm** for `prometeu.json`.
|
||||
|
||||
This specification is **normative** for PBS v0.
|
||||
### Scope Clarification
|
||||
|
||||
* `prometeu.json` **defines project identity and declared dependencies only**.
|
||||
* **Dependency resolution, fetching, version selection, and conflict handling are responsibilities of the Prometeu Compiler**, not the VM and not the runtime bytecode format.
|
||||
* The Virtual Machine **never reads or interprets `prometeu.json`**.
|
||||
|
||||
### Compiler Responsibility
|
||||
|
||||
The compiler is responsible for:
|
||||
|
||||
* Resolving dependency sources (`path`, `git`, registry, etc.)
|
||||
* Selecting versions (exact, range, or `latest`)
|
||||
* Applying aliasing / renaming rules
|
||||
* Detecting conflicts and incompatibilities
|
||||
* Producing a **fully linked, closed-world Program Image**
|
||||
|
||||
After compilation and linking:
|
||||
|
||||
* All symbols are resolved
|
||||
* All function indices are fixed
|
||||
* All imports are flattened into the final bytecode image
|
||||
|
||||
The VM consumes **only the resulting bytecode blob** and associated metadata.
|
||||
|
||||
### Separate Specification
|
||||
|
||||
A **dedicated specification** will define:
|
||||
|
||||
* The complete schema of `prometeu.json`
|
||||
* Dependency version semantics
|
||||
* Resolution order and override rules
|
||||
* Tooling expectations (compiler, build system, CI)
|
||||
|
||||
This addendum exists to explicitly state the boundary:
|
||||
|
||||
> **`prometeu.json` is a compiler concern; dependency management is not part of the VM or bytecode execution model.**
|
||||
|
||||
268
docs/specs/pbs/PBS - prometeu.json specs.ms
Normal file
268
docs/specs/pbs/PBS - prometeu.json specs.ms
Normal file
@ -0,0 +1,268 @@
|
||||
# Prometeu.json — Project Manifest Specification
|
||||
|
||||
## Status
|
||||
|
||||
Draft · Complementary specification to the PBS Linking & Module Model
|
||||
|
||||
## Purpose
|
||||
|
||||
`prometeu.json` is the **project manifest** for Prometeu-based software.
|
||||
|
||||
Its role is to:
|
||||
|
||||
* Identify a Prometeu project
|
||||
* Declare its dependencies
|
||||
* Provide **input metadata to the compiler and linker**
|
||||
|
||||
It is **not** consumed by the Virtual Machine.
|
||||
|
||||
---
|
||||
|
||||
## Design Principles
|
||||
|
||||
1. **Compiler-owned**
|
||||
|
||||
* Only the Prometeu Compiler reads `prometeu.json`.
|
||||
* The VM and runtime never see this file.
|
||||
|
||||
2. **Declarative, not procedural**
|
||||
|
||||
* The manifest declares *what* the project depends on, not *how* to resolve it.
|
||||
|
||||
3. **Closed-world output**
|
||||
|
||||
* Compilation + linking produce a single, fully resolved bytecode blob.
|
||||
|
||||
4. **Stable identity**
|
||||
|
||||
* Project identity is explicit and versioned.
|
||||
|
||||
---
|
||||
|
||||
## File Location
|
||||
|
||||
`prometeu.json` must be located at the **root of the project**.
|
||||
|
||||
---
|
||||
|
||||
## Top-level Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my_project",
|
||||
"version": "0.1.0",
|
||||
"kind": "app",
|
||||
"dependencies": {
|
||||
"std": {
|
||||
"git": "https://github.com/prometeu/std",
|
||||
"version": ">=0.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fields
|
||||
|
||||
### `name`
|
||||
|
||||
**Required**
|
||||
|
||||
* Logical name of the project
|
||||
* Used as the **default module namespace**
|
||||
|
||||
Rules:
|
||||
|
||||
* ASCII lowercase recommended
|
||||
* Must be unique within the dependency graph
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
"name": "sector_crawl"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `version`
|
||||
|
||||
**Required**
|
||||
|
||||
* Semantic version of the project
|
||||
* Used by the compiler for compatibility checks
|
||||
|
||||
Format:
|
||||
|
||||
```
|
||||
MAJOR.MINOR.PATCH
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `kind`
|
||||
|
||||
**Optional** (default: `app`)
|
||||
|
||||
Defines how the project is treated by tooling.
|
||||
|
||||
Allowed values:
|
||||
|
||||
* `app` — executable program
|
||||
* `lib` — reusable module/library
|
||||
* `system` — firmware / system component
|
||||
|
||||
---
|
||||
|
||||
### `dependencies`
|
||||
|
||||
**Optional**
|
||||
|
||||
A map of **dependency aliases** to dependency specifications.
|
||||
|
||||
```json
|
||||
"dependencies": {
|
||||
"alias": { /* spec */ }
|
||||
}
|
||||
```
|
||||
|
||||
#### Alias semantics
|
||||
|
||||
* The **key** is the name by which the dependency is referenced **inside this project**.
|
||||
* It acts as a **rename / namespace alias**.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
"dependencies": {
|
||||
"gfx": {
|
||||
"path": "../prometeu-gfx"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Internally, the dependency will be referenced as `gfx`, regardless of its original project name.
|
||||
|
||||
---
|
||||
|
||||
## Dependency Specification
|
||||
|
||||
Each dependency entry supports the following fields.
|
||||
|
||||
### `path`
|
||||
|
||||
Local filesystem dependency.
|
||||
|
||||
```json
|
||||
{
|
||||
"path": "../std"
|
||||
}
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
* Relative paths are resolved from the current `prometeu.json`
|
||||
* Absolute paths are allowed but discouraged
|
||||
|
||||
---
|
||||
|
||||
### `git`
|
||||
|
||||
Git-based dependency.
|
||||
|
||||
```json
|
||||
{
|
||||
"git": "https://github.com/prometeu/std",
|
||||
"version": "^0.3.0"
|
||||
}
|
||||
```
|
||||
|
||||
The compiler is responsible for:
|
||||
|
||||
* Cloning / fetching
|
||||
* Version selection
|
||||
* Caching
|
||||
|
||||
---
|
||||
|
||||
### `version`
|
||||
|
||||
Optional version constraint.
|
||||
|
||||
Examples:
|
||||
|
||||
* Exact:
|
||||
|
||||
```json
|
||||
"version": "0.3.1"
|
||||
```
|
||||
|
||||
* Range:
|
||||
|
||||
```json
|
||||
"version": ">=0.2.0 <1.0.0"
|
||||
```
|
||||
|
||||
* Latest:
|
||||
|
||||
```json
|
||||
"version": "latest"
|
||||
```
|
||||
|
||||
Semantics are defined by the compiler.
|
||||
|
||||
---
|
||||
|
||||
## Resolution Model (Compiler-side)
|
||||
|
||||
The compiler must:
|
||||
|
||||
1. Load root `prometeu.json`
|
||||
2. Resolve all dependencies recursively
|
||||
3. Apply aliasing rules
|
||||
4. Detect:
|
||||
|
||||
* Cycles
|
||||
* Version conflicts
|
||||
* Name collisions
|
||||
5. Produce a **flat module graph**
|
||||
6. Invoke the linker to generate a **single Program Image**
|
||||
|
||||
---
|
||||
|
||||
## Interaction with the Linker
|
||||
|
||||
* `prometeu.json` feeds the **module graph**
|
||||
* The linker:
|
||||
|
||||
* Assigns final function indices
|
||||
* Fixes imports/exports
|
||||
* Emits a closed bytecode image
|
||||
|
||||
After linking:
|
||||
|
||||
> No module boundaries or dependency information remain at runtime.
|
||||
|
||||
---
|
||||
|
||||
## Explicit Non-Goals
|
||||
|
||||
This specification does **not** define:
|
||||
|
||||
* Lockfiles
|
||||
* Registry formats
|
||||
* Caching strategies
|
||||
* Build profiles
|
||||
* Conditional dependencies
|
||||
|
||||
These may be added in future specs.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
* `prometeu.json` is the **single source of truth for project identity and dependencies**
|
||||
* Dependency management is **compiler-owned**
|
||||
* The VM executes **only fully linked bytecode**
|
||||
|
||||
This file completes the boundary between **project structure** and **runtime execution**.
|
||||
@ -59,6 +59,8 @@ Import resolution:
|
||||
|
||||
* The import prefix `@project:` is resolved relative to `{root}/src/main/modules`.
|
||||
* Any path after `@project:` is interpreted as a **module path**, not a file path.
|
||||
* `project` is declared into `prometeu.json` as the project name. and int the case of
|
||||
missing it we should use `{root}` as project name.
|
||||
|
||||
If `{root}/src/main/modules` does not exist, compilation fails.
|
||||
|
||||
|
||||
@ -1,23 +1,10 @@
|
||||
# VM PR Plan — PBS v0 Executable (Industrial Baseline)
|
||||
# PRs for Junie — Compiler Dependency Resolution & Linking Pipeline
|
||||
|
||||
> **Goal:** make *all PBS v0 functionality* executable on the VM with **deterministic semantics**, **closed stack/locals contract**, **stable ABI**, and **integration-grade tests**.
|
||||
>
|
||||
> **Non-goal:** new language features. If something must be reworked to achieve industrial quality, it *must* be reworked.
|
||||
> Goal: Move dependency resolution + linking orchestration into **prometeu_compiler** so that the compiler produces a **single fully-linked bytecode blob**, and the VM/runtime only **loads + executes**.
|
||||
|
||||
---
|
||||
## Non-goals (for this PR set)
|
||||
|
||||
## Guiding invariants (apply to every PR)
|
||||
|
||||
### VM invariants
|
||||
|
||||
1. **Every opcode has an explicit stack effect**: `pop_n → push_m` (in *slots*, not “values”).
|
||||
2. **Frames are explicit**: params/locals/operand stack are separate or formally delimited.
|
||||
3. **No implicit behavior**: if it isn’t encoded in bytecode or runtime state, it doesn’t exist.
|
||||
4. **Deterministic traps** only (no UB): trap includes `trap_code`, `pc`, `opcode`, and (if present) `span`.
|
||||
5. **Bytecode stability**: versioned format; opcodes are immutable once marked v0.
|
||||
|
||||
### Compiler/VM boundary invariants
|
||||
|
||||
1. **Types map to slot counts** deterministically (including flattened SAFE structs and multi-slot returns).
|
||||
2. **Calling convention is frozen**: param order, return slots, caller/callee responsibilities.
|
||||
3. **Imports are compile/link-time only**; VM runs a fully-linked program image.
|
||||
* No lockfile format (yet)
|
||||
* No registry (yet)
|
||||
* No advanced SAT solver: first iteration is deterministic and pragmatic
|
||||
* No incremental compilation (yet)
|
||||
@ -1,34 +1,337 @@
|
||||
## PR-12 — VM test harness: stepper, trace, and property tests
|
||||
## PR-09 — Add `prometeu.json` manifest parser + schema validation
|
||||
|
||||
**Why:** Industrial quality means test tooling, not just “it runs”.
|
||||
**Why:** Dependency resolution cannot exist without a stable project manifest.
|
||||
|
||||
### Scope
|
||||
|
||||
* Add `VmRunner` test harness:
|
||||
* Implement `prometeu_compiler::manifest` module:
|
||||
|
||||
* step limit
|
||||
* deterministic trace of stack deltas
|
||||
* snapshot of locals
|
||||
* Add property tests (lightweight):
|
||||
* `Manifest` struct mirroring the spec fields:
|
||||
|
||||
* stack never underflows in verified programs
|
||||
* verified programs never jump out of bounds
|
||||
* `name`, `version`, `kind`
|
||||
* `dependencies: HashMap<Alias, DependencySpec>`
|
||||
* Support `DependencySpec` variants:
|
||||
|
||||
* `path`
|
||||
* `git` (+ optional `version`)
|
||||
* Validate:
|
||||
|
||||
* required fields present
|
||||
* dependency entry must specify exactly one source (`path` or `git`)
|
||||
* dependency aliases must be unique
|
||||
* basic name rules (non-empty, no whitespace)
|
||||
|
||||
### Deliverables
|
||||
|
||||
* `load_manifest(project_root) -> Result<Manifest, ManifestError>`
|
||||
* Diagnostic errors with file path + JSON pointer (or best-effort context)
|
||||
|
||||
### Tests
|
||||
|
||||
* parse minimal manifest
|
||||
* missing name/version errors
|
||||
* invalid dependency shape errors
|
||||
|
||||
### Acceptance
|
||||
|
||||
* Debugging is fast, and regressions are caught.
|
||||
* Compiler can reliably load + validate `prometeu.json`.
|
||||
|
||||
---
|
||||
|
||||
## Definition of Done (DoD) for PBS v0 “minimum executable”
|
||||
## PR-10 — Dependency Resolver v0: build a resolved project graph
|
||||
|
||||
A single canonical cartridge runs end-to-end:
|
||||
**Why:** We need a deterministic **module graph** from manifest(s) before compiling.
|
||||
|
||||
* `let` declarations (locals)
|
||||
* arithmetic (+, -, *, /, %, comparisons)
|
||||
* `if/else` control flow
|
||||
* `when` expression (if present in lowering)
|
||||
* function calls with params + returns (including `void`)
|
||||
* multiple return slots (flattened structs / hardware value types)
|
||||
* host syscalls (e.g., `GfxClear565`, `InputPadSnapshot`, `InputTouchSnapshot`)
|
||||
* deterministic traps (OOB bounded, invalid local, invalid call target, stack underflow)
|
||||
### Scope
|
||||
|
||||
* Implement `prometeu_compiler::deps::resolver`:
|
||||
|
||||
* Input: root project dir
|
||||
* Output: `ResolvedGraph`
|
||||
* Graph nodes:
|
||||
|
||||
* project identity: `{name, version}`
|
||||
* local alias name (the key used by the parent)
|
||||
* root path in filesystem (after fetch/resolve)
|
||||
* manifest loaded for each node
|
||||
* Resolution rules (v0):
|
||||
|
||||
* DFS/stack walk from root
|
||||
* cycle detection
|
||||
* collision handling:
|
||||
|
||||
* If the same (project name) appears with incompatible versions, error
|
||||
* aliasing:
|
||||
|
||||
* alias is local to the edge, but graph also stores the underlying project identity
|
||||
|
||||
### Deliverables
|
||||
|
||||
* `resolve_graph(root_dir) -> Result<ResolvedGraph, ResolveError>`
|
||||
* `ResolveError` variants:
|
||||
|
||||
* cycle detected (show chain)
|
||||
* missing dependency (path not found / git not fetchable)
|
||||
* version conflict (same project name, incompatible constraints)
|
||||
* name collision (two distinct projects claiming same name)
|
||||
|
||||
### Tests
|
||||
|
||||
* simple root -> dep path graph
|
||||
* cycle detection
|
||||
* alias rename does not change project identity
|
||||
|
||||
### Acceptance
|
||||
|
||||
* Compiler can produce a stable, deterministic dependency graph.
|
||||
|
||||
---
|
||||
|
||||
## PR-11 — Dependency Fetching v0: local cache layout + git/path fetch
|
||||
|
||||
**Why:** Graph resolution needs a concrete directory for each dependency.
|
||||
|
||||
### Scope
|
||||
|
||||
* Implement `prometeu_compiler::deps::fetch`:
|
||||
|
||||
* `fetch_path(dep, base_dir) -> ProjectDir`
|
||||
* `fetch_git(dep, cache_dir) -> ProjectDir`
|
||||
* Define a cache layout:
|
||||
|
||||
* `~/.prometeu/cache/git/<hash>/...` (or configurable)
|
||||
* the dependency is *materialized* as a directory containing `prometeu.json`
|
||||
* For git deps (v0):
|
||||
|
||||
* accept `git` URL + optional `version`
|
||||
* support `version: "latest"` as default
|
||||
* implementation can pin to HEAD for now (but must expose in diagnostics)
|
||||
|
||||
### Deliverables
|
||||
|
||||
* Config option: `PROMETEU_CACHE_DIR` override
|
||||
* Errors:
|
||||
|
||||
* clone failed
|
||||
* missing manifest in fetched project
|
||||
|
||||
### Tests
|
||||
|
||||
* path fetch resolves relative paths
|
||||
* cache path generation deterministic
|
||||
|
||||
### Acceptance
|
||||
|
||||
* Resolver can rely on fetcher to produce directories.
|
||||
|
||||
---
|
||||
|
||||
## PR-12 — Module Discovery v0: find PBS sources per project
|
||||
|
||||
**Why:** Once deps are resolved, the compiler must discover compilation units.
|
||||
|
||||
### Scope
|
||||
|
||||
* Define a convention (v0):
|
||||
|
||||
* `src/**/*.pbs` are source files
|
||||
* `src/main.pbs` for `kind=app` (entry)
|
||||
* Implement `prometeu_compiler::sources::discover(project_dir)`:
|
||||
|
||||
* returns ordered list of source files
|
||||
* Enforce:
|
||||
|
||||
* `kind=app` must have `src/main.pbs`
|
||||
* `kind=lib` must not require `main`
|
||||
|
||||
### Deliverables
|
||||
|
||||
* `ProjectSources { main: Option<Path>, files: Vec<Path> }`
|
||||
|
||||
### Tests
|
||||
|
||||
* app requires main
|
||||
* lib without main accepted
|
||||
|
||||
### Acceptance
|
||||
|
||||
* Compiler can list sources for every node in the graph.
|
||||
|
||||
---
|
||||
|
||||
## PR-13 — Build Plan v0: deterministic compilation order
|
||||
|
||||
**Why:** We need a stable pipeline: compile deps first, then root.
|
||||
|
||||
### Scope
|
||||
|
||||
* Implement `prometeu_compiler::build::plan`:
|
||||
|
||||
* Input: `ResolvedGraph`
|
||||
* Output: topologically sorted build steps
|
||||
* Each step contains:
|
||||
|
||||
* project identity
|
||||
* project dir
|
||||
* sources list
|
||||
* dependency edge map (alias -> resolved project)
|
||||
|
||||
### Deliverables
|
||||
|
||||
* `BuildPlan { steps: Vec<BuildStep> }`
|
||||
|
||||
### Tests
|
||||
|
||||
* topo ordering stable across runs
|
||||
|
||||
### Acceptance
|
||||
|
||||
* BuildPlan is deterministic and includes all info needed to compile.
|
||||
|
||||
---
|
||||
|
||||
## PR-14 — Compiler Output Format v0: emit per-project object module (intermediate)
|
||||
|
||||
**Why:** Linking needs an intermediate representation (IR/object) per project.
|
||||
|
||||
### Scope
|
||||
|
||||
* Define `CompiledModule` (compiler output) containing:
|
||||
|
||||
* `module_name` (project name)
|
||||
* `exports` (functions/symbols)
|
||||
* `imports` (symbol refs by (dep-alias, symbol))
|
||||
* `const_pool` fragment
|
||||
* `code` fragment
|
||||
* `function_metas` fragment
|
||||
* This is **not** the final VM blob.
|
||||
|
||||
### Deliverables
|
||||
|
||||
* `compile_project(step) -> Result<CompiledModule, CompileError>`
|
||||
|
||||
### Tests
|
||||
|
||||
* compile root-only project to `CompiledModule`
|
||||
|
||||
### Acceptance
|
||||
|
||||
* Compiler can produce a linkable unit per project.
|
||||
|
||||
---
|
||||
|
||||
## PR-15 — Link Orchestration v0 inside `prometeu_compiler`
|
||||
|
||||
**Why:** The compiler must produce the final closed-world blob.
|
||||
|
||||
### Scope
|
||||
|
||||
* Move “link pipeline” responsibility to `prometeu_compiler`:
|
||||
|
||||
* Input: `Vec<CompiledModule>` in build order
|
||||
* Output: `ProgramImage` (single bytecode blob)
|
||||
* Define linker responsibilities (v0):
|
||||
|
||||
* resolve imports to exports across modules
|
||||
* assign final `FunctionTable` indices
|
||||
* patch CALL targets to `func_id`
|
||||
* merge const pools deterministically
|
||||
* emit the final PBS v0 module image
|
||||
|
||||
### Deliverables
|
||||
|
||||
* `link(modules) -> Result<ProgramImage, LinkError>`
|
||||
* `LinkError`:
|
||||
|
||||
* unresolved import
|
||||
* duplicate export
|
||||
* incompatible symbol signatures (if available)
|
||||
|
||||
### Tests
|
||||
|
||||
* `archive-pbs/test01` becomes an integration test:
|
||||
|
||||
* root depends on a lib
|
||||
* root calls into lib
|
||||
* output blob runs in VM
|
||||
|
||||
### Acceptance
|
||||
|
||||
* Compiler emits a single executable blob; VM only loads it.
|
||||
|
||||
---
|
||||
|
||||
## PR-16 — VM Boundary Cleanup: remove linker behavior from runtime
|
||||
|
||||
**Why:** Runtime should be dumb: no dependency resolution, no linking.
|
||||
|
||||
### Scope
|
||||
|
||||
* Audit `prometeu_core` + `prometeu_bytecode`:
|
||||
|
||||
* VM loads PBS v0 module
|
||||
* VM verifies (optional) and executes
|
||||
* Remove/disable any linker-like logic in runtime:
|
||||
|
||||
* no search for func idx by address beyond function table
|
||||
* no module graph assumptions
|
||||
|
||||
### Deliverables
|
||||
|
||||
* VM init uses:
|
||||
|
||||
* `BytecodeLoader::load()` => `(code, const_pool, functions)`
|
||||
* verifier as a gate
|
||||
|
||||
### Tests
|
||||
|
||||
* runtime loads compiler-produced blob
|
||||
|
||||
### Acceptance
|
||||
|
||||
* Linking is fully compiler-owned.
|
||||
|
||||
---
|
||||
|
||||
## PR-17 — Diagnostics UX: show dependency graph + resolution trace
|
||||
|
||||
**Why:** When deps fail, we need actionable feedback.
|
||||
|
||||
### Scope
|
||||
|
||||
* Add CLI output (or compiler API output) showing:
|
||||
|
||||
* resolved graph
|
||||
* alias mapping
|
||||
* where a conflict occurred
|
||||
* Add `--explain-deps` mode (or equivalent)
|
||||
|
||||
### Deliverables
|
||||
|
||||
* human-readable resolution trace
|
||||
|
||||
### Tests
|
||||
|
||||
* snapshot tests for error messages (best-effort)
|
||||
|
||||
### Acceptance
|
||||
|
||||
* Users can debug dependency issues without guessing.
|
||||
|
||||
---
|
||||
|
||||
## Suggested execution order
|
||||
|
||||
1. PR-09 → PR-10 → PR-11
|
||||
2. PR-12 → PR-13
|
||||
3. PR-14 → PR-15
|
||||
4. PR-16 → PR-17
|
||||
|
||||
---
|
||||
|
||||
## Notes for Junie
|
||||
|
||||
* Keep all “v0” decisions simple and deterministic.
|
||||
* Favor explicit errors over silent fallback.
|
||||
* Treat `archive-pbs/test01` as the north-star integration scenario.
|
||||
* No background tasks: every PR must include tests proving the behavior.
|
||||
|
||||
5
test-cartridges/sdk/prometeu.json
Normal file
5
test-cartridges/sdk/prometeu.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"project": "sdk",
|
||||
"script_fe": "pbs",
|
||||
"produces": "lib"
|
||||
}
|
||||
12
test-cartridges/sdk/src/main/modules/gfx/gfx.pbs
Normal file
12
test-cartridges/sdk/src/main/modules/gfx/gfx.pbs
Normal file
@ -0,0 +1,12 @@
|
||||
declare struct Color(raw: bounded)
|
||||
[[
|
||||
BLACK: Color(0b),
|
||||
WHITE: Color(65535b),
|
||||
RED: Color(63488b),
|
||||
GREEN: Color(2016b),
|
||||
BLUE: Color(31b)
|
||||
]]
|
||||
|
||||
declare contract Gfx host {
|
||||
fn clear(color: Color): void;
|
||||
}
|
||||
29
test-cartridges/sdk/src/main/modules/input/input.pbs
Normal file
29
test-cartridges/sdk/src/main/modules/input/input.pbs
Normal file
@ -0,0 +1,29 @@
|
||||
declare struct ButtonState(
|
||||
pressed: bool,
|
||||
released: bool,
|
||||
down: bool,
|
||||
hold_frames: bounded
|
||||
)
|
||||
|
||||
declare struct Pad(
|
||||
up: ButtonState,
|
||||
down: ButtonState,
|
||||
left: ButtonState,
|
||||
right: ButtonState,
|
||||
a: ButtonState,
|
||||
b: ButtonState,
|
||||
x: ButtonState,
|
||||
y: ButtonState,
|
||||
l: ButtonState,
|
||||
r: ButtonState,
|
||||
start: ButtonState,
|
||||
select: ButtonState
|
||||
)
|
||||
|
||||
declare contract Input host {
|
||||
fn pad(): Pad;
|
||||
}
|
||||
|
||||
fn add(a: int, b: int): int {
|
||||
return a + b;
|
||||
}
|
||||
@ -1,7 +1,10 @@
|
||||
{
|
||||
"project": "test01",
|
||||
"script_fe": "pbs",
|
||||
"produces": "app",
|
||||
"entry": "src/main.pbs",
|
||||
"out": "build/program.pbc",
|
||||
"emit_disasm": true,
|
||||
"emit_symbols": true
|
||||
"dependencies": {
|
||||
"sdk": "../sdk"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,66 +0,0 @@
|
||||
// CartridgeCanonical.pbs
|
||||
// Purpose: VM Heartbeat Test (Industrial Baseline)
|
||||
|
||||
declare struct Color(raw: bounded)
|
||||
[[
|
||||
BLACK: Color(0b),
|
||||
WHITE: Color(65535b),
|
||||
RED: Color(63488b),
|
||||
GREEN: Color(2016b),
|
||||
BLUE: Color(31b)
|
||||
]]
|
||||
|
||||
declare struct ButtonState(
|
||||
pressed: bool,
|
||||
released: bool,
|
||||
down: bool,
|
||||
hold_frames: bounded
|
||||
)
|
||||
|
||||
declare struct Pad(
|
||||
up: ButtonState,
|
||||
down: ButtonState,
|
||||
left: ButtonState,
|
||||
right: ButtonState,
|
||||
a: ButtonState,
|
||||
b: ButtonState,
|
||||
x: ButtonState,
|
||||
y: ButtonState,
|
||||
l: ButtonState,
|
||||
r: ButtonState,
|
||||
start: ButtonState,
|
||||
select: ButtonState
|
||||
)
|
||||
|
||||
declare contract Gfx host {
|
||||
fn clear(color: Color): void;
|
||||
}
|
||||
|
||||
declare contract Input host {
|
||||
fn pad(): Pad;
|
||||
}
|
||||
|
||||
fn add(a: int, b: int): int {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
fn frame(): void {
|
||||
// 1. Locals & Arithmetic
|
||||
let x = 10;
|
||||
let y = 20;
|
||||
let z = add(x, y);
|
||||
|
||||
// 2. Control Flow (if)
|
||||
if z == 30 {
|
||||
// 3. Syscall Clear
|
||||
Gfx.clear(Color.GREEN);
|
||||
} else {
|
||||
Gfx.clear(Color.RED);
|
||||
}
|
||||
|
||||
// 4. Input Snapshot & Nested Member Access
|
||||
let p = Input.pad();
|
||||
if p.a.down {
|
||||
Gfx.clear(Color.BLUE);
|
||||
}
|
||||
}
|
||||
22
test-cartridges/test01/src/main/modules/main.pbs
Normal file
22
test-cartridges/test01/src/main/modules/main.pbs
Normal file
@ -0,0 +1,22 @@
|
||||
import { Color, Gfx, Input } from "@test01:sdk";
|
||||
|
||||
fn frame(): void {
|
||||
// 1. Locals & Arithmetic
|
||||
let x = 10;
|
||||
let y = 20;
|
||||
let z = add(x, y);
|
||||
|
||||
// 2. Control Flow (if)
|
||||
if z == 30 {
|
||||
// 3. Syscall Clear
|
||||
Gfx.clear(Color.GREEN);
|
||||
} else {
|
||||
Gfx.clear(Color.RED);
|
||||
}
|
||||
|
||||
// 4. Input Snapshot & Nested Member Access
|
||||
let p = Input.pad();
|
||||
if p.a.down {
|
||||
Gfx.clear(Color.BLUE);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user