Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions .github/workflows/gate-zero.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Gate 0
name: Native gates

on:
pull_request:
Expand All @@ -11,7 +11,7 @@ permissions:

jobs:
verify:
runs-on: ubuntu-latest
runs-on: macos-14
steps:
- name: Check out TypeRB Native
uses: actions/checkout@v5
Expand All @@ -20,7 +20,7 @@ jobs:
uses: actions/checkout@v5
with:
repository: type-rb/type-rb
ref: 30b5f5206680a39a02966d1579f76de55760a349
ref: fc4c511a4ebed28cc83fbca56af0d31fb481010c
path: .type-rb

- name: Set up Go for the bootstrap compiler
Expand All @@ -32,13 +32,33 @@ jobs:
- name: Verify the compiler revision pin
run: test "$(cat TYPE_RB_REVISION)" = "$(git -C .type-rb rev-parse HEAD)"

- name: Build the pinned TypeRB compiler
working-directory: .type-rb
run: go build -o "$RUNNER_TEMP/trb" ./cmd/trb

- name: Build pinned QBE 1.3
run: |
curl -L https://c9x.me/compile/release/qbe-1.3.tar.xz -o "$RUNNER_TEMP/qbe-1.3.tar.xz"
echo "d587905d620dc5e1d2bfa7c2cc642b9b837aa89a3188c6e37b53d756cf66e320 $RUNNER_TEMP/qbe-1.3.tar.xz" | shasum -a 256 -c -
tar -C "$RUNNER_TEMP" -xf "$RUNNER_TEMP/qbe-1.3.tar.xz"
make -C "$RUNNER_TEMP/qbe-1.3"

- name: Verify formatting
run: .type-rb/trb fmt --check .
run: |
"$RUNNER_TEMP/trb" fmt --check .

