diff --git a/moonscript/compile.lua b/moonscript/compile.lua index 54bf39e..088724b 100644 --- a/moonscript/compile.lua +++ b/moonscript/compile.lua @@ -18,11 +18,9 @@ do end local concat, insert = table.concat, table.insert local pos_to_line, get_closest_line, trim = util.pos_to_line, util.get_closest_line, util.trim -local bubble_names = { - "has_varargs" -} local Line -Line = (function(_parent_0) +Line = (function() + local _parent_0 = nil local _base_0 = { _append_single = function(self, item) if util.moon.type(item) == Line then @@ -85,17 +83,18 @@ Line = (function(_parent_0) end }, { __index = _base_0, - __call = function(mt, ...) - local self = setmetatable({}, _base_0) - mt.__init(self, ...) - return self + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 end }) _base_0.__class = _class_0 return _class_0 end)() local Block_ -Block_ = (function(_parent_0) +Block_ = (function() + local _parent_0 = nil local _base_0 = { header = "do", footer = "end", @@ -251,15 +250,6 @@ Block_ = (function(_parent_0) if t == "string" then self:add_line_text(line) elseif t == Block then - do - local _item_0 = bubble_names - for _index_0 = 1, #_item_0 do - local name = _item_0[_index_0] - if line[name] then - self[name] = line.name - end - end - end self:add(self:line(line)) elseif t == Line then self:add_line_tables(line) @@ -396,24 +386,30 @@ Block_ = (function(_parent_0) if not ret then ret = default_return end - local i = 1 - while i < #stms do - self:stm(stms[i]) - i = i + 1 + local last_exp_id = 0 + for i = #stms, 1, -1 do + local stm = stms[i] + if stm and util.moon.type(stm) ~= transform.Run then + last_exp_id = i + break + end end - local last_exp = stms[i] - if last_exp then - if cascading[ntype(last_exp)] then - self:stm(last_exp, ret) - elseif self:is_value(last_exp) then - local line = ret(stms[i]) - if self:is_stm(line) then - self:stm(line) + for i, stm in ipairs(stms) do + if i == last_exp_id then + if cascading[ntype(stm)] then + self:stm(stm, ret) + elseif self:is_value(stm) then + local line = ret(stms[i]) + if self:is_stm(line) then + self:stm(line) + else + error("got a value from implicit return") + end else - error("got a value from implicit return") + self:stm(stm) end else - self:stm(last_exp) + self:stm(stm) end end return nil @@ -456,17 +452,18 @@ Block_ = (function(_parent_0) end }, { __index = _base_0, - __call = function(mt, ...) - local self = setmetatable({}, _base_0) - mt.__init(self, ...) - return self + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 end }) _base_0.__class = _class_0 return _class_0 end)() local RootBlock -RootBlock = (function(_parent_0) +RootBlock = (function() + local _parent_0 = Block_ local _base_0 = { render = function(self) self:_insert_breaks() @@ -485,15 +482,15 @@ RootBlock = (function(_parent_0) end }, { __index = _base_0, - __call = function(mt, ...) - local self = setmetatable({}, _base_0) - mt.__init(self, ...) - return self + __call = function(cls, ...) + local _self_0 = setmetatable({}, _base_0) + cls.__init(_self_0, ...) + return _self_0 end }) _base_0.__class = _class_0 return _class_0 -end)(Block_) +end)() Block = Block_ format_error = function(msg, pos, file_str) local line = pos_to_line(file_str, pos) diff --git a/moonscript/compile.moon b/moonscript/compile.moon index aab11bb..cec0c31 100644 --- a/moonscript/compile.moon +++ b/moonscript/compile.moon @@ -19,8 +19,6 @@ import pos_to_line, get_closest_line, trim from util export tree, value, format_error export Block -bubble_names = { "has_varargs" } - -- buffer for building up a line class Line _append_single: (item) => @@ -167,9 +165,6 @@ class Block_ if t == "string" @add_line_text line elseif t == Block - for name in *bubble_names - self[name] = line.name if line[name] - @add @line line elseif t == Line @add_line_tables line @@ -262,26 +257,29 @@ class Block_ if not ret ret = default_return - -- wow I really need a for loop - i = 1 - while i < #stms - @stm stms[i] - i = i + 1 + -- find last exp for explicit return + last_exp_id = 0 + for i = #stms, 1, -1 + stm = stms[i] + if stm and util.moon.type(stm) != transform.Run + last_exp_id = i + break - last_exp = stms[i] - - if last_exp - if cascading[ntype(last_exp)] - @stm last_exp, ret - elseif @is_value last_exp - line = ret stms[i] - if @is_stm line - @stm line + for i, stm in ipairs stms + if i == last_exp_id + if cascading[ntype(stm)] + @stm stm, ret + elseif @is_value stm + line = ret stms[i] + if @is_stm line + @stm line + else + error "got a value from implicit return" else - error "got a value from implicit return" + -- nothing we can do with a statement except show it + @stm stm else - -- nothing we can do with a statement except show it - @stm last_exp + @stm stm nil diff --git a/moonscript/compile/value.lua b/moonscript/compile/value.lua index 2ae27f5..817b4ac 100644 --- a/moonscript/compile/value.lua +++ b/moonscript/compile/value.lua @@ -201,6 +201,13 @@ value_compile = { return error("Unknown chain action: " .. t) end end + if ntype(callee) == "self" and node[3] and ntype(node[3]) == "call" then + callee[1] = "self_colon" + end + local callee_value = self:value(callee) + if ntype(callee) == "exp" then + callee_value = self:line("(", callee_value, ")") + end local actions do local _with_0 = self:line() @@ -213,13 +220,6 @@ value_compile = { end actions = _with_0 end - if ntype(callee) == "self" and node[3] and ntype(node[3]) == "call" then - callee[1] = "self_colon" - end - local callee_value = self:name(callee) - if ntype(callee) == "exp" then - callee_value = self:line("(", callee_value, ")") - end return self:line(callee_value, actions) end, fndef = function(self, node) @@ -258,7 +258,7 @@ value_compile = { insert(arg_names, 1, "self") end do - local _with_0 = self:block("function(" .. concat(arg_names, ", ") .. ")") + local _with_0 = self:block() if #whitelist > 0 then _with_0:whitelist_names(whitelist) end @@ -320,6 +320,25 @@ value_compile = { }) end _with_0:ret_stms(block) + if #args > #arg_names then + arg_names = (function() + local _accum_0 = { } + local _len_0 = 0 + do + local _item_0 = args + for _index_0 = 1, #_item_0 do + local arg = _item_0[_index_0] + local _value_0 = arg[1] + if _value_0 ~= nil then + _len_0 = _len_0 + 1 + _accum_0[_len_0] = _value_0 + end + end + end + return _accum_0 + end)() + end + _with_0.header = "function(" .. concat(arg_names, ", ") .. ")" return _with_0 end end, diff --git a/moonscript/compile/value.moon b/moonscript/compile/value.moon index 60e76cd..010091c 100644 --- a/moonscript/compile/value.moon +++ b/moonscript/compile/value.moon @@ -105,6 +105,7 @@ value_compile = chain_item = (node) -> t, arg = unpack node if t == "call" + -- print arg, util.dump arg "(", @values(arg), ")" elseif t == "index" "[", @value(arg), "]" @@ -117,15 +118,15 @@ value_compile = else error "Unknown chain action: "..t - actions = with @line! - \append chain_item action for action in *node[3:] - if ntype(callee) == "self" and node[3] and ntype(node[3]) == "call" callee[1] = "self_colon" - callee_value = @name callee + callee_value = @value callee callee_value = @line "(", callee_value, ")" if ntype(callee) == "exp" + actions = with @line! + \append chain_item action for action in *node[3:] + @line callee_value, actions fndef: (node) => @@ -147,7 +148,7 @@ value_compile = if arrow == "fat" insert arg_names, 1, "self" - with @block "function("..concat(arg_names, ", ")..")" + with @block! if #whitelist > 0 \whitelist_names whitelist @@ -166,6 +167,11 @@ value_compile = \stm {"assign", self_args, self_arg_values} if #self_args > 0 \ret_stms block + if #args > #arg_names -- will only work for simple adjustments + arg_names = for arg in *args + arg[1] + + .header = "function("..concat(arg_names, ", ")..")" table: (node) => _, items = unpack node diff --git a/moonscript/transform.lua b/moonscript/transform.lua index 85e654c..b9c39fd 100644 --- a/moonscript/transform.lua +++ b/moonscript/transform.lua @@ -73,7 +73,6 @@ NameProxy = (function(_parent_0) _base_0.__class = _class_0 return _class_0 end)() -local Run Run = (function(_parent_0) local _base_0 = { call = function(self, state) @@ -104,11 +103,18 @@ local constructor_name = "new" local transformer transformer = function(transformers) return function(n) - transformer = transformers[ntype(n)] - if transformer then - return transformer(n) or n - else - return n + while true do + transformer = transformers[ntype(n)] + local res + if transformer then + res = transformer(n) or n + else + res = n + end + if res == n then + return n + end + n = res end end end @@ -334,7 +340,7 @@ value = transformer({ table.remove(node, #node) local base_name = NameProxy("base") local fn_name = NameProxy("fn") - return build.block_exp({ + return value(build.block_exp({ build.assign({ names = { base_name @@ -376,14 +382,24 @@ value = transformer({ }) } }) - }) + })) end end, block_exp = function(node) local _, body = unpack(node) - local fn = build.fndef({ + local fn = nil + local arg_list = { } + insert(body, Run(function(self) + if self.has_varargs then + insert(arg_list, "...") + return insert(fn.args, { + "..." + }) + end + end)) + fn = smart_node(build.fndef({ body = body - }) + })) return build.chain({ base = { "parens", @@ -391,7 +407,7 @@ value = transformer({ }, { "call", - { } + arg_list } }) end diff --git a/moonscript/transform.moon b/moonscript/transform.moon index f21e814..deed5c3 100644 --- a/moonscript/transform.moon +++ b/moonscript/transform.moon @@ -8,7 +8,7 @@ data = require "moonscript.data" import ntype, build, smart_node from types import insert from table -export stm, value, NameProxy +export stm, value, NameProxy, Run class NameProxy new: (@prefix) => @@ -49,11 +49,14 @@ constructor_name = "new" transformer = (transformers) -> (n) -> - transformer = transformers[ntype n] - if transformer - transformer(n) or n - else - n + while true + transformer = transformers[ntype n] + res = if transformer + transformer(n) or n + else + n + return n if res == n + n = res stm = transformer { class: (node using nil) -> @@ -176,7 +179,7 @@ value = transformer { base_name = NameProxy "base" fn_name = NameProxy "fn" - build.block_exp { + value build.block_exp { build.assign { names: {base_name} values: {node} @@ -201,7 +204,16 @@ value = transformer { block_exp: (node) -> _, body = unpack node - fn = build.fndef body: body - build.chain { base: {"parens", fn}, {"call", {}} } + + fn = nil + arg_list = {} + + insert body, Run => + if @has_varargs + insert arg_list, "..." + insert fn.args, {"..."} + + fn = smart_node build.fndef body: body + build.chain { base: {"parens", fn}, {"call", arg_list} } } diff --git a/tests/inputs/stub.moon b/tests/inputs/stub.moon index 19ce047..f8f6c3f 100644 --- a/tests/inputs/stub.moon +++ b/tests/inputs/stub.moon @@ -11,3 +11,6 @@ print fn! print x\val! +-- ... should be bubbled up anon functions +x = hello(...)\world + diff --git a/tests/outputs/stub.lua b/tests/outputs/stub.lua index 6ab73cc..1f02d09 100644 --- a/tests/outputs/stub.lua +++ b/tests/outputs/stub.lua @@ -12,4 +12,11 @@ local fn = (function() end end)() print(fn()) -print(x:val()) \ No newline at end of file +print(x:val()) +x = (function(...) + local _base_0 = hello(...) + local _fn_0 = _base_0.world + return function(...) + return _fn_0(_base_0, ...) + end +end)(...) \ No newline at end of file