diff --git a/common/space_lua/eval.test.ts b/common/space_lua/eval.test.ts index 2638106a..6d20be78 100644 --- a/common/space_lua/eval.test.ts +++ b/common/space_lua/eval.test.ts @@ -45,7 +45,13 @@ Deno.test("Evaluator test", async () => { assertEquals(evalExpr(`true and false`), false); assertEquals(evalExpr(`true or false`), true); assertEquals(evalExpr(`not true`), false); - + // Test eager evaluation of left operand + assertEquals( + evalExpr( + `true or (function() error("this should not be evaluated") end)()`, + ), + true, + ); // Tables const tbl = evalExpr(`{3, 1, 2}`); assertEquals(tbl.get(1), 3); diff --git a/common/space_lua/eval.ts b/common/space_lua/eval.ts index acfd4ea1..8b3631f7 100644 --- a/common/space_lua/eval.ts +++ b/common/space_lua/eval.ts @@ -53,6 +53,22 @@ export function evalExpression( case "Nil": return null; case "Binary": { + if (e.operator === "or") { + // Special case: eagerly evaluate left before even attempting right + const left = evalExpression(e.left, env, sf); + if (left instanceof Promise) { + return left.then((left) => { + if (luaTruthy(left)) { + return left; + } + return evalExpression(e.right, env, sf); + }); + } else if (luaTruthy(left)) { + return left; + } else { + return evalExpression(e.right, env, sf); + } + } const values = evalPromiseValues([ evalExpression(e.left, env, sf), evalExpression(e.right, env, sf),