add intrinsics PRs

This commit is contained in:
bQUARKz 2026-03-02 19:40:35 +00:00
parent 39d1214f03
commit f126a64099
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
4 changed files with 695 additions and 0 deletions

View File

@ -0,0 +1,236 @@
# PR-001 Runtime Builtin Registry and Intrinsic Metadata
## Goal
Introduce the runtime-owned metadata layer required for VM-owned builtin types
and intrinsic operations without touching the host syscall path.
This PR creates the semantic foundation that the frontend can target later.
## Why
Today the host-backed path already exists conceptually:
- canonical host identity,
- PBX `SYSC`,
- `HOSTCALL`,
- loader resolution,
- final `SYSCALL`.
Builtin semantics need a different ownership path:
- runtime-owned builtin type metadata,
- runtime-owned intrinsic metadata,
- flattened slot layouts,
- and VM execution that never crosses the host boundary.
Without this layer, the runtime will be forced to encode builtin behavior as
ad hoc helpers or as pseudo-syscalls, both of which conflict with the PBS model.
## Scope
Add runtime data structures and lookup APIs for:
- builtin type identity,
- builtin field layout,
- builtin constant identity,
- intrinsic identity,
- intrinsic stack layouts,
- and intrinsic implementation registration.
Do not add bytecode execution changes in this PR.
Do not add loader-side host changes in this PR.
## Required Runtime Concepts
### 1. Builtin type identity
Canonical builtin identity must be:
```text
(name, version)
```
Examples:
- `("color", 1)`
- `("vec2", 1)`
- `("pixel", 1)`
This is distinct from source-visible PBS names such as `Color` or `Vec2`.
### 2. Builtin layout descriptor
Introduce a runtime descriptor roughly shaped like:
```text
BuiltinTypeMeta {
id: u32
name: string
version: u16
fields: [BuiltinFieldMeta]
flat_slot_layout: [AbiType]
flat_slot_width: u16
}
```
with:
```text
BuiltinFieldMeta {
name: string
start_slot: u16
field_type: BuiltinLayoutType
flat_slot_width: u16
}
```
`BuiltinLayoutType` should support:
- fixed-width scalar runtime types,
- builtin nominal type references,
- and recursively flattenable aggregate builtin layouts.
### 3. Builtin constant descriptor
Introduce a constant registry keyed by:
```text
(target, name, version)
```
Examples:
- `("vec2", "zero", 1)`
This registry must return either:
- direct materialization metadata,
- or a runtime-owned constant implementation hook.
### 4. Intrinsic descriptor
Introduce an intrinsic registry keyed by:
```text
(owner, name, version)
```
Examples:
- `("vec2", "dot", 1)`
- `("vec2", "length", 1)`
Descriptor shape should include at minimum:
```text
IntrinsicMeta {
id: u32
owner: string
name: string
version: u16
arg_layout: [AbiType]
ret_layout: [AbiType]
deterministic: bool
may_allocate: bool
}
```
## Design Rules
1. This registry is runtime-owned, not host-owned.
2. It must not reuse `SYSC`.
3. It must not depend on capability grants.
4. It must not resolve through the host syscall registry.
5. It must preserve flattened slot width for verifier and executor use.
6. It must preserve nominal builtin identity even when two builtins share the same width.
## Representation Guidance
### Scalars
Support at least:
- `int`
- `float`
- `bool`
- builtin nominal scalars such as `color`
For nominal scalars like `color`, allow either:
- a dedicated runtime value variant,
- or a 1-slot carrier with explicit builtin type tagging in metadata.
The important requirement is that `color` remain semantically distinct from a
plain `int` even if it shares width.
### Aggregates
Builtin aggregates such as `vec2` and `pixel` should remain stack-shaped.
The registry must treat them as:
- fixed-width,
- finite,
- flattenable,
- and non-heap in this phase.
No heap object model is required.
## Suggested API Surface
Introduce runtime APIs along these lines:
- `lookup_builtin_type(name, version) -> BuiltinTypeMeta`
- `lookup_builtin_constant(target, name, version) -> BuiltinConstMeta`
- `lookup_intrinsic(owner, name, version) -> IntrinsicMeta`
- `lookup_intrinsic_by_id(id) -> IntrinsicMeta`
Avoid exposing host-like resolution APIs for this subsystem.
## Out of Scope
- `INTRINSIC` opcode execution
- `INTRCALL` preload resolution
- loader patching
- frontend lowering
- host integration
- HAL color adaptation
## Acceptance Criteria
1. Runtime contains a distinct builtin/intrinsic registry subsystem.
2. Registry keys use canonical builtin and intrinsic identities, not source aliases.
3. Builtin layouts support recursive flattening and expose total flat slot width.
4. Builtin constants have a dedicated registry keyed separately from intrinsics.
5. No part of the implementation routes through host syscall metadata.
6. Unit tests cover lookup and flattening for `color`, `vec2`, and `pixel`.
## Test Cases
### Builtin layout flattening
- `color` flattens to width `1`
- `vec2` flattens to width `2`
- `pixel(x: int, y: int, color: color)` flattens to width `3`
### Nested field offsets
- `vec2.x` starts at slot `0`
- `vec2.y` starts at slot `1`
- `pixel.color` starts at slot `2`
### Intrinsic metadata
- `vec2.dot` has arg width `4` and ret width `1`
- `vec2.length` has arg width `2` and ret width `1`
## Notes for Follow-up PRs
This PR should intentionally stop short of execution.
The next PR should consume these descriptors in:
- bytecode decoding,
- verifier stack-effect calculation,
- and runtime dispatch for `INTRINSIC <id>`.

