diff --git a/moonscript/compile/value.lua b/moonscript/compile/value.lua index 0e6fad0..f4352ea 100644 --- a/moonscript/compile/value.lua +++ b/moonscript/compile/value.lua @@ -46,9 +46,9 @@ local value_compilers = { do local _with_0 = self:line() _with_0:append_list((function() + local _list_0 = node local _accum_0 = { } local _len_0 = 1 - local _list_0 = node for _index_0 = 2, #_list_0 do local v = _list_0[_index_0] _accum_0[_len_0] = self:value(v) diff --git a/moonscript/errors.lua b/moonscript/errors.lua index 83e701d..e36780c 100644 --- a/moonscript/errors.lua +++ b/moonscript/errors.lua @@ -42,9 +42,9 @@ truncate_traceback = function(traceback, chunk_func) end stop = stop - 1 end + local _list_0 = traceback traceback = { } local _len_0 = 1 - local _list_0 = traceback local _max_0 = stop for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do local t = _list_0[_index_0] diff --git a/moonscript/transform.lua b/moonscript/transform.lua index 6910307..dd0351d 100644 --- a/moonscript/transform.lua +++ b/moonscript/transform.lua @@ -349,11 +349,13 @@ Statement = Transformer({ if "comprehension" == _exp_0 then local first_name = names[1] local a = Accumulator(first_name) - node = self.transform.statement(first_value, function(exp) + local action + action = function(exp) return a:mutate_body({ exp }) - end) + end + node = self.transform.statement(first_value, action, node) return a:wrap(node, "group") end end @@ -585,9 +587,9 @@ Statement = Transformer({ wrapped = build.group({ build.declare({ names = (function() + local _list_0 = stm[2] local _accum_0 = { } local _len_0 = 1 - local _list_0 = stm[2] for _index_0 = 1, #_list_0 do local name = _list_0[_index_0] if type(name) == "string" then @@ -699,7 +701,7 @@ Statement = Transformer({ end)() }) end, - foreach = function(self, node) + foreach = function(self, node, _, parent_assign) smart_node(node) local source = unpack(node.iter) local destructures = { } @@ -727,7 +729,11 @@ Statement = Transformer({ if ntype(source) == "unpack" then local list = source[2] local index_name = NameProxy("index") - local list_name = self:is_local(list) and list or NameProxy("list") + local assign_name + if parent_assign then + assign_name = parent_assign[2][1] + end + local list_name = assign_name ~= list and self:is_local(list) and list or NameProxy("list") local slice_var = nil local bounds if is_slice(list) then @@ -768,7 +774,7 @@ Statement = Transformer({ } } end - return build.group({ + local out = build.group({ list_name ~= list and build.assign_one(list_name, list) or NOOP, slice_var or NOOP, build["for"]({ @@ -786,6 +792,8 @@ Statement = Transformer({ } }) }) + out.has_unpack_copy = true + return out end node.body = with_continue_listener(node.body) end, @@ -1085,9 +1093,9 @@ Statement = Transformer({ end return self:set("super", function(block, chain) if chain then + local _list_0 = chain local slice = { } local _len_0 = 1 - local _list_0 = chain for _index_0 = 3, #_list_0 do local item = _list_0[_index_0] slice[_len_0] = item @@ -1244,7 +1252,16 @@ do if group_type == nil then group_type = "block_exp" end + local copy_list + if rawget(node, "has_unpack_copy") then + do + local _with_0 = node[2][1] + node[2][1] = NOOP + copy_list = _with_0 + end + end return build[group_type]({ + copy_list or NOOP, build.assign_one(self.accum_name, build.table()), build.assign_one(self.len_name, 1), node, diff --git a/moonscript/transform.moon b/moonscript/transform.moon index 801b5cf..92bc441 100644 --- a/moonscript/transform.moon +++ b/moonscript/transform.moon @@ -181,8 +181,8 @@ Statement = Transformer { first_name = names[1] a = Accumulator first_name - node = @transform.statement first_value, (exp) -> - a\mutate_body { exp } + action = (exp) -> a\mutate_body { exp } + node = @transform.statement first_value, action, node return a\wrap node, "group" @@ -389,7 +389,7 @@ Statement = Transformer { ret scope_name } - foreach: (node) => + foreach: (node, _, parent_assign) => smart_node node source = unpack node.iter @@ -409,7 +409,8 @@ Statement = Transformer { list = source[2] index_name = NameProxy "index" - list_name = @is_local(list) and list or NameProxy "list" + assign_name = parent_assign[2][1] if parent_assign + list_name = assign_name != list and @is_local(list) and list or NameProxy "list" slice_var = nil bounds = if is_slice list @@ -430,7 +431,7 @@ Statement = Transformer { else {1, {"length", list_name}} - return build.group { + out = build.group { list_name != list and build.assign_one(list_name, list) or NOOP slice_var or NOOP build["for"] { @@ -443,6 +444,9 @@ Statement = Transformer { } } + out.has_unpack_copy = true + return out + node.body = with_continue_listener node.body while: (node) => @@ -721,7 +725,12 @@ class Accumulator -- wrap the node into a block_exp wrap: (node, group_type="block_exp") => + copy_list = if rawget node, "has_unpack_copy" + with node[2][1] + node[2][1] = NOOP + build[group_type] { + copy_list or NOOP build.assign_one @accum_name, build.table! build.assign_one @len_name, 1 node diff --git a/moonscript/types.lua b/moonscript/types.lua index 4a171a2..a6d70fa 100644 --- a/moonscript/types.lua +++ b/moonscript/types.lua @@ -1,14 +1,18 @@ local util = require("moonscript.util") -local data = require("moonscript.data") +local Set +do + local _table_0 = require("moonscript.data") + Set = _table_0.Set +end local insert = table.insert local unpack = util.unpack -local manual_return = data.Set({ +local manual_return = Set({ "foreach", "for", "while", "return" }) -local cascading = data.Set({ +local cascading = Set({ "if", "unless", "with", diff --git a/moonscript/types.moon b/moonscript/types.moon index 992ff77..e603f60 100644 --- a/moonscript/types.moon +++ b/moonscript/types.moon @@ -1,17 +1,17 @@ util = require "moonscript.util" -data = require "moonscript.data" +import Set from require "moonscript.data" import insert from table import unpack from util -- implicit return does not work on these statements -manual_return = data.Set{"foreach", "for", "while", "return"} +manual_return = Set{"foreach", "for", "while", "return"} -- Assigns and returns are bubbled into their bodies. -- All cascading statement transform functions accept a second arugment that -- is the transformation to apply to the last statement in their body -cascading = data.Set{ "if", "unless", "with", "switch", "class", "do" } +cascading = Set{ "if", "unless", "with", "switch", "class", "do" } -- type of node as string ntype = (node) -> diff --git a/spec/outputs/bubbling.lua b/spec/outputs/bubbling.lua index 4d83336..38c0757 100644 --- a/spec/outputs/bubbling.lua +++ b/spec/outputs/bubbling.lua @@ -40,11 +40,11 @@ end)() local m m = function(...) return (function(...) - local _accum_0 = { } - local _len_1 = 1 local _list_0 = { ... } + local _accum_0 = { } + local _len_1 = 1 for _index_0 = 1, #_list_0 do local x = _list_0[_index_0] if f(...) > 4 then @@ -68,11 +68,11 @@ local x = (function(...) end return _accum_0 end)(...) -local y = { } -local _len_1 = 1 local _list_0 = { ... } +local y = { } +local _len_1 = 1 for _index_0 = 1, #_list_0 do x = _list_0[_index_0] y[_len_1] = x diff --git a/thoughts b/thoughts index ae5ecb9..735f668 100644 --- a/thoughts +++ b/thoughts @@ -37,4 +37,5 @@ x = for thing in *things if is_important thing break thing +-- all function literals have a string that is their function definition