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
37 changes: 37 additions & 0 deletions .trinity/seals/t27b_T27bTsEmit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"built_by": "t27c-bootstrap@0.5.2+a1b584b29",
"closure": [
{
"spec": "specs/tri/t27b/text_escape.t27",
"spec_hash": "sha256:c88981799b2e3f97cd0815471d288e48550f5a785c504412546ca58c0b19656a"
},
{
"spec": "specs/tri/t27b/ts_plan.t27",
"spec_hash": "sha256:d046e9702ec1a0a9db5b9d8666e0bc8f7f38361f1bc320e5d9420931f7887e46"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:91d80cba62f45cc2dd2e052287b1336b88a00fec91e65f98653f7ae2f90bebc1",
"gen_hash_rust": "sha256:a902659f2f30c887876e487094668138d7fcd90f266c7ca4a56e859cc94bff34",
"gen_hash_verilog": "sha256:204115c5a4cbcac65f725db2cc393b9b909ce9faedf4132ad05feb2f5c0aa736",
"gen_hash_zig": "sha256:1eaa2c4f003d1912304766da67ddd8679b0dbc86edf6101344fbdb4f5dd68971",
"module": "T27bTsEmit",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-17T17:23:04Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:bc52c75db0f5923f9b3bdd4f9373e0d2b45ae62c7119eb135519c25d3d419ecb",
"spec_path": "specs/tri/t27b/ts_emit.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 4,
"total": 4,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d",
"zig": "0.16.0"
}
}
33 changes: 33 additions & 0 deletions .trinity/seals/t27b_T27bTsPlan.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"built_by": "t27c-bootstrap@0.5.2+a1b584b29",
"closure": [
{
"spec": "specs/tri/t27b/verilog_plan.t27",
"spec_hash": "sha256:6178c276f6928f211b1cb65f470a93a5fcfbb11119bad7a26030072d777e8e70"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:c6741e3f49b460e9b22518adc6e429d46d7b4f42db3eef859fd570e191f1326d",
"gen_hash_rust": "sha256:228558265ac328ea4bd7696e216554b2bfd804ad2b363981ce3716d299a0c170",
"gen_hash_verilog": "sha256:dd6906ff28d579f1d59194cc69199f1abf934dea86141846680233d97976ad8d",
"gen_hash_zig": "sha256:d4255ad99d97654379ea3e017fbc087776752b51eadf3ec87b75d087073485c8",
"module": "T27bTsPlan",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-17T17:23:01Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:d046e9702ec1a0a9db5b9d8666e0bc8f7f38361f1bc320e5d9420931f7887e46",
"spec_path": "specs/tri/t27b/ts_plan.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 6,
"total": 6,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d",
"zig": "0.16.0"
}
}
24 changes: 24 additions & 0 deletions cli/t27b/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ t27b test <file.t27> [--overflow trap|wrap] [--time] [--quiet] [--check] [--bl
t27b build <file.t27> -o <out.o> [--elf | --macho] [--overflow trap|wrap] [--time]
t27b asm <file.t27> [--overflow trap|wrap]
t27b verilog <file.t27>
t27b ts <file.t27>
t27b corpus <dir> [--timeout-ms N] [--jobs N] [--overflow trap|wrap] [--list]
[--json <path>] [--runner "<cmd> [args]"]
[--blockers [--reference <t27c> [--reference-cache <file>]
Expand All @@ -332,6 +333,29 @@ refused by name, exit 2. Every decision is in `specs/tri/t27b/verilog_plan.t27`:
The writer is `specs/tri/t27b/verilog_emit.t27`. The fixtures are
`specs/tri/t27b/conformance/verilog_*.t27` (#8796).

`t27b ts` writes the spec's consts, its pure fns over `u8`..`u32`, `i8`..`i32`
and `bool`, and its tests as one TypeScript module to stdout (#9994). Each
`test` is an exported self-check that returns how many asserts it ran, and
`t27_report()` prints the assert table of `t27c test-report`, line for line.
Each `invariant` is an exported self-check too. `t27_failures()` names each
check that throws. The integers keep Zig's meaning: `+ - *` throw on overflow,
`+% -% *%` wrap, and a narrowing cast truncates. An assert whose operands are
all compile-time constants is checked but not counted, the same as
test-report. Anything outside that subset is refused, exit 2, with
``t27b: ts: unsupported construct <what> `<name>` at line <n>``.

The decisions are in `specs/tri/t27b/ts_plan.t27`: the types, the operator
forms, folding, reserved names, and the prelude and coda. The writer is
`specs/tri/t27b/ts_emit.t27`. Node 24 runs the output as `.mts`:

```
t27b ts specs/queen/key_failover.t27 > /tmp/kf.mts
node -e 'import("/tmp/kf.mts").then(m => console.log(m.t27_report()))'
```

A top-level declaration that is refused reports `at line 0`, because the t27c
parser records no line for it.

Options:

* `--time`: prints per-phase milliseconds to stderr: read, parse, typecheck,
Expand Down
13 changes: 6 additions & 7 deletions cli/t27b/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7393,12 +7393,11 @@ fn flat<'n>(ns: impl IntoIterator<Item = &'n Node>) -> (Vec<u8>, Vec<u8>) {
(a, t)
}
const _: () = assert!(NodeKind::StmtExpr as u8 == aw::K_STMT_EXPR && NodeKind::ExprRange as u8 == aw::K_EXPR_RANGE);
#[path = "../../../gen/rust/tri/t27b/verilog_emit.rs"] #[allow(dead_code, unused_parens, unused_variables, while_true)]
mod ve; // t27c gen-rust of specs/tri/t27b/verilog_emit.t27: `t27b verilog` (#8796)
#[path = "../../../gen/rust/tri/t27b/verilog_plan.rs"] #[allow(dead_code, unused_parens, unused_variables, while_true)]
mod vp; // t27c gen-rust of specs/tri/t27b/verilog_plan.t27: hw_consts, the consts only the hardware reads
/// `t27b verilog`: `flat`'s bytes and per node four u32 (flags 1 var, 2 pub; line; its params' span in `p`).
pub fn verilog(ast: &Node) -> Result<String, String> {
#[path = "../../../gen/rust/tri/t27b/verilog_emit.rs"] #[allow(dead_code, unused_parens, unused_variables, while_true)] mod ve; // t27c gen-rust of specs/tri/t27b/verilog_emit.t27: `t27b verilog` (#8796)
#[path = "../../../gen/rust/tri/t27b/verilog_plan.rs"] #[allow(dead_code, unused_parens, unused_variables, while_true)] mod vp; // t27c gen-rust of specs/tri/t27b/verilog_plan.t27: hw_consts, the consts only the hardware reads
#[path = "../../../gen/rust/tri/t27b/ts_emit.rs"] #[allow(dead_code, unused_parens, unused_variables, while_true)] mod tse; // specs/tri/t27b/ts_emit.t27: `t27b ts` (#9994)
/// `t27b verilog` (`t27b ts` when `ts`): `flat`'s bytes and per node four u32 (flags 1 var, 2 pub; line; its params' span in `p`).
pub fn verilog(ast: &Node, ts: bool) -> Result<String, String> {
fn meta(n: &Node, m: &mut Vec<u8>, p: &mut Vec<u8>) {
let lo = p.len() as u32; n.params.iter().for_each(|(a, b)| p.extend(format!("{a}:{b}\n").bytes()));
for v in [n.extra_mutable as u32 | (n.extra_pub as u32) << 1, n.line, lo, p.len() as u32] { m.extend(v.to_le_bytes()) }
Expand All @@ -7407,7 +7406,7 @@ pub fn verilog(ast: &Node) -> Result<String, String> {
let ((a, t), mut m, mut p) = (flat([ast]), Vec::new(), Vec::new());
meta(ast, &mut m, &mut p);
let (mut w, mut out) = (vec![0u8; a.len() / aw::REC * 2 + 70], vec![0u8; 4 * (a.len() + t.len()) + (1 << 20)]);
let n = ve::emit(&a, &t, &m, &p, &mut w, &mut out);
let n = (if ts { tse::emit } else { ve::emit })(&a, &t, &m, &p, &mut w, &mut out);
let s = String::from_utf8_lossy(&out[..n.unsigned_abs() as usize]).into_owned();
(n >= 0).then(|| s.clone()).ok_or(s)
}
Expand Down
7 changes: 4 additions & 3 deletions cli/t27b/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const USAGE: &str = "usage:
t27b build <file.t27> -o <out.o> [--elf | --macho] [--overflow trap|wrap] [--time]
t27b asm <file.t27> [--overflow trap|wrap]
t27b verilog <file.t27> (the module, and its test bench under `ifdef T27B_TESTBENCH)
t27b ts <file.t27> (consts, scalar fns and tests as TypeScript; specs/tri/t27b/ts_emit.t27)
t27b corpus <dir> [--timeout-ms N] [--jobs N] [--overflow trap|wrap] [--list]
[--json <path>] [--runner \"<cmd> [args]\"]
[--blockers [--reference <t27c> [--reference-cache <file>]
Expand Down Expand Up @@ -212,7 +213,7 @@ fn main() -> ExitCode {
Err(e) => return usage(&e),
};
match o.cmd.as_str() {
"test" | "build" | "asm" | "verilog" => {
"test" | "build" | "asm" | "verilog" | "ts" => {
let Some(input) = o.input.clone() else {
return usage("missing input file");
};
Expand Down Expand Up @@ -267,8 +268,8 @@ fn compile_front(input: &str, o: &Opts) -> Result<(Program, Phases), u8> {
}
return Err(EXIT_FRONTEND);
}
if o.cmd == "verilog" {
return Err(lower::verilog(&parsed.ast).map_or_else(|e| { errln!("{}", e); EXIT_UNSUPPORTED }, |v| { out(&v); 0 }));
if o.cmd == "verilog" || o.cmd == "ts" {
return Err(lower::verilog(&parsed.ast, o.cmd == "ts").map_or_else(|e| { errln!("{}", e); EXIT_UNSUPPORTED }, |v| { out(&v); 0 }));
}
if o.blockers {
// Every unsupported construct, not just the first; a file with none
Expand Down
2 changes: 2 additions & 0 deletions docs/reports/t27b_expectations.json
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,8 @@
{"path": "specs/tri/t27b/stdmem_plan.t27", "t27b": "pass"},
{"path": "specs/tri/t27b/steward.t27", "t27b": "pass"},
{"path": "specs/tri/t27b/text_escape.t27", "t27b": "pass"},
{"path": "specs/tri/t27b/ts_emit.t27", "t27b": "pass"},
{"path": "specs/tri/t27b/ts_plan.t27", "t27b": "pass"},
{"path": "specs/tri/t27b/tuple_local_plan.t27", "t27b": "pass"},
{"path": "specs/tri/t27b/type_text.t27", "t27b": "pass"},
{"path": "specs/tri/t27b/undefined_arg_plan.t27", "t27b": "pass"},
Expand Down
Loading
Loading