From bd41ad4a9c11e0b1fb0dbb5c5d0d93a706ea1771 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Wed, 19 Jul 2023 01:14:55 -0300 Subject: [PATCH] gen: output bit32 ops even for invalid variables Do not short-circuit the 5.1 adaptation of the output code when an invalid type is detected. (That patching of the AST shouldn't really be at the type checking stage...) Fixes #673. --- spec/cli/gen_spec.lua | 20 ++++++++++++++++++++ tl.lua | 6 +++--- tl.tl | 6 +++--- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/spec/cli/gen_spec.lua b/spec/cli/gen_spec.lua index b95e8fe9..3eddc4e6 100644 --- a/spec/cli/gen_spec.lua +++ b/spec/cli/gen_spec.lua @@ -197,6 +197,26 @@ describe("tl gen", function() local y = bit32.lshift(2, 3) ]], util.read_file(lua_name)) end) + + it("generates bit32 operations even for invalid variables (regression test for #673)", function() + local name = util.write_tmp_file(finally, [[ + + local foo = require("nonexisting") + local y = 2 | (foo.wat << 9) + local x = ~y + ]]) + local pd = io.popen(util.tl_cmd("gen", "--gen-target=5.1", name), "r") + local output = pd:read("*a") + util.assert_popen_close(0, pd:close()) + local lua_name = tl_to_lua(name) + assert.match("Wrote: " .. lua_name, output, 1, true) + util.assert_line_by_line([[ + local bit32 = bit32; if not bit32 then local p, m = pcall(require, 'bit32'); if p then bit32 = m end end + local foo = require("nonexisting") + local y = bit32.bor(2, (bit32.lshift(foo.wat, 9))) + local x = bit32.bnot(y) + ]], util.read_file(lua_name)) + end) end) describe("with --gen-target=5.3", function() diff --git a/tl.lua b/tl.lua index bbc5f2ae..fbe13ac6 100644 --- a/tl.lua +++ b/tl.lua @@ -9986,14 +9986,14 @@ tl.type_check = function(ast, opts) if not node.type then node.type, meta_on_operator = check_metamethod(node, node.op.op, a) if not node.type then - return node_error(node, "cannot use operator '" .. node.op.op:gsub("%%", "%%%%") .. "' on type %s", resolve_tuple(orig_a)) + node_error(node, "cannot use operator '" .. node.op.op:gsub("%%", "%%%%") .. "' on type %s", resolve_tuple(orig_a)) end end if a.typename == "map" then if a.keys.typename == "number" or a.keys.typename == "integer" then node_warning("hint", node, "using the '#' operator on a map with numeric key type may produce unexpected results") else - return node_error(node, "using the '#' operator on this map will always return 0") + node_error(node, "using the '#' operator on this map will always return 0") end end @@ -10032,7 +10032,7 @@ tl.type_check = function(ast, opts) if not node.type then node.type, meta_on_operator = check_metamethod(node, node.op.op, a, b) if not node.type then - return node_error(node, "cannot use operator '" .. node.op.op:gsub("%%", "%%%%") .. "' for types %s and %s", resolve_tuple(orig_a), resolve_tuple(orig_b)) + node_error(node, "cannot use operator '" .. node.op.op:gsub("%%", "%%%%") .. "' for types %s and %s", resolve_tuple(orig_a), resolve_tuple(orig_b)) end end diff --git a/tl.tl b/tl.tl index 8615ec8d..76df6a0c 100644 --- a/tl.tl +++ b/tl.tl @@ -9986,14 +9986,14 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string if not node.type then node.type, meta_on_operator = check_metamethod(node, node.op.op, a) if not node.type then - return node_error(node, "cannot use operator '" .. node.op.op:gsub("%%", "%%%%") .. "' on type %s", resolve_tuple(orig_a)) + node_error(node, "cannot use operator '" .. node.op.op:gsub("%%", "%%%%") .. "' on type %s", resolve_tuple(orig_a)) end end if a.typename == "map" then if a.keys.typename == "number" or a.keys.typename == "integer" then node_warning("hint", node, "using the '#' operator on a map with numeric key type may produce unexpected results") else - return node_error(node, "using the '#' operator on this map will always return 0") + node_error(node, "using the '#' operator on this map will always return 0") end end @@ -10032,7 +10032,7 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string if not node.type then node.type, meta_on_operator = check_metamethod(node, node.op.op, a, b) if not node.type then - return node_error(node, "cannot use operator '" .. node.op.op:gsub("%%", "%%%%") .. "' for types %s and %s", resolve_tuple(orig_a), resolve_tuple(orig_b)) + node_error(node, "cannot use operator '" .. node.op.op:gsub("%%", "%%%%") .. "' for types %s and %s", resolve_tuple(orig_a), resolve_tuple(orig_b)) end end