perf(cli): compile binary output and assembly report once
4 files changed, +21 −7
- cli/driver.ML modified +3 −4
- src/Export.thy modified +1 −1
- src/Frontend.thy modified +11 −0
- tests/cli.py modified +6 −2
cli/driver.ML modified
| @@ -35,13 +35,12 @@ fun run args = | ||
| 35 | 35 | | ["disassemble", file] => output (Span.disassemble (chars (read file))) |
| 36 | 36 | | ["assemble", file, "-o", destination] => |
| 37 | 37 | let |
| 38 | - val input = chars (read file) | |
| 39 | - val (ok, bytes) = Span.binary input | |
| 38 | + val ((ok, bytes), report) = Span.artifact (chars (read file)) | |
| 40 | 39 | in |
| 41 | 40 | if ok then |
| 42 | 41 | (write destination (text bytes); |
| 43 | - output (Span.process [chars "assemble"] input)) | |
| 44 | - else output (false, bytes) | |
| 42 | + output (true, report)) | |
| 43 | + else output (false, report) | |
| 45 | 44 | end |
| 46 | 45 | | ["run", file] => output (Span.process (map chars ["run", "4096"]) (chars (read file))) |
| 47 | 46 | | ["run", file, fuel] => output (Span.process (map chars ["run", fuel]) (chars (read file))) |
src/Export.thy modified
| @@ -6,6 +6,6 @@ definition ascii :: "integer \<Rightarrow> char" where "ascii = char_of" | ||
| 6 | 6 | |
| 7 | 7 | definition ordinal :: "char \<Rightarrow> integer" where "ordinal = of_char" |
| 8 | 8 | |
| 9 | -export_code process binary disassemble ascii ordinal in SML module_name Span file_prefix span | |
| 9 | +export_code process binary artifact disassemble ascii ordinal in SML module_name Span file_prefix span | |
| 10 | 10 | |
| 11 | 11 | end |
src/Frontend.thy modified
| @@ -237,4 +237,15 @@ definition process :: "string list \<Rightarrow> string \<Rightarrow> bool \<tim | ||
| 237 | 237 | case checked p of Error e \<Rightarrow> (False, (if args = [''trace''] then trace p else []) @ e @ newline) |
| 238 | 238 | | Ok bs \<Rightarrow> inspect args p bs)" |
| 239 | 239 | |
| 240 | +definition artifact :: "string \<Rightarrow> (bool \<times> string) \<times> string" where | |
| 241 | + "artifact s = (case source s of Error e \<Rightarrow> ((False, e @ newline), e @ newline) | |
| 242 | + | Ok p \<Rightarrow> case checked p of Error e \<Rightarrow> ((False, e @ newline), e @ newline) | |
| 243 | + | Ok bs \<Rightarrow> ((True, map char_of_nat bs), summary p bs @ hex bs @ newline))" | |
| 244 | + | |
| 245 | +theorem artifact_binary: "fst (artifact s) = binary s" | |
| 246 | + by (auto simp: artifact_def binary_def compile_def split: result.splits) | |
| 247 | + | |
| 248 | +theorem artifact_report: "(fst (fst (artifact s)), snd (artifact s)) = process [''assemble''] s" | |
| 249 | + by (auto simp: artifact_def process_def inspect_def Let_def split: result.splits) | |
| 250 | + | |
| 240 | 251 | end |
tests/cli.py modified
| @@ -148,7 +148,8 @@ def main(): | ||
| 148 | 148 | expected = rows[pc][0] if pc < length else len(out.read_bytes()) |
| 149 | 149 | report = cli("run", "-", "256", text=text) |
| 150 | 150 | check(f"pc={expected} acc={acc}\n" in report, f"execution mismatch in case {case}") |
| 151 | - cli("assemble", "examples/countdown.span", "-o", out) | |
| 151 | + report = cli("assemble", "examples/countdown.span", "-o", out) | |
| 152 | + check(report == cli("assemble", "examples/countdown.span"), "binary report changed") | |
| 152 | 153 | check(out.read_bytes() == bytes([1, 1, 1, 2, 17, 130, 16, 123, 3]), "binary output") |
| 153 | 154 | check("jmp.8 -5" in cli("disassemble", out), "binary disassembly") |
| 154 | 155 | out.write_bytes(bytes([18, 0])) |
| @@ -156,8 +157,11 @@ def main(): | ||
| 156 | 157 | out.write_bytes(bytes([255])) |
| 157 | 158 | check("invalid encoding" in cli("disassemble", out, ok=False), "unknown opcode accepted") |
| 158 | 159 | out.write_bytes(b"preserve") |
| 159 | - cli("assemble", "-", "-o", out, text="jmp missing", ok=False) | |
| 160 | + error = cli("assemble", "-", "-o", out, text="jmp missing", ok=False) | |
| 161 | + check(error == cli("assemble", "-", text="jmp missing", ok=False), "binary error changed") | |
| 160 | 162 | check(out.read_bytes() == b"preserve", "failed assembly clobbered output") |
| 163 | + cli("assemble", "-", "-o", out, text="") | |
| 164 | + check(out.read_bytes() == b"", "empty binary output") | |
| 161 | 165 | print(f"{CHECKS} checks passed, including 36 exhaustive layout comparisons") |
| 162 | 166 | |
| 163 | 167 | |