unpack slices

This commit is contained in:
leaf corcoran 2011-07-13 01:44:08 -07:00
parent daab983550
commit b7813a868b
6 changed files with 78 additions and 169 deletions

View File

@ -38,6 +38,7 @@ has_value = function(node)
end
end
is_non_atomic = function(node) return non_atomic[ntype(node)] end
is_slice = function(node) return ntype(node) == "chain" and ntype(node[#node]) == "slice" end
count_lines = function(str)
local count = 1
for _ in str:gmatch("\n") do

View File

@ -8,7 +8,7 @@ import Set, ntype from data
import concat, insert from table
export indent_char, returner, moonlib, cascading, non_atomic, has_value, is_non_atomic
export count_lines
export count_lines, is_slice
indent_char = " "
@ -41,6 +41,9 @@ has_value = (node) ->
is_non_atomic = (node) ->
non_atomic[ntype(node)]
is_slice = (node) ->
ntype(node) == "chain" and ntype(node[#node]) == "slice"
count_lines = (str) ->
count = 1
count += 1 for _ in str\gmatch "\n"

View File

@ -7,8 +7,6 @@ local reversed = util.reversed
local ntype = data.ntype
local concat, insert = table.concat, table.insert
local constructor_name = "new"
local is_slice
is_slice = function(node) return ntype(node) == "chain" and ntype(node[#node]) == "slice" end
line_compile = {
raw = function(self, node)
local _, text = unpack(node)
@ -28,7 +26,7 @@ line_compile = {
assign = function(self, node)
local _, names, values = unpack(node)
local undeclared = self:declare(names)
local declare = "local " .. (concat(undeclared, ", "))
local declare = "local " .. concat(undeclared, ", ")
if self:is_stm(values) then
if #undeclared > 0 then
self:add(declare)
@ -219,11 +217,40 @@ line_compile = {
foreach = function(self, node)
local _, names, exp, block = unpack(node)
if ntype(exp) == "unpack" then
local iter = exp[2]
local loop
do
local _with_0 = self:block()
local tmp_var = _with_0:init_free_var("item", exp[2])
local items_tmp = _with_0:free_name("item", true)
local bounds
if is_slice(iter) then
local slice = iter[#iter]
table.remove(iter)
table.remove(slice, 1)
if slice[2] and slice[2] ~= "" then
local max_tmp = _with_0:init_free_var("max", slice[2])
slice[2] = {
"exp",
max_tmp,
"<",
0,
"and",
{ "length", items_tmp },
"+",
max_tmp,
"or",
max_tmp
}
else
slice[2] = { "length", items_tmp }
end
bounds = slice
else
print("tmp", items_tmp)
bounds = { 1, { "length", items_tmp } }
end
local index_tmp = _with_0:free_name("index")
_with_0:stm({ "assign", { items_tmp }, { iter } })
block = (function()
local _moon_0 = {}
local _item_0 = block
@ -233,11 +260,11 @@ line_compile = {
end
return _moon_0
end)()
insert(block, 1, { "assign", names, { { "chain", tmp_var, { "index", index_tmp } } } })
insert(block, 1, { "assign", names, { { "chain", items_tmp, { "index", index_tmp } } } })
_with_0:stm({
"for",
index_tmp,
{ 1, { "length", tmp_var } },
bounds,
block
})
loop = _with_0
@ -416,84 +443,6 @@ line_compile = {
end
return self:stm(statement)
end,
xxxx = function(self)
if not action then
local action = self:block()
action:stm(exp)
end
local depth = #clauses
action:set_indent(self.indent + depth)
local render_clause
render_clause = function(self, clause)
local t = clause[1]
local action = self:block()
action:set_indent(self.indent - 1)
if "for" == t then
local _, names, iter = unpack(clause)
local name_list = concat((function()
local _moon_0 = {}
local _item_0 = names
for _index_0=1,#_item_0 do
local name = _item_0[_index_0]
table.insert(_moon_0, self:name(name))
end
return _moon_0
end)(), ", ")
if ntype(iter) == "unpack" then
iter = iter[2]
local items_tmp = action:free_name("item")
local index_tmp = action:free_name("index")
local max_tmp = nil
insert(self._lines, 1, ("local %s = %s[%s]"):format(name_list, items_tmp, index_tmp))
local min, max, skip = 1, ("#%s"):format(items_tmp, nil)
if is_slice(iter) then
local slice = iter[#iter]
table.remove(iter)
min = action:value(slice[2])
if slice[3] and slice[3] ~= "" then
max_tmp = action:free_name("max", true)
action:stm({ "assign", { max_tmp }, { slice[3] } })
max = action:value({
"exp",
max_tmp,
"<",
0,
"and",
{
"exp",
{ "length", items_tmp },
"+",
max_tmp
},
"or",
max_tmp
})
end
if slice[4] then
skip = action:value(slice[4])
end
end
return action:add_lines({
("local %s = %s"):format(items_tmp, action:value(iter)),
("for %s=%s do"):format(index_tmp, concat({ min, max, skip }, ",")),
self:render(true),
"end"
})
else
return action:add_lines({ ("for %s in %s do"):format(name_list, action:value(iter)), self:render(true), "end" })
end
elseif "when" == t then
local _, cond = unpack(clause)
return action:add_lines({ ("if %s then"):format(self:value(cond)), self:render(true), "end" })
else
return error("Unknown comprehension clause: " .. t)
end
end
for i, clause in reversed(clauses) do
render_clause(action, clause)
end
return self:add_lines(action._lines)
end,
with = function(self, node, ret)
local _, exp, block = unpack(node)
do

View File

@ -14,9 +14,6 @@ export line_compile
constructor_name = "new"
is_slice = (node) ->
ntype(node) == "chain" and ntype(node[#node]) == "slice"
line_compile =
raw: (node) =>
_, text = unpack node
@ -33,7 +30,7 @@ line_compile =
_, names, values = unpack node
undeclared = @declare names
declare = "local "..(concat undeclared, ", ")
declare = "local "..concat(undeclared, ", ")
if @is_stm values
@add declare if #undeclared > 0
@ -154,16 +151,38 @@ line_compile =
_, names, exp, block = unpack node
if ntype(exp) == "unpack"
iter = exp[2]
loop = with @block!
tmp_var = \init_free_var "item", exp[2]
items_tmp = \free_name "item", true
-- handle unpacked slices directly
bounds = if is_slice iter
slice = iter[#iter]
table.remove iter
table.remove slice, 1
slice[2] = if slice[2] and slice[2] != ""
max_tmp = \init_free_var "max", slice[2]
{"exp", max_tmp, "<", 0
"and", {"length", items_tmp}, "+", max_tmp
"or", max_tmp }
else
{"length", items_tmp}
slice
else
print "tmp", items_tmp
{1, {"length", items_tmp}}
index_tmp = \free_name "index"
\stm {"assign", {items_tmp}, {iter}}
block = [s for s in *block]
insert block, 1, {"assign", names, {
{"chain", tmp_var, {"index", index_tmp}}
{"chain", items_tmp, {"index", index_tmp}}
}}
\stm {"for", index_tmp, {1, {"length", tmp_var}}, block }
\stm {"for", index_tmp, bounds, block }
return loop
@ -300,73 +319,6 @@ line_compile =
build_clause clause for i, clause in reversed clauses
@stm statement
xxxx: =>
-- kill me
if not action
action = @block!
action\stm exp
depth = #clauses
action\set_indent @indent + depth
render_clause = (clause) =>
t = clause[1]
action = @block!
action\set_indent @indent - 1
if "for" == t
_, names, iter = unpack clause
name_list = concat [@name name for name in *names], ", "
if ntype(iter) == "unpack"
iter = iter[2]
items_tmp = action\free_name "item"
index_tmp = action\free_name "index"
max_tmp = nil
insert self._lines, 1, ("local %s = %s[%s]")\format name_list, items_tmp, index_tmp
-- slice shortcut
min, max, skip = 1, ("#%s")\format items_tmp, nil
if is_slice iter
slice = iter[#iter]
table.remove iter
min = action\value slice[2]
if slice[3] and slice[3] != ""
max_tmp = action\free_name "max", true
action\stm {"assign", {max_tmp}, {slice[3]}}
max = action\value {"exp", max_tmp, "<", 0
"and", {"exp", {"length", items_tmp}, "+", max_tmp}
"or", max_tmp
}
if slice[4]
skip = action\value slice[4]
action\add_lines {
("local %s = %s")\format items_tmp, action\value iter
("for %s=%s do")\format index_tmp, concat {min, max, skip}, ","
@render true
"end"
}
else
action\add_lines {
("for %s in %s do")\format name_list, action\value iter
@render true
"end"
}
elseif "when" == t
_, cond = unpack clause
action\add_lines {
("if %s then")\format @value cond
@render true
"end"
}
else
error "Unknown comprehension clause: "..t
render_clause action, clause for i, clause in reversed clauses
@add_lines action._lines -- do this better?
with: (node, ret) =>
_, exp, block = unpack node

View File

@ -14,15 +14,19 @@ value_compile = {
end
return self:value(value)
end
return concat((function()
local _moon_0 = {}
for i, v in ipairs(node) do
if i > 1 then
table.insert(_moon_0, _comp(i, v))
do
local _with_0 = self:line()
_with_0:append_list((function()
local _moon_0 = {}
for i, v in ipairs(node) do
if i > 1 then
table.insert(_moon_0, _comp(i, v))
end
end
end
return _moon_0
end)(), " ")
return _moon_0
end)(), " ")
return _with_0
end
end,
update = function(self, node)
local _, name = unpack(node)

View File

@ -19,8 +19,8 @@ value_compile =
value = "~="
@value value
-- ugly
concat [_comp i,v for i,v in ipairs node when i > 1], " "
with @line!
\append_list [_comp i,v for i,v in ipairs node when i > 1], " "
update: (node) =>
_, name = unpack node