diff --git a/src/interpreter.mjs b/src/interpreter.mjs index fb5bcdd..2d1a651 100644 --- a/src/interpreter.mjs +++ b/src/interpreter.mjs @@ -12,7 +12,7 @@ // flag is truthy, bounded by ctx.maxIterations. Commands run top-to-bottom. export function tokenize(src) { - const re = /("(?:[^"\\]|\\.)*")|(\/\/[^\n]*)|(\d+(?:\.\d+)?)|([A-Za-z_]\w*)|([(){};,])|(\s+)/g; + const re = /("(?:[^"\\]|\\.)*")|(\/\/[^\n]*)|(-?\d+(?:\.\d+)?)|([A-Za-z_]\w*)|([(){};,])|(\s+)/g; const tokens = []; let m; let lastIndex = 0; diff --git a/test/interpreter.test.mjs b/test/interpreter.test.mjs index 41f71d0..a1322d7 100644 --- a/test/interpreter.test.mjs +++ b/test/interpreter.test.mjs @@ -1,6 +1,7 @@ import assert from "node:assert/strict"; import test from "node:test"; -import { compile, tokenize } from "../src/interpreter.mjs"; +import { defaultCommands } from "../src/commands.mjs"; +import { compile, run, tokenize } from "../src/interpreter.mjs"; test("tokenize rejects unexpected characters between valid tokens", () => { assert.throws(() => tokenize("say(@);"), /unexpected character/); @@ -15,6 +16,18 @@ test("compile preserves valid moshscript behavior", () => { }); }); +test("negative numeric arguments reach command validation", async () => { + const ast = compile("sleep(-1);"); + const ctx = { + vars: { alive: true }, + iter: 0, + maxIterations: 1, + commands: defaultCommands(), + }; + + await assert.rejects(() => run(ast, ctx), /finite non-negative number/); +}); + test("compile requires commas between call arguments", () => { assert.throws(() => compile("say(\"one\" \"two\");"), /expected comma/); assert.throws(() => compile("say(\"one\",);"), /expected argument after comma/);