- name: Check TypeRB sources
run: .type-rb/trb check
run: |
"$RUNNER_TEMP/trb" check
"$RUNNER_TEMP/trb" check --config tools/gate1-benchmark/trbconfig.jsonc
for config in corpus/gate1/*/trbconfig.jsonc; do
"$RUNNER_TEMP/trb" check --config "$config"
done

- name: Run Gate 0 tests and fixtures
- name: Run gate tests, fixtures, and source differential corpus
env:
TYPE_RB_NATIVE_ROOT: ${{ github.workspace }}
run: .type-rb/trb test
TYPE_RB_NATIVE_REFERENCE_TRB: ${{ runner.temp }}/trb
TYPE_RB_NATIVE_QBE: ${{ runner.temp }}/qbe-1.3/qbe
run: |
"$RUNNER_TEMP/trb" test
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,21 @@ Gate 0 implements the experimental boundary in TypeRB: strict decoding of
versioned, data-only bootstrap snapshots, lowering to Native MIR, MIR
verification, deterministic diagnostics, and source-origin preservation.

Gate 1 is active. Its first vertical slice decodes snapshot v2, verifies a
heap-free scalar MIR, emits QBE IL from TypeRB code, and builds a working
`darwin/arm64` executable with pinned QBE 1.3 and the system linker. The current
subset includes functions, direct calls, block parameters, branches, loops,
Boolean, portable Integer, binary64 Float, static UTF-8 output, and deterministic
arithmetic failure. It provides no production runtime, stable ABI, stable
artifact format, or compatibility guarantee. Records and tagged values are
deferred to Gate 2.
Gate 1 is complete at its experimental checkpoint. A pinned, process-based
reference producer now connects real TypeRB source to snapshot v2, verified
heap-free scalar MIR, TypeRB-authored QBE emission, and working `darwin/arm64`
executables. The differential corpus covers functions, direct calls, block
parameters, branches, loops, Boolean, portable Integer including checked power,
binary64 Float, static UTF-8 output, and deterministic arithmetic failure.

On the recorded Apple M2 Pro run, native warm build time improved by 30.5% to
36.3%, stripped executable size improved by 96.85%, and the worst runtime result
was a 16.0% regression, within the pre-registered 25% bound. See the
[Gate 1 result](results/2026-08-28-gate1-qbe-darwin-arm64/README.md). Development
stops before Gate 2 for maintainer review. The result does not select QBE for
production or measure the final self-hosted compiler. The current path provides
no production runtime, stable ABI, stable artifact format, or compatibility
guarantee. Records and tagged values remain deferred to Gate 2.

## Intended boundary

Expand Down Expand Up @@ -137,6 +144,7 @@ repository.
- [Architecture](docs/architecture.md)
- [Experiment plan](docs/experiment-plan.md)
- [Gate 1 QBE vertical slice](docs/gate-1-qbe.md)
- [Gate 1 QBE Darwin arm64 result](results/2026-08-28-gate1-qbe-darwin-arm64/README.md)
- [Decision 0001: Experimental native toolchain boundary](docs/decisions/0001-experimental-native-toolchain.md)
- [Decision 0002: TypeRB-owned self-hosting](docs/decisions/0002-typerb-owned-self-hosting.md)
- [Decision 0003: Gate 1 QBE and Darwin arm64 profile](docs/decisions/0003-gate-1-qbe-target.md)
Expand Down
2 changes: 1 addition & 1 deletion TYPE_RB_REVISION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
30b5f5206680a39a02966d1579f76de55760a349
fc4c511a4ebed28cc83fbca56af0d31fb481010c
4 changes: 4 additions & 0 deletions corpus/gate1/division-by-zero/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Generated from trbconfig.jsonc by trb.
module github.com/type-rb/type-rb-native/corpus/gate1/division-by-zero

go 1.27
7 changes: 7 additions & 0 deletions corpus/gate1/division-by-zero/src/main.trb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
def main()
zero := 0
if 1 / zero == 0
return
end
return
end
8 changes: 8 additions & 0 deletions corpus/gate1/division-by-zero/trbconfig.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "gate1-division-by-zero",
"mode": "go",
"sourceDir": "src",
"go": {
"module": "github.com/type-rb/type-rb-native/corpus/gate1/division-by-zero"
}
}
4 changes: 4 additions & 0 deletions corpus/gate1/integer-kernel/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Generated from trbconfig.jsonc by trb.
module github.com/type-rb/type-rb-native/corpus/gate1/integer-kernel

go 1.27
22 changes: 22 additions & 0 deletions corpus/gate1/integer-kernel/src/main.trb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
def kernel(iterations: Integer): Integer
mut index := 0
mut total := 0
while index < iterations
total += (index % 97) * 3
total -= index % 31
if total > 1000000
total /= 2
end
index += 1
end
return total
end

def main()
if kernel(5000000) > 0
puts("gate1-integer-kernel")
return
end
puts("gate1-integer-kernel-failed")
return
end
8 changes: 8 additions & 0 deletions corpus/gate1/integer-kernel/trbconfig.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "gate1-integer-kernel",
"mode": "go",
"sourceDir": "src",
"go": {
"module": "github.com/type-rb/type-rb-native/corpus/gate1/integer-kernel"
}
}
4 changes: 4 additions & 0 deletions corpus/gate1/integer-overflow/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Generated from trbconfig.jsonc by trb.
module github.com/type-rb/type-rb-native/corpus/gate1/integer-overflow

go 1.27
8 changes: 8 additions & 0 deletions corpus/gate1/integer-overflow/src/main.trb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
def main()
mut value := 9007199254740991
value += 1
if value == 0
return
end
return
end
8 changes: 8 additions & 0 deletions corpus/gate1/integer-overflow/trbconfig.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "gate1-integer-overflow",
"mode": "go",
"sourceDir": "src",
"go": {
"module": "github.com/type-rb/type-rb-native/corpus/gate1/integer-overflow"
}
}
4 changes: 4 additions & 0 deletions corpus/gate1/integer-power-overflow/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Generated from trbconfig.jsonc by trb.
module github.com/type-rb/type-rb-native/corpus/gate1/integer-power-overflow

go 1.27
6 changes: 6 additions & 0 deletions corpus/gate1/integer-power-overflow/src/main.trb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
def main()
if 2 ** 53 == 0
return
end
return
end
8 changes: 8 additions & 0 deletions corpus/gate1/integer-power-overflow/trbconfig.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "gate1-integer-power-overflow",
"mode": "go",
"sourceDir": "src",
"go": {
"module": "github.com/type-rb/type-rb-native/corpus/gate1/integer-power-overflow"
}
}
4 changes: 4 additions & 0 deletions corpus/gate1/negative-integer-exponent/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Generated from trbconfig.jsonc by trb.
module github.com/type-rb/type-rb-native/corpus/gate1/negative-integer-exponent

go 1.27
7 changes: 7 additions & 0 deletions corpus/gate1/negative-integer-exponent/src/main.trb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
def main()
exponent :=- 1
if 2 ** exponent == 0
return
end
return
end
8 changes: 8 additions & 0 deletions corpus/gate1/negative-integer-exponent/trbconfig.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "gate1-negative-integer-exponent",
"mode": "go",
"sourceDir": "src",
"go": {
"module": "github.com/type-rb/type-rb-native/corpus/gate1/negative-integer-exponent"
}
}
4 changes: 4 additions & 0 deletions corpus/gate1/scalar-control-flow/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Generated from trbconfig.jsonc by trb.
module github.com/type-rb/type-rb-native/corpus/gate1/scalar-control-flow

go 1.27
46 changes: 46 additions & 0 deletions corpus/gate1/scalar-control-flow/src/main.trb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
def sum_to(limit: Integer): Integer
mut index := 0
mut total := 0
while index < limit
index += 1
total += index
end
return total
end

def reduce(mut value: Integer): Integer
while value > 3
if value % 2 == 0
value /= 2
else
value -= 1
end
end
return value
end

def scale(value: Float): Float
return value * 1.5
end

def main()
total := sum_to(100)
if total == 5050
if reduce(42) == 2
if - 7 / 3 == - 2
if - 7 % 3 == - 1
if !false
if scale(2.0) == 3.0
if 3 ** 4 == 81
puts("gate1-scalar-control-flow")
return
end
end
end
end
end
end
end
puts("gate1-scalar-control-flow-failed")
return
end
8 changes: 8 additions & 0 deletions corpus/gate1/scalar-control-flow/trbconfig.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "gate1-scalar-control-flow",
"mode": "go",
"sourceDir": "src",
"go": {
"module": "github.com/type-rb/type-rb-native/corpus/gate1/scalar-control-flow"
}
}
4 changes: 4 additions & 0 deletions corpus/gate1/static-output/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Generated from trbconfig.jsonc by trb.
module github.com/type-rb/type-rb-native/corpus/gate1/static-output

go 1.27
4 changes: 4 additions & 0 deletions corpus/gate1/static-output/src/main.trb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def main()
puts("gate1-static-output")
return
end
8 changes: 8 additions & 0 deletions corpus/gate1/static-output/trbconfig.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "gate1-static-output",
"mode": "go",
"sourceDir": "src",
"go": {
"module": "github.com/type-rb/type-rb-native/corpus/gate1/static-output"
}
}
4 changes: 4 additions & 0 deletions corpus/gate1/unsupported-dynamic-output/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Generated from trbconfig.jsonc by trb.
module github.com/type-rb/type-rb-native/corpus/gate1/unsupported-dynamic-output

go 1.27
4 changes: 4 additions & 0 deletions corpus/gate1/unsupported-dynamic-output/src/main.trb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def main()
puts(42)
return
end
8 changes: 8 additions & 0 deletions corpus/gate1/unsupported-dynamic-output/trbconfig.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "gate1-unsupported-dynamic-output",
"mode": "go",
"sourceDir": "src",
"go": {
"module": "github.com/type-rb/type-rb-native/corpus/gate1/unsupported-dynamic-output"
}
}
14 changes: 9 additions & 5 deletions docs/gate-1-qbe.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ correct native executable cheaply enough to justify connecting it to the
reference frontend. It is an experimental checkpoint, not a supported TypeRB
target or a measurement of the final self-hosted compiler.

The source-connected differential corpus and provisional measurements are
complete. Gate 1 passes; see the
[recorded result](../results/2026-08-28-gate1-qbe-darwin-arm64/README.md).

## Current pipeline

```text
Expand Down Expand Up @@ -48,7 +52,7 @@ contract.
Supported instructions are:

- `boolean_literal`, `integer_literal`, and `float_literal`;
- `integer_binary` with `add`, `subtract`, `multiply`, `divide`, or `remainder`;
- `integer_binary` with `add`, `subtract`, `multiply`, `divide`, `remainder`, or `power`;
- `float_binary` with `add`, `subtract`, `multiply`, or `divide`;
- `integer_compare` and `float_compare` with the six ordered comparison names;
- `boolean_not`;
Expand All @@ -63,10 +67,10 @@ and the decoder applies resource limits before code generation.

Portable Integer values remain within `-9007199254740991` through
`9007199254740991`. Arithmetic is checked before an out-of-range result can be
observed. Divide-by-zero, remainder-by-zero, and range failures write a fixed
diagnostic to standard error and exit with status 70 in this temporary runtime.
The exact failure text remains experimental until the source-connected
differential corpus establishes the reference behavior.
observed. The source-connected differential corpus runs the optimized Go
baseline with `GOTRACEBACK=none`; range and division-by-zero failures then
match its exact standard error and status 2. This process envelope remains an
internal Gate 1 convention rather than a promoted language guarantee.

Boolean values use QBE words, Integer values use QBE longs, and Float values
use QBE doubles. Non-entry block parameters are lowered through typed stack
Expand Down
Loading