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
8 changes: 4 additions & 4 deletions .trinity/seals/TernaryGates.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"gen_hash_c": "sha256:608e9f52b077faf20ba1e274f02a386bb48f27767c878ec5683567bd5b6a755d",
"gen_hash_c": "sha256:87ac584ac4d46a1011b6ebcdc8bda48bd7b578e7f34a6f8df1942c0b12a5a247",
"gen_hash_rust": "sha256:d50d3454f51312df8ae97f8885d1ef89eccf26835aab641ec4a7d131a94556a4",
"gen_hash_verilog": "sha256:a0ecc024bbf108bf40c663321efaadc401dc9e22f8d45323eae4913dc08738bc",
"gen_hash_zig": "sha256:50a48d04ba20fe714abc08eeeba6821801b1db40bce026966670030291dc4819",
"gen_hash_zig": "sha256:d9602a0e9c3228201cb27c2a83f47a149871059fbfb3c7fa1b73ec47eda8cbcf",
"module": "TernaryGates",
"ring": 12,
"sealed_at": "2026-10-10T12:32:59Z",
"spec_hash": "sha256:48513ed8f9c995547a1b374a3c09c7ac428c9a11b40834a78e75028b956903ca",
"sealed_at": "2026-10-10T13:36:51Z",
"spec_hash": "sha256:94fc7637fe4d830a624d700ad231075159fdaed1a79b0d605a5bdacb38083b0c",
"spec_path": "specs/isa/ternary_gates.t27",
"tests": {
"failed": 0,
Expand Down
10 changes: 5 additions & 5 deletions .trinity/seals/isa_TernaryGates.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
{
"built_by": "t27c-bootstrap@0.5.2+c494cc5",
"built_by": "t27c-bootstrap@0.5.2+3c0ae4d49",
"closure": [
{
"spec": "specs/base/types.t27",
"spec_hash": "sha256:9d02d8b1016993658e1e9748e4bc13bc4f3732535c16e3484abdaeeafcf608bc"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:608e9f52b077faf20ba1e274f02a386bb48f27767c878ec5683567bd5b6a755d",
"gen_hash_c": "sha256:87ac584ac4d46a1011b6ebcdc8bda48bd7b578e7f34a6f8df1942c0b12a5a247",
"gen_hash_rust": "sha256:d50d3454f51312df8ae97f8885d1ef89eccf26835aab641ec4a7d131a94556a4",
"gen_hash_verilog": "sha256:a0ecc024bbf108bf40c663321efaadc401dc9e22f8d45323eae4913dc08738bc",
"gen_hash_zig": "sha256:50a48d04ba20fe714abc08eeeba6821801b1db40bce026966670030291dc4819",
"gen_hash_zig": "sha256:d9602a0e9c3228201cb27c2a83f47a149871059fbfb3c7fa1b73ec47eda8cbcf",
"module": "TernaryGates",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-10T12:32:59Z",
"sealed_at": "2026-10-10T13:36:51Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:48513ed8f9c995547a1b374a3c09c7ac428c9a11b40834a78e75028b956903ca",
"spec_hash": "sha256:94fc7637fe4d830a624d700ad231075159fdaed1a79b0d605a5bdacb38083b0c",
"spec_path": "specs/isa/ternary_gates.t27",
"tests": {
"failed": 0,
Expand Down
18 changes: 9 additions & 9 deletions .trinity/seals/t27b_T27bDiscardPlan.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
{
"built_by": "t27c-bootstrap@0.5.2+5d5d2cdef",
"built_by": "t27c-bootstrap@0.5.2+3c0ae4d49",
"closure": [],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:95bdef51d7d83ec98fd1df0adbb7dd26ba707b33e2bc13dcadbd7c75857ed19f",
"gen_hash_rust": "sha256:1a068c18c77ef1bb3a34f116501b6c794ded4b50086c1d867f1c0e7f72ebf869",
"gen_hash_verilog": "sha256:48ffbb7235fbdb556a2d06f9f9d920c88daa31b1087c956a4d933eeecbc7df97",
"gen_hash_zig": "sha256:59c5b80da21ff3c327b46ee14bce77bb445604eae90e2362695b8058dc001a6a",
"gen_hash_c": "sha256:c9fdbc89627e959585ccc9a35b15953f241aabe076af0bfe307b3c5e3d87bc43",
"gen_hash_rust": "sha256:4651655a9576deecffd83b5cbb135703587e3d711d707a24a99ea79b51a5dc52",
"gen_hash_verilog": "sha256:c9fc6a3d44087796ad3f96e53227faf9755babf5a3cb8dce76fc688ba8944140",
"gen_hash_zig": "sha256:e984cd161839534c3a1fe6159e0d6b298b89a4d151f1134e523daae68c3f8e2a",
"module": "T27bDiscardPlan",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-09T14:58:35Z",
"sealed_at": "2026-10-10T13:36:52Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:f255459b0b4e1feb33373c09a9e1fb1c7368796cc261177db4dc6613b5c3881d",
"spec_hash": "sha256:f136521731ed02abfe8e7d04578f3407479efcca16e3054998728880d3778491",
"spec_path": "specs/tri/t27b/discard_plan.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 4,
"total": 4
"passed": 6,
"total": 6
},
"toolchain": {
"test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d",
Expand Down
2 changes: 1 addition & 1 deletion cli/t27b/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2523,7 +2523,7 @@ impl<'a> Lower<'a> {
if name == "_" && (op.is_empty() || op == "=") {
let (mut calls, top) = (Vec::new(), self.scopes.len() == 1);
calls_in(std::slice::from_ref(rhs), &mut calls);
match dp::plan(rhs.kind == NodeKind::ExprIdentifier, self.in_test && top, !self.in_test && top, !calls.is_empty()) {
match dp::plan(rhs.kind == NodeKind::ExprIdentifier, self.in_test && top, self.in_bench, !self.in_test && top, !calls.is_empty()) {
dp::DELETED => return Ok(()),
dp::EVALUATE => return self.discard_value(rhs, out),
_ => {}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# NOW -- t27b: a bench's `_ = e;` is a discard; ternary_gates' benches type-check once referenced (2026-10-10)

## t27b blocker after c7570433e (Closes #8546; see #8195)

- arty_a7_integration.t27: its bench discards a u32, a u32, then a bool at the top level. t27b's test-binding path bound `_` as a u32 variable and refused the bool (`type mismatch`). t27c prints each one as Zig's `_ = e;`. specs/tri/t27b/discard_plan.t27 now evaluates and drops every `_ = e;` at the top of a bench. The glue changes one line.
- ternary_gates.t27: t27b was right. Once a test calls the benches, zig 0.16 refuses them three ways: signed `%`, an i32 into a u32, and a run-time index into a tuple. The spec now uses a `[3]i32` array and `@intCast(result + 1)`. With a test that calls all four benches, the reference passes 13/13.
- t27b `test --check` passes both specs: 12/12 with 122 asserts and 6/6 with 13. Both ledger rows are back to pass, and max_not_pass goes from 27 to 25.
6 changes: 3 additions & 3 deletions docs/reports/t27b_expectations.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"reference-bug": "the reference passes it for the wrong reason; t27b is right not to",
"n/a": "outside what t27b is for (say why in the PR that sets it)"
},
"max_not_pass": 27,
"max_not_pass": 25,
"entries": [
{"path": "specs/a/b_c.t27", "t27b": "pass"},
{"path": "specs/a_b/c.t27", "t27b": "pass"},
Expand Down Expand Up @@ -263,7 +263,7 @@
{"path": "specs/docs/system.t27", "t27b": "pass"},
{"path": "specs/fpga/adapter.t27", "t27b": "pass"},
{"path": "specs/fpga/assembler.t27", "t27b": "pass"},
{"path": "specs/fpga/boards/arty_a7_integration.t27", "t27b": "blocked", "blocker": "type mismatch", "reason": "unimplemented"},
{"path": "specs/fpga/boards/arty_a7_integration.t27", "t27b": "pass"},
{"path": "specs/fpga/boards/qmtech_a100t_integration.t27", "t27b": "pass"},
{"path": "specs/fpga/bootrom.t27", "t27b": "pass"},
{"path": "specs/fpga/bpsk.t27", "t27b": "pass"},
Expand Down Expand Up @@ -355,7 +355,7 @@
{"path": "specs/isa/t27a.t27", "t27b": "pass"},
{"path": "specs/isa/t27a_mnemonics.t27", "t27b": "pass"},
{"path": "specs/isa/ternary_encoding.t27", "t27b": "pass"},
{"path": "specs/isa/ternary_gates.t27", "t27b": "blocked", "blocker": "type mismatch", "reason": "unimplemented"},
{"path": "specs/isa/ternary_gates.t27", "t27b": "pass"},
{"path": "specs/isa/ternary_graph.t27", "t27b": "pass"},
{"path": "specs/isa/tri27_bytecode.t27", "t27b": "pass"},
{"path": "specs/isa/tri27_machine.t27", "t27b": "pass"},
Expand Down
6 changes: 3 additions & 3 deletions gen/rust/tri/t27b/discard_plan.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Generated from .t27 spec
// DO NOT EDIT — generated by t27c
// NOT LOWERED BY THIS BACKEND: 4 test(s), 0 invariant(s), 0 function(s) with no body.
// NOT LOWERED BY THIS BACKEND: 6 test(s), 0 invariant(s), 0 function(s) with no body.
// This backend emits declarations only. The spec's checks live in
// the Zig and Verilog outputs; do not read this file as verified.

Expand All @@ -10,11 +10,11 @@ pub const DELETED: u8 = 1;

pub const EVALUATE: u8 = 2;

pub fn plan(name: bool, test_top: bool, fn_top: bool, call: bool) -> u8 {
pub fn plan(name: bool, test_top: bool, in_bench: bool, fn_top: bool, call: bool) -> u8 {
if name {
return NOT_MINE;
}
if test_top {
if (test_top && !(in_bench)) {
return NOT_MINE;
}
if (fn_top && !(call)) {
Expand Down
14 changes: 7 additions & 7 deletions specs/isa/ternary_gates.t27
Original file line number Diff line number Diff line change
Expand Up @@ -372,33 +372,33 @@ module TernaryGates {
bench ternary_min_performance
// Measure: cycles to compute 1000 MIN operations
// Target: < 1000 cycles
const vals = [_]i32{TRIT_NEG, TRIT_ZERO, TRIT_POS};
const vals : [3]i32 = [_]i32{TRIT_NEG, TRIT_ZERO, TRIT_POS};
var result : i32 = 0;
var i : u32 = 0;
while i < 1000 {
var idx : u32 = (result + 1) % 3;
result = ternary_min(result, vals[idx]);
const idx : u32 = @intCast(result + 1);
result = ternary_min(result, vals[idx % 3]);
i = i + 1;
}
_ = result;

bench ternary_max_performance
// Measure: cycles to compute 1000 MAX operations
// Target: < 1000 cycles
const vals = [_]i32{TRIT_NEG, TRIT_ZERO, TRIT_POS};
const vals : [3]i32 = [_]i32{TRIT_NEG, TRIT_ZERO, TRIT_POS};
var result : i32 = 0;
var i : u32 = 0;
while i < 1000 {
var idx : u32 = (result + 1) % 3;
result = ternary_max(result, vals[idx]);
const idx : u32 = @intCast(result + 1);
result = ternary_max(result, vals[idx % 3]);
i = i + 1;
}
_ = result;

bench ternary_consensus_performance
// Measure: cycles to compute 1000 CONSENSUS operations
// Target: < 2000 cycles
const vals = [_]i32{TRIT_NEG, TRIT_ZERO, TRIT_POS};
const vals : [3]i32 = [_]i32{TRIT_NEG, TRIT_ZERO, TRIT_POS};
var result : i32 = 0;
var idx : u32 = 0;
var i : u32 = 0;
Expand Down
50 changes: 35 additions & 15 deletions specs/tri/t27b/discard_plan.t27
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,19 @@
; `if` traps), and drops the value, void or not.
; - At the top level of a test, t27c's test-binding form prints `const _ = e;`, and Zig refuses it ("'_' used
; as an identifier without @"_" syntax").
; - At the top level of a bench, t27c's gen_bench_block prints every `_ = e;` as written: the first through
; its W608 discard spelling, each later one through gen_stmt. Each is Zig's discard, whatever e's type, in
; an uncalled `fn bench_<name>() void` Zig never analyzes. specs/fpga/boards/arty_a7_integration.t27
; discards a u32, a u32, then a bool there (see #8195, #8546).
; - specs/port/bootstrap/src/compiler/collect_type_decls.t27 writes `_ = process(node);` (a void fn) at the top
; of a body, `_ = "literal";` in the arms of an `if`, and a trailing `_ = "literal";` that is deleted.
; --
; What t27b does. DELETED: at the top level of a fn body, an e with no call is not lowered at all, as the
; reference deletes it. EVALUATE: anywhere else, e is lowered and evaluated for its effects and its traps, and
; its value is dropped. NOT_MINE: a bare name (`_ = p;`, t27b's parameter-discard path, which models Zig's
; pointless-discard rule), and any `_ = e;` at the top level of a test, invariant or bench (t27b's test-binding
; path, left as it was).
; pointless-discard rule), and any `_ = e;` at the top level of a test or invariant (t27b's test-binding path,
; left as it was). At the top level of a bench that path bound `_` as a variable of the first e's type and
; refused a later e of another type (`type mismatch`); there a discard is EVALUATE too, compiled, never run.
; ASCII only (L3)
; phi^2 + 1/phi^2 = 3 | TRINITY

Expand All @@ -35,11 +40,11 @@ pub const DELETED : u8 = 1;
pub const EVALUATE : u8 = 2;

/// The decision for one `_ = e;`. name: e is a bare name. test_top: the statement is at the top level of a test,
/// invariant or bench. fn_top: it is at the top level of a fn body, where the reference's dead-store pass runs.
/// call: e holds a call anywhere in it.
pub fn plan(name: bool, test_top: bool, fn_top: bool, call: bool) -> u8 {
/// invariant or bench. in_bench: it is in a bench body. fn_top: it is at the top level of a fn body, where the
/// reference's dead-store pass runs. call: e holds a call anywhere in it.
pub fn plan(name: bool, test_top: bool, in_bench: bool, fn_top: bool, call: bool) -> u8 {
if (name) { return NOT_MINE; }
if (test_top) { return NOT_MINE; }
if (test_top and !in_bench) { return NOT_MINE; }
if (fn_top and !call) { return DELETED; }
return EVALUATE;
}
Expand All @@ -55,28 +60,43 @@ pub fn runs(act: u8) -> bool {

test a_call_discarded_at_the_top_of_a_fn_runs {
// collect_type_decls.t27's `_ = process_node_for_types(node);`: kept by keep_call_discards.
assert(plan(false, false, true, true) == EVALUATE);
assert(plan(false, false, false, true, true) == EVALUATE);
assert(runs(EVALUATE));
}

test a_discard_with_no_call_at_the_top_of_a_fn_is_deleted {
// collect_type_decls.t27's trailing `_ = "children_processed";`, and `_ = a + b;`, which then cannot trap.
assert(plan(false, false, true, false) == DELETED);
assert(plan(false, false, false, true, false) == DELETED);
assert(!runs(DELETED));
}

test a_nested_discard_runs_with_or_without_a_call {
// collect_type_decls.t27's `_ = "struct_fields_collected";` in an arm of an `if`; a nested
// `_ = a + b;` traps on overflow, as the reference's does.
assert(plan(false, false, false, false) == EVALUATE);
assert(plan(false, false, false, true) == EVALUATE);
assert(plan(false, false, false, false, false) == EVALUATE);
assert(plan(false, false, false, false, true) == EVALUATE);
}

test a_bare_name_and_a_test_binding_are_left_alone {
assert(plan(true, false, true, false) == NOT_MINE);
assert(plan(true, false, false, true) == NOT_MINE);
assert(plan(true, true, false, true) == NOT_MINE);
assert(plan(false, true, false, true) == NOT_MINE);
assert(plan(false, true, false, false) == NOT_MINE);
assert(plan(true, false, false, true, false) == NOT_MINE);
assert(plan(true, false, false, false, true) == NOT_MINE);
assert(plan(true, true, false, false, true) == NOT_MINE);
assert(plan(false, true, false, false, true) == NOT_MINE);
assert(plan(false, true, false, false, false) == NOT_MINE);
assert(!runs(NOT_MINE));
}

test every_discard_at_the_top_of_a_bench_runs {
// arty_a7_integration.t27's bench_integration_config: `_ = calc_baud_divisor(..);` (a u32), then
// `_ = verify_pin_config(..);` (a bool), each its own discard.
assert(plan(false, true, true, false, true) == EVALUATE);
assert(plan(false, true, true, false, false) == EVALUATE);
assert(runs(plan(false, true, true, false, true)));
}

test a_nested_discard_in_a_bench_runs_and_a_bare_name_there_is_left_alone {
assert(plan(false, false, true, false, true) == EVALUATE);
assert(plan(false, false, true, false, false) == EVALUATE);
// ternary_gates.t27's `_ = result;` closing each bench.
assert(plan(true, true, true, false, false) == NOT_MINE);
}
Loading