View File

@ -0,0 +1,168 @@
# PR-002 Runtime INTRINSIC Opcode, Verification, and Dispatch
## Goal
Add a dedicated runtime execution path for VM-owned intrinsics using the
metadata introduced in PR-001.
This PR should establish that intrinsic execution is a first-class VM path,
separate from host-backed syscall execution.
## Why
The runtime currently has a conceptual host-backed path centered on `SYSCALL`.
Builtin semantics cannot be layered cleanly on top of that path because:
- intrinsic ownership is VM-owned, not host-owned,
- intrinsic execution must not require host resolution,
- intrinsic execution must not depend on capabilities,
- and verifier stack effects must come from builtin layout metadata.
The runtime therefore needs its own instruction and dispatch path.
## MVP Decision
This PR should implement direct final-form execution:
```text
INTRINSIC <id>
```
Do not implement `INTRCALL` in this PR unless the runtime already has a clear
preload declaration mechanism that can be reused without coupling to `SYSC`.
The intent is:
- keep the runtime simple,
- let the frontend eventually emit final intrinsic ids for a selected VM line,
- and avoid pulling loader complexity into the first implementation.
## Scope
Add:
- runtime opcode support for `INTRINSIC <id>`,
- verifier support for intrinsic stack effects,
- execution dispatch by intrinsic id,
- trap behavior for unknown intrinsic ids,
- and tests proving separation from the syscall pipeline.
Do not add host loader changes in this PR.
## Required Changes
### 1. Bytecode/ISA support
Introduce a dedicated intrinsic opcode in the runtime bytecode interpreter.
Normative behavior:
- decode `INTRINSIC <id>`,
- lookup intrinsic metadata by numeric id,
- verify or assume verifier-proven stack shape,
- execute runtime-owned implementation,
- push results back according to intrinsic return layout.
### 2. Verifier support
The verifier must derive intrinsic stack effects from runtime intrinsic metadata.
Required behavior:
- lookup intrinsic meta by id,
- compute argument slot width from flattened `arg_layout`,
- compute result slot width from flattened `ret_layout`,
- reject underflow,
- reject invalid slot shape,
- and preserve existing verifier guarantees for control flow.
Examples:
- `vec2.dot(vec2, vec2) -> float` becomes `pop 4, push 1`
- `vec2.length(vec2) -> float` becomes `pop 2, push 1`
### 3. Trap behavior
Add deterministic failure for:
- unknown intrinsic id,
- malformed intrinsic metadata,
- verifier/runtime disagreement on intrinsic width,
- and execution-time misuse that escapes verifier guarantees.
If trap enums exist, add a runtime-specific invalid intrinsic trap rather than
reusing invalid syscall traps.
### 4. Dispatch separation
Ensure the interpreter or executor has two clearly distinct paths:
- `SYSCALL <id>` for host-backed services
- `INTRINSIC <id>` for VM-owned semantics
These paths must not share registry lookup semantics.
## Suggested Runtime Shape
Use a structure roughly like:
```text
execute_intrinsic(id, stack, runtime_ctx) -> Result<(), Trap>
```
where:
- `stack` is mutated using metadata-defined widths,
- `runtime_ctx` is VM-internal context only,
- and no host syscall registry access occurs.
If an execution table already exists for opcodes, add intrinsic dispatch as a
parallel branch rather than as a host-call subtype.
## Acceptance Criteria
1. Runtime recognizes and executes `INTRINSIC <id>`.
2. Verifier derives stack effects from intrinsic metadata rather than hardcoded arity alone.
3. Unknown intrinsic ids fail deterministically.
4. `INTRINSIC` does not route through host binding, loader syscall resolution, or capability checks.
5. `SYSCALL` behavior remains unchanged.
6. Tests demonstrate that intrinsic execution and syscall execution are distinct runtime paths.
## Test Cases
### Positive
- execute `vec2.dot` over two canonical `vec2` values and obtain one float result
- execute `vec2.length` over one canonical `vec2` value and obtain one float result
### Verification
- verifier accepts a correct stack program using `INTRINSIC <vec2.dot>`
- verifier rejects a program with insufficient stack width for `INTRINSIC <vec2.dot>`
### Separation
- `SYSCALL` still resolves and executes host-backed operations as before
- invalid intrinsic id produces intrinsic-specific failure, not syscall failure
## Out of Scope
- frontend parser/lowering changes
- preload `INTRCALL` resolution
- builtin constant source lowering
- new host bindings
## Notes for Follow-up PRs
The next PR should populate the registry and executor with the first builtin
set:
- `color`
- `vec2`
- `pixel`
and with first intrinsic implementations:
- `vec2.dot`
- `vec2.length`
- optionally `vec2.distance`

