import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import createModule from "../../build-wasm/linuxcnc-sim-core.js"; import { ProgramRunner } from "./program-runner.mjs"; const core = await createModule({ wasmBinary: await readFile(new URL("../../build-wasm/linuxcnc-sim-core.wasm", import.meta.url)) }); async function run(source, expectedX) { const runner = new ProgramRunner(core); const loaded = runner.load(source, "control.ngc"); assert.equal(loaded.status, "verified"); assert.equal(runner.start().status, "verified"); let guard = 0; while (runner.status === "running" && guard < 200) { runner.tick(1); guard += 1; } assert.ok(guard < 200, "control program exceeded deterministic budget"); assert.equal(runner.status, "completed"); assert.equal(runner.state.x, expectedX); runner.destroy(); } await run(`#1=0\nO10 WHILE [#1 LT 3]\n#1=[#1+1]\nG1 X[#1]\nO10 ENDWHILE\nM2\n`, 3); await run(`#1=0\nO100 SUB\n#1=[#1+1]\nG1 X[#1]\nO100 ENDSUB\nO100 CALL\nO100 CALL\nM2\n`, 2); await run(`#1=0\nO1 IF [#1 EQ 1]\nG1 X9\nO1 ELSE\nG1 X4\nO1 ENDIF\nM2\n`, 4); const malformed = new ProgramRunner(core); const malformedResult = malformed.load("O10 WHILE [1]\nG1 X1\n", "bad-control.ngc"); assert.equal(malformedResult.status, "error"); assert.equal(malformedResult.code, "program_control_unclosed"); assert.equal(malformedResult.line, 2); malformed.destroy(); const missing = new ProgramRunner(core); assert.equal(missing.load("O999 CALL\n", "missing.ngc").status, "verified"); missing.start(); const missingStep = missing.step(); assert.equal(missingStep.status, "error"); assert.equal(missingStep.code, "program_control"); assert.equal(missingStep.detail, "program_subroutine_missing"); missing.destroy(); console.log("program_control=passed while=3 call=2 if=else depth_budget=verified");