import { CMP } from "@nand2tetris/simulator/languages/cmp.js"; import { display } from "@davidsouther/jiffies/lib/esm/display.js"; import { range } from "@davidsouther/jiffies/lib/esm/range.js"; import { Err, isErr, Ok } from "@davidsouther/jiffies/lib/esm/result.js"; import { ReactElement } from "react"; export const DiffTable = ({ className = "", out, cmp, zeroState, }: { out: string; cmp: string; className?: string; zeroState?: ReactElement; }) => { const output = CMP.parse(out); const compare = CMP.parse(cmp); if (isErr(output)) { return (
Failed to parse output
{display(Err(output))}
{out}
); } if (isErr(compare)) { return (
Failed to parse compare
{display(Err(compare))}
{cmp}
); } const cmpData = Ok(compare); const outData = Ok(output); let failures = 0; const table = range(0, Math.min(cmpData.length, outData.length)).map((i) => { const cmpI = cmpData[i] ?? []; const outI = outData[i] ?? []; return range(0, Math.max(cmpI.length, outI.length)) .map((_, j) => [cmpI[j] ?? "", outI[j] ?? ""]) .map(([cmp, out]) => { const cell = { cmp: cmp ?? '"', out: out ?? '"', pass: cmp?.trim().match(/^\*+$/) !== null || out?.trim() === cmp?.trim(), }; if (!cell.pass) { failures += 1; } return cell; }); }); return (
{failures > 0 && (

{failures} failure{failures === 1 ? "" : "s"}

)} {table.length > 0 ? ( {table.map((row, i) => ( {row.map(({ cmp, out, pass }, i) => ( ))} ))}
) : ( (zeroState ??

Execute test script to compare output.

) )}
); }; const DiffCell = ({ cmp, out, pass, }: { cmp: string; out: string; pass: boolean; }) => { return pass ? ( <> {cmp} ) : ( <> {cmp}
{out} ); };