View File

@ -0,0 +1,273 @@
# PR-003 Runtime First Builtins: Color, Vec2, Pixel
## Goal
Implement the first concrete builtin types, constants, and intrinsic behaviors
so the frontend can target a stable MVP builtin line.
This PR should be the first runtime feature slice that a PBS frontend can map
to directly.
## Why
After PR-001 and PR-002, the runtime has the machinery but not the domain set.
This PR makes the model real by installing the first builtin registry entries
and execution implementations.
The initial scope should match the current agenda and spec direction:
- scalar builtin `color`
- aggregate builtin `vec2`
- aggregate builtin `pixel`
- intrinsic methods for `vec2`
- builtin constant for `vec2.zero`
## Scope
Add runtime registry entries and implementations for:
- builtin type `color`
- builtin type `vec2`
- builtin type `pixel`
- builtin constant `("vec2", "zero", 1)`
- intrinsic `("vec2", "dot", 1)`
- intrinsic `("vec2", "length", 1)`
`("vec2", "distance", 1)` may be included if the numeric contract is already
clear enough for portable behavior.
If not, leave it for a follow-up PR.
## Builtin Type Contracts
### 1. `color`
Canonical identity:
```text
("color", 1)
```
Expected properties:
- scalar builtin
- flat slot width `1`
- runtime semantic distinctness from plain `int`
Suggested field model:
- `raw` carrier field if the runtime benefits from explicit internal naming
### 2. `vec2`
Canonical identity:
```text
("vec2", 1)
```
Expected properties:
- aggregate builtin
- flattened layout `[float, float]`
- field `x` at slot `0`
- field `y` at slot `1`
- flat slot width `2`
### 3. `pixel`
Canonical identity:
```text
("pixel", 1)
```
Expected properties:
- aggregate builtin
- semantic layout `[int, int, color]`
- flattened width `3`
- field `x` at slot `0`
- field `y` at slot `1`
- field `color` at slot `2`
## Builtin Constant Contract
### `vec2.zero`
Canonical identity:
```text
("vec2", "zero", 1)
```
Expected materialized value:
```text
[0.0, 0.0]
```
This constant must be runtime-owned and materialized without touching the host.
## Intrinsic Contracts
### 1. `vec2.dot`
Canonical identity:
```text
("vec2", "dot", 1)
```
Stack contract:
```text
args: [float, float, float, float]
ret: [float]
```
Semantic behavior:
```text
(x1 * x2) + (y1 * y2)
```
### 2. `vec2.length`
Canonical identity:
```text
("vec2", "length", 1)
```
Stack contract:
```text
args: [float, float]
ret: [float]
```
Semantic behavior:
```text
sqrt((x * x) + (y * y))
```
### 3. Optional: `vec2.distance`
Canonical identity:
```text
("vec2", "distance", 1)
```
Stack contract:
```text
args: [float, float, float, float]
ret: [float]
```
Semantic behavior:
```text
sqrt(((x1 - x2)^2) + ((y1 - y2)^2))
```
Only include this if the runtime already has a clear portable numeric contract
for `sqrt`.
## Representation Guidance
### `color`
Choose one of:
1. dedicated scalar runtime variant with builtin nominal tag
2. 1-slot scalar carrier plus explicit builtin registry identity
The critical rule is:
- `color` must remain semantically a builtin color type,
- even if its carrier width matches `int`.
### `vec2` and `pixel`
Do not allocate heap objects for these in the MVP.
Represent them as:
- canonical stack-shaped flattened values,
- with runtime metadata describing field offsets and nominal builtin identity.
## Numeric Contract Note
`vec2.dot` is straightforward and should land in this PR.
`vec2.length` and `vec2.distance` depend on the runtime's floating-point
portability story. If that story is not already stable, implement:
1. `vec2.dot`
2. `vec2.zero`
3. builtin type descriptors for `color`, `vec2`, `pixel`
and either:
- gate `length`/`distance` behind the current platform float rules,
- or defer them into a follow-up PR.
## Acceptance Criteria
1. Runtime registry contains builtin entries for `color`, `vec2`, and `pixel`.
2. Runtime registry contains builtin constant entry for `("vec2", "zero", 1)`.
3. Runtime registry contains intrinsic entries for at least `vec2.dot` and `vec2.length`.
4. `vec2` layout is width `2` and `pixel` layout is width `3`.
5. `pixel` composes `color` through builtin layout metadata rather than by special-case host code.
6. Executing `vec2.dot` and `vec2.length` through `INTRINSIC <id>` produces correct runtime results.
7. No part of the implementation routes through `SYSC`, `HOSTCALL`, or `SYSCALL`.
## Test Cases
### Builtin metadata
- `color` width is `1`
- `vec2` width is `2`
- `pixel` width is `3`
### Constant materialization
- materializing `("vec2", "zero", 1)` yields `[0.0, 0.0]`
### Intrinsic execution
- `dot([1, 2], [3, 4]) == 11`
- `length([3, 4]) == 5`
### Composition
- `pixel(x=1, y=2, color=<red>)` uses builtin metadata width `3`
- `pixel.color` points at slot `2`
## Frontend Alignment
This PR should be implemented so the following frontend surfaces map naturally:
```pbs
[BuiltinType(name="vec2", version=1)]
declare builtin type Vec2(
[Slot(0)] pub x: float,
[Slot(1)] pub y: float,
) {
[IntrinsicCall(name="dot")]
fn dot(other: Vec2) -> float;
[IntrinsicCall(name="length")]
fn length() -> float;
}
[BuiltinConst(target="vec2", name="zero", version=1)]
declare const ZERO: Vec2;
```
The runtime should not care whether the source-visible type name is `Vec2`,
`vec2`, or something else.
It should care only about canonical identities and flattened layout.

