add spec docs
This commit is contained in:
parent
f3be4f7946
commit
aa1e0860d2
91
docs/specs/pbs/1. Language Charter.md
Normal file
91
docs/specs/pbs/1. Language Charter.md
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# PBS Language Charter
|
||||||
|
|
||||||
|
Status: Draft v1
|
||||||
|
Applies to: Prometeu Base Script (PBS) language design
|
||||||
|
|
||||||
|
## 1. Mission
|
||||||
|
|
||||||
|
PBS exists to make 2D game development on Prometeu intuitive for beginners and reliable for experienced developers, without sacrificing deterministic runtime behavior.
|
||||||
|
|
||||||
|
## 2. Product Vision
|
||||||
|
|
||||||
|
PBS is a game-first language for a logical, evolving hardware platform.
|
||||||
|
It must feel fluid for frame-driven gameplay code while remaining strict enough to produce stable, verifiable bytecode for a closed VM target.
|
||||||
|
|
||||||
|
## 3. Target Users
|
||||||
|
|
||||||
|
- Beginner creators building their first playable 2D games.
|
||||||
|
- Intermediate developers shipping complete games with predictable behavior.
|
||||||
|
- Advanced developers who need explicit control of architecture and performance costs.
|
||||||
|
|
||||||
|
## 4. Core Principles
|
||||||
|
|
||||||
|
1. Game-first ergonomics: common gameplay patterns must be concise.
|
||||||
|
2. Determinism first: same program + same inputs/events => same behavior.
|
||||||
|
3. Explicit boundaries: host interaction, costs, and side effects must be visible.
|
||||||
|
4. Safe defaults: simple code paths should be hard to misuse.
|
||||||
|
5. Progressive power: advanced control is opt-in, not mandatory.
|
||||||
|
6. Compatibility discipline: language evolution must not silently break cartridges.
|
||||||
|
|
||||||
|
## 5. Scope of PBS v1
|
||||||
|
|
||||||
|
- Stable core syntax and grammar contract.
|
||||||
|
- Static and dynamic semantics for deterministic game code.
|
||||||
|
- Typed host function declarations (`host fn`) aligned with syscall/capability model.
|
||||||
|
- Module visibility and import model suitable for multi-file game projects.
|
||||||
|
- Diagnostics and conformance requirements for interoperable implementations.
|
||||||
|
|
||||||
|
## 6. Out of Scope for PBS v1
|
||||||
|
|
||||||
|
- New VM opcodes as a language requirement.
|
||||||
|
- Non-deterministic async execution models.
|
||||||
|
- Mandatory custom allocator model replacing runtime GC.
|
||||||
|
- Advanced memory syntax (`alloc/borrow/mutate/...`) before explicit profile activation.
|
||||||
|
|
||||||
|
## 7. Non-Negotiable Constraints
|
||||||
|
|
||||||
|
- Runtime and bytecode authority override language preferences.
|
||||||
|
- Closed VM compatibility is mandatory.
|
||||||
|
- `FRAME_SYNC`-based execution semantics are preserved.
|
||||||
|
- Host API usage remains capability-gated and versioned.
|
||||||
|
|
||||||
|
## 8. Evolution Commitments
|
||||||
|
|
||||||
|
- Additive-first evolution for minor releases.
|
||||||
|
- Incompatible changes only in major lines with migration guidance.
|
||||||
|
- Canonical host primitive versioning by `(module, name, version)`.
|
||||||
|
- Deterministic loader rejection when target contracts are unsupported.
|
||||||
|
|
||||||
|
## 9. Quality Bar
|
||||||
|
|
||||||
|
PBS is considered healthy only if:
|
||||||
|
|
||||||
|
- newcomers can produce a working 2D game loop quickly,
|
||||||
|
- generated behavior is deterministic and replayable,
|
||||||
|
- diagnostics are stable and actionable,
|
||||||
|
- performance risks are visible in tooling,
|
||||||
|
- older supported cartridges keep running across updates.
|
||||||
|
|
||||||
|
## 10. Required Spec Set Before Implementation
|
||||||
|
|
||||||
|
Before implementation starts, PBS must define at least:
|
||||||
|
|
||||||
|
1. Core Syntax Specification.
|
||||||
|
2. Static Semantics Specification.
|
||||||
|
3. Dynamic Semantics Specification.
|
||||||
|
4. Memory and Lifetime Specification.
|
||||||
|
5. Host ABI Binding Specification.
|
||||||
|
6. Module/Package Specification.
|
||||||
|
7. Diagnostics Specification.
|
||||||
|
8. IR and Lowering Specification.
|
||||||
|
9. Conformance Test Specification.
|
||||||
|
10. Compatibility and Evolution Policy.
|
||||||
|
|
||||||
|
## 11. Decision Rule
|
||||||
|
|
||||||
|
When trade-offs appear, decisions must prioritize, in order:
|
||||||
|
|
||||||
|
1. Determinism and compatibility.
|
||||||
|
2. Clarity for beginners.
|
||||||
|
3. Fluency for real game workflows.
|
||||||
|
4. Performance transparency for advanced users.
|
||||||
150
docs/specs/pbs/2. Governance and Versioning.md
Normal file
150
docs/specs/pbs/2. Governance and Versioning.md
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
# PBS Governance and Versioning
|
||||||
|
|
||||||
|
Status: Draft v1
|
||||||
|
Applies to: PBS language, profiles, and related specifications
|
||||||
|
|
||||||
|
## 1. Purpose
|
||||||
|
|
||||||
|
This document defines how PBS decisions are made and how versions evolve without breaking the ecosystem unpredictably.
|
||||||
|
|
||||||
|
## 2. Scope
|
||||||
|
|
||||||
|
This policy governs:
|
||||||
|
|
||||||
|
- language specification changes,
|
||||||
|
- profile changes (for example, Core/Game),
|
||||||
|
- standard library specification changes,
|
||||||
|
- compatibility policy updates,
|
||||||
|
- release and deprecation decisions.
|
||||||
|
|
||||||
|
## 3. Governance Model
|
||||||
|
|
||||||
|
PBS uses a spec-first governance model.
|
||||||
|
No implementation change is considered normative until the relevant spec change is accepted.
|
||||||
|
|
||||||
|
### 3.1 Roles
|
||||||
|
|
||||||
|
- Maintainers: approve/reject RFCs and cut releases.
|
||||||
|
- Editors: keep specs coherent, complete, and cross-referenced.
|
||||||
|
- Implementers: provide feasibility feedback and conformance evidence.
|
||||||
|
- Community contributors: propose RFCs and review drafts.
|
||||||
|
|
||||||
|
### 3.2 Authority Rule
|
||||||
|
|
||||||
|
If a governance decision conflicts with runtime/bytecode authority, runtime/bytecode authority wins.
|
||||||
|
|
||||||
|
## 4. Decision Process (RFC)
|
||||||
|
|
||||||
|
All non-trivial changes MUST go through RFC.
|
||||||
|
|
||||||
|
### 4.1 RFC Lifecycle
|
||||||
|
|
||||||
|
1. Draft: problem, proposal, alternatives, migration impact.
|
||||||
|
2. Review: open feedback period.
|
||||||
|
3. Decision: `Accepted`, `Rejected`, or `Deferred`.
|
||||||
|
4. Spec Merge: normative documents updated.
|
||||||
|
5. Implementation: only after spec merge.
|
||||||
|
6. Conformance: tests and diagnostics updated before release.
|
||||||
|
|
||||||
|
### 4.2 Fast-Track
|
||||||
|
|
||||||
|
Fast-track is allowed only for:
|
||||||
|
|
||||||
|
- critical correctness fixes,
|
||||||
|
- security/capability violations,
|
||||||
|
- deterministic behavior regressions.
|
||||||
|
|
||||||
|
Fast-track changes still require post-merge RFC backfill.
|
||||||
|
|
||||||
|
## 5. Version Domains
|
||||||
|
|
||||||
|
PBS versioning is separated by domain to avoid ambiguity.
|
||||||
|
|
||||||
|
1. Language Version (`pbs_lang`): syntax + semantics.
|
||||||
|
2. Profile Version (`pbs_profile`): profile-specific surface (Core/Game).
|
||||||
|
3. Stdlib Version (`pbs_stdlib`): standard library contract.
|
||||||
|
4. Compatibility Policy Version (`pbs_compat`): evolution/deprecation policy text.
|
||||||
|
|
||||||
|
Host primitives remain versioned by canonical identity `(module, name, version)`.
|
||||||
|
|
||||||
|
## 6. Versioning Scheme
|
||||||
|
|
||||||
|
Each domain uses semantic versioning:
|
||||||
|
|
||||||
|
- `MAJOR`: incompatible changes.
|
||||||
|
- `MINOR`: backward-compatible additions.
|
||||||
|
- `PATCH`: clarifications/fixes with no intended behavior break.
|
||||||
|
|
||||||
|
## 7. Change Classification
|
||||||
|
|
||||||
|
### 7.1 Patch Changes
|
||||||
|
|
||||||
|
- wording fixes,
|
||||||
|
- unambiguous typo corrections,
|
||||||
|
- diagnostics wording adjustments without code/behavior contract changes.
|
||||||
|
|
||||||
|
### 7.2 Minor Changes
|
||||||
|
|
||||||
|
- additive syntax behind explicit profile gates,
|
||||||
|
- new stdlib APIs,
|
||||||
|
- new host primitive versions added without removing old supported versions.
|
||||||
|
|
||||||
|
### 7.3 Major Changes
|
||||||
|
|
||||||
|
- behavior changes that can alter valid program outcomes,
|
||||||
|
- removal of previously supported constructs,
|
||||||
|
- incompatible type or resolution rule changes.
|
||||||
|
|
||||||
|
## 8. Compatibility Rules
|
||||||
|
|
||||||
|
- Supported old versions MUST continue to compile/link/run as declared by the compatibility window.
|
||||||
|
- A release MUST publish a compatibility matrix for language/profile/stdlib domains.
|
||||||
|
- Toolchains MUST reject unsupported targets deterministically with explicit diagnostics.
|
||||||
|
|
||||||
|
## 9. Deprecation and Removal Policy
|
||||||
|
|
||||||
|
Deprecation stages:
|
||||||
|
|
||||||
|
1. Introduce deprecation notice in specs and tooling.
|
||||||
|
2. Keep feature functional during declared support window.
|
||||||
|
3. Remove only in a subsequent major version.
|
||||||
|
|
||||||
|
Every deprecation MUST include:
|
||||||
|
|
||||||
|
- replacement path,
|
||||||
|
- migration notes,
|
||||||
|
- timeline (first deprecated version, last supported version, removal version).
|
||||||
|
|
||||||
|
## 10. Release Requirements
|
||||||
|
|
||||||
|
Before any version release:
|
||||||
|
|
||||||
|
1. Specs for changed domains are updated.
|
||||||
|
2. Changelog is published with change classification.
|
||||||
|
3. Conformance suite is updated and passing.
|
||||||
|
4. Compatibility matrix is published.
|
||||||
|
5. Migration guide is provided for any major-impact changes.
|
||||||
|
|
||||||
|
## 11. Documentation Contract
|
||||||
|
|
||||||
|
Every accepted change MUST update, when relevant:
|
||||||
|
|
||||||
|
- normative spec sections,
|
||||||
|
- examples,
|
||||||
|
- diagnostics documentation,
|
||||||
|
- conformance tests,
|
||||||
|
- compatibility matrix/changelog.
|
||||||
|
|
||||||
|
## 12. Conflict Resolution
|
||||||
|
|
||||||
|
When maintainers disagree, the tie-breaker is:
|
||||||
|
|
||||||
|
1. determinism and compatibility,
|
||||||
|
2. clarity for beginners,
|
||||||
|
3. implementation feasibility and tooling stability.
|
||||||
|
|
||||||
|
## 13. Non-Goals
|
||||||
|
|
||||||
|
- Replacing runtime authority with governance-only decisions.
|
||||||
|
- Defining subsystem-specific API semantics in this document.
|
||||||
|
- Granting implementation behavior override over normative specs.
|
||||||
1077
docs/specs/pbs/3. Core Syntax Specification.md
Normal file
1077
docs/specs/pbs/3. Core Syntax Specification.md
Normal file
File diff suppressed because it is too large
Load Diff
565
docs/specs/pbs/4. Static Semantics Specification.md
Normal file
565
docs/specs/pbs/4. Static Semantics Specification.md
Normal file
@ -0,0 +1,565 @@
|
|||||||
|
# PBS Static Semantics Specification
|
||||||
|
|
||||||
|
Status: Draft v1 (Normative)
|
||||||
|
Scope: binding, callable formation, type checking, and deterministic function application
|
||||||
|
|
||||||
|
## 1. Purpose
|
||||||
|
|
||||||
|
This document defines the static semantics of PBS core language.
|
||||||
|
|
||||||
|
It is intended to:
|
||||||
|
|
||||||
|
- give deterministic meaning to declarations accepted by the syntax specification,
|
||||||
|
- define callable identity and application rules,
|
||||||
|
- make type checking stable across implementations,
|
||||||
|
- preserve beginner-facing clarity without hidden callable behavior.
|
||||||
|
|
||||||
|
## 2. Core Semantic Model
|
||||||
|
|
||||||
|
### 2.1 Authority and precedence
|
||||||
|
|
||||||
|
Normative precedence:
|
||||||
|
|
||||||
|
1. Runtime authority (`docs/specs/hardware/topics/chapter-2.md`, `chapter-3.md`, `chapter-9.md`, `chapter-12.md`, `chapter-16.md`)
|
||||||
|
2. Bytecode authority (`docs/specs/bytecode/ISA_CORE.md`)
|
||||||
|
3. `3. Core Syntax Specification.md`
|
||||||
|
4. This document
|
||||||
|
|
||||||
|
If a rule here conflicts with higher authority, it is invalid.
|
||||||
|
|
||||||
|
### 2.2 Semantic namespaces
|
||||||
|
|
||||||
|
PBS distinguishes at least:
|
||||||
|
|
||||||
|
- type namespace,
|
||||||
|
- value namespace,
|
||||||
|
- callable namespace.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `declare struct`, `declare contract`, `declare error`, `declare enum`, and `declare callback` introduce names in the type namespace.
|
||||||
|
- `let`, parameters, and `declare const` introduce names in the value namespace.
|
||||||
|
- Top-level `fn`, service methods, and `host fn` participate in the callable namespace.
|
||||||
|
- `fn` declarations are not first-class values in v1 core and therefore do not become ordinary value expressions.
|
||||||
|
- `bind(...)` is a callback-formation construct, not a general function-value construct.
|
||||||
|
|
||||||
|
### 2.3 Tuple shapes
|
||||||
|
|
||||||
|
Static checking uses tuple shapes as semantic objects.
|
||||||
|
|
||||||
|
Definitions:
|
||||||
|
|
||||||
|
- Input tuple shape: ordered sequence of zero or more input slots.
|
||||||
|
- Output tuple shape: ordered sequence of zero or more output slots.
|
||||||
|
- Each slot has a type and a stable label.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- Tuple shapes in PBS core are always named, except for unit `()`.
|
||||||
|
- Input slot labels come from parameter names and are local frame names.
|
||||||
|
- Output slot labels come from return annotations and are visible for multi-slot member projection.
|
||||||
|
- Tuple-shape identity for overload and resolution ignores labels.
|
||||||
|
- Tuple-shape compatibility requires matching arity and positional slot types.
|
||||||
|
- Labels must still be preserved as part of declaration surface and projection metadata.
|
||||||
|
- A single-slot tuple shape has a distinguished carrier value type equal to its slot type.
|
||||||
|
- In value positions, single-slot tuple values collapse to their carrier value type.
|
||||||
|
- Single-slot tuple shapes have no dedicated tuple-literal surface in v1 core.
|
||||||
|
|
||||||
|
## 3. Functions and `apply`
|
||||||
|
|
||||||
|
### 3.1 Canonical function model
|
||||||
|
|
||||||
|
Every callable `fn` in PBS is modeled statically as:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Fn : InputTuple -> OutputTuple
|
||||||
|
```
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `fn f(a: A, b: B)` has input tuple shape `(a: A, b: B)`.
|
||||||
|
- `fn f()` has empty input tuple shape `()`.
|
||||||
|
- `-> void`, `-> ()`, and omitted return annotation all denote empty output tuple shape `()`.
|
||||||
|
- `-> T` denotes a single-slot output tuple shape `(value: T)`.
|
||||||
|
- `-> (x: T)` denotes a single-slot output tuple shape `(x: T)`.
|
||||||
|
- `-> (x: T, y: U)` denotes a two-slot output tuple shape `(x: T, y: U)`.
|
||||||
|
- `-> T` and `-> (x: T)` are identical for overload identity and differ only in preserved label metadata.
|
||||||
|
- `optional T` is a regular value type and may appear in parameters, locals, fields, and plain returns.
|
||||||
|
- `optional T` with single-slot payload is internally normalized to `optional<(value: T)>`.
|
||||||
|
- `optional` and `optional void` are invalid type surfaces.
|
||||||
|
- `-> result<E> T` denotes a result return surface over payload shape `T` and error type `E`.
|
||||||
|
- `-> result<E> T` with single-slot payload is internally normalized to `result<E, (value: T)>`.
|
||||||
|
- `-> result<E>` is valid and denotes a result return surface with unit payload.
|
||||||
|
- A function return surface may be plain or `result<E>`.
|
||||||
|
- A function return surface must not combine `optional` and `result` in the same declaration.
|
||||||
|
- `result<E>` wraps the declared success payload; the payload itself may be scalar or a named tuple shape.
|
||||||
|
|
||||||
|
### 3.2 Callable categories
|
||||||
|
|
||||||
|
The following constructs are callable in v1 core:
|
||||||
|
|
||||||
|
- top-level `fn`,
|
||||||
|
- struct methods on concrete receivers,
|
||||||
|
- contract values,
|
||||||
|
- callback values,
|
||||||
|
- service methods,
|
||||||
|
- `host fn`.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- All callable categories use the same input/output tuple model.
|
||||||
|
- A struct method is identified by `(struct type, method name, input tuple shape excluding the receiver slot, output tuple shape)`.
|
||||||
|
- A contract value is identified at the type level by its contract type and at runtime by an underlying concrete struct instance plus its selected implementation.
|
||||||
|
- A callback declaration defines a nominal callable type with exactly one input/output tuple shape.
|
||||||
|
- A service method is identified by `(service name, method name, input tuple shape, output tuple shape)`.
|
||||||
|
- A top-level `fn` is identified by `(name, input tuple shape, output tuple shape)`.
|
||||||
|
- A callback value is identified at the type level by its declared callback type and signature.
|
||||||
|
- A `host fn` is identified by `(name, input tuple shape, output tuple shape)` and has no PBS body.
|
||||||
|
- Contract signatures and barrel signatures must preserve the same callable shape.
|
||||||
|
|
||||||
|
### 3.3 Declaration validity
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- Parameter names in a single `ParamList` must be unique.
|
||||||
|
- Output labels in a named tuple return annotation must be unique.
|
||||||
|
- Error case labels in a single `declare error` body must be unique.
|
||||||
|
- Enum case labels in a single `declare enum` must be unique.
|
||||||
|
- Enum case integer identifiers in a single `declare enum` must be unique.
|
||||||
|
- Two declarations with the same callable name and the same input/output tuple shape are duplicates.
|
||||||
|
- Changing only parameter names does not create a new callable.
|
||||||
|
- Changing only input labels in `ParamList` does not create a new callable.
|
||||||
|
- Changing only output labels does not create a new callable.
|
||||||
|
- `mod.barrel` function entries are matched by callable identity, ignoring labels.
|
||||||
|
- Barrel labels may differ from implementation labels.
|
||||||
|
- Any return surface that combines `optional` and `result` is statically invalid.
|
||||||
|
- Any payload-less `optional` type surface is statically invalid.
|
||||||
|
- Any `optional void` type surface is statically invalid.
|
||||||
|
|
||||||
|
### 3.4 Enum declarations and values
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `declare enum Name(case1, case2, ...);` introduces a nominal enum type `Name`.
|
||||||
|
- `declare enum Name(case1 = n1, case2 = n2, ...);` introduces explicit integer identifiers for enum cases.
|
||||||
|
- If no enum case uses an explicit identifier, identifiers are assigned as `0..n-1` in declaration order.
|
||||||
|
- If any enum case uses an explicit identifier, then every enum case in that declaration must use an explicit identifier.
|
||||||
|
- `Name.case` is a valid enum value surface only when `Name` resolves to a declared enum type and `case` resolves to a declared case of that enum.
|
||||||
|
- The static type of `Name.case` is the enum type `Name`.
|
||||||
|
- Error labels are not enum cases and must not be used where enum case values are required.
|
||||||
|
|
||||||
|
### 3.5 Structs, methods, and contracts
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- Struct values are heap-backed reference values in v1 core.
|
||||||
|
- `new Struct(args...)` allocates a new struct instance of the declared struct type.
|
||||||
|
- `new Struct.ctorName(args...)` invokes a named constructor declared in the enclosing struct body and produces a new struct instance of that type.
|
||||||
|
- Struct construction arguments are matched positionally to the declared struct field order.
|
||||||
|
- Assigning a struct value copies the reference, not the underlying field storage.
|
||||||
|
- Struct fields are mutable and accessible by default in v1 core.
|
||||||
|
- A struct method declared in a struct body has an implicit receiver binding `this` of type `Self`.
|
||||||
|
- `this` is valid only inside struct method bodies.
|
||||||
|
- `Self` is valid only in struct method and `ctor` declarations and denotes the enclosing struct type.
|
||||||
|
- A named `ctor` declared in a struct body is not a method and does not introduce `this`.
|
||||||
|
- `ctor` bodies return the enclosing struct type and may use explicit `return`.
|
||||||
|
- Methods declared in a struct body belong to the direct method namespace of that concrete struct type.
|
||||||
|
- `receiver.method(...)` on a concrete struct receiver resolves only against methods declared directly in that struct body.
|
||||||
|
- `receiver.ctorName(...)` is never valid on a concrete struct value.
|
||||||
|
- Contract implementations do not inject their methods into the direct method namespace of the concrete struct.
|
||||||
|
- `implements Contract for Struct using s { ... }` is unique per `(Contract, Struct)` pair.
|
||||||
|
- A contract for a struct may be implemented only in the module where the struct itself is declared.
|
||||||
|
- Contracts may be declared in other modules and implemented for the local struct in its owner module.
|
||||||
|
- An `implements` block has no independent visibility; its observability follows the visibility of the struct, and the contract must also be nameable at the use site.
|
||||||
|
- A struct value may be coerced to a contract value when exactly one visible `implements Contract for Struct ...` applies.
|
||||||
|
- Contract coercion may happen by explicit `expr as ContractType` or by contextual typing in assignments, parameter passing, and returns.
|
||||||
|
- A contract value carries the underlying struct reference together with the selected contract implementation for runtime dispatch.
|
||||||
|
- Calling `contractValue.method(...)` uses dynamic dispatch through the contract value.
|
||||||
|
- Calling `structValue.contractMethod(...)` is not valid unless that method is also declared directly on the struct.
|
||||||
|
- Structs do not have static methods in v1 core; named constructors are their only type-qualified callable members.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
declare contract StasisProcess {
|
||||||
|
fn stasis() -> int;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare struct Struct(a: int) {
|
||||||
|
fn compute() -> int {
|
||||||
|
return this.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctor createWithSomethingSpecial(x: int) {
|
||||||
|
return new Struct(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
implements StasisProcess for Struct using s {
|
||||||
|
fn stasis() -> int {
|
||||||
|
return s.compute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn demo() -> int {
|
||||||
|
let s = new Struct(1);
|
||||||
|
let s2 = new Struct.createWithSomethingSpecial(2);
|
||||||
|
let sp: StasisProcess = s;
|
||||||
|
let sp2 = s as StasisProcess;
|
||||||
|
let a = s.compute();
|
||||||
|
let _ = s2.compute();
|
||||||
|
let b = sp.stasis();
|
||||||
|
let c = sp2.stasis();
|
||||||
|
return a + b + c;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.6 Nominal callbacks
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `declare callback Name(params...) -> R;` introduces a nominal callback type `Name`.
|
||||||
|
- A callback type is not a `fn`, and a `fn` declaration does not implicitly define a callback type.
|
||||||
|
- A value of callback type may be formed only from a compatible top-level `fn` in v1 core.
|
||||||
|
- A value of callback type may also be formed by `bind(context, fn_name)` when the surrounding static type context expects a callback type.
|
||||||
|
- Service methods are not assignable to callback values in v1 core.
|
||||||
|
- `host fn` declarations are not assignable to callback values in v1 core.
|
||||||
|
- Callback values do not capture local environment implicitly.
|
||||||
|
- Assignment of a top-level `fn` to a callback type succeeds only when exactly one visible overload matches the callback signature.
|
||||||
|
- `bind(context, fn_name)` succeeds only when exactly one visible top-level `fn` overload matches after consuming the first parameter with `context`.
|
||||||
|
- Valid expected callback contexts for `bind(context, fn_name)` include variable initialization with an explicit callback type, assignment to an explicitly typed callback location, argument passing to a callback-typed parameter, and return from a callback-typed function.
|
||||||
|
- The context expression in `bind(context, fn_name)` is evaluated once at bind time and stored explicitly in the resulting callback value.
|
||||||
|
- The stored context follows normal value semantics for its type.
|
||||||
|
- `bind(context, fn_name)` does not introduce general closures; it is explicit partial binding of the first parameter only.
|
||||||
|
- Callback compatibility ignores labels and compares ordered input/output slot types plus the return-surface kind.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
declare callback TickCb(dt: int) -> void;
|
||||||
|
|
||||||
|
fn on_tick(dt: int) -> void {
|
||||||
|
}
|
||||||
|
|
||||||
|
let cb: TickCb = on_tick;
|
||||||
|
```
|
||||||
|
|
||||||
|
Bound example:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
declare callback UpdateCb(dt: int) -> void;
|
||||||
|
|
||||||
|
declare struct Enemy(hp: int);
|
||||||
|
|
||||||
|
fn update_enemy(self: Enemy, dt: int) -> void {
|
||||||
|
}
|
||||||
|
|
||||||
|
let cb: UpdateCb = bind(enemy, update_enemy);
|
||||||
|
```
|
||||||
|
|
||||||
|
Ambiguous overload example:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
declare callback TickCb(dt: int) -> void;
|
||||||
|
|
||||||
|
fn tick(dt: int) -> void {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tick(time: int) -> void {
|
||||||
|
}
|
||||||
|
|
||||||
|
let cb: TickCb = tick; // error: ambiguous overloaded fn assignment
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.7 Canonical application
|
||||||
|
|
||||||
|
The canonical surface form for function application is:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
callee apply arg
|
||||||
|
```
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `apply` is an infix operator that is right-associative.
|
||||||
|
- `f1 apply f2 apply x` is defined as `f1 apply (f2 apply x)`.
|
||||||
|
- `f1 apply f2 apply f3 apply params` is defined as `f1 apply (f2 apply (f3 apply params))`.
|
||||||
|
- The left operand of `apply` must resolve to one of: a callable candidate set, a bound struct method target, a contract-method target, or a callback value.
|
||||||
|
- The right operand of `apply` is an argument expression.
|
||||||
|
- If the callable input arity is `0`, the argument expression must be `()`.
|
||||||
|
- If the callable input arity is `1`, the argument expression is checked against the carrier type of the single input slot.
|
||||||
|
- If the callable input arity is `2..6`, the argument expression must have a named tuple shape with matching arity and positional types.
|
||||||
|
- Input labels are not used for compatibility.
|
||||||
|
- No single-slot tuple argument literal is required or recognized in surface syntax.
|
||||||
|
- There is no partial application in v1 core.
|
||||||
|
- There is no currying in v1 core.
|
||||||
|
- Chained `apply` is nested ordinary application, not callable composition as a first-class value.
|
||||||
|
- Callback values, `host fn`, service methods, struct methods, and contract-method targets use the same `apply` rules as top-level `fn`.
|
||||||
|
|
||||||
|
### 3.8 Call sugar
|
||||||
|
|
||||||
|
The surface form:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
callee(arg1, arg2, ..., argN)
|
||||||
|
```
|
||||||
|
|
||||||
|
desugars to the canonical `apply` surface according to arity.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- The desugaring is purely syntactic.
|
||||||
|
- `f()` is exact sugar for `f apply ()`.
|
||||||
|
- `f(x)` is exact sugar for `f apply x`.
|
||||||
|
- `f(x1, x2, ..., xn)` for `n >= 2` is exact sugar for `f apply (x1, x2, ..., xn)`.
|
||||||
|
- No semantic distinction exists between direct call sugar and its canonical `apply` form.
|
||||||
|
- When `(arg1, ..., argN)` is used as positional tuple sugar, the callee input tuple shape supplies the effective labels.
|
||||||
|
- All overload resolution, diagnostics, and type checking are defined on the canonical `apply` form.
|
||||||
|
|
||||||
|
### 3.9 Result type of application
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- If the selected callable output arity is `0`, the result of `apply` is unit.
|
||||||
|
- If the selected callable output arity is `1`, the result of `apply` is the carrier type of the single output slot.
|
||||||
|
- If the selected callable output arity is `2..6`, the result of `apply` has the named output tuple shape of the selected callable.
|
||||||
|
- Multi-slot output tuple results expose their labels for member projection.
|
||||||
|
- If the selected callable is a callback value, the visible multi-slot output labels come from the callback type rather than from the original source `fn`.
|
||||||
|
- If the selected callable returns `()`, the application result is unit.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
fn func(a: int, b: int) -> (c: int, d: float) {
|
||||||
|
return (c: a + b, d: 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let params: (a: int, b: int) = (1, 2);
|
||||||
|
let r = func apply params;
|
||||||
|
let c = r.c;
|
||||||
|
let d = r.d;
|
||||||
|
```
|
||||||
|
|
||||||
|
In the example above:
|
||||||
|
|
||||||
|
- `func` has input tuple shape `(a: int, b: int)`,
|
||||||
|
- `func` has output tuple shape `(c: int, d: float)`,
|
||||||
|
- `r` has named output tuple type `(c: int, d: float)`,
|
||||||
|
- `r.c` has type `int`,
|
||||||
|
- `r.d` has type `float`.
|
||||||
|
|
||||||
|
Single-slot example:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
fn plus_one(x: int) -> int {
|
||||||
|
return x + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = plus_one apply 1;
|
||||||
|
if r == 2 { }
|
||||||
|
```
|
||||||
|
|
||||||
|
In the example above:
|
||||||
|
|
||||||
|
- `plus_one` has input tuple shape `(x: int)`,
|
||||||
|
- the argument `1` is accepted directly as the carrier value for the single input slot,
|
||||||
|
- `plus_one` has output tuple shape `(value: int)`,
|
||||||
|
- the value produced by `plus_one apply 1` has carrier type `int`,
|
||||||
|
- `r.value` is not required and should not be used.
|
||||||
|
|
||||||
|
### 3.10 Overload resolution
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- Overload resolution starts from the visible callable candidates with the selected name.
|
||||||
|
- Candidate filtering first uses callable kind and input tuple arity.
|
||||||
|
- Remaining candidates are filtered by positional input type compatibility.
|
||||||
|
- If exactly one candidate remains, resolution succeeds.
|
||||||
|
- If multiple candidates remain, expected output types or expected multi-slot output tuple shapes may be used as a tie-breaker when statically available.
|
||||||
|
- If multiple candidates still remain, the `apply` is ambiguous and compilation fails.
|
||||||
|
- If no candidate remains, the `apply` is unresolved and compilation fails.
|
||||||
|
- Overloads that differ only by labels are duplicates and are forbidden.
|
||||||
|
- Overloads that differ only by output positional types are permitted, but uncontextualized `apply` sites may become ambiguous.
|
||||||
|
|
||||||
|
### 3.11 Member access and projection
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `TypeName.case` is valid when `TypeName` resolves to a declared enum type and `case` resolves to one of its declared enum cases.
|
||||||
|
- `TypeName.case` has static type `TypeName`.
|
||||||
|
- `expr.name` is valid when the static type of `expr` is a declared `struct` containing field `name`.
|
||||||
|
- For `struct` field access, the projected member type is the declared field type.
|
||||||
|
- `expr.method` is a valid method-call target when the static type of `expr` is a concrete struct type declaring method `method`.
|
||||||
|
- `expr.method` over a concrete struct receiver does not search visible contract implementations.
|
||||||
|
- `TypeName.ctorName` is not a general member access surface; named constructors are entered only through `new TypeName.ctorName(...)`.
|
||||||
|
- `expr.method` is a valid method-call target when the static type of `expr` is a contract value whose contract declares method `method`.
|
||||||
|
- `expr.name` is valid when the static type of `expr` is a multi-slot named output tuple containing label `name`.
|
||||||
|
- For named output tuples, the projected member type is the type of the corresponding output slot.
|
||||||
|
- Projection is label-based, not position-based.
|
||||||
|
- `expr.hasSome()` and `expr.hasNone()` are valid intrinsic method-call surfaces when the static type of `expr` is `optional<P>`.
|
||||||
|
- `expr.hasSome()` and `expr.hasNone()` both have static type `bool`.
|
||||||
|
- `expr.name()` and `expr.key()` are valid intrinsic method-call surfaces when the static type of `expr` is an enum type.
|
||||||
|
- `expr.name()` has static type `str`.
|
||||||
|
- `expr.key()` has static type `int`.
|
||||||
|
- Access to a missing output label is a compile-time error.
|
||||||
|
- Access to a missing struct field is a compile-time error.
|
||||||
|
- Access to a missing struct method is a compile-time error.
|
||||||
|
- Access to a missing contract method is a compile-time error.
|
||||||
|
- Member projection is not defined for single-slot collapsed carrier values.
|
||||||
|
|
||||||
|
### 3.12 Block expressions and function fallthrough
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- A block expression with a `TailExpr` has the static type of that final expression.
|
||||||
|
- A block expression without a `TailExpr` has static type unit.
|
||||||
|
- Only the final unsemicoloned expression in a block contributes to the block result.
|
||||||
|
- A function body does not implicitly return its trailing `TailExpr`; explicit `return` and ordinary control-flow rules still apply.
|
||||||
|
- Reaching the end of a plain non-unit function is a compile-time error unless all control-flow paths are proven to return explicitly.
|
||||||
|
- Reaching the end of a `void` or `()` function is valid and yields unit.
|
||||||
|
- Reaching the end of an `optional P` function yields `none`.
|
||||||
|
- Reaching the end of a `result<E>` function is a compile-time error.
|
||||||
|
|
||||||
|
### 3.13 Loop forms
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `while cond { ... }` requires `cond` to have static type `bool`.
|
||||||
|
- `for i: T from start until end { ... }` is the declarative counted loop form in v1 core.
|
||||||
|
- `for i: T from start until end step s { ... }` is the explicit-step counted loop form in v1 core.
|
||||||
|
- In `for`, the declared iteration variable `i` introduces a loop-local binding of type `T`.
|
||||||
|
- `start`, `end`, and `step` expressions in `for` must be type-compatible with the declared iteration type `T`.
|
||||||
|
- If `step` is omitted, the loop uses the integer value `1` of the iteration type domain.
|
||||||
|
- `for` iteration proceeds by evaluating `start`, `end`, and optional `step` once before loop entry.
|
||||||
|
- `for ... until ...` uses an exclusive upper bound.
|
||||||
|
- `continue` inside `while` transfers control to the next condition check.
|
||||||
|
- `continue` inside `for` transfers control to the step update and then to the next bound check.
|
||||||
|
- `break` exits the nearest enclosing loop.
|
||||||
|
|
||||||
|
### 3.14 `if` and `switch` conditional expressions
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- In `if cond { a } else { b }`, `cond` must have static type `bool`.
|
||||||
|
- Only the selected branch is evaluated at runtime.
|
||||||
|
- The branch expressions `a` and `b` must have the same static type, subject only to ordinary contextual typing already defined elsewhere in the language.
|
||||||
|
- The static result type of the `if` expression is that shared static type.
|
||||||
|
- In `switch selector { pattern: { ... }, ... }`, the selector expression is evaluated once.
|
||||||
|
- `switch` accepts enum selectors and literal-comparable scalar selectors; `error` selectors are invalid.
|
||||||
|
- Each non-wildcard `switch` arm pattern must be unique within the same `switch`.
|
||||||
|
- Each non-wildcard `switch` arm pattern must be type-compatible with the selector expression.
|
||||||
|
- Enum-case switch patterns must resolve to declared cases of the selector's enum type.
|
||||||
|
- Error labels are not valid switch patterns.
|
||||||
|
- `default` and `_` are equivalent wildcard spellings for `switch`.
|
||||||
|
- At most one wildcard arm may appear in a `switch`.
|
||||||
|
- A `switch` must not mix `default` and `_` in the same arm set.
|
||||||
|
- The blocks of all `switch` arms must have the same static type, subject only to ordinary contextual typing already defined elsewhere in the language.
|
||||||
|
- The static result type of the `switch` expression is that shared static type.
|
||||||
|
- A `switch` used as an `ExprStmt` is valid when the selected arm blocks evaluate to unit.
|
||||||
|
- A `switch` expression used in a value-required position must be exhaustive, either by a wildcard arm or by another statically proven exhaustive case set.
|
||||||
|
|
||||||
|
### 3.15 `optional` construction and extraction
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `some(expr)` forms an `optional<P>` value where `P` is the static type of `expr`, unless an expected `optional<Q>` context is present and constrains `expr` to be compatible with `Q`.
|
||||||
|
- `some(expr)` is invalid when the payload normalizes to `void`.
|
||||||
|
- `none` is valid only when an expected `optional<P>` type is available from context.
|
||||||
|
- `opt else fallback` requires the left operand to have static type `optional<P>`.
|
||||||
|
- In `opt else fallback`, the `fallback` expression must be compatible with payload shape `P`.
|
||||||
|
- The static result type of `opt else fallback` is the carrier value type for single-slot payloads and the named tuple payload shape for multi-slot payloads.
|
||||||
|
- `opt else fallback` does not introduce implicit mutation or unwrapping side effects beyond normal expression evaluation.
|
||||||
|
|
||||||
|
### 3.16 `result<E>` return flow and handling
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `return ok(expr);` is valid only inside a function whose declared return surface is `result<E> P`.
|
||||||
|
- In `return ok(expr);`, `expr` must be compatible with the declared success payload shape `P`.
|
||||||
|
- `return err(E.label);` is valid only inside a function whose declared return surface is `result<E> P`.
|
||||||
|
- In `return err(E.label);`, the error path must resolve to a declared case of the same error type `E`.
|
||||||
|
- `ok(...)` and `err(...)` do not denote ordinary value expressions in v1 core.
|
||||||
|
- `expr!` requires `expr` to have static type `result<E> P`.
|
||||||
|
- `expr!` is valid only when the enclosing function returns `result<E> Q` for the same error type `E`.
|
||||||
|
- The static result type of `expr!` is the extracted success payload shape `P`, collapsed to its carrier value when single-slot.
|
||||||
|
- `handle expr { ... }` requires `expr` to have static type `result<E1> P`.
|
||||||
|
- `handle expr { ... }` is valid only when the enclosing function returns `result<E2> Q` for some payload `Q`.
|
||||||
|
- Each non-wildcard `handle` arm must match a distinct declared case of `E1`.
|
||||||
|
- Each mapped error path on the right side of a `handle` arm must resolve to a declared case of `E2`.
|
||||||
|
- `handle` arms must be exhaustive over `E1`, either by naming all cases exactly once or by providing `_`.
|
||||||
|
- The static result type of `handle expr { ... }` is the extracted success payload shape `P`, collapsed to its carrier value when single-slot.
|
||||||
|
- On error, `handle` performs an immediate enclosing-function return with the mapped `err(...)`.
|
||||||
|
|
||||||
|
### 3.17 Required static diagnostics
|
||||||
|
|
||||||
|
At minimum, deterministic static diagnostics are required for:
|
||||||
|
|
||||||
|
- duplicate parameter names in `fn` declarations,
|
||||||
|
- duplicate output labels in named tuple returns,
|
||||||
|
- duplicate error case labels in `declare error`,
|
||||||
|
- duplicate enum case labels in `declare enum`,
|
||||||
|
- duplicate enum case identifiers in `declare enum`,
|
||||||
|
- invalid mixed implicit/explicit enum case identifiers,
|
||||||
|
- invalid `this` usage outside struct method body,
|
||||||
|
- invalid `Self` type usage outside struct method or `ctor` declarations,
|
||||||
|
- invalid struct method declaration shape,
|
||||||
|
- invalid `ctor` declaration shape,
|
||||||
|
- duplicate `implements Contract for Struct` pair,
|
||||||
|
- `implements` declared outside the owner module of the struct,
|
||||||
|
- incompatible or missing contract method implementation,
|
||||||
|
- invalid contract coercion from concrete struct value,
|
||||||
|
- unresolved barrel function signature after label-insensitive matching,
|
||||||
|
- unresolved callback barrel entry,
|
||||||
|
- invalid enum case path,
|
||||||
|
- invalid enum intrinsic member call,
|
||||||
|
- invalid named constructor target,
|
||||||
|
- incompatible top-level `fn` assignment to callback type,
|
||||||
|
- ambiguous overloaded top-level `fn` assignment to callback type,
|
||||||
|
- attempted assignment of service method to callback type,
|
||||||
|
- attempted assignment of `host fn` to callback type,
|
||||||
|
- use of `bind(...)` without an expected callback type,
|
||||||
|
- incompatible `bind(...)` context type for callback target,
|
||||||
|
- ambiguous overloaded top-level `fn` target in `bind(...)`,
|
||||||
|
- `apply` on a non-callable target,
|
||||||
|
- arity mismatch in `apply`,
|
||||||
|
- argument type mismatch in `apply`,
|
||||||
|
- `apply` chain with incompatible intermediate carrier/tuple shape,
|
||||||
|
- ambiguous overload resolution,
|
||||||
|
- unresolved callable application,
|
||||||
|
- possible fallthrough of plain non-unit function,
|
||||||
|
- non-boolean `while` condition,
|
||||||
|
- invalid `for` iteration type,
|
||||||
|
- incompatible `for` bound or step type,
|
||||||
|
- non-boolean `if` expression condition,
|
||||||
|
- incompatible `if` expression branch types,
|
||||||
|
- duplicate `switch` arm pattern,
|
||||||
|
- mixed `default` and `_` wildcard arms in `switch`,
|
||||||
|
- invalid `switch` selector type,
|
||||||
|
- selector-pattern type mismatch in `switch`,
|
||||||
|
- invalid enum case switch pattern,
|
||||||
|
- incompatible `switch` arm block types,
|
||||||
|
- non-exhaustive `switch` expression in value position,
|
||||||
|
- invalid mixed `optional`/`result` return surface,
|
||||||
|
- invalid payload-less `optional` type surface,
|
||||||
|
- invalid `optional void` type surface,
|
||||||
|
- invalid `none` usage without expected optional type,
|
||||||
|
- invalid `else` extraction over non-optional operand,
|
||||||
|
- fallback type mismatch in `else` extraction,
|
||||||
|
- invalid `some(...)` construction form,
|
||||||
|
- use of `ok(...)` or `err(...)` outside `return`,
|
||||||
|
- invalid `ok(...)` construction form,
|
||||||
|
- invalid `err(...)` construction form,
|
||||||
|
- invalid error label in `err(...)`,
|
||||||
|
- invalid `!` propagation on non-result expression,
|
||||||
|
- mismatched error type in `!` propagation,
|
||||||
|
- invalid `handle` on non-result expression,
|
||||||
|
- non-exhaustive `handle` mapping,
|
||||||
|
- duplicate `handle` mapping arm,
|
||||||
|
- invalid mapped error label in `handle`,
|
||||||
|
- attempted use of a single-slot tuple literal where no such surface form exists,
|
||||||
|
- member access on a missing struct field,
|
||||||
|
- member access on a missing struct method,
|
||||||
|
- member access on a missing contract method,
|
||||||
|
- member projection on a single-slot carrier value,
|
||||||
|
- invalid optional intrinsic member call,
|
||||||
|
- member projection on a missing named output label.
|
||||||
90
docs/specs/pbs/Heap Model - Discussion Agenda.md
Normal file
90
docs/specs/pbs/Heap Model - Discussion Agenda.md
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
# PBS Heap Model - Discussion Agenda
|
||||||
|
|
||||||
|
Status: Working agenda (pre-spec)
|
||||||
|
Purpose: define how PBS will expose heap usage after the RC/HIP era
|
||||||
|
|
||||||
|
## 1. Context
|
||||||
|
|
||||||
|
Legacy PBS experiments used explicit RC/HIP syntax (`alloc`, `borrow`, `mutate`, `peek`, `take`, `weak`).
|
||||||
|
Current runtime authority is GC-based with deterministic safepoints.
|
||||||
|
|
||||||
|
We need a clear PBS heap story that:
|
||||||
|
|
||||||
|
- stays compatible with closed VM/runtime authority,
|
||||||
|
- remains simple for beginners,
|
||||||
|
- gives advanced developers explicit performance control,
|
||||||
|
- keeps frame-time behavior predictable.
|
||||||
|
|
||||||
|
## 2. Decisions to Produce
|
||||||
|
|
||||||
|
This agenda must end with decisions for:
|
||||||
|
|
||||||
|
1. Heap surface in core language (what is in/out of core syntax).
|
||||||
|
2. Heap control surface in stdlib/tooling (what is explicit but optional).
|
||||||
|
3. Cost visibility contract (what diagnostics/profiling must report).
|
||||||
|
4. Migration policy from legacy RC/HIP concepts.
|
||||||
|
|
||||||
|
## 3. Core Questions
|
||||||
|
|
||||||
|
### Q1. Baseline model
|
||||||
|
|
||||||
|
- Is GC always the default execution model for PBS core? (expected: yes)
|
||||||
|
- Are there any mandatory explicit lifetime constructs in core syntax? (expected: no)
|
||||||
|
|
||||||
|
### Q2. Language vs library boundary
|
||||||
|
|
||||||
|
- Should explicit memory workflows live in syntax or only in stdlib APIs?
|
||||||
|
- Which old RC/HIP concepts become API patterns instead of keywords?
|
||||||
|
|
||||||
|
### Q3. Reserved keywords strategy
|
||||||
|
|
||||||
|
- Keep `alloc/borrow/mutate/peek/take/weak` reserved only?
|
||||||
|
- Or activate a subset in a future opt-in profile?
|
||||||
|
- What hard criteria must be met before activation?
|
||||||
|
|
||||||
|
### Q4. Determinism and frame budget
|
||||||
|
|
||||||
|
- How do we guarantee predictable frame behavior under GC pressure?
|
||||||
|
- What static/dynamic tooling must warn on hot-path allocations?
|
||||||
|
|
||||||
|
### Q5. Heap collections and identity semantics
|
||||||
|
|
||||||
|
- What collection semantics are required in v1 stdlib for games?
|
||||||
|
- Which operations must be explicit due to allocation/copy costs?
|
||||||
|
|
||||||
|
### Q6. Host memory boundary
|
||||||
|
|
||||||
|
- How does PBS communicate "VM heap vs host-owned memory" to users?
|
||||||
|
- Which host calls may allocate, and how should that appear in diagnostics?
|
||||||
|
|
||||||
|
### Q7. Advanced performance patterns
|
||||||
|
|
||||||
|
- Should pools/reuse patterns be standardized as library primitives?
|
||||||
|
- If yes, what minimum API contract is required (without changing VM model)?
|
||||||
|
|
||||||
|
### Q8. Error and safety model
|
||||||
|
|
||||||
|
- Which heap-related failures become traps vs status values?
|
||||||
|
- What compile-time checks are mandatory for safer defaults?
|
||||||
|
|
||||||
|
## 4. Proposed Output Documents
|
||||||
|
|
||||||
|
After discussion, produce:
|
||||||
|
|
||||||
|
1. `4. Static Semantics Specification.md` (binding/mutability/type rules impacted by heap model).
|
||||||
|
2. `5. Dynamic Semantics Specification.md` (evaluation and runtime-visible behavior).
|
||||||
|
3. `6. Memory and Lifetime Specification.md` (authoritative PBS heap model).
|
||||||
|
4. `9. Diagnostics Specification.md` (heap/cost diagnostics contract).
|
||||||
|
|
||||||
|
## 5. Non-Goals for This Agenda
|
||||||
|
|
||||||
|
- Defining new VM opcodes.
|
||||||
|
- Reintroducing RC as mandatory runtime strategy.
|
||||||
|
- Designing full stdlib APIs in this discussion pass.
|
||||||
|
|
||||||
|
## 6. Working Assumptions (to validate)
|
||||||
|
|
||||||
|
1. GC remains baseline for PBS core.
|
||||||
|
2. Explicit heap control is opt-in and likely library/tooling-driven.
|
||||||
|
3. Deterministic behavior and frame-sync constraints are non-negotiable.
|
||||||
|
4. Language should expose cost signals without forcing expert-only syntax.
|
||||||
@ -0,0 +1,144 @@
|
|||||||
|
# PBS - Compatibility and Evolution Policy v1 (Draft)
|
||||||
|
|
||||||
|
Status: Draft (Normative policy for language/runtime evolution)
|
||||||
|
Scope: Compatibility contract for PBS features across hardware/runtime updates
|
||||||
|
Language: English
|
||||||
|
|
||||||
|
## 1. Purpose
|
||||||
|
|
||||||
|
This document defines how PBS remains stable while the logical hardware evolves.
|
||||||
|
|
||||||
|
Goals:
|
||||||
|
|
||||||
|
- preserve existing cartridge behavior across updates,
|
||||||
|
- allow additive platform growth without silent regressions,
|
||||||
|
- keep evolution deterministic and verifier-friendly,
|
||||||
|
- define explicit upgrade/rejection rules for toolchains and firmware.
|
||||||
|
|
||||||
|
## 2. Authority and precedence
|
||||||
|
|
||||||
|
Normative precedence order:
|
||||||
|
|
||||||
|
1. Runtime authority (`docs/specs/hardware/topics/chapter-2.md`, `chapter-3.md`, `chapter-9.md`, `chapter-12.md`, `chapter-16.md`)
|
||||||
|
2. Bytecode authority (`docs/specs/bytecode/ISA_CORE.md`)
|
||||||
|
3. `PBS - Language Syntax Specification v0.md`
|
||||||
|
4. `PBS - Game Language Profile v1 (Draft).md`
|
||||||
|
5. `PBS - Game Profile Syntax Specification v1 (Draft).md`
|
||||||
|
6. This document
|
||||||
|
7. Legacy references (`docs/specs/pbs_old/*`)
|
||||||
|
|
||||||
|
If any rule here conflicts with higher authority, this document is invalid for that rule.
|
||||||
|
|
||||||
|
## 3. Core stability model
|
||||||
|
|
||||||
|
### 3.1 Frozen core contract
|
||||||
|
|
||||||
|
The following contracts MUST remain stable once released in a major line:
|
||||||
|
|
||||||
|
- frame synchronization semantics (`FRAME_SYNC` as deterministic safepoint),
|
||||||
|
- trap and verifier invariants,
|
||||||
|
- stack/call/return discipline for valid bytecode,
|
||||||
|
- deterministic scheduling and host-call contract rules.
|
||||||
|
|
||||||
|
Behavioral changes to frozen core contracts require a new major line.
|
||||||
|
|
||||||
|
### 3.2 Additive extension rule
|
||||||
|
|
||||||
|
New features SHOULD be additive by default.
|
||||||
|
Existing valid programs MUST keep their previous behavior unless they explicitly target a newer incompatible major.
|
||||||
|
|
||||||
|
## 4. Primitive and host API versioning
|
||||||
|
|
||||||
|
### 4.1 Canonical identity
|
||||||
|
|
||||||
|
Host-call primitives MUST be versioned by canonical identity:
|
||||||
|
|
||||||
|
`(module, name, version)`
|
||||||
|
|
||||||
|
An incompatible change MUST create a new `version`.
|
||||||
|
The old version MUST remain resolvable during its supported compatibility window.
|
||||||
|
|
||||||
|
### 4.2 No semantic retcon
|
||||||
|
|
||||||
|
Implementations MUST NOT silently change semantics of an existing canonical identity.
|
||||||
|
If semantics must change incompatibly, publish a new identity version and deprecate the old one by policy.
|
||||||
|
|
||||||
|
## 5. Cartridge target contract
|
||||||
|
|
||||||
|
Each cartridge/app manifest MUST declare, at minimum:
|
||||||
|
|
||||||
|
- target VM/runtime major (or compatible range),
|
||||||
|
- language profile and profile version,
|
||||||
|
- required canonical host-call identities and versions,
|
||||||
|
- required capabilities.
|
||||||
|
|
||||||
|
Loader behavior MUST be deterministic:
|
||||||
|
|
||||||
|
- load and run when all requirements resolve,
|
||||||
|
- reject with explicit diagnostic when requirements are missing or incompatible.
|
||||||
|
|
||||||
|
Implicit fallback to a different major/version is forbidden.
|
||||||
|
|
||||||
|
## 6. Evolution policy (major/minor)
|
||||||
|
|
||||||
|
### 6.1 Minor updates
|
||||||
|
|
||||||
|
Minor updates MUST be backward compatible.
|
||||||
|
Allowed examples:
|
||||||
|
|
||||||
|
- adding new host-call identities,
|
||||||
|
- adding optional metadata/diagnostics,
|
||||||
|
- adding syntax/features gated behind explicit profile selection.
|
||||||
|
|
||||||
|
### 6.2 Major updates
|
||||||
|
|
||||||
|
Major updates MAY introduce incompatible changes.
|
||||||
|
When this happens, maintainers MUST provide:
|
||||||
|
|
||||||
|
- explicit migration notes,
|
||||||
|
- compatibility window policy for prior majors,
|
||||||
|
- deterministic loader diagnostics for unsupported targets.
|
||||||
|
|
||||||
|
## 7. Compatibility layer policy
|
||||||
|
|
||||||
|
Runtime/firmware SHOULD provide compatibility shims for older identity versions for a defined window.
|
||||||
|
|
||||||
|
If shims are provided:
|
||||||
|
|
||||||
|
- shim behavior MUST be deterministic,
|
||||||
|
- shim scope and support horizon MUST be documented,
|
||||||
|
- shim removal MUST occur only in a new major line.
|
||||||
|
|
||||||
|
## 8. Toolchain requirements
|
||||||
|
|
||||||
|
Compiler/linker/tooling MUST:
|
||||||
|
|
||||||
|
- resolve host calls by canonical identity and declared version,
|
||||||
|
- fail deterministically on unresolved identities,
|
||||||
|
- emit target/profile metadata in output artifacts,
|
||||||
|
- avoid emitting instructions/features not supported by selected target contracts.
|
||||||
|
|
||||||
|
## 9. Conformance and replay guarantees
|
||||||
|
|
||||||
|
Each release MUST pass compatibility conformance suites that include:
|
||||||
|
|
||||||
|
- bytecode verifier invariants,
|
||||||
|
- host-call resolution checks by version,
|
||||||
|
- deterministic replay checks under fixed input/event traces.
|
||||||
|
|
||||||
|
For supported target contracts, the same cartridge plus the same input/event sequence MUST produce the same observable behavior.
|
||||||
|
|
||||||
|
## 10. Deprecation policy
|
||||||
|
|
||||||
|
Deprecation MUST be explicit and non-breaking during its support window.
|
||||||
|
Required stages:
|
||||||
|
|
||||||
|
1. Mark as deprecated (tooling warning + documentation).
|
||||||
|
2. Maintain compatibility through declared window.
|
||||||
|
3. Remove only in a subsequent major line.
|
||||||
|
|
||||||
|
## 11. Non-goals
|
||||||
|
|
||||||
|
- Defining subsystem-specific syscall tables.
|
||||||
|
- Defining game-stdlib API surfaces.
|
||||||
|
- Replacing runtime authority with PBS-layer policy.
|
||||||
106
docs/specs/random/pbs/PBS - Game Language Profile v1 (Draft).md
Normal file
106
docs/specs/random/pbs/PBS - Game Language Profile v1 (Draft).md
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
# PBS - Game Language Profile v1 (Draft)
|
||||||
|
|
||||||
|
Status: Draft (Language/Product direction)
|
||||||
|
Scope: PBS game-first language contract for 2D workloads
|
||||||
|
Language: English
|
||||||
|
|
||||||
|
## 1. Purpose
|
||||||
|
|
||||||
|
This document defines the language-level direction for PBS as a game-first scripting language.
|
||||||
|
|
||||||
|
The profile targets:
|
||||||
|
|
||||||
|
- intuitive onboarding for beginners,
|
||||||
|
- predictable frame behavior for real-time 2D games,
|
||||||
|
- explicit performance/cost surfaces for advanced developers,
|
||||||
|
- strict compatibility with a closed VM and its bytecode/runtime authority.
|
||||||
|
|
||||||
|
This document is language-contract oriented. It does not define bytecode encoding details.
|
||||||
|
|
||||||
|
## 2. Authority and compatibility
|
||||||
|
|
||||||
|
Normative precedence order:
|
||||||
|
|
||||||
|
1. Runtime authority (`docs/specs/hardware/topics/chapter-2.md`, `chapter-3.md`, `chapter-9.md`, `chapter-12.md`, `chapter-16.md`)
|
||||||
|
2. Bytecode authority (`docs/specs/bytecode/ISA_CORE.md`)
|
||||||
|
3. `PBS - Language Syntax Specification v0.md`
|
||||||
|
4. This document (Game Profile direction and requirements)
|
||||||
|
5. Legacy references (`docs/specs/pbs_old/*`)
|
||||||
|
|
||||||
|
If any rule here conflicts with runtime or bytecode authority, this document is invalid for that rule.
|
||||||
|
|
||||||
|
## 3. Design constraints
|
||||||
|
|
||||||
|
- The VM is a closed execution target.
|
||||||
|
- Language features must lower to supported VM/bytecode behavior.
|
||||||
|
- Determinism and frame synchronization are non-negotiable.
|
||||||
|
- GC is the baseline memory strategy.
|
||||||
|
|
||||||
|
## 4. Ten normative rules
|
||||||
|
|
||||||
|
### Rule 1 - Frame-first semantics
|
||||||
|
|
||||||
|
PBS game-facing language features MUST preserve deterministic frame execution.
|
||||||
|
Language constructs MUST NOT imply hidden asynchronous callbacks or preemptive execution.
|
||||||
|
|
||||||
|
### Rule 2 - Closed-VM compatibility
|
||||||
|
|
||||||
|
PBS MUST only define features that can be represented by the closed VM contract.
|
||||||
|
Language design MUST NOT require custom allocators, hidden host threads, or runtime behaviors outside VM authority.
|
||||||
|
|
||||||
|
### Rule 3 - GC-first memory model
|
||||||
|
|
||||||
|
PBS MUST treat GC-managed heap semantics as the default and beginner path.
|
||||||
|
Any future lifetime tools (such as pools/arena-like workflows) MUST be additive at API/library level unless runtime authority changes.
|
||||||
|
|
||||||
|
### Rule 4 - Explicit cost surfaces
|
||||||
|
|
||||||
|
PBS SHOULD make high-cost operations visible to users through language diagnostics and tooling contracts.
|
||||||
|
At minimum, allocation pressure, frequent host calls, and hot-loop risk points SHOULD be reportable in deterministic diagnostics.
|
||||||
|
|
||||||
|
### Rule 5 - 2D game-native type surface
|
||||||
|
|
||||||
|
PBS SHOULD provide a first-class game-oriented type surface through core language + standard library alignment.
|
||||||
|
The profile MUST support fluent expression of common 2D tasks (positions, velocities, bounds, colors, sprite/tile identifiers, frame counters).
|
||||||
|
|
||||||
|
### Rule 6 - Service boundary as gameplay architecture
|
||||||
|
|
||||||
|
`service` MUST remain the primary executable boundary for gameplay systems.
|
||||||
|
Language guidance SHOULD promote service-oriented decomposition for input, simulation, rendering orchestration, audio, and UI flows.
|
||||||
|
|
||||||
|
### Rule 7 - Typed host contract boundary
|
||||||
|
|
||||||
|
Host interactions MUST remain typed and explicit at language level.
|
||||||
|
Language constructs for host-facing APIs MUST preserve capability checks and syscall determinism from runtime authority.
|
||||||
|
|
||||||
|
### Rule 8 - Frame-based event and timer model
|
||||||
|
|
||||||
|
Game-facing event/timer language patterns MUST be frame-based and deterministic.
|
||||||
|
Language evolution MUST NOT reintroduce interrupt-like user execution semantics.
|
||||||
|
|
||||||
|
### Rule 9 - Progressive complexity in one language
|
||||||
|
|
||||||
|
PBS MUST support both beginner and advanced developers without forking into separate languages.
|
||||||
|
The beginner path MUST keep defaults simple and safe; advanced control MUST be explicit and opt-in.
|
||||||
|
|
||||||
|
### Rule 10 - Fluency for game loops
|
||||||
|
|
||||||
|
PBS syntax and standard patterns SHOULD optimize for high-frequency game-loop code:
|
||||||
|
|
||||||
|
- concise state updates,
|
||||||
|
- clear system boundaries,
|
||||||
|
- predictable data flow across update/render stages,
|
||||||
|
- minimal boilerplate for frame-driven logic.
|
||||||
|
|
||||||
|
## 5. Non-goals for this draft
|
||||||
|
|
||||||
|
- Defining new bytecode opcodes.
|
||||||
|
- Replacing runtime GC with a new mandatory memory subsystem.
|
||||||
|
- Adding language-level async callbacks or non-deterministic host behavior.
|
||||||
|
|
||||||
|
## 6. Planned follow-up specs
|
||||||
|
|
||||||
|
1. Game Profile syntax additions (if needed), layered on top of v0 Core.
|
||||||
|
2. Game-oriented standard library contract (collections, timers, ECS-adjacent utilities).
|
||||||
|
3. Tooling diagnostics spec for frame-cost visibility.
|
||||||
|
4. Host API declaration surface aligned with capability and syscall metadata.
|
||||||
@ -0,0 +1,186 @@
|
|||||||
|
# PBS - Game Profile Syntax Specification v1 (Draft)
|
||||||
|
|
||||||
|
Status: Draft (Normative for Game Profile parser/lowering work)
|
||||||
|
Scope: Syntax delta over `PBS - Language Syntax Specification v0.md`
|
||||||
|
Language: English
|
||||||
|
|
||||||
|
## 1. Purpose
|
||||||
|
|
||||||
|
This document defines the parser-facing syntax additions for the PBS Game Profile.
|
||||||
|
|
||||||
|
Goals:
|
||||||
|
|
||||||
|
- keep beginner usage fluid for 2D game construction,
|
||||||
|
- preserve deterministic/frame-oriented execution,
|
||||||
|
- remain compatible with closed VM + bytecode/runtime authority,
|
||||||
|
- avoid introducing hidden runtime behavior in language syntax.
|
||||||
|
|
||||||
|
## 2. Authority and precedence
|
||||||
|
|
||||||
|
Normative precedence order:
|
||||||
|
|
||||||
|
1. Runtime authority (`docs/specs/hardware/topics/chapter-2.md`, `chapter-3.md`, `chapter-9.md`, `chapter-12.md`, `chapter-16.md`)
|
||||||
|
2. Bytecode authority (`docs/specs/bytecode/ISA_CORE.md`)
|
||||||
|
3. `PBS - Language Syntax Specification v0.md`
|
||||||
|
4. This document
|
||||||
|
5. Legacy references (`docs/specs/pbs_old/*`)
|
||||||
|
|
||||||
|
If a rule here conflicts with higher authority, the rule is invalid.
|
||||||
|
|
||||||
|
## 3. Profile activation
|
||||||
|
|
||||||
|
Game Profile syntax is enabled by toolchain profile selection (`game` profile).
|
||||||
|
Without this profile, v0 Core syntax rules remain in effect.
|
||||||
|
|
||||||
|
## 4. Lexical delta (keywords)
|
||||||
|
|
||||||
|
### 4.1 Newly active keywords in Game Profile
|
||||||
|
|
||||||
|
- `host`
|
||||||
|
- `while`
|
||||||
|
- `break`
|
||||||
|
- `continue`
|
||||||
|
|
||||||
|
### 4.2 Still reserved in this draft
|
||||||
|
|
||||||
|
- `alloc`, `borrow`, `mutate`, `peek`, `take`, `weak`
|
||||||
|
- `spawn`, `yield`, `sleep`
|
||||||
|
- `handle`
|
||||||
|
|
||||||
|
This draft does not activate heap-specialized syntax or coroutine syntax.
|
||||||
|
|
||||||
|
## 5. Top-level grammar delta
|
||||||
|
|
||||||
|
Game Profile extends top-level declarations with host function declarations.
|
||||||
|
|
||||||
|
```ebnf
|
||||||
|
TopDecl ::= TypeDecl | ServiceDecl | FunctionDecl | HostFnDecl
|
||||||
|
|
||||||
|
HostFnDecl ::= 'host' 'fn' Identifier ParamList ReturnType? ';'
|
||||||
|
```
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `host fn` declares a host-provided call surface only (no body).
|
||||||
|
- Calling `host fn` lowers to syscall-linked call sites.
|
||||||
|
- Host functions are callable entities, never first-class function values.
|
||||||
|
- Service-shaped facades over host functions belong to stdlib design, not to host syntax.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
host fn input_state(): (int, int, int);
|
||||||
|
host fn gfx_present();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. Statement grammar delta
|
||||||
|
|
||||||
|
Game Profile adds imperative loop/control and assignment statements.
|
||||||
|
|
||||||
|
```ebnf
|
||||||
|
Stmt ::= LetStmt
|
||||||
|
| AssignStmt
|
||||||
|
| ReturnStmt
|
||||||
|
| IfStmt
|
||||||
|
| ForStmt
|
||||||
|
| WhileStmt
|
||||||
|
| BreakStmt
|
||||||
|
| ContinueStmt
|
||||||
|
| ExprStmt
|
||||||
|
|
||||||
|
WhileStmt ::= 'while' Expr Block
|
||||||
|
BreakStmt ::= 'break' ';'
|
||||||
|
ContinueStmt ::= 'continue' ';'
|
||||||
|
|
||||||
|
AssignStmt ::= LValue AssignOp Expr ';'
|
||||||
|
AssignOp ::= '=' | '+=' | '-=' | '*=' | '/=' | '%='
|
||||||
|
LValue ::= Identifier LValueSuffix*
|
||||||
|
LValueSuffix ::= '.' Identifier | '[' Expr ']'
|
||||||
|
```
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `break` and `continue` are valid only inside `for`/`while`.
|
||||||
|
- Assignment is a statement, not an expression.
|
||||||
|
- `LValue` cannot contain function calls.
|
||||||
|
- Compound assignments are semantic sugar over read/compute/write.
|
||||||
|
|
||||||
|
## 7. Expression grammar delta
|
||||||
|
|
||||||
|
Game Profile adds postfix member/index access chains for fluent gameplay code.
|
||||||
|
|
||||||
|
```ebnf
|
||||||
|
UnaryExpr ::= ('!' | '-') UnaryExpr | PostfixExpr
|
||||||
|
PostfixExpr ::= PrimaryExpr PostfixSuffix*
|
||||||
|
PostfixSuffix ::= CallSuffix | MemberSuffix | IndexSuffix
|
||||||
|
CallSuffix ::= '(' ArgList? ')'
|
||||||
|
MemberSuffix ::= '.' Identifier
|
||||||
|
IndexSuffix ::= '[' Expr ']'
|
||||||
|
```
|
||||||
|
|
||||||
|
This replaces the v0 Core `CallExpr` chain and enables expressions such as:
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
gfx_present();
|
||||||
|
player.transform.position.x;
|
||||||
|
tiles[i].id;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 8. Determinism and lowering constraints
|
||||||
|
|
||||||
|
Game Profile syntax additions MUST preserve:
|
||||||
|
|
||||||
|
- deterministic control flow,
|
||||||
|
- verifier-friendly stack effects,
|
||||||
|
- explicit host call boundaries.
|
||||||
|
|
||||||
|
Lowering requirements:
|
||||||
|
|
||||||
|
- `host` call sites map to resolved syscall identities.
|
||||||
|
- `while`/`break`/`continue` lower to structured jumps compatible with verifier rules.
|
||||||
|
- Member/index read-write operations must lower to deterministic, type-checked access paths.
|
||||||
|
|
||||||
|
## 9. Diagnostics requirements (parser + early semantic phase)
|
||||||
|
|
||||||
|
Implementations MUST produce deterministic diagnostics for:
|
||||||
|
|
||||||
|
- `break`/`continue` outside loops,
|
||||||
|
- invalid `LValue` targets,
|
||||||
|
- duplicate host signatures in the same scope,
|
||||||
|
- unresolved host declarations at link/resolve stage,
|
||||||
|
- use of still-reserved keywords as active syntax.
|
||||||
|
|
||||||
|
## 10. Minimal canonical examples
|
||||||
|
|
||||||
|
### 10.1 Frame loop style with while
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
host fn gfx_present();
|
||||||
|
|
||||||
|
fn run(): int {
|
||||||
|
let running = true;
|
||||||
|
while running {
|
||||||
|
update_world();
|
||||||
|
render_world();
|
||||||
|
gfx_present();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.2 Assignment and member/index access
|
||||||
|
|
||||||
|
```pbs
|
||||||
|
fn integrate(p: Vec2, v: Vec2): Vec2 {
|
||||||
|
let out = p;
|
||||||
|
out.x += v.x;
|
||||||
|
out.y += v.y;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 11. Non-goals of this syntax draft
|
||||||
|
|
||||||
|
- Defining pool/arena memory syntax.
|
||||||
|
- Enabling `alloc/borrow/mutate` in surface syntax.
|
||||||
|
- Defining coroutine syntax (`spawn/yield/sleep`) before bytecode/runtime profile activation.
|
||||||
@ -19,3 +19,6 @@ When a rule conflicts with runtime or bytecode authority, runtime and bytecode a
|
|||||||
## Files
|
## Files
|
||||||
|
|
||||||
- `PBS - Language Syntax Specification v0.md`: normative syntax and grammar for PBS v0 Core profile, including mandatory `mod.barrel` visibility rules.
|
- `PBS - Language Syntax Specification v0.md`: normative syntax and grammar for PBS v0 Core profile, including mandatory `mod.barrel` visibility rules.
|
||||||
|
- `PBS - Game Language Profile v1 (Draft).md`: game-first language direction for 2D workloads, defining ten normative design rules aligned with the closed VM and GC-first baseline.
|
||||||
|
- `PBS - Game Profile Syntax Specification v1 (Draft).md`: parser/lowering syntax delta for Game Profile over v0 Core (host `fn` declarations, assignment, while/break/continue, member/index postfix access).
|
||||||
|
- `PBS - Compatibility and Evolution Policy v1 (Draft).md`: compatibility contract for PBS across logical hardware updates (frozen core rules, canonical versioning, target manifests, major/minor policy, replay/conformance guarantees).
|
||||||
Loading…
x
Reference in New Issue
Block a user