Repository navigation
t27 cannot express the I/O of thin glue: file read and hash, process run, file write #8298
Description
Parent: #5980. Motivating case: #8295 and PR #8296, where t27c silicon reuses a cached bitstream.
Since the 2026-10-09 rule, hand-written code may not grow. Every new piece of glue therefore has to be paid for by porting the same number of lines elsewhere. #8296 paid with math_compare.rs's Pell code. That works once, but not as the normal way to add I/O.
What the bitstream cache needed, all of it plain I/O that t27 cannot write today:
- read a file's bytes and hash them (sha256);
- run a command and read its stdout (
yosys -V,git rev-parse HEAD); - create a directory, write a file, read a small text file;
- read an environment variable (
HOME,T27_SILICON_REBUILD).
The decisions already live in t27: bitstream_reuse.t27 decides REUSE, MISSING, INCOMPLETE, CORRUPT or FORCED. Only the plumbing is Rust.
Proposal: a small host-I/O surface that t27 can call and t27c lowers per backend (std::fs and std::process in gen-rust, std.fs in gen-zig). Glue like #8296's could then be generated, and the no-growth rule would bind without a porting tax.
Acceptance criteria
- a .t27 function can read a file, hash it, run a command and write a file, and
t27c gen-rustoutput compiles - the bitstream-cache glue of t27c silicon reuses its bitstream; a ported script pays for the glue (Closes #8295) #8296 is regenerated from .t27, and the hand-written lines it added are removed
Boundary
bootstrap/src/compiler.rs
User Scenarios
- Given a .t27 spec that declares a function to read a file, compute its SHA-256 hash, and return the digest, when
t27c gen-rustcompiles that spec, then the generated Rust code callsstd::fs::readand a SHA-256 implementation and the crate builds withcargo build --releaseexit 0. - Given a .t27 spec that declares a function to run
yosys -Vand capture its stdout, whent27c gen-rustcompiles that spec, then the generated Rust code usesstd::process::Commandto execute the command and returns the output string, and the crate builds withcargo build --releaseexit 0. - Given a .t27 spec that declares a function to create a directory, write a file, read a small text file, and read an environment variable (
HOMEorT27_SILICON_REBUILD), whent27c gen-rustcompiles that spec, then the generated Rust code usesstd::fs::create_dir_all,std::fs::write,std::fs::read_to_string, andstd::env::var, and the crate builds withcargo build --releaseexit 0.
Requirements
- FR-001: The t27 language MUST provide a host-I/O surface with operations for file read, file write, directory creation, file hash (SHA-256), process execution with stdout capture, and environment variable read.
- FR-002: The compiler
t27cMUST lower each host-I/O operation to the target backend's standard library (std::fs, std::process, std::env for gen-rust; std.fs, std.process for gen-zig). - FR-003: The bitstream-cache glue logic from PR t27c silicon reuses its bitstream; a ported script pays for the glue (Closes #8295) #8296 MUST be expressible entirely in .t27 using the new host-I/O surface, and
t27c gen-rustoutput MUST compile without hand-written Rust I/O code. - FR-004: The existing decision logic in
bitstream_reuse.t27(REUSE, MISSING, INCOMPLETE, CORRUPT, FORCED) MUST remain unchanged; only the I/O plumbing is replaced by generated code.
Activity