varargs bubbling moved to block_exp

This commit is contained in:
leaf corcoran 2011-10-09 15:58:39 -07:00
parent 9c8828e8fa
commit 0131786390
8 changed files with 156 additions and 98 deletions

View File

@ -18,11 +18,9 @@ do
end end
local concat, insert = table.concat, table.insert 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 pos_to_line, get_closest_line, trim = util.pos_to_line, util.get_closest_line, util.trim
local bubble_names = {
"has_varargs"
}
local Line local Line
Line = (function(_parent_0) Line = (function()
local _parent_0 = nil
local _base_0 = { local _base_0 = {
_append_single = function(self, item) _append_single = function(self, item)
if util.moon.type(item) == Line then if util.moon.type(item) == Line then
@ -85,17 +83,18 @@ Line = (function(_parent_0)
end end
}, { }, {
__index = _base_0, __index = _base_0,
__call = function(mt, ...) __call = function(cls, ...)
local self = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
mt.__init(self, ...) cls.__init(_self_0, ...)
return self return _self_0
end end
}) })
_base_0.__class = _class_0 _base_0.__class = _class_0
return _class_0 return _class_0
end)() end)()
local Block_ local Block_
Block_ = (function(_parent_0) Block_ = (function()
local _parent_0 = nil
local _base_0 = { local _base_0 = {
header = "do", header = "do",
footer = "end", footer = "end",
@ -251,15 +250,6 @@ Block_ = (function(_parent_0)
if t == "string" then if t == "string" then
self:add_line_text(line) self:add_line_text(line)
elseif t == Block then 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)) self:add(self:line(line))
elseif t == Line then elseif t == Line then
self:add_line_tables(line) self:add_line_tables(line)
@ -396,24 +386,30 @@ Block_ = (function(_parent_0)
if not ret then if not ret then
ret = default_return ret = default_return
end end
local i = 1 local last_exp_id = 0
while i < #stms do for i = #stms, 1, -1 do
self:stm(stms[i]) local stm = stms[i]
i = i + 1 if stm and util.moon.type(stm) ~= transform.Run then
last_exp_id = i
break
end
end end
local last_exp = stms[i] for i, stm in ipairs(stms) do
if last_exp then if i == last_exp_id then
if cascading[ntype(last_exp)] then if cascading[ntype(stm)] then
self:stm(last_exp, ret) self:stm(stm, ret)
elseif self:is_value(last_exp) then elseif self:is_value(stm) then
local line = ret(stms[i]) local line = ret(stms[i])
if self:is_stm(line) then if self:is_stm(line) then
self:stm(line) self:stm(line)
else
error("got a value from implicit return")
end
else else
error("got a value from implicit return") self:stm(stm)
end end
else else
self:stm(last_exp) self:stm(stm)
end end
end end
return nil return nil
@ -456,17 +452,18 @@ Block_ = (function(_parent_0)
end end
}, { }, {
__index = _base_0, __index = _base_0,
__call = function(mt, ...) __call = function(cls, ...)
local self = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
mt.__init(self, ...) cls.__init(_self_0, ...)
return self return _self_0
end end
}) })
_base_0.__class = _class_0 _base_0.__class = _class_0
return _class_0 return _class_0
end)() end)()
local RootBlock local RootBlock
RootBlock = (function(_parent_0) RootBlock = (function()
local _parent_0 = Block_
local _base_0 = { local _base_0 = {
render = function(self) render = function(self)
self:_insert_breaks() self:_insert_breaks()
@ -485,15 +482,15 @@ RootBlock = (function(_parent_0)
end end
}, { }, {
__index = _base_0, __index = _base_0,
__call = function(mt, ...) __call = function(cls, ...)
local self = setmetatable({}, _base_0) local _self_0 = setmetatable({}, _base_0)
mt.__init(self, ...) cls.__init(_self_0, ...)
return self return _self_0
end end
}) })
_base_0.__class = _class_0 _base_0.__class = _class_0
return _class_0 return _class_0
end)(Block_) end)()
Block = Block_ Block = Block_
format_error = function(msg, pos, file_str) format_error = function(msg, pos, file_str)
local line = pos_to_line(file_str, pos) local line = pos_to_line(file_str, pos)

View File

@ -19,8 +19,6 @@ import pos_to_line, get_closest_line, trim from util
export tree, value, format_error export tree, value, format_error
export Block export Block
bubble_names = { "has_varargs" }
-- buffer for building up a line -- buffer for building up a line
class Line class Line
_append_single: (item) => _append_single: (item) =>
@ -167,9 +165,6 @@ class Block_
if t == "string" if t == "string"
@add_line_text line @add_line_text line
elseif t == Block elseif t == Block
for name in *bubble_names
self[name] = line.name if line[name]
@add @line line @add @line line
elseif t == Line elseif t == Line
@add_line_tables line @add_line_tables line
@ -262,26 +257,29 @@ class Block_
if not ret if not ret
ret = default_return ret = default_return
-- wow I really need a for loop -- find last exp for explicit return
i = 1 last_exp_id = 0
while i < #stms for i = #stms, 1, -1
@stm stms[i] stm = stms[i]
i = i + 1 if stm and util.moon.type(stm) != transform.Run
last_exp_id = i
break
last_exp = stms[i] for i, stm in ipairs stms
if i == last_exp_id
if last_exp if cascading[ntype(stm)]
if cascading[ntype(last_exp)] @stm stm, ret
@stm last_exp, ret elseif @is_value stm
elseif @is_value last_exp line = ret stms[i]
line = ret stms[i] if @is_stm line
if @is_stm line @stm line
@stm line else
error "got a value from implicit return"
else else
error "got a value from implicit return" -- nothing we can do with a statement except show it
@stm stm
else else
-- nothing we can do with a statement except show it @stm stm
@stm last_exp
nil nil

