diff --git a/src/operators.ts b/src/operators.ts index 6556f00..5a91df4 100644 --- a/src/operators.ts +++ b/src/operators.ts @@ -37,8 +37,15 @@ const binaryBooleanArithmetic = ( const bool = (value: LuaType): boolean => coerceToBoolean(value) // logical -const and = (l: LuaType, r: LuaType): LuaType => coerceToBoolean(l) ? r : l -const or = (l: LuaType, r: LuaType): LuaType => coerceToBoolean(l) ? l : r +const and = (l: () => LuaType, r: () => LuaType): LuaType => { + const lv = l() + return coerceToBoolean(lv) ? r() : lv +} + +const or = (l: () => LuaType, r: () => LuaType): LuaType => { + const lv = l() + return coerceToBoolean(lv) ? lv : r() +} // unary const not = (value: LuaType): boolean => !bool(value) diff --git a/src/parser.ts b/src/parser.ts index c3d5caf..dca6690 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -303,10 +303,10 @@ const generate = (node: luaparse.Node): string | MemExpr => { const operator = node.operator if (operator === 'and') { - return `__lua.and(${left},${right})` + return `__lua.and(() => ${left}, () => ${right})` } if (operator === 'or') { - return `__lua.or(${left},${right})` + return `__lua.or(() => ${left}, () => ${right})` } throw new Error(`Unhandled logical operator: ${node.operator}`) } diff --git a/tests/lua-5.3/logical_operations.lua b/tests/lua-5.3/logical_operations.lua new file mode 100644 index 0000000..c9176c8 --- /dev/null +++ b/tests/lua-5.3/logical_operations.lua @@ -0,0 +1,6 @@ +local x = nil +local x_ = (x and x.k or "fallback") +assert(x_ == "fallback") +local y = "ok" +local y_ = (y or error("should not raise")) +assert(y == y_) \ No newline at end of file diff --git a/tests/test.js b/tests/test.js index 9406ea5..1d18745 100644 --- a/tests/test.js +++ b/tests/test.js @@ -24,6 +24,7 @@ let exitCode = 0 }) luaEnv.parseFile('goto.lua').exec() luaEnv.parseFile('bwcoercion.lua').exec() + luaEnv.parseFile('logical_operations.lua').exec() } {