added specs for linkage model

This commit is contained in:
Nilton Constantino 2026-02-02 11:41:26 +00:00
parent 239d7251c3
commit 7f831d8d37
No known key found for this signature in database
11 changed files with 923 additions and 204 deletions

View File

@ -1,167 +1,321 @@
# PBS v0 — Module & Linking Model (SelfContained 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 selfcontained 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, indexbased 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
* Controlflow 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 **selfcontained**: 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 addressbased 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 ABIcorrect syscall usage
Handled exclusively by the compiler:
The output must be a **readytorun 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 (NonGoals for v0)
## 11. Final Note
PBS v0 explicitly does **not** define:
After adoption of this document:
* Multimodule 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, selfcontained 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.**

View 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**.

View File

@ -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.

View File

@ -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 isnt encoded in bytecode or runtime state, it doesnt 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)

View File

@ -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.

View File

@ -0,0 +1,5 @@
{
"project": "sdk",
"script_fe": "pbs",
"produces": "lib"
}

View 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;
}

View 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;
}

View File

@ -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"
}
}

View File

@ -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);
}
}

View 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);
}
}