metalua icon indicating copy to clipboard operation
metalua copied to clipboard

`Function node encountered while traversing faulty AST

Open KINFOO opened this issue 13 years ago • 0 comments

Hi,

I'm on branch konekildt. I created an AST containing an error, while traversing it, I got a function instead of an ``Error` node. Here is the code to reproduce.

require 'metalua.compiler'
local walk = require 'metalua.treequery.walk'['block']
local ast = mlc.luastring_to_ast( 'f = function()x end')
local errorhandling = function(node, ...)
    table.print(node, 'nohash', 1)
end
local cfg = { error = errorhandling }
walk(cfg, ast)

Here is the output

$ metalua functionerror.lua
`Function{ { }, 
            { `Error "line 1, char 15: This expression (\"x\") is an identifier; a statement was expected, and only function and method call expressions can be used as statements\n>>> f = function()x end\n>>>                ^" }, 
            `Error "A keyword was expected, probably `end'." }

I browsed the code to find where this bug may come from walk.mlua in M.traverse.expr. In the match statement, the faulty function node does not match the guard ``Function{ params, body }` and is treated like an error node.

   match x with
   | `Paren{ e }               -> E(e)
   | `Call{...} | `Invoke{...} -> EL(x)
   | `Index{ a, b }            -> E(a); E(b)
   | `Op{ opid, ... }          -> E(x[2]); if #x==3 then E(x[3]) end
   | `Function{ params, body } -> OS(body); IL(params); B(body); CS(body)
   | `Stat{ b, e }             -> OS(body); B(b); E(e); CS(body)
   | `Id{ name }               -> M.occurrence(cfg, x, unpack(ancestors))
   | `Table{ ... }             ->
      for i = 1, #x do match x[i] with
         | `Pair{ k, v } -> E(k); E(v)
         | v             -> E(v)
      end end
   | `Nil|`Dots|`True|`False|`Number{_}|`String{_} -> -- terminal node
   | { tag=tag, ...} if M.tags.expr[tag]-> M.malformed (cfg, x, unpack (ancestors))
   | _ -> M.unknown (cfg, x, unpack (ancestors))
   end

I think the cause of its malformation comes from funcdef_builder in mlp_stat.lua, where we can see a Function{ {}, {}, {} }` is created in error cases, instead of a Function{ {}, {} }aswalk.traverse.expr` expects it.

local function funcdef_builder(x)

   local name   = x[1] or gg.earlier_error()
   local method = x[2]
   local func   = x[3] or gg.earlier_error()


   if method then 
      name = { tag="Index", name, method, lineinfo = {
         first = name.lineinfo.first,
         last  = method.lineinfo.last } }
      _G.table.insert (func[1], 1, {tag="Id", "self"}) 
   end
   local r = { tag="Set", {name}, {func} } 
   r[1].lineinfo = name.lineinfo
   r[2].lineinfo = func.lineinfo
   return r
end 

So I think I get the bug, but I am not sure of the clean way to fix it, should I:

  • Fix the way the ``Function{ {}, {}, {} }is created infuncdef_builder`?
  • Catch ``Functionin the error node handling inM.traverse.expr`?

Do you have a better idea?

KINFOO avatar Sep 18 '12 14:09 KINFOO