View File

@ -201,6 +201,13 @@ value_compile = {
return error("Unknown chain action: " .. t) return error("Unknown chain action: " .. t)
end end
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 local actions
do do
local _with_0 = self:line() local _with_0 = self:line()
@ -213,13 +220,6 @@ value_compile = {
end end
actions = _with_0 actions = _with_0
end 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) return self:line(callee_value, actions)
end, end,
fndef = function(self, node) fndef = function(self, node)
@ -258,7 +258,7 @@ value_compile = {
insert(arg_names, 1, "self") insert(arg_names, 1, "self")
end end
do do
local _with_0 = self:block("function(" .. concat(arg_names, ", ") .. ")") local _with_0 = self:block()
if #whitelist > 0 then if #whitelist > 0 then
_with_0:whitelist_names(whitelist) _with_0:whitelist_names(whitelist)
end end
@ -320,6 +320,25 @@ value_compile = {
}) })
end end
_with_0:ret_stms(block) _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 return _with_0
end end
end, end,

View File

@ -105,6 +105,7 @@ value_compile =
chain_item = (node) -> chain_item = (node) ->
t, arg = unpack node t, arg = unpack node
if t == "call" if t == "call"
-- print arg, util.dump arg
"(", @values(arg), ")" "(", @values(arg), ")"
elseif t == "index" elseif t == "index"
"[", @value(arg), "]" "[", @value(arg), "]"
@ -117,15 +118,15 @@ value_compile =
else else
error "Unknown chain action: "..t 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" if ntype(callee) == "self" and node[3] and ntype(node[3]) == "call"
callee[1] = "self_colon" callee[1] = "self_colon"
callee_value = @name callee callee_value = @value callee
callee_value = @line "(", callee_value, ")" if ntype(callee) == "exp" 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 @line callee_value, actions
fndef: (node) => fndef: (node) =>
@ -147,7 +148,7 @@ value_compile =
if arrow == "fat" if arrow == "fat"
insert arg_names, 1, "self" insert arg_names, 1, "self"
with @block "function("..concat(arg_names, ", ")..")" with @block!
if #whitelist > 0 if #whitelist > 0
\whitelist_names whitelist \whitelist_names whitelist
@ -166,6 +167,11 @@ value_compile =
\stm {"assign", self_args, self_arg_values} if #self_args > 0 \stm {"assign", self_args, self_arg_values} if #self_args > 0
\ret_stms block \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) => table: (node) =>
_, items = unpack node _, items = unpack node

View File

@ -73,7 +73,6 @@ NameProxy = (function(_parent_0)
_base_0.__class = _class_0 _base_0.__class = _class_0
return _class_0 return _class_0
end)() end)()
local Run
Run = (function(_parent_0) Run = (function(_parent_0)
local _base_0 = { local _base_0 = {
call = function(self, state) call = function(self, state)
@ -104,11 +103,18 @@ local constructor_name = "new"
local transformer local transformer
transformer = function(transformers) transformer = function(transformers)
return function(n) return function(n)
transformer = transformers[ntype(n)] while true do
if transformer then transformer = transformers[ntype(n)]
return transformer(n) or n local res
else if transformer then
return n res = transformer(n) or n
else
res = n
end
if res == n then
return n
end
n = res
end end
end end
end end
@ -334,7 +340,7 @@ value = transformer({
table.remove(node, #node) table.remove(node, #node)
local base_name = NameProxy("base") local base_name = NameProxy("base")
local fn_name = NameProxy("fn") local fn_name = NameProxy("fn")
return build.block_exp({ return value(build.block_exp({
build.assign({ build.assign({
names = { names = {
base_name base_name
@ -376,14 +382,24 @@ value = transformer({
}) })
} }
}) })
}) }))
end end
end, end,
block_exp = function(node) block_exp = function(node)
local _, body = unpack(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 body = body
}) }))
return build.chain({ return build.chain({
base = { base = {
"parens", "parens",
@ -391,7 +407,7 @@ value = transformer({
}, },
{ {
"call", "call",
{ } arg_list
} }
}) })
end end

View File

@ -8,7 +8,7 @@ data = require "moonscript.data"
import ntype, build, smart_node from types import ntype, build, smart_node from types
import insert from table import insert from table
export stm, value, NameProxy export stm, value, NameProxy, Run
class NameProxy class NameProxy
new: (@prefix) => new: (@prefix) =>
@ -49,11 +49,14 @@ constructor_name = "new"
transformer = (transformers) -> transformer = (transformers) ->
(n) -> (n) ->
transformer = transformers[ntype n] while true
if transformer transformer = transformers[ntype n]
transformer(n) or n res = if transformer
else transformer(n) or n
n else
n
return n if res == n
n = res
stm = transformer { stm = transformer {
class: (node using nil) -> class: (node using nil) ->
@ -176,7 +179,7 @@ value = transformer {
base_name = NameProxy "base" base_name = NameProxy "base"
fn_name = NameProxy "fn" fn_name = NameProxy "fn"
build.block_exp { value build.block_exp {
build.assign { build.assign {
names: {base_name} names: {base_name}
values: {node} values: {node}
@ -201,7 +204,16 @@ value = transformer {
block_exp: (node) -> block_exp: (node) ->
_, body = unpack 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} }
} }

View File

@ -11,3 +11,6 @@ print fn!
print x\val! print x\val!
-- ... should be bubbled up anon functions
x = hello(...)\world

View File

@ -13,3 +13,10 @@ local fn = (function()
end)() end)()
print(fn()) print(fn())
print(x:val()) print(x:val())
x = (function(...)
local _base_0 = hello(...)
local _fn_0 = _base_0.world
return function(...)
return _fn_0(_base_0, ...)
end
end)(...)