View File

@ -0,0 +1,18 @@
# Runtime PR Series for VM-owned Builtins and Intrinsics
This directory contains proposed pull requests for implementing VM-owned builtin
types and intrinsic execution in the runtime.
The series is designed so that the frontend model described in:
- [6. VM-owned vs Host-backed](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/pbs/6.%20VM-owned%20vs%20Host-backed.md)
- [6.1. Intrinsics and Builtin Types Specification](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/pbs/6.1.%20Intrinsics%20and%20Builtin%20Types%20Specification.md)
- [PBS Intrinsics and Builtin Types Agenda](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/agendas/PBS%20Intrinsics%20and%20Builtin%20Types%20Agenda.md)
can lower cleanly into the runtime without reusing the host syscall pipeline.
Recommended order:
1. [PR-001 Runtime Builtin Registry and Intrinsic Metadata](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/pull-requests/PR-001-runtime-builtin-registry-and-intrinsic-metadata.md)
2. [PR-002 Runtime INTRINSIC Opcode, Verification, and Dispatch](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/pull-requests/PR-002-runtime-intrinsic-opcode-verification-and-dispatch.md)
3. [PR-003 Runtime First Builtins: Color, Vec2, Pixel](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/pull-requests/PR-003-runtime-first-builtins-color-vec2-pixel.md)