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
|
> **Status:** Canonical / Replaces all previous module & linking specs
|
||||||
|
>
|
||||||
**Accepted (v0)** — This specification defines the authoritative execution and linking model for PBS v0.
|
> 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**:
|
||||||
|
|
||||||
```
|
* Resolves symbols or names
|
||||||
load → verify → execute
|
* 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
|
Dependency resolution is **purely a compiler concern**.
|
||||||
* Control‑flow targets (JMP / conditional branches)
|
|
||||||
* Constant pool indexing
|
|
||||||
* Syscall signature binding
|
|
||||||
|
|
||||||
All of this must be **fully resolved by the compiler/toolchain**.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 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
|
* A module is a directory inside a project
|
||||||
* `functions: [FunctionMeta]` — function table
|
* Each module contains one or more `.pbs` source files
|
||||||
* `const_pool: [Const]` — constant pool
|
|
||||||
* (optional) metadata (build id, debug info, hashes)
|
|
||||||
|
|
||||||
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
|
```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`:
|
No relocations or fixups remain.
|
||||||
|
|
||||||
* `code_offset`
|
|
||||||
* `code_len`
|
|
||||||
* `param_slots`
|
|
||||||
* `local_slots`
|
|
||||||
* `return_slots`
|
|
||||||
* (optional) `max_stack_slots` (precomputed)
|
|
||||||
|
|
||||||
The compiler is responsible for emitting **correct metadata**.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Control Flow (JMP / Branches)
|
## 7. Runtime Execution Contract
|
||||||
|
|
||||||
* All jump targets are **relative to the start of the current function**.
|
### 7.1 VM Input Requirements
|
||||||
* Targets must land on **valid instruction boundaries**.
|
|
||||||
|
|
||||||
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`
|
Handled exclusively by the compiler:
|
||||||
* 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
|
|
||||||
|
|
||||||
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
|
* Single-blob execution
|
||||||
* Verifying structural and semantic correctness
|
* No runtime linking
|
||||||
* Executing bytecode deterministically
|
* 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
|
* Dynamic module loading
|
||||||
* Stack underflow / overflow
|
* Runtime imports
|
||||||
* Invalid `func_id`
|
* Hot reloading
|
||||||
* Invalid jump targets
|
* Partial linking
|
||||||
* Syscall signature mismatches
|
|
||||||
|
|
||||||
These checks exist for **safety and determinism**, not for late binding.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 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:
|
> **Rule of thumb:**
|
||||||
|
> If it requires names, symbols, or intent → compiler.
|
||||||
* Legacy `CALL addr` encodings are **rejected** under Policy (A)
|
> If it requires bytes, slots, or PCs → VM.
|
||||||
* Only `CALL func_id` is valid in PBS v0
|
|
||||||
|
|
||||||
Compatibility handling is **orthogonal** to the linking model.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Future Evolution (Non‑Goals for v0)
|
## 11. Final Note
|
||||||
|
|
||||||
PBS v0 explicitly does **not** define:
|
After adoption of this document:
|
||||||
|
|
||||||
* Multi‑module linking
|
* Any existing or future document describing PBS modules or linking **must defer to this spec**
|
||||||
* Dynamic imports
|
* Any behavior conflicting with this spec is considered **non-compliant**
|
||||||
* Runtime symbol resolution
|
* The Prometeu VM is formally defined as a **pure executor**, not a linker
|
||||||
* Relocation tables
|
|
||||||
|
|
||||||
These may appear in future versions (v1+), but **v0 is closed and static by design**.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Summary
|
## Addendum — `prometeu.json` and Dependency Management
|
||||||
|
|
||||||
* PBS modules are **single, self‑contained blobs**
|
This specification intentionally **does not standardize the full dependency resolution algorithm** for `prometeu.json`.
|
||||||
* All linking happens **before runtime**
|
|
||||||
* The VM is a **verifying executor**, not a linker
|
|
||||||
* This model enables aggressive optimization, predictability, and simplicity
|
|
||||||
|
|
||||||
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`.
|
* 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.
|
* 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.
|
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**.
|
> 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-goal:** new language features. If something must be reworked to achieve industrial quality, it *must* be reworked.
|
|
||||||
|
|
||||||
---
|
## Non-goals (for this PR set)
|
||||||
|
|
||||||
## Guiding invariants (apply to every PR)
|
* No lockfile format (yet)
|
||||||
|
* No registry (yet)
|
||||||
### VM invariants
|
* No advanced SAT solver: first iteration is deterministic and pragmatic
|
||||||
|
* No incremental compilation (yet)
|
||||||
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.
|
|
||||||
@ -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
|
### Scope
|
||||||
|
|
||||||
* Add `VmRunner` test harness:
|
* Implement `prometeu_compiler::manifest` module:
|
||||||
|
|
||||||
* step limit
|
* `Manifest` struct mirroring the spec fields:
|
||||||
* deterministic trace of stack deltas
|
|
||||||
* snapshot of locals
|
|
||||||
* Add property tests (lightweight):
|
|
||||||
|
|
||||||
* stack never underflows in verified programs
|
* `name`, `version`, `kind`
|
||||||
* verified programs never jump out of bounds
|
* `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
|
### 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)
|
### Scope
|
||||||
* arithmetic (+, -, *, /, %, comparisons)
|
|
||||||
* `if/else` control flow
|
* Implement `prometeu_compiler::deps::resolver`:
|
||||||
* `when` expression (if present in lowering)
|
|
||||||
* function calls with params + returns (including `void`)
|
* Input: root project dir
|
||||||
* multiple return slots (flattened structs / hardware value types)
|
* Output: `ResolvedGraph`
|
||||||
* host syscalls (e.g., `GfxClear565`, `InputPadSnapshot`, `InputTouchSnapshot`)
|
* Graph nodes:
|
||||||
* deterministic traps (OOB bounded, invalid local, invalid call target, stack underflow)
|
|
||||||
|
* 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",
|
"script_fe": "pbs",
|
||||||
|
"produces": "app",
|
||||||
"entry": "src/main.pbs",
|
"entry": "src/main.pbs",
|
||||||
"out": "build/program.pbc",
|
"out": "build/program.pbc",
|
||||||
"emit_disasm": true,
|
"dependencies": {
|
||||||
"emit_symbols": true
|
"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