add PBS docs
This commit is contained in:
parent
62e68bf7ff
commit
c795eeb3dc
@ -6,7 +6,7 @@ This directory contains the technical documentation and specifications for the P
|
|||||||
|
|
||||||
### 📜 [Specifications (Specs)](./specs)
|
### 📜 [Specifications (Specs)](./specs)
|
||||||
Detailed documentation on system architecture, cartridge format, VM instruction set, and more.
|
Detailed documentation on system architecture, cartridge format, VM instruction set, and more.
|
||||||
- [Topic Index](./specs/topics/table-of-contents.md)
|
- [Topic Index](specs/hardware/topics/table-of-contents.md)
|
||||||
|
|
||||||
### 🐞 [Debugger](./debugger)
|
### 🐞 [Debugger](./debugger)
|
||||||
Documentation on debugging tools and how to integrate new tools into the ecosystem.
|
Documentation on debugging tools and how to integrate new tools into the ecosystem.
|
||||||
|
|||||||
359
docs/specs/pbs/PBS - Canonical Addenda.md
Normal file
359
docs/specs/pbs/PBS - Canonical Addenda.md
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
# PBS v0 Canonical Addenda
|
||||||
|
|
||||||
|
> **Purpose:** eliminate ambiguity for Junie and for golden tests.
|
||||||
|
>
|
||||||
|
> This document is **normative** for PBS Frontend v0 and complements:
|
||||||
|
>
|
||||||
|
> * **PBS Frontend Spec v0 — Implementer Edition**
|
||||||
|
> * **Junie PR Plan**
|
||||||
|
>
|
||||||
|
> These addenda define:
|
||||||
|
>
|
||||||
|
> 1. operator precedence & associativity
|
||||||
|
> 2. canonical AST JSON shape (v0)
|
||||||
|
> 3. canonical diagnostic codes (v0)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1) Operator Precedence and Associativity (v0)
|
||||||
|
|
||||||
|
### 1.1 Guiding rule
|
||||||
|
|
||||||
|
PBS v0 prioritizes **minimal ambiguity** and **easy parsing**.
|
||||||
|
|
||||||
|
* Most operators are **left-associative**.
|
||||||
|
* Assignment is **not** an expression in v0 (no `=` operator expressions).
|
||||||
|
* Member access and indexing are not part of v0 surface syntax unless already defined elsewhere.
|
||||||
|
|
||||||
|
### 1.2 Precedence table
|
||||||
|
|
||||||
|
From **highest** to **lowest**:
|
||||||
|
|
||||||
|
1. **Primary**
|
||||||
|
|
||||||
|
* literals (`10`, `3.14`, `"text"`, `none`, `some(x)`, `ok(x)`, `err(e)`)
|
||||||
|
* identifiers (`foo`)
|
||||||
|
* parenthesized expression (`(expr)`)
|
||||||
|
* block expression (`{ ... }`) (when allowed as `Expr`)
|
||||||
|
|
||||||
|
2. **Call** (left-associative)
|
||||||
|
|
||||||
|
* `callee(arg1, arg2, ...)`
|
||||||
|
|
||||||
|
3. **Unary prefix** (right-associative)
|
||||||
|
|
||||||
|
* `-expr`
|
||||||
|
* `!expr`
|
||||||
|
* `as` casts are **not unary**; see level 6.
|
||||||
|
|
||||||
|
4. **Multiplicative** (left-associative)
|
||||||
|
|
||||||
|
* `*`, `/`, `%`
|
||||||
|
|
||||||
|
5. **Additive** (left-associative)
|
||||||
|
|
||||||
|
* `+`, `-`
|
||||||
|
|
||||||
|
6. **Cast** (left-associative)
|
||||||
|
|
||||||
|
* `expr as Type`
|
||||||
|
|
||||||
|
7. **Comparison** (non-associative)
|
||||||
|
|
||||||
|
* `<`, `<=`, `>`, `>=`
|
||||||
|
|
||||||
|
8. **Equality** (non-associative)
|
||||||
|
|
||||||
|
* `==`, `!=`
|
||||||
|
|
||||||
|
9. **Logical AND** (left-associative)
|
||||||
|
|
||||||
|
* `&&`
|
||||||
|
|
||||||
|
10. **Logical OR** (left-associative)
|
||||||
|
|
||||||
|
* `||`
|
||||||
|
|
||||||
|
11. **Control expressions** (special)
|
||||||
|
|
||||||
|
* `if ... { ... } else { ... }` (expression form only if your v0 allows it; otherwise statement)
|
||||||
|
* `when { ... }` (expression)
|
||||||
|
|
||||||
|
### 1.3 Non-associative rule
|
||||||
|
|
||||||
|
Comparison and equality are **non-associative**:
|
||||||
|
|
||||||
|
* `a < b < c` is an error
|
||||||
|
* `a == b == c` is an error
|
||||||
|
|
||||||
|
Diagnostic: `E_PARSE_NON_ASSOC`.
|
||||||
|
|
||||||
|
### 1.4 Notes on `when`
|
||||||
|
|
||||||
|
`when` binds weaker than all binary operators.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
let x = a + b when { ... };
|
||||||
|
```
|
||||||
|
|
||||||
|
Parses as:
|
||||||
|
|
||||||
|
```
|
||||||
|
let x = (a + b) when { ... };
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2) Canonical AST JSON (v0)
|
||||||
|
|
||||||
|
### 2.1 Canonicalization goals
|
||||||
|
|
||||||
|
Canonical AST JSON is used for:
|
||||||
|
|
||||||
|
* golden tests
|
||||||
|
* frontend determinism validation
|
||||||
|
* diff-friendly debugging
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
* JSON keys are **stable** and **ordered** (when writing JSON)
|
||||||
|
* All nodes include `kind` and `span`
|
||||||
|
* Spans are byte offsets into the file content
|
||||||
|
|
||||||
|
### 2.2 Span encoding
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"file":"main.pbs","start":12,"end":18}
|
||||||
|
```
|
||||||
|
|
||||||
|
Where:
|
||||||
|
|
||||||
|
* `start` is inclusive
|
||||||
|
* `end` is exclusive
|
||||||
|
|
||||||
|
### 2.3 Root
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"kind": "File",
|
||||||
|
"span": {"file":"...","start":0,"end":123},
|
||||||
|
"imports": [ ... ],
|
||||||
|
"decls": [ ... ]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.4 Import node
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"kind": "Import",
|
||||||
|
"span": {"file":"...","start":0,"end":20},
|
||||||
|
"spec": {"kind":"ImportSpec","path":["Foo","Bar"]},
|
||||||
|
"from": "./lib.pbs"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`ImportSpec.path` is an array of identifiers.
|
||||||
|
|
||||||
|
### 2.5 Declarations
|
||||||
|
|
||||||
|
#### 2.5.1 Service
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"kind": "ServiceDecl",
|
||||||
|
"span": {"file":"...","start":0,"end":50},
|
||||||
|
"vis": "pub",
|
||||||
|
"name": "Audio",
|
||||||
|
"extends": null,
|
||||||
|
"members": [ ... ]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A service member (method signature only in v0):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"kind": "ServiceFnSig",
|
||||||
|
"span": {"file":"...","start":0,"end":10},
|
||||||
|
"name": "play",
|
||||||
|
"params": [ {"name":"sound","ty": {"kind":"TypeName","name":"Sound"}} ],
|
||||||
|
"ret": {"kind":"TypeName","name":"void"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.5.2 Function
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"kind": "FnDecl",
|
||||||
|
"span": {"file":"...","start":0,"end":80},
|
||||||
|
"name": "main",
|
||||||
|
"params": [],
|
||||||
|
"ret": null,
|
||||||
|
"else": null,
|
||||||
|
"body": {"kind":"Block", ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.5.3 TypeDecl (struct/contract/error)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"kind": "TypeDecl",
|
||||||
|
"span": {"file":"...","start":0,"end":100},
|
||||||
|
"vis": "pub",
|
||||||
|
"typeKind": "struct",
|
||||||
|
"name": "Vector",
|
||||||
|
"body": {"kind":"TypeBody","members":[ ... ]}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.6 Blocks and statements
|
||||||
|
|
||||||
|
Block:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"kind": "Block",
|
||||||
|
"span": {"file":"...","start":0,"end":20},
|
||||||
|
"stmts": [ ... ],
|
||||||
|
"tail": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* `stmts` are statements.
|
||||||
|
* `tail` is an optional final expression (only if your parser supports expression blocks).
|
||||||
|
|
||||||
|
Statement kinds (v0 minimum):
|
||||||
|
|
||||||
|
* `LetStmt`
|
||||||
|
* `ExprStmt`
|
||||||
|
* `ReturnStmt`
|
||||||
|
|
||||||
|
Let:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"kind": "LetStmt",
|
||||||
|
"span": {"file":"...","start":0,"end":20},
|
||||||
|
"name": "x",
|
||||||
|
"isMut": false,
|
||||||
|
"ty": null,
|
||||||
|
"init": {"kind":"IntLit", "value": 10, "span": ...}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Return:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"kind": "ReturnStmt",
|
||||||
|
"span": {"file":"...","start":0,"end":10},
|
||||||
|
"expr": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.7 Expressions
|
||||||
|
|
||||||
|
All expressions include `kind` and `span`.
|
||||||
|
|
||||||
|
Minimal v0 expression node kinds:
|
||||||
|
|
||||||
|
* `IntLit` `{ value: i64 }`
|
||||||
|
* `FloatLit` `{ value: f64 }`
|
||||||
|
* `BoundedLit` `{ value: u32 }`
|
||||||
|
* `StringLit` `{ value: string }`
|
||||||
|
* `Ident` `{ name: string }`
|
||||||
|
* `Call` `{ callee: Expr, args: Expr[] }`
|
||||||
|
* `Unary` `{ op: "-"|"!", expr: Expr }`
|
||||||
|
* `Binary` `{ op: string, left: Expr, right: Expr }`
|
||||||
|
* `Cast` `{ expr: Expr, ty: TypeRef }`
|
||||||
|
* `IfExpr` `{ cond: Expr, then: Block, els: Block }` (if expression is supported)
|
||||||
|
* `WhenExpr` `{ arms: WhenArm[] }`
|
||||||
|
|
||||||
|
Type references:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"kind":"TypeName","name":"int"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Generics:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"kind":"TypeApp","base":"optional","args":[{"kind":"TypeName","name":"int"}]}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.8 Canonical JSON ordering
|
||||||
|
|
||||||
|
When writing AST JSON, always order fields as:
|
||||||
|
|
||||||
|
1. `kind`
|
||||||
|
2. `span`
|
||||||
|
3. semantic fields (stable order)
|
||||||
|
|
||||||
|
This makes diffs deterministic.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3) Diagnostic Codes (v0)
|
||||||
|
|
||||||
|
### 3.1 Diagnostic format
|
||||||
|
|
||||||
|
All diagnostics must be serializable to canonical JSON:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"severity": "error",
|
||||||
|
"code": "E_PARSE_UNEXPECTED_TOKEN",
|
||||||
|
"message": "Unexpected token '}'",
|
||||||
|
"span": {"file":"main.pbs","start":12,"end":13}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Severity is one of: `error`, `warning`.
|
||||||
|
|
||||||
|
### 3.2 Parse/Lex errors (E_PARSE_*)
|
||||||
|
|
||||||
|
* `E_LEX_INVALID_CHAR` — invalid character
|
||||||
|
* `E_LEX_UNTERMINATED_STRING` — string literal not closed
|
||||||
|
* `E_PARSE_UNEXPECTED_TOKEN` — token not expected in current context
|
||||||
|
* `E_PARSE_EXPECTED_TOKEN` — missing required token
|
||||||
|
* `E_PARSE_NON_ASSOC` — chained comparison/equality (non-associative)
|
||||||
|
|
||||||
|
### 3.3 Symbol/Resolve errors (E_RESOLVE_*)
|
||||||
|
|
||||||
|
* `E_RESOLVE_UNDEFINED` — undefined identifier
|
||||||
|
* `E_RESOLVE_DUPLICATE_SYMBOL` — duplicate symbol in same namespace
|
||||||
|
* `E_RESOLVE_NAMESPACE_COLLISION` — name exists in both type and value namespaces
|
||||||
|
* `E_RESOLVE_VISIBILITY` — symbol not visible from this scope/module
|
||||||
|
* `E_RESOLVE_INVALID_IMPORT` — import spec/path invalid
|
||||||
|
|
||||||
|
### 3.4 Type errors (E_TYPE_*)
|
||||||
|
|
||||||
|
* `E_TYPE_MISMATCH` — type mismatch
|
||||||
|
* `E_TYPE_UNKNOWN_TYPE` — unknown type name
|
||||||
|
* `E_TYPE_MUTABILITY` — mutability violation
|
||||||
|
* `E_TYPE_RETURN_PATH` — not all paths return a value
|
||||||
|
* `E_TYPE_INVALID_CAST` — invalid cast
|
||||||
|
|
||||||
|
### 3.5 Lowering errors (E_LOWER_*)
|
||||||
|
|
||||||
|
* `E_LOWER_UNSUPPORTED` — feature not supported in v0 lowering
|
||||||
|
|
||||||
|
### 3.6 Warnings (W_*)
|
||||||
|
|
||||||
|
Warnings are allowed in v0 but should be used sparingly.
|
||||||
|
|
||||||
|
* `W_UNUSED_LET` — unused local binding
|
||||||
|
* `W_SHADOWING` — local shadows another binding
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Notes (Non-normative)
|
||||||
|
|
||||||
|
* Keep these addenda in `spec/` in the repo.
|
||||||
|
* Use them to drive golden tests for AST and diagnostics.
|
||||||
|
* If a future change alters canonical AST, bump a version and regenerate goldens deliberately.
|
||||||
357
docs/specs/pbs/PRs para Junie.md
Normal file
357
docs/specs/pbs/PRs para Junie.md
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
# PBS Compiler — Junie PR Plan
|
||||||
|
|
||||||
|
> **Purpose:** this document defines a sequence of small, focused Pull Requests to be implemented by *Junie*, one at a time.
|
||||||
|
>
|
||||||
|
> **Audience:** compiler implementer (AI or human).
|
||||||
|
>
|
||||||
|
> **Scope:** PBS-first compiler architecture. TS and Lua frontends are assumed **removed**.
|
||||||
|
>
|
||||||
|
> **Hard rules:**
|
||||||
|
>
|
||||||
|
> * Each PR must compile and pass tests.
|
||||||
|
> * Each PR must include tests.
|
||||||
|
> * No speculative features.
|
||||||
|
> * Follow the `Prometeu Base Script (PBS) - Implementation Spec`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Global Architectural Direction (Non-negotiable)
|
||||||
|
|
||||||
|
* PBS is the **primary language**.
|
||||||
|
* Frontend is implemented **before** runtime integration.
|
||||||
|
* Architecture uses **two IR layers**:
|
||||||
|
|
||||||
|
* **Core IR** (PBS-semantic, typed, resolved)
|
||||||
|
* **VM IR** (stack-based, backend-friendly)
|
||||||
|
* VM IR remains simple and stable.
|
||||||
|
* Lowering is explicit and testable.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-01 — ProjectConfig and Frontend Selection
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Introduce a project-level configuration that selects the frontend and entry file explicitly.
|
||||||
|
|
||||||
|
### Motivation
|
||||||
|
|
||||||
|
The compiler must not hardcode entry points or languages. PBS will be the first frontend, others may return later.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* Add `ProjectConfig` (serde-deserializable) loaded from `prometeu.json`
|
||||||
|
* Fields (v0):
|
||||||
|
|
||||||
|
* `script_fe: "pbs"`
|
||||||
|
* `entry: "main.pbs"`
|
||||||
|
* Refactor compiler entry point to:
|
||||||
|
|
||||||
|
* load config
|
||||||
|
* select frontend by `script_fe`
|
||||||
|
* resolve entry path relative to project root
|
||||||
|
|
||||||
|
### Files Likely Touched
|
||||||
|
|
||||||
|
* `compiler/mod.rs`
|
||||||
|
* `compiler/driver.rs`
|
||||||
|
* `common/config.rs` (new)
|
||||||
|
|
||||||
|
### Tests (mandatory)
|
||||||
|
|
||||||
|
* unit test: load valid `prometeu.json`
|
||||||
|
* unit test: invalid frontend → diagnostic
|
||||||
|
* integration test: project root + entry resolution
|
||||||
|
|
||||||
|
### Notes to Junie
|
||||||
|
|
||||||
|
Do **not** add PBS parsing yet. This PR is infrastructure only.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-02 — Core IR Skeleton (PBS-first)
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Introduce a **Core IR** layer independent from the VM IR.
|
||||||
|
|
||||||
|
### Motivation
|
||||||
|
|
||||||
|
PBS semantics must be represented before lowering to VM instructions.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* Add new module: `ir_core`
|
||||||
|
* Define minimal structures:
|
||||||
|
|
||||||
|
* `Program`
|
||||||
|
* `Module`
|
||||||
|
* `Function`
|
||||||
|
* `Block`
|
||||||
|
* `Instr`
|
||||||
|
* `Terminator`
|
||||||
|
* IDs only (no string-based calls):
|
||||||
|
|
||||||
|
* `FunctionId`
|
||||||
|
* `ConstId`
|
||||||
|
* `TypeId`
|
||||||
|
|
||||||
|
### Constraints
|
||||||
|
|
||||||
|
* Core IR must NOT reference VM opcodes
|
||||||
|
* No lowering yet
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
* construct Core IR manually in tests
|
||||||
|
* snapshot test (JSON) for deterministic shape
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-03 — Constant Pool and IDs
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Introduce a stable constant pool shared by Core IR and VM IR.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* Add `ConstPool`:
|
||||||
|
|
||||||
|
* strings
|
||||||
|
* numbers
|
||||||
|
* Replace inline literals in VM IR with `ConstId`
|
||||||
|
* Update existing VM IR to accept `PushConst(ConstId)`
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
* const pool deduplication
|
||||||
|
* deterministic ConstId assignment
|
||||||
|
* IR snapshot stability
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-04 — VM IR Cleanup (Stabilization)
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Stabilize VM IR as a **lowering target**, not a language IR.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* Replace string-based calls with `FunctionId`
|
||||||
|
* Ensure locals are accessed via slots
|
||||||
|
* Remove or internalize `PushScope` / `PopScope`
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
* golden VM IR tests
|
||||||
|
* lowering smoke test (Core IR → VM IR)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-05 — Core IR → VM IR Lowering Pass
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Implement the lowering pass from Core IR to VM IR.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* New module: `lowering/core_to_vm.rs`
|
||||||
|
* Lowering rules:
|
||||||
|
|
||||||
|
* Core blocks → labels
|
||||||
|
* Core calls → VM calls
|
||||||
|
* Host calls preserved
|
||||||
|
* No PBS frontend yet
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
* lowering correctness
|
||||||
|
* instruction ordering
|
||||||
|
* label resolution
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-06 — PBS Frontend: Lexer
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Implement PBS lexer according to the spec.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* Token kinds
|
||||||
|
* Keyword table
|
||||||
|
* Span tracking
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
* tokenization tests
|
||||||
|
* keyword vs identifier tests
|
||||||
|
* bounded literals
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-07 — PBS Frontend: Parser (Raw AST)
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Parse PBS source into a raw AST.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* Imports
|
||||||
|
* Top-level declarations
|
||||||
|
* Blocks
|
||||||
|
* Expressions (calls, literals, control flow)
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
* valid programs
|
||||||
|
* syntax error recovery
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-08 — PBS Frontend: Symbol Collection and Resolver
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Resolve names, modules, and visibility.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* Type namespace vs value namespace
|
||||||
|
* Visibility rules
|
||||||
|
* Import resolution
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
* duplicate symbols
|
||||||
|
* invalid imports
|
||||||
|
* visibility errors
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-09 — PBS Frontend: Type Checking
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Validate PBS semantics.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* Primitive types
|
||||||
|
* Structs
|
||||||
|
* `optional<T>` and `result<T, E>`
|
||||||
|
* Mutability rules
|
||||||
|
* Return path validation
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
* type mismatch
|
||||||
|
* mutability violations
|
||||||
|
* implicit `none` behavior
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-10 — PBS Frontend: Semantic Lowering to Core IR
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Lower typed PBS AST into Core IR.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* ID-based calls
|
||||||
|
* ConstPool usage
|
||||||
|
* Control flow lowering
|
||||||
|
* SAFE vs HIP effects represented explicitly
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
* PBS → Core IR snapshots
|
||||||
|
* semantic correctness
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-11 — Host-bound Contracts and Syscall Mapping
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Connect PBS host-bound contracts to runtime syscalls (without executing them).
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* Contract registry
|
||||||
|
* Mapping: contract.method → syscall id
|
||||||
|
* Core IR host call nodes
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
* invalid contract calls
|
||||||
|
* correct syscall mapping
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-12 — Diagnostics Canonicalization
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Standardize diagnostics output.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* Error codes (`E_*`, `W_*`)
|
||||||
|
* Stable messages
|
||||||
|
* Span accuracy
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
* golden diagnostics
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-13 — Backend Integration (VM IR → Bytecode)
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Reconnect the pipeline to the Prometeu runtime backend.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* VM IR → bytecode emission
|
||||||
|
* No PBS semantics here
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
* bytecode emission smoke test
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# PR-14 — End-to-End PBS Compile Test
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Prove the full pipeline works.
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
* Sample PBS project
|
||||||
|
* Compile → bytecode
|
||||||
|
* Diagnostics only (no execution)
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
* golden bytecode snapshot
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Final Note to Junie
|
||||||
|
|
||||||
|
Do **not** skip PRs.
|
||||||
|
Do **not** merge multiple PRs together.
|
||||||
|
If the spec is unclear, create a failing test and document the ambiguity.
|
||||||
|
|
||||||
|
This plan is the authoritative roadmap for PBS frontend implementation.
|
||||||
@ -0,0 +1,446 @@
|
|||||||
|
# Prometeu Base Script (PBS)
|
||||||
|
|
||||||
|
## Frontend Spec v0 — Implementer Edition
|
||||||
|
|
||||||
|
> **Normative specification for building a PBS frontend (lexer, parser, AST, resolver, typechecker) targeting the Prometeu Fantasy Console runtime.**
|
||||||
|
>
|
||||||
|
> This document is **not** a user guide.
|
||||||
|
> It exists to make PBS *implementable*, *deterministic*, and *testable*.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. Scope and Non‑Goals
|
||||||
|
|
||||||
|
### 0.1 Scope
|
||||||
|
|
||||||
|
This specification defines:
|
||||||
|
|
||||||
|
* lexical structure (tokens)
|
||||||
|
* grammar and parsing rules
|
||||||
|
* canonical AST shapes
|
||||||
|
* frontend phases and their responsibilities
|
||||||
|
* name resolution and visibility rules
|
||||||
|
* type system rules
|
||||||
|
* desugaring and lowering rules
|
||||||
|
* diagnostic categories (errors vs warnings)
|
||||||
|
* required guarantees for runtime integration
|
||||||
|
|
||||||
|
The goal is that **two independent frontends** built from this spec:
|
||||||
|
|
||||||
|
* accept the same programs
|
||||||
|
* reject the same programs
|
||||||
|
* produce equivalent ASTs
|
||||||
|
* emit equivalent diagnostics
|
||||||
|
|
||||||
|
### 0.2 Non‑Goals
|
||||||
|
|
||||||
|
This spec does **not** define:
|
||||||
|
|
||||||
|
* runtime performance characteristics
|
||||||
|
* bytecode layout
|
||||||
|
* JIT or interpreter design
|
||||||
|
* editor tooling or IDE features
|
||||||
|
|
||||||
|
Those are explicitly out of scope.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Frontend Pipeline Overview
|
||||||
|
|
||||||
|
A PBS frontend **must** be structured as the following pipeline:
|
||||||
|
|
||||||
|
```
|
||||||
|
Source Text
|
||||||
|
↓
|
||||||
|
Lexer
|
||||||
|
↓
|
||||||
|
Parser
|
||||||
|
↓
|
||||||
|
Raw AST
|
||||||
|
↓
|
||||||
|
Symbol Collection
|
||||||
|
↓
|
||||||
|
Resolver
|
||||||
|
↓
|
||||||
|
Typed AST
|
||||||
|
↓
|
||||||
|
Desugaring / Lowering
|
||||||
|
↓
|
||||||
|
Runtime‑ready IR / AST
|
||||||
|
```
|
||||||
|
|
||||||
|
Each stage has **strict responsibilities**.
|
||||||
|
No stage may perform work assigned to a later stage.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Lexical Structure
|
||||||
|
|
||||||
|
### 2.1 Tokens
|
||||||
|
|
||||||
|
A PBS lexer must recognize at minimum the following token classes:
|
||||||
|
|
||||||
|
* identifiers
|
||||||
|
* keywords
|
||||||
|
* numeric literals
|
||||||
|
* string literals
|
||||||
|
* punctuation
|
||||||
|
* operators
|
||||||
|
* comments
|
||||||
|
|
||||||
|
Whitespace is insignificant except as a separator.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.2 Keywords (Reserved)
|
||||||
|
|
||||||
|
The following keywords are **reserved** and may not be used as identifiers:
|
||||||
|
|
||||||
|
```
|
||||||
|
import
|
||||||
|
pub
|
||||||
|
mod
|
||||||
|
service
|
||||||
|
fn
|
||||||
|
let
|
||||||
|
mut
|
||||||
|
declare
|
||||||
|
struct
|
||||||
|
contract
|
||||||
|
host
|
||||||
|
error
|
||||||
|
optional
|
||||||
|
result
|
||||||
|
some
|
||||||
|
none
|
||||||
|
ok
|
||||||
|
err
|
||||||
|
if
|
||||||
|
else
|
||||||
|
when
|
||||||
|
for
|
||||||
|
in
|
||||||
|
return
|
||||||
|
handle
|
||||||
|
borrow
|
||||||
|
mutate
|
||||||
|
peek
|
||||||
|
take
|
||||||
|
alloc
|
||||||
|
weak
|
||||||
|
as
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.3 Literals
|
||||||
|
|
||||||
|
#### Numeric Literals
|
||||||
|
|
||||||
|
* `int` — decimal digits
|
||||||
|
* `float` — decimal with `.`
|
||||||
|
* `bounded` — decimal digits suffixed with `b`
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
10
|
||||||
|
42
|
||||||
|
3.14
|
||||||
|
0b
|
||||||
|
255b
|
||||||
|
```
|
||||||
|
|
||||||
|
#### String Literals
|
||||||
|
|
||||||
|
* delimited by `"`
|
||||||
|
* UTF‑8 encoded
|
||||||
|
* immutable
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.4 Comments
|
||||||
|
|
||||||
|
* line comment: `// until end of line`
|
||||||
|
* block comments are **not supported** in v0
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Grammar (EBNF‑style)
|
||||||
|
|
||||||
|
> This grammar is **normative** but simplified for readability.
|
||||||
|
> Implementers may refactor internally as long as semantics are preserved.
|
||||||
|
|
||||||
|
### 3.1 File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
File ::= Import* TopLevelDecl*
|
||||||
|
Import ::= 'import' ImportSpec 'from' StringLiteral
|
||||||
|
TopLevelDecl::= TypeDecl | ServiceDecl | FnDecl
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.2 Type Declarations
|
||||||
|
|
||||||
|
```
|
||||||
|
TypeDecl ::= Visibility? 'declare' TypeKind Identifier TypeBody
|
||||||
|
TypeKind ::= 'struct' | 'contract' | 'error'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.3 Services
|
||||||
|
|
||||||
|
```
|
||||||
|
ServiceDecl ::= Visibility 'service' Identifier (':' Identifier)? Block
|
||||||
|
```
|
||||||
|
|
||||||
|
Visibility is mandatory for services.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.4 Functions
|
||||||
|
|
||||||
|
```
|
||||||
|
FnDecl ::= 'fn' Identifier ParamList ReturnType? ElseFallback? Block
|
||||||
|
```
|
||||||
|
|
||||||
|
Top‑level `fn` are always file‑private.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.5 Expressions (Partial)
|
||||||
|
|
||||||
|
```
|
||||||
|
Expr ::= Literal
|
||||||
|
| Identifier
|
||||||
|
| CallExpr
|
||||||
|
| Block
|
||||||
|
| IfExpr
|
||||||
|
| WhenExpr
|
||||||
|
| ForExpr
|
||||||
|
| ReturnExpr
|
||||||
|
```
|
||||||
|
|
||||||
|
Expression grammar is intentionally restricted in v0.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Canonical AST
|
||||||
|
|
||||||
|
The frontend **must** produce a canonical AST.
|
||||||
|
|
||||||
|
### 4.1 AST Invariants
|
||||||
|
|
||||||
|
* AST nodes are immutable after creation
|
||||||
|
* Parent pointers are optional
|
||||||
|
* Source spans must be preserved for diagnostics
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.2 Core Node Kinds
|
||||||
|
|
||||||
|
Minimal required node kinds:
|
||||||
|
|
||||||
|
* `FileNode`
|
||||||
|
* `ImportNode`
|
||||||
|
* `ServiceNode`
|
||||||
|
* `FunctionNode`
|
||||||
|
* `StructDeclNode`
|
||||||
|
* `ContractDeclNode`
|
||||||
|
* `BlockNode`
|
||||||
|
* `LetNode`
|
||||||
|
* `CallNode`
|
||||||
|
* `IfNode`
|
||||||
|
* `WhenNode`
|
||||||
|
* `ForNode`
|
||||||
|
* `ReturnNode`
|
||||||
|
|
||||||
|
Implementers may add internal nodes but must normalize before later phases.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Symbol Collection Phase
|
||||||
|
|
||||||
|
### 5.1 Purpose
|
||||||
|
|
||||||
|
Symbol Collection builds **module‑level symbol tables** without resolving bodies.
|
||||||
|
|
||||||
|
Collected symbols:
|
||||||
|
|
||||||
|
* `pub` and `mod` type declarations
|
||||||
|
* `pub` and `mod` services
|
||||||
|
|
||||||
|
Excluded:
|
||||||
|
|
||||||
|
* function bodies
|
||||||
|
* expressions
|
||||||
|
* local bindings
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5.2 Namespaces
|
||||||
|
|
||||||
|
PBS has **two namespaces**:
|
||||||
|
|
||||||
|
* Type namespace
|
||||||
|
* Value namespace
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
* A name may not exist in both namespaces
|
||||||
|
* Violations are compile‑time errors
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Resolver Phase
|
||||||
|
|
||||||
|
### 6.1 Responsibilities
|
||||||
|
|
||||||
|
Resolver must:
|
||||||
|
|
||||||
|
* resolve all identifiers
|
||||||
|
* enforce visibility rules
|
||||||
|
* bind references to symbols
|
||||||
|
|
||||||
|
Resolution order (per namespace):
|
||||||
|
|
||||||
|
1. local bindings
|
||||||
|
2. file‑private declarations
|
||||||
|
3. module symbols
|
||||||
|
4. imported symbols
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6.2 Visibility Rules (Normative)
|
||||||
|
|
||||||
|
* file‑private: visible only in the same file
|
||||||
|
* `mod`: visible within the module
|
||||||
|
* `pub`: visible across modules via import
|
||||||
|
|
||||||
|
Violations are errors.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Type Checking
|
||||||
|
|
||||||
|
### 7.1 Type Categories
|
||||||
|
|
||||||
|
Frontend must support:
|
||||||
|
|
||||||
|
* primitive types
|
||||||
|
* struct value types
|
||||||
|
* `optional<T>`
|
||||||
|
* `result<T, E>`
|
||||||
|
* gate‑backed types (opaque at frontend level)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7.2 Mutability Rules
|
||||||
|
|
||||||
|
* mutability belongs to bindings, not types
|
||||||
|
* `mut` is part of binding metadata
|
||||||
|
* mutability violations are compile‑time errors
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 7.3 Function Checking
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
* all paths must return a value unless `else` fallback exists
|
||||||
|
* `optional<T>` may implicitly return `none`
|
||||||
|
* `result<T,E>` must return explicitly
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Desugaring and Lowering
|
||||||
|
|
||||||
|
### 8.1 Purpose
|
||||||
|
|
||||||
|
Lowering transforms surface syntax into a minimal core language.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
* `take x.push(v)` → `mutate x as t { t.push(v) }`
|
||||||
|
* `when` → conditional expression node
|
||||||
|
* implicit `return none` for `optional<T>`
|
||||||
|
|
||||||
|
Lowered AST must contain **no syntactic sugar**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Diagnostics Model
|
||||||
|
|
||||||
|
Diagnostics are first‑class frontend outputs.
|
||||||
|
|
||||||
|
### 9.1 Categories
|
||||||
|
|
||||||
|
* Error — compilation must fail
|
||||||
|
* Warning — compilation may continue
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 9.2 Required Errors
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
* unresolved identifier
|
||||||
|
* visibility violation
|
||||||
|
* type mismatch
|
||||||
|
* mutability violation
|
||||||
|
* invalid gate conversion
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Runtime Interface Assumptions
|
||||||
|
|
||||||
|
Frontend assumes:
|
||||||
|
|
||||||
|
* host‑bound contracts map to runtime syscalls
|
||||||
|
* allocation primitives exist (`alloc`)
|
||||||
|
* reference counting is handled by runtime
|
||||||
|
|
||||||
|
Frontend must **not** assume GC or heap layout.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Determinism Guarantees
|
||||||
|
|
||||||
|
A valid PBS frontend **must guarantee**:
|
||||||
|
|
||||||
|
* deterministic parsing
|
||||||
|
* deterministic name resolution
|
||||||
|
* deterministic type checking
|
||||||
|
* deterministic diagnostics
|
||||||
|
|
||||||
|
No frontend stage may depend on execution order or host state.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Conformance Criteria
|
||||||
|
|
||||||
|
A frontend is PBS‑v0‑conformant if:
|
||||||
|
|
||||||
|
* it implements all rules in this document
|
||||||
|
* it produces canonical ASTs
|
||||||
|
* it rejects all invalid programs defined herein
|
||||||
|
|
||||||
|
This document is the **source of truth** for PBS v0 frontend behavior.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. Future Evolution (Non‑Normative)
|
||||||
|
|
||||||
|
Future versions may add:
|
||||||
|
|
||||||
|
* pattern matching
|
||||||
|
* richer type inference
|
||||||
|
* macros
|
||||||
|
|
||||||
|
No v0 frontend is required to support these.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## End of Spec
|
||||||
341
docs/specs/pbs/Prometeu Scripting - Language Tour.md
Normal file
341
docs/specs/pbs/Prometeu Scripting - Language Tour.md
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
# Prometeu Base Script (PBS)
|
||||||
|
|
||||||
|
> **A didactic scripting language for game development with explicit cost, explicit memory, and predictable runtime.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. What PBS Is (and What It Is Not)
|
||||||
|
|
||||||
|
PBS (Prometeu Base Script) is a **small, explicit scripting language designed for game engines and real‑time runtimes**.
|
||||||
|
|
||||||
|
Its core goals are:
|
||||||
|
|
||||||
|
* **Didactic clarity** — the language teaches how memory, data, and APIs really work.
|
||||||
|
* **Game‑friendly execution** — predictable runtime, no hidden allocation, no tracing GC.
|
||||||
|
* **Explicit cost model** — you always know *when* you allocate, *where* data lives, and *who* can mutate it.
|
||||||
|
|
||||||
|
PBS is **not**:
|
||||||
|
|
||||||
|
* a general‑purpose application language
|
||||||
|
* a productivity scripting language like Python or Lua
|
||||||
|
* a language that hides runtime cost
|
||||||
|
|
||||||
|
PBS is intentionally opinionated. It is built for developers who want **control, predictability, and understanding**, especially in **game and engine contexts**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. The Core Philosophy
|
||||||
|
|
||||||
|
PBS is built around one rule:
|
||||||
|
|
||||||
|
> **If you do not allocate, you are safe. If you allocate, you are responsible.**
|
||||||
|
|
||||||
|
From this rule, everything else follows.
|
||||||
|
|
||||||
|
### 1.1 Two Worlds
|
||||||
|
|
||||||
|
PBS has **two explicit memory worlds**:
|
||||||
|
|
||||||
|
| World | Purpose | Properties |
|
||||||
|
| ----- | -------------- | ---------------------------------------------- |
|
||||||
|
| SAFE | Stack / values | No aliasing, no leaks, no shared mutation |
|
||||||
|
| HIP | Storage / heap | Explicit aliasing, shared mutation, refcounted |
|
||||||
|
|
||||||
|
You never cross between these worlds implicitly.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. First Contact: SAFE‑Only PBS
|
||||||
|
|
||||||
|
A PBS program that never allocates lives entirely in the SAFE world.
|
||||||
|
|
||||||
|
SAFE code:
|
||||||
|
|
||||||
|
* uses value semantics
|
||||||
|
* copies data on assignment (conceptually)
|
||||||
|
* cannot leak memory
|
||||||
|
* cannot accidentally share mutable state
|
||||||
|
|
||||||
|
This makes SAFE PBS ideal for:
|
||||||
|
|
||||||
|
* gameplay logic
|
||||||
|
* math and simulation
|
||||||
|
* AI logic
|
||||||
|
* scripting without fear
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
let a = Vector(1, 2);
|
||||||
|
let b = a; // conceptual copy
|
||||||
|
|
||||||
|
b.scale(2);
|
||||||
|
// a is unchanged
|
||||||
|
```
|
||||||
|
|
||||||
|
No pointers. No references. No surprises.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Values, Not Objects
|
||||||
|
|
||||||
|
PBS does not have objects with identity by default.
|
||||||
|
|
||||||
|
### 3.1 Value Types
|
||||||
|
|
||||||
|
All basic types are **values**:
|
||||||
|
|
||||||
|
* numbers
|
||||||
|
* bool
|
||||||
|
* string (immutable)
|
||||||
|
* tuples
|
||||||
|
* user‑defined `struct`
|
||||||
|
|
||||||
|
A value:
|
||||||
|
|
||||||
|
* has no identity
|
||||||
|
* has no lifetime beyond its scope
|
||||||
|
* is safe to copy
|
||||||
|
|
||||||
|
This matches how most gameplay data *should* behave.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Structs (Data First)
|
||||||
|
|
||||||
|
Structs are **pure data models**.
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
declare struct Vector(x: float, y: float)
|
||||||
|
{
|
||||||
|
pub fn len(self: this): float { ... }
|
||||||
|
pub fn scale(self: mut this, s: float): void { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
* fields are private
|
||||||
|
* mutation is explicit (`mut this`)
|
||||||
|
* no inheritance
|
||||||
|
* no identity
|
||||||
|
|
||||||
|
Structs are designed to be:
|
||||||
|
|
||||||
|
* cache‑friendly
|
||||||
|
* predictable
|
||||||
|
* easy to reason about
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Mutability Is a Property of Bindings
|
||||||
|
|
||||||
|
In PBS, **types are never mutable**. Bindings are.
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
let v = Vector.ZERO;
|
||||||
|
v.scale(); // ERROR
|
||||||
|
|
||||||
|
let w = mut Vector.ZERO;
|
||||||
|
w.scale(); // OK
|
||||||
|
```
|
||||||
|
|
||||||
|
This single rule eliminates entire classes of bugs.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. When You Need Power: Allocation (HIP World)
|
||||||
|
|
||||||
|
Allocation is **explicit**.
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
let enemies = alloc list<Enemy>();
|
||||||
|
```
|
||||||
|
|
||||||
|
Once you allocate:
|
||||||
|
|
||||||
|
* data lives in Storage (heap)
|
||||||
|
* access happens through **gates** (handles)
|
||||||
|
* aliasing is real and visible
|
||||||
|
|
||||||
|
This is intentional and explicit.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Gates (Handles, Not Pointers)
|
||||||
|
|
||||||
|
A gate is a small value that refers to heap storage.
|
||||||
|
|
||||||
|
Properties:
|
||||||
|
|
||||||
|
* cheap to copy
|
||||||
|
* may alias shared data
|
||||||
|
* managed by reference counting
|
||||||
|
|
||||||
|
### 7.1 Strong vs Weak Gates
|
||||||
|
|
||||||
|
* **Strong gate** — keeps data alive
|
||||||
|
* **Weak gate** — observes without ownership
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
let a = alloc Node;
|
||||||
|
let w: weak<Node> = a as weak;
|
||||||
|
let maybeA = w as strong;
|
||||||
|
```
|
||||||
|
|
||||||
|
This model mirrors real engine constraints without hiding them.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Controlled Access to Storage
|
||||||
|
|
||||||
|
Heap data is never accessed directly.
|
||||||
|
|
||||||
|
You must choose *how*:
|
||||||
|
|
||||||
|
* `peek` — copy to SAFE
|
||||||
|
* `borrow` — temporary read‑only access
|
||||||
|
* `mutate` — temporary mutable access
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
mutate enemies as e
|
||||||
|
{
|
||||||
|
e.push(newEnemy);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This keeps mutation visible and scoped.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Errors Are Values
|
||||||
|
|
||||||
|
PBS has no exceptions.
|
||||||
|
|
||||||
|
### 9.1 `optional<T>`
|
||||||
|
|
||||||
|
Used when absence is normal.
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
let x = maybeValue else 0;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9.2 `result<T, E>`
|
||||||
|
|
||||||
|
Used when failure matters.
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
let v = loadTexture(path)?;
|
||||||
|
```
|
||||||
|
|
||||||
|
Error propagation is explicit and typed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Control Flow Without Surprises
|
||||||
|
|
||||||
|
PBS favors explicit flow:
|
||||||
|
|
||||||
|
* `if` — control only
|
||||||
|
* `when` — expression
|
||||||
|
* `for` — bounded loops only
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
for i in [0b..count] {
|
||||||
|
update(i);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
No unbounded iteration by accident.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Services: Explicit API Boundaries
|
||||||
|
|
||||||
|
A `service` is how behavior crosses module boundaries.
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
pub service Audio
|
||||||
|
{
|
||||||
|
fn play(sound: Sound): void;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Services are:
|
||||||
|
|
||||||
|
* explicit
|
||||||
|
* statically checked
|
||||||
|
* singleton‑like
|
||||||
|
|
||||||
|
They map naturally to engine subsystems.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Contracts: Static Guarantees
|
||||||
|
|
||||||
|
Contracts define **what exists**, not how.
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
pub declare contract Gfx host
|
||||||
|
{
|
||||||
|
fn drawText(x: int, y: int, msg: string): void;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Contracts:
|
||||||
|
|
||||||
|
* have no runtime cost
|
||||||
|
* are validated at compile time
|
||||||
|
* define engine ↔ script boundaries
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. Modules (Simple and Predictable)
|
||||||
|
|
||||||
|
* one directory = one module
|
||||||
|
* only `pub` symbols cross modules
|
||||||
|
* no side effects on import
|
||||||
|
|
||||||
|
This keeps build and runtime deterministic.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14. Why PBS Works for Games
|
||||||
|
|
||||||
|
PBS is designed around real engine needs:
|
||||||
|
|
||||||
|
* frame‑based execution
|
||||||
|
* explicit allocation
|
||||||
|
* deterministic cleanup
|
||||||
|
* predictable performance
|
||||||
|
|
||||||
|
It teaches developers **why engines are written the way they are**, instead of hiding reality.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15. Who PBS Is For
|
||||||
|
|
||||||
|
PBS is for:
|
||||||
|
|
||||||
|
* game developers who want control
|
||||||
|
* engine developers
|
||||||
|
* students learning systems concepts
|
||||||
|
* educators teaching memory and runtime models
|
||||||
|
|
||||||
|
PBS is *not* for:
|
||||||
|
|
||||||
|
* rapid prototyping without constraints
|
||||||
|
* general app scripting
|
||||||
|
* hiding complexity
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 16. Design Promise
|
||||||
|
|
||||||
|
PBS makes one promise:
|
||||||
|
|
||||||
|
> **Nothing happens behind your back.**
|
||||||
|
|
||||||
|
If you understand PBS, you understand your runtime.
|
||||||
|
|
||||||
|
That is the product.
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,648 +0,0 @@
|
|||||||
# Prometeu Base Script (PBS)
|
|
||||||
|
|
||||||
**Status:** v0 (frontend-freeze)
|
|
||||||
**Goal:** stack-only language, no GC, explicit semantics, predictable runtime
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 0. Philosophy (anchor section)
|
|
||||||
|
|
||||||
PBS is designed as:
|
|
||||||
|
|
||||||
* **Value-first** (no implicit references, no aliasing of mutable state)
|
|
||||||
* **Stack-only** (no heap, no GC)
|
|
||||||
* **Explicit mutability** (bindings, not types)
|
|
||||||
* **Didactic** (rules visible in syntax)
|
|
||||||
* **Runtime-cheap** (frontend-heavy, backend-simple)
|
|
||||||
|
|
||||||
Everything in the language flows from these constraints.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. Project, Files & Modules
|
|
||||||
|
|
||||||
### 1.1 Files
|
|
||||||
|
|
||||||
* Extension: `.pbs`
|
|
||||||
* Project has a **root directory**
|
|
||||||
* `@path` is resolved relative to project root
|
|
||||||
|
|
||||||
### 1.2 Module Model
|
|
||||||
|
|
||||||
* **One directory = one module**.
|
|
||||||
* A module boundary is **real**: parent/child/sibling directories do **not** get automatic visibility.
|
|
||||||
* Code in `@project:modA` does **not** automatically see declarations in `@project:modA/sub`.
|
|
||||||
* Code in `@project:modA/sub` does **not** automatically see declarations in `@project:modA`.
|
|
||||||
* Sibling modules (e.g., `@project:modA` and `@project:modB`) are completely isolated unless you `import`.
|
|
||||||
* **Cross-module access always requires `import`**, and only `pub` symbols may cross module boundaries.
|
|
||||||
|
|
||||||
### 1.3 Automatic Module Index
|
|
||||||
|
|
||||||
* No mandatory barrel file
|
|
||||||
* Compiler builds an index from:
|
|
||||||
|
|
||||||
* all `pub` symbols
|
|
||||||
* in `.pbs` files **directly inside the directory**
|
|
||||||
* Subdirectories are excluded
|
|
||||||
|
|
||||||
### 1.4 Visibility Modifiers
|
|
||||||
|
|
||||||
PBS uses explicit visibility modifiers to control symbol exposure. Visibility is the **only** mechanism that decides whether another file/module can see a symbol.
|
|
||||||
|
|
||||||
* **default (no modifier)** — **file-private**
|
|
||||||
|
|
||||||
* Visible **only** within the declaring `.pbs` file.
|
|
||||||
* Never visible from any other file, even inside the same module.
|
|
||||||
|
|
||||||
* **`mod`** — **module-visible**
|
|
||||||
|
|
||||||
* Visible to **all files** in the same module (same directory).
|
|
||||||
* Not visible outside the module.
|
|
||||||
* No `import` is required for other files in the same module to refer to it.
|
|
||||||
|
|
||||||
* **`pub`** — **public API**
|
|
||||||
|
|
||||||
* Exported as part of the module’s public surface.
|
|
||||||
* May be imported by other modules.
|
|
||||||
* Within the same module, `pub` behaves like `mod` (visible across files without import).
|
|
||||||
|
|
||||||
Important:
|
|
||||||
|
|
||||||
* A symbol is either **file-private**, **module-visible**, or **public**. There is no other visibility level.
|
|
||||||
* Visibility is checked independently in the **type** and **value** namespaces.
|
|
||||||
|
|
||||||
Visibility applies uniformly to:
|
|
||||||
|
|
||||||
* `declare` type declarations
|
|
||||||
* `service`
|
|
||||||
* value-level symbols
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. Namespaces & Visibility
|
|
||||||
|
|
||||||
### 2.1 Global Namespaces
|
|
||||||
|
|
||||||
Existem **dois namespaces globais**:
|
|
||||||
|
|
||||||
**Type namespace**
|
|
||||||
|
|
||||||
Tipos são introduzidos **exclusivamente** por declarações `declare`.
|
|
||||||
O que vem após `declare` define a categoria do tipo.
|
|
||||||
|
|
||||||
Formas válidas:
|
|
||||||
|
|
||||||
```pbs
|
|
||||||
declare struct Name { ... }
|
|
||||||
declare error Name { ... }
|
|
||||||
declare contract Name { ... }
|
|
||||||
```
|
|
||||||
|
|
||||||
**Value namespace**
|
|
||||||
|
|
||||||
Introduzido por declarações executáveis:
|
|
||||||
|
|
||||||
* `fn`
|
|
||||||
* `service`
|
|
||||||
* `let`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. Top-level Declarations
|
|
||||||
|
|
||||||
A `.pbs` file may contain:
|
|
||||||
|
|
||||||
* `import`
|
|
||||||
* **type declarations** via `declare`:
|
|
||||||
|
|
||||||
* `declare struct`
|
|
||||||
* `declare error`
|
|
||||||
* `declare contract`
|
|
||||||
* `service`
|
|
||||||
* `fn` (always file-private)
|
|
||||||
|
|
||||||
Order is free.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. Resolver Rules
|
|
||||||
|
|
||||||
This section defines how the compiler resolves modules, imports, and symbol names into concrete declarations.
|
|
||||||
|
|
||||||
### 4.1 Units of compilation
|
|
||||||
|
|
||||||
* The compilation unit is a **project** (root + all referenced modules/files).
|
|
||||||
* The root of the project is associated with the src/main/modules
|
|
||||||
* A **module** is exactly one directory.
|
|
||||||
* A **file unit** is one `.pbs` file.
|
|
||||||
|
|
||||||
Examples, lets say we have a project called: `project`:
|
|
||||||
```
|
|
||||||
project
|
|
||||||
|- prometeu.json
|
|
||||||
|- prometeu-cache
|
|
||||||
| |-cache.lock
|
|
||||||
|- src
|
|
||||||
| |- main
|
|
||||||
| | |- modules
|
|
||||||
| | | |- module-1
|
|
||||||
| | | | |- file-1.pbs
|
|
||||||
| | | | |- file-2.pbs
|
|
||||||
| | | | | |- fearture A
|
|
||||||
| | | | |- file-3.pbs
|
|
||||||
| | | | |- module-2
|
|
||||||
| | | | | |- file-1.pbs
|
|
||||||
| | | | | |- file-2.pbs
|
|
||||||
| | | | | | |- fearture B
|
|
||||||
| | | | | |- file-3.pbs
|
|
||||||
| |- resources
|
|
||||||
| | |- resource-1.txt
|
|
||||||
| |- test
|
|
||||||
| | |- modules
|
|
||||||
| | | |- module-1
|
|
||||||
| | | | |- file-1.pbs
|
|
||||||
| | | | |- file-2.pbs
|
|
||||||
| | | | |- file-3.pbs
|
|
||||||
| | |- resources
|
|
||||||
```
|
|
||||||
|
|
||||||
For a project `project/src/main/` is the root, and it will be presented in the import as (when looking for feature A and B):
|
|
||||||
```
|
|
||||||
import { featureA } from "@project:module-1"
|
|
||||||
import { featureB } from "@project:module-1/module-2"
|
|
||||||
```
|
|
||||||
|
|
||||||
The project name is a configuration inside `prometeu.json`. A project always defines a unit compilation. Other compilation
|
|
||||||
units could be linked to the project as a dependency. When building a project, all dependencies will be copied into a
|
|
||||||
directory called `prometeu-cache` (read-only) inside the project root.
|
|
||||||
A `project.json` could be look like.
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"name": "project",
|
|
||||||
"dependencies":{
|
|
||||||
"project-A": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"source": "path:../project-A"
|
|
||||||
},
|
|
||||||
"project-B": {
|
|
||||||
"version": "1.5.3",
|
|
||||||
"source": "git:https://github.com/project-B.git"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
When compiling, all deps and current project will be flattened, and Project names should be unique otherwise it will
|
|
||||||
cause conflicts and compilation errors on the current project.
|
|
||||||
|
|
||||||
### 4.2 Namespaces
|
|
||||||
|
|
||||||
Resolution is performed in **two independent namespaces**:
|
|
||||||
|
|
||||||
* **Type namespace**: declarations introduced by `declare` (`struct`, `error`, `contract`).
|
|
||||||
* **Value namespace**: declarations introduced by `service`, `fn`, and `let`.
|
|
||||||
|
|
||||||
A name may exist in both namespaces, but this is **discouraged**; toolchains may report this as an error or warning.
|
|
||||||
|
|
||||||
### 4.3 Visibility gates
|
|
||||||
|
|
||||||
For any candidate symbol `S`, visibility is checked explicitly:
|
|
||||||
|
|
||||||
* **file-private (default)** — visible only within the same file
|
|
||||||
* **`mod`** — visible to any file in the same module
|
|
||||||
* **`pub`** — visible to other modules via `import`
|
|
||||||
|
|
||||||
No implicit visibility exists beyond these rules.
|
|
||||||
|
|
||||||
### 4.4 Module index construction
|
|
||||||
|
|
||||||
For each module directory `M`:
|
|
||||||
|
|
||||||
* The compiler scans all `.pbs` files **directly inside** `M`.
|
|
||||||
* The module’s **public index** contains **only** `pub` symbols from those files.
|
|
||||||
* Subdirectories never contribute to the parent module’s index.
|
|
||||||
|
|
||||||
Duplicate rules:
|
|
||||||
|
|
||||||
* Any `structs, services, contracts, errors` duplicate `pub` names in the same namespace cause a compile error:
|
|
||||||
|
|
||||||
* `duplicate public symbol in module`.
|
|
||||||
|
|
||||||
### 4.5 Import resolution
|
|
||||||
|
|
||||||
Imports are the **only** mechanism for cross-module access.
|
|
||||||
|
|
||||||
```pbs
|
|
||||||
import { X, Y as Z } from "@project:module";
|
|
||||||
```
|
|
||||||
|
|
||||||
Rules:
|
|
||||||
|
|
||||||
* Only `pub` symbols may be imported.
|
|
||||||
* Import-by-module resolves against the module public index.
|
|
||||||
* Import-by-file is not allowed at all.
|
|
||||||
|
|
||||||
### 4.6 Local resolution order
|
|
||||||
|
|
||||||
Within a file, name lookup follows this order **within each namespace**:
|
|
||||||
|
|
||||||
1. Local bindings (parameters, local `let`, innermost scope first) but with warnings
|
|
||||||
- when `import { X as Y } from "@project:module"` and `let Y: int = 0;` `let Y` wins but could generate a warning
|
|
||||||
2. File-level declarations (file-private, `mod`, and `pub` in the same file)
|
|
||||||
3. Imported bindings
|
|
||||||
4. When `import { X } from "@project:module"` (or when using `as`) and we already have a `mod X ...` for this module, compilation error.
|
|
||||||
|
|
||||||
Shadowing rules:
|
|
||||||
|
|
||||||
* Local `let` shadowing is allowed.
|
|
||||||
* Shadowing of `fn` and `service` names is not allowed.
|
|
||||||
|
|
||||||
### 4.7 Cross-file and cross-module access
|
|
||||||
|
|
||||||
**Within the same module:**
|
|
||||||
|
|
||||||
* `mod` and `pub` symbols are visible across files without `import`.
|
|
||||||
* file-private symbols are never visible.
|
|
||||||
|
|
||||||
**Across modules:**
|
|
||||||
|
|
||||||
* only `pub` symbols are visible
|
|
||||||
* access always requires an explicit `import`.
|
|
||||||
|
|
||||||
### 4.8 Cycles
|
|
||||||
|
|
||||||
* Import cycles are allowed only if name resolution can be completed.
|
|
||||||
* PBS has no top-level execution, so cycles are resolved purely at the symbol level.
|
|
||||||
* Any cycle that prevents construction of a complete symbol table is a compile error.
|
|
||||||
|
|
||||||
### 4.9 Contracts and services
|
|
||||||
|
|
||||||
* `declare contract C` introduces `C` in the **type namespace**.
|
|
||||||
* `service S: C` resolves `C` as a type and validates that `S` implements all declared signatures.
|
|
||||||
* they can be implemented by the Prometeu runtime / host environment.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. Services
|
|
||||||
|
|
||||||
A `service` represents an **explicit API boundary** between PBS code and either:
|
|
||||||
|
|
||||||
* other PBS modules, or
|
|
||||||
* it is definitely a singleton by design
|
|
||||||
* can implement a contract, or not
|
|
||||||
- when implementing a contract, signatures must match exactly
|
|
||||||
* every `fn` inside in a `service` will follow the same visibility as the service it belongs (`pub` or `mod`).
|
|
||||||
- once being able to see the service, it can see all its methods.
|
|
||||||
|
|
||||||
A service is never an implementation detail.
|
|
||||||
|
|
||||||
### 4.1 Declaration and visibility
|
|
||||||
|
|
||||||
A service must always be declared with an explicit visibility modifier:
|
|
||||||
|
|
||||||
* `pub service` — part of the module’s public API
|
|
||||||
* `mod service` — internal API, visible only inside the module
|
|
||||||
|
|
||||||
There is **no such thing** as a private service.
|
|
||||||
|
|
||||||
### 4.2 Service methods
|
|
||||||
|
|
||||||
* All methods declared inside a service are **public within that service**.
|
|
||||||
* There are no private or helper methods inside a service.
|
|
||||||
* A service method may call:
|
|
||||||
|
|
||||||
* top-level `fn` in the same file
|
|
||||||
* other services it can legally see
|
|
||||||
|
|
||||||
### 4.3 Implementation rule
|
|
||||||
|
|
||||||
If logic is not conceptually part of the API, it **must not** live inside a service.
|
|
||||||
Such logic must be implemented as file-private `fn`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. Types
|
|
||||||
|
|
||||||
This section describes all value types available in PBS and how they are declared.
|
|
||||||
|
|
||||||
### 6.1 Primitive types
|
|
||||||
|
|
||||||
PBS provides a small, fixed set of primitive types:
|
|
||||||
|
|
||||||
* `void`
|
|
||||||
* `int` (32-bit signed)
|
|
||||||
* `long` (64-bit signed)
|
|
||||||
* `float` (32-bit IEEE-754)
|
|
||||||
* `double` (64-bit IEEE-754)
|
|
||||||
* `bool`
|
|
||||||
* `char` (Unicode code point, 32-bit)
|
|
||||||
* `string`
|
|
||||||
|
|
||||||
Important notes:
|
|
||||||
|
|
||||||
* `string` values are **immutable**.
|
|
||||||
* Strings exist only as literals stored in a constant pool.
|
|
||||||
* There is no dynamic string allocation at runtime.
|
|
||||||
|
|
||||||
### 6.2 Struct types
|
|
||||||
|
|
||||||
User-defined value types are declared using `declare struct`.
|
|
||||||
|
|
||||||
A struct:
|
|
||||||
|
|
||||||
* is a **pure value type**
|
|
||||||
* has no identity
|
|
||||||
* follow the rules of **mutability and borrowing" described below
|
|
||||||
* has no inheritance or subtyping
|
|
||||||
* it is only copied when mutated, otherwise it is **viewed as immutable** and passed as ref by default.
|
|
||||||
|
|
||||||
All behavior related to the type must be defined inside the struct body.
|
|
||||||
|
|
||||||
### 6.3 `this`
|
|
||||||
|
|
||||||
Inside a struct body, the special type `this` refers to the struct itself.
|
|
||||||
|
|
||||||
Rules:
|
|
||||||
|
|
||||||
* `this` may only appear inside a `declare struct` body.
|
|
||||||
* Outside a struct, `this` is illegal.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. Structs & Constructors
|
|
||||||
|
|
||||||
```pbs
|
|
||||||
declare struct Vector(x: float, y: float)
|
|
||||||
[
|
|
||||||
(): (0,0) as default { }
|
|
||||||
(a: float): (a,a) as square { }
|
|
||||||
(): (1,1) as normalize { }
|
|
||||||
]
|
|
||||||
[[
|
|
||||||
ZERO: default()
|
|
||||||
ONE: square(1.0)
|
|
||||||
]]
|
|
||||||
{
|
|
||||||
pub fn len(self: this): float { ... }
|
|
||||||
pub fn scale(self: mut this): void { ... }
|
|
||||||
pub fn normalize(self: mut this): void { ... }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Key rules:
|
|
||||||
|
|
||||||
* fields private by default
|
|
||||||
* constructor aliases live in type namespace but can never be imported, in the exemplo only `Vector` can be imported.
|
|
||||||
* no static methods
|
|
||||||
* static block values are compile-time constants
|
|
||||||
|
|
||||||
There will never be a conflict between an alias and a method of the same name.
|
|
||||||
A constructor will be called as `let v = Vector.normalize()` and methods will be called as `v.normalize()`.
|
|
||||||
In fact, they call different things, one is static, and the other is an instance method (there are no static methods on structs).
|
|
||||||
|
|
||||||
The static block `[[ ]]` should be static (and generate static on constant pool) and can use only constructors and static values, as helpers.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. Mutability & Borrow Model (Core Rule)
|
|
||||||
|
|
||||||
This is a foundational rule of PBS.
|
|
||||||
|
|
||||||
Mutability is **never** a property of a type.
|
|
||||||
Mutability belongs **only** to bindings (variables and parameters).
|
|
||||||
|
|
||||||
### 8.1 Immutable by default
|
|
||||||
|
|
||||||
All bindings are immutable unless explicitly marked `mut`.
|
|
||||||
|
|
||||||
```pbs
|
|
||||||
let v = Vector.ZERO; // immutable binding
|
|
||||||
let mut w = Vector.ZERO; // mutable binding (local copy)
|
|
||||||
```
|
|
||||||
|
|
||||||
Some examples of mutable bindings:
|
|
||||||
```pbs
|
|
||||||
let v = Vector.ZERO;
|
|
||||||
v.scale(); // ERROR: cannot mutate a read-only binding
|
|
||||||
|
|
||||||
let mut w = v;
|
|
||||||
w.scale(); // OK: when mut it copies the value, and could be changed
|
|
||||||
|
|
||||||
fn f(v: Vector): Vector
|
|
||||||
{
|
|
||||||
let mut w = v;
|
|
||||||
return w; // when it happens compiler will generate a copy otherwise w will be lost in the stack
|
|
||||||
}
|
|
||||||
|
|
||||||
fn g(v: Vector): void
|
|
||||||
{
|
|
||||||
let vro = f(Vector.ZERO); // OK! and it will be a readonly copy
|
|
||||||
let vrw = mut f(Vector.ZERO); // OK! and it will be a mutable copy of the copy
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.2 Consequences of binding-based mutability
|
|
||||||
|
|
||||||
* Mutating a value never affects any other binding.
|
|
||||||
* Static values can never be mutated.
|
|
||||||
* There is no aliasing of mutable state.
|
|
||||||
|
|
||||||
### 8.3 Parameters and copying
|
|
||||||
|
|
||||||
Function parameters follow these rules:
|
|
||||||
|
|
||||||
* `T` parameters are passed as **read-only borrows**.
|
|
||||||
* `mut T` parameters create a **local mutable copy**.
|
|
||||||
|
|
||||||
The caller is never affected by mutations performed inside the function.
|
|
||||||
|
|
||||||
### 8.4 Method receivers
|
|
||||||
|
|
||||||
Methods on structs declare mutability explicitly on the receiver:
|
|
||||||
|
|
||||||
```pbs
|
|
||||||
fn len(self: this): float // read-only
|
|
||||||
fn scale(self: mut this): void // mutating
|
|
||||||
```
|
|
||||||
|
|
||||||
A mutating method:
|
|
||||||
|
|
||||||
* requires a **mutable lvalue** at the call site
|
|
||||||
* cannot be called on temporaries or static values
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 9. Expressions & Control Flow
|
|
||||||
|
|
||||||
* `if / else`
|
|
||||||
* `for` with ranges
|
|
||||||
* `when` expression
|
|
||||||
* `return`
|
|
||||||
|
|
||||||
`when`:
|
|
||||||
|
|
||||||
```pbs
|
|
||||||
let x = when a > b then 1 else 2;
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 10. Return Fallback (`else`)
|
|
||||||
|
|
||||||
```pbs
|
|
||||||
fn v(): Vector else Vector.ZERO
|
|
||||||
{
|
|
||||||
if cond return Vector.ONE;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Used to guarantee total functions without boilerplate.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 11. Numeric Rules
|
|
||||||
|
|
||||||
* implicit widen: `int → long → float → double`
|
|
||||||
* no implicit narrowing
|
|
||||||
* cast syntax: `expr as Type`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 12. `bounded`
|
|
||||||
|
|
||||||
`bounded` is a dedicated scalar type for **indices and sizes**.
|
|
||||||
|
|
||||||
### 12.1 Purpose
|
|
||||||
|
|
||||||
The goal of `bounded` is to make indexing and counting:
|
|
||||||
|
|
||||||
* explicit
|
|
||||||
* safe
|
|
||||||
* visually distinct from general arithmetic
|
|
||||||
|
|
||||||
### 12.2 Representation
|
|
||||||
|
|
||||||
* Internally represented as an unsigned 16-bit integer (`u16`).
|
|
||||||
* Valid range: `0 .. 65535`.
|
|
||||||
|
|
||||||
### 12.3 Usage rules
|
|
||||||
|
|
||||||
`bounded` is used for:
|
|
||||||
|
|
||||||
* array indices
|
|
||||||
* array lengths
|
|
||||||
* default `for` loop counters
|
|
||||||
|
|
||||||
Operations are intentionally limited:
|
|
||||||
|
|
||||||
* allowed: comparison, checked `+` and `-`
|
|
||||||
* disallowed: multiplication, division, bitwise operations
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 13. Fixed Arrays
|
|
||||||
|
|
||||||
```pbs
|
|
||||||
Array<T>[Nb]
|
|
||||||
```
|
|
||||||
|
|
||||||
* `Nb` is compile-time `bounded` literal
|
|
||||||
* immutable bindings = view
|
|
||||||
* mutable bindings = owned storage
|
|
||||||
|
|
||||||
Supports:
|
|
||||||
|
|
||||||
* indexing (`bounded` only)
|
|
||||||
* slicing `[a..b[` (half-open)
|
|
||||||
|
|
||||||
Return escape model prevents dangling views.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 14. `optional<T>`
|
|
||||||
|
|
||||||
`optional<T>` represents the explicit presence or absence of a value.
|
|
||||||
|
|
||||||
### 14.1 Design intent
|
|
||||||
|
|
||||||
* Absence is a **normal, explicit state**.
|
|
||||||
* No traps or implicit unwraps exist.
|
|
||||||
* No heap allocation is involved.
|
|
||||||
|
|
||||||
### 14.2 Extraction rule
|
|
||||||
|
|
||||||
The **only** supported way to extract a value from an optional is with `else`:
|
|
||||||
|
|
||||||
```pbs
|
|
||||||
let x: int = opt else 0;
|
|
||||||
```
|
|
||||||
|
|
||||||
This makes fallback behavior explicit at the call site.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 15. `result<T,E>`
|
|
||||||
|
|
||||||
* typed errors
|
|
||||||
* no exceptions
|
|
||||||
* no implicit extraction
|
|
||||||
|
|
||||||
```pbs
|
|
||||||
let v = f()?;
|
|
||||||
```
|
|
||||||
|
|
||||||
### Error handling with `handle`
|
|
||||||
|
|
||||||
`handle` is the *only* construct that allows value extraction from a `result` while mapping errors.
|
|
||||||
|
|
||||||
```pbs
|
|
||||||
let x: int = handle r
|
|
||||||
{
|
|
||||||
ErrorA.not_found => ErrorB.io,
|
|
||||||
ErrorA.denied => ErrorB.permission,
|
|
||||||
_ => ErrorB.unknown,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Semantics:
|
|
||||||
|
|
||||||
* If `r` is `ok(v)`, the expression evaluates to `v`
|
|
||||||
* If `r` is `err(e)`, the first matching arm is selected and an early `return err(mapped)` is executed
|
|
||||||
|
|
||||||
Rules:
|
|
||||||
|
|
||||||
* Arms must be exhaustive (explicit or via `_`)
|
|
||||||
* Right-hand side must be a label of the destination error type
|
|
||||||
* No traps are permitted
|
|
||||||
* **The only possible way to extract a value is by handling the error**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 16. What is *deliberately missing* (v0)
|
|
||||||
|
|
||||||
* heap allocation
|
|
||||||
* GC
|
|
||||||
* references
|
|
||||||
* inheritance
|
|
||||||
* traits / interfaces
|
|
||||||
* async
|
|
||||||
* closures
|
|
||||||
* generics (beyond containers)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 17. Roadmap (v1+ ideas)
|
|
||||||
|
|
||||||
This is a non-binding list of future directions. None of these are part of v0.
|
|
||||||
|
|
||||||
* generics for `struct`
|
|
||||||
* slice views with runtime bounds
|
|
||||||
* iterator sugar
|
|
||||||
* `defer`
|
|
||||||
* pattern matching on `result`
|
|
||||||
* ABI boundary spec (VM ↔ PBS)
|
|
||||||
* contract versioning
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**This document is now the canonical organized v0 spec.****
|
|
||||||
Loading…
x
Reference in New Issue
Block a user