silverbullet/common/space_lua/eval.test.ts

189 lines
4.7 KiB
TypeScript
Raw Normal View History

2024-09-12 23:01:54 +08:00
import { assertEquals } from "@std/assert/equals";
2024-09-24 16:15:22 +08:00
import { LuaEnv, LuaNativeJSFunction, singleResult } from "./runtime.ts";
import { parse } from "./parse.ts";
2024-09-27 15:11:03 +08:00
import type { LuaBlock, LuaFunctionCallStatement } from "./ast.ts";
import { evalExpression, evalStatement } from "./eval.ts";
2024-09-12 23:01:54 +08:00
function evalExpr(s: string, e = new LuaEnv()): any {
return evalExpression(
(parse(`e(${s})`).statements[0] as LuaFunctionCallStatement).call
.args[0],
e,
);
}
2024-09-27 15:11:03 +08:00
function evalBlock(s: string, e = new LuaEnv()): Promise<void> {
return evalStatement(parse(s) as LuaBlock, e);
}
2024-09-12 23:01:54 +08:00
Deno.test("Evaluator test", async () => {
const env = new LuaEnv();
2024-09-24 16:15:22 +08:00
env.set("test", new LuaNativeJSFunction((n) => n));
env.set("asyncTest", new LuaNativeJSFunction((n) => Promise.resolve(n)));
2024-09-12 23:01:54 +08:00
2024-09-24 16:15:22 +08:00
// Basic arithmetic
assertEquals(evalExpr(`1 + 2 + 3 - 3`), 3);
assertEquals(evalExpr(`4 // 3`), 1);
assertEquals(evalExpr(`4 % 3`), 1);
2024-09-27 15:11:03 +08:00
// Strings
assertEquals(evalExpr(`"a" .. "b"`), "ab");
// Logic
assertEquals(evalExpr(`true and false`), false);
assertEquals(evalExpr(`true or false`), true);
assertEquals(evalExpr(`not true`), false);
2024-09-24 16:15:22 +08:00
// Tables
const tbl = evalExpr(`{3, 1, 2}`);
2024-09-27 15:11:03 +08:00
assertEquals(tbl.get(1), 3);
assertEquals(tbl.get(2), 1);
assertEquals(tbl.get(3), 2);
2024-09-24 16:15:22 +08:00
assertEquals(tbl.toArray(), [3, 1, 2]);
assertEquals(evalExpr(`{name=test("Zef"), age=100}`, env).toObject(), {
name: "Zef",
age: 100,
});
assertEquals(
(await evalExpr(`{name="Zef", age=asyncTest(100)}`, env)).toObject(),
{
name: "Zef",
age: 100,
},
);
assertEquals(evalExpr(`{[3+2]=1, ["a".."b"]=2}`).toObject(), {
5: 1,
ab: 2,
});
assertEquals(evalExpr(`#{}`), 0);
assertEquals(evalExpr(`#{1, 2, 3}`), 3);
// Unary operators
assertEquals(await evalExpr(`-asyncTest(3)`, env), -3);
2024-09-27 15:11:03 +08:00
// Function calls
2024-09-24 16:15:22 +08:00
assertEquals(singleResult(evalExpr(`test(3)`, env)), 3);
assertEquals(singleResult(await evalExpr(`asyncTest(3) + 1`, env)), 4);
2024-09-12 23:01:54 +08:00
});
2024-09-27 15:11:03 +08:00
Deno.test("Statement evaluation", async () => {
const env = new LuaEnv();
env.set("test", new LuaNativeJSFunction((n) => n));
env.set("asyncTest", new LuaNativeJSFunction((n) => Promise.resolve(n)));
assertEquals(undefined, await evalBlock(`a = 3`, env));
assertEquals(env.get("a"), 3);
assertEquals(undefined, await evalBlock(`b = test(3)`, env));
assertEquals(env.get("b"), 3);
await evalBlock(`c = asyncTest(3)`, env);
assertEquals(env.get("c"), 3);
// Multiple assignments
const env2 = new LuaEnv();
assertEquals(undefined, await evalBlock(`a, b = 1, 2`, env2));
assertEquals(env2.get("a"), 1);
assertEquals(env2.get("b"), 2);
// Other lvalues
const env3 = new LuaEnv();
await evalBlock(`tbl = {1, 2, 3}`, env3);
await evalBlock(`tbl[1] = 3`, env3);
assertEquals(env3.get("tbl").toArray(), [3, 2, 3]);
await evalBlock("tbl.name = 'Zef'", env3);
assertEquals(env3.get("tbl").get("name"), "Zef");
await evalBlock(`tbl[2] = {age=10}`, env3);
await evalBlock(`tbl[2].age = 20`, env3);
assertEquals(env3.get("tbl").get(2).get("age"), 20);
// Blocks and scopes
const env4 = new LuaEnv();
env4.set("print", new LuaNativeJSFunction(console.log));
await evalBlock(
`
a = 1
do
-- sets global a to 3
a = 3
print("The number is: " .. a)
end`,
env4,
);
assertEquals(env4.get("a"), 3);
const env5 = new LuaEnv();
env5.set("print", new LuaNativeJSFunction(console.log));
await evalBlock(
`
a = 1
if a > 0 then
a = 3
else
a = 0
end`,
env5,
);
assertEquals(env5.get("a"), 3);
await evalBlock(
`
if a < 0 then
a = -1
elseif a > 0 then
a = 1
else
a = 0
end`,
env5,
);
assertEquals(env5.get("a"), 1);
await evalBlock(
`
var = 1
do
local var
var = 2
end`,
env5,
);
assertEquals(env5.get("var"), 1);
// While loop
const env6 = new LuaEnv();
await evalBlock(
`
c = 0
while true do
c = c + 1
if c == 3 then
break
end
end
`,
env6,
);
assertEquals(env6.get("c"), 3);
// Repeat loop
const env7 = new LuaEnv();
await evalBlock(
`
c = 0
repeat
c = c + 1
if c == 3 then
break
end
until false
`,
env7,
);
assertEquals(env7.get("c"), 3);
});