From 16c191c5a66c710173f2444081054893d229ee4a Mon Sep 17 00:00:00 2001 From: shviller Date: Wed, 1 Oct 2014 19:48:34 +0400 Subject: [PATCH 1/3] Bring ast_to_src up to date Bring ast_to_src up to date with the main repository at http://git.eclipse.org/c/koneki/org.eclipse.koneki.metalua.git/ --- metalua/compiler/ast_to_src.mlua | 89 ++++++++++++++------------------ 1 file changed, 39 insertions(+), 50 deletions(-) diff --git a/metalua/compiler/ast_to_src.mlua b/metalua/compiler/ast_to_src.mlua index 65283c6..ca80a12 100644 --- a/metalua/compiler/ast_to_src.mlua +++ b/metalua/compiler/ast_to_src.mlua @@ -21,6 +21,7 @@ local M = { } M.__index = M +M.__call = |self, ...| self:run(...) local pp=require 'metalua.pprint' @@ -160,24 +161,34 @@ local op_symbol = { -------------------------------------------------------------------------------- function M:node (node) assert (self~=M and self._acc) - if node==nil then self:acc'<>'; return end - if not node.tag then -- tagless block. - self:list (node, self.nl) - else - local f = M[node.tag] - if type (f) == "function" then -- Delegate to tag method. - f (self, node, unpack (node)) - elseif type (f) == "string" then -- tag string. - self:acc (f) - else -- No appropriate method, fall back to splice dumping. - -- This cannot happen in a plain Lua AST. - self:acc " -{ " - self:acc (pp.tostring (node, {metalua_tag=1, hide_hash=1}), 80) - self:acc " }" + if node==nil then self:acc'<>' + elseif not self.custom_printer or not self.custom_printer (self, node) then + if not node.tag then -- tagless (henceunindented) block. + self:list (node, self.nl) + else + local f = M[node.tag] + if type (f) == "function" then -- Delegate to tag method. + f (self, node, unpack (node)) + elseif type (f) == "string" then -- tag string. + self:acc (f) + else -- No appropriate method, fall back to splice dumping. + -- This cannot happen in a plain Lua AST. + self:acc " -{ " + self:acc (pp.tostring (node, {metalua_tag=1, hide_hash=1}), 80) + self:acc " }" + end end end end +function M:block(body) + if not self.custom_printer or not self.custom_printer (self, body) then + self:nlindent () + self:list (body, self.nl) + self:nldedent () + end +end + -------------------------------------------------------------------------------- -- Convert every node in the AST list `list' passed as 1st arg. -- `sep' is an optional separator to be accumulated between each list element, @@ -225,9 +236,7 @@ end function M:Do (node) self:acc "do" - self:nlindent () - self:list (node, self.nl) - self:nldedent () + self:block (node) self:acc "end" end @@ -244,9 +253,7 @@ function M:Set (node) self:acc " (" self:list (params, ", ", 2) self:acc ")" - self:nlindent () - self:list (body, self.nl) - self:nldedent () + self:block (body) self:acc "end" | `Set{ { lhs }, { `Function{ params, body } } } if is_idx_stack (lhs) -> @@ -256,9 +263,7 @@ function M:Set (node) self:acc " (" self:list (params, ", ") self:acc ")" - self:nlindent () - self:list (body, self.nl) - self:nldedent () + self:block (body) self:acc "end" | `Set{ { `Id{ lhs1name } == lhs1, ... } == lhs, rhs } @@ -303,17 +308,13 @@ function M:While (node, cond, body) self:acc "while " self:node (cond) self:acc " do" - self:nlindent () - self:list (body, self.nl) - self:nldedent () + self:block (body) self:acc "end" end function M:Repeat (node, body, cond) self:acc "repeat" - self:nlindent () - self:list (body, self.nl) - self:nldedent () + self:block (body) self:acc "until " self:node (cond) end @@ -325,16 +326,12 @@ function M:If (node) self:acc (i==1 and "if " or "elseif ") self:node (cond) self:acc " then" - self:nlindent () - self:list (body, self.nl) - self:nldedent () + self:block (body) end -- odd number of children --> last one is an `else' clause -- if #node%2 == 1 then self:acc "else" - self:nlindent () - self:list (node[#node], self.nl) - self:nldedent () + self:block (node[#node]) end self:acc "end" end @@ -352,9 +349,7 @@ function M:Fornum (node, var, first, last) self:node (node[4]) end self:acc " do" - self:nlindent () - self:list (body, self.nl) - self:nldedent () + self:block (body) self:acc "end" end @@ -364,9 +359,7 @@ function M:Forin (node, vars, generators, body) self:acc " in " self:list (generators, ", ") self:acc " do" - self:nlindent () - self:list (body, self.nl) - self:nldedent () + self:block (body) self:acc "end" end @@ -392,7 +385,7 @@ function M:Local (node, lhs, rhs, annots) self:list (rhs, ", ") end else -- Can't create a local statement with 0 variables in plain Lua - self:acc (table.tostring (node, 'nohash', 80)) + self:acc (pp.tostring (node, {metalua_tag=1, hide_hash=1, fix_indent=2})) end end @@ -406,16 +399,14 @@ function M:Localrec (node, lhs, rhs) self:acc " (" self:list (params, ", ") self:acc ")" - self:nlindent () - self:list (body, self.nl) - self:nldedent () + self:block (body) self:acc "end" | _ -> -- Other localrec are unprintable ==> splice them -- -- This cannot happen in a plain Lua AST. -- self:acc "-{ " - self:acc (table.tostring (node, 'nohash', 80)) + self:acc (pp.tostring (node, {metalua_tag=1, hide_hash=1, fix_indent=2})) self:acc " }" end end @@ -488,9 +479,7 @@ function M:Function (node, params, body, annots) self:list (params, ", ") end self:acc ")" - self:nlindent () - self:list (body, self.nl) - self:nldedent () + self:block (body) self:acc "end" end @@ -690,4 +679,4 @@ for name, tag in pairs{ const='TConst', var='TVar', currently='TCurrently', just end end -return (|x| M.run(x)) +return M From a4561518093925ac39bc3c9250fe326541e6ae08 Mon Sep 17 00:00:00 2001 From: shviller Date: Wed, 1 Oct 2014 20:12:38 +0400 Subject: [PATCH 2/3] Multiple enhancements to ast_to_src Processes unary minus correctly, produces valid code for string literal method calls and IIFEs, processes label, goto, and the `Stat node, escapes invalid identifiers. --- metalua/compiler/ast_to_src.mlua | 91 +++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 8 deletions(-) diff --git a/metalua/compiler/ast_to_src.mlua b/metalua/compiler/ast_to_src.mlua index ca80a12..b363cb1 100644 --- a/metalua/compiler/ast_to_src.mlua +++ b/metalua/compiler/ast_to_src.mlua @@ -127,7 +127,7 @@ local op_preprec = { { "concat" }, { "add", "sub" }, { "mul", "div", "mod" }, - { "unary", "not", "len" }, + { "unm", "not", "len" }, { "pow" }, { "index" } } @@ -150,7 +150,9 @@ local op_symbol = { div = " / ", mod = " % ", pow = " ^ ", concat = " .. ", eq = " == ", ne = " ~= ", lt = " < ", le = " <= ", ["and"] = " and ", - ["or"] = " or ", ["not"] = "not ", len = "# " } + ["or"] = " or ", ["not"] = "not ", len = "# ", + ["unm"] = " - ", +} -------------------------------------------------------------------------------- -- Accumulate the source representation of AST `node' in @@ -272,9 +274,7 @@ function M:Set (node) -- In that case, the spliced 1st variable must get parentheses, -- to be distinguished from a statement splice. -- This cannot happen in a plain Lua AST. - self:acc "(" self:node (lhs1) - self:acc ")" if lhs[2] then -- more than one lhs variable self:acc ", " self:list (lhs, ", ", 2) @@ -282,6 +282,10 @@ function M:Set (node) self:acc " = " self:list (rhs, ", ") + | `Set{{`Paren{lhs}}, rhs} -> + self:Set(`Set{{lhs}, rhs}) + | `Set{{`Paren{lhs}}, rhs, annot} -> + self:Set(`Set{{lhs}, rhs, annot}) | `Set{ lhs, rhs } -> -- ``... = ...'', no syntax sugar -- self:list (lhs, ", ") @@ -294,7 +298,7 @@ function M:Set (node) local ell, a = lhs[i], annot[i] self:node (ell) if a then - self:acc ' #' + self:acc ' --' self:node(a) end if i~=n then self:acc ', ' end @@ -413,13 +417,21 @@ end function M:Call (node, f) -- single string or table literal arg ==> no need for parentheses. -- - local parens + local parens, wrap + match node with + | `Call{`Function{...}, _} -> wrap = true + | `Call{`Function{...}} -> wrap = true + | _ -> wrap = false + end --[[ !! I doubt this should be here. Code that produces this AST should + produce a syntax error instead. ]] match node with | `Call{ _, `String{_} } | `Call{ _, `Table{...}} -> parens = false | _ -> parens = true end + self:acc (wrap and "(" or "") self:node (f) + self:acc (wrap and ")" or "") self:acc (parens and " (" or " ") self:list (node, ", ", 2) -- skip `f'. self:acc (parens and ")") @@ -591,11 +603,19 @@ function M:Index (node, table, key) end end +local function sanitize_name(name) + return name:gsub('%.', '__') +end + function M:Id (node, name) if is_ident (name) then self:acc (name) - else -- Unprintable identifier, fall back to splice representation. - -- This cannot happen in a plain Lua AST. + else -- Unprintable identifier + local sanitized_name = sanitize_name(name) + if is_ident(sanitized_name) then + self:acc(sanitized_name) + return nil + end self:acc "-{`Id " self:String (node, name) self:acc "}" @@ -679,4 +699,59 @@ for name, tag in pairs{ const='TConst', var='TVar', currently='TCurrently', just end end +function M:Label(node, name) + match name with + | `Id{n} -> self:Label(node, n) + | _ -> + if is_ident(name) then + self:acc "::" + self:acc(name) + self:acc "::" + else -- Unprintable identifier + local sanitized_name = sanitize_name(name) + if is_ident(sanitized_name) then + self:acc "::" + self:acc(sanitized_name) + self:acc "::" + return nil + end + self:acc "-{`Id " + self:String(node, name) + self:acc "}" + end + end +end + +function M:Goto(node, name) + match name with + | `Id{n} -> self:Goto(node, n) + | _ -> + if is_ident(name) then + self:acc "goto " + self:acc(name) + else -- Unprintable identifier + local sanitized_name = sanitize_name(name) + if is_ident(sanitized_name) then + self:acc "goto " + self:acc(sanitized_name) + return nil + end + self:acc "-{`Goto " + self:String(node, name) + self:acc "}" + end + end +end + +function M:Stat(node, body, ret) + self:acc "(function()" + self:nlindent() + self:list (body, self.nl) + self:nl () + self:acc "return " + self:node (ret) + self:nldedent() + self:acc "end)()" +end + return M From 30603a82a02c4c2e3b63032eec1a6d1d99e10013 Mon Sep 17 00:00:00 2001 From: shviller Date: Fri, 3 Oct 2014 21:09:46 +0400 Subject: [PATCH 3/3] ast_to_src handles "string literal":method() ast_to_src wraps "string literal" in parens to produce valud lua syntax. --- metalua/compiler/ast_to_src.mlua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/metalua/compiler/ast_to_src.mlua b/metalua/compiler/ast_to_src.mlua index b363cb1..5bf9665 100644 --- a/metalua/compiler/ast_to_src.mlua +++ b/metalua/compiler/ast_to_src.mlua @@ -439,13 +439,19 @@ end function M:Invoke (node, f, method) -- single string or table literal arg ==> no need for parentheses. -- - local parens + local parens, wrap + match node with + | `Invoke{ `String{_}, ...} -> wrap = true + | _ -> wrap = false + end match node with | `Invoke{ _, _, `String{_} } | `Invoke{ _, _, `Table{...}} -> parens = false | _ -> parens = true end + self:acc (wrap and "(" or "") self:node (f) + self:acc (wrap and ")" or "") self:acc ":" self:acc (method[1]) self:acc (parens and " (" or " ")