comprehension decorator, non return value compile for comprehension

This commit is contained in:
leaf corcoran 2011-05-29 14:40:40 -07:00
parent 6cd61d336c
commit d8ff74ccba
6 changed files with 105 additions and 41 deletions

View File

@ -43,8 +43,14 @@ local moonlib = {
end end
} }
-- these are always expressions, never statements, must be sent into temp variable
local must_return = data.Set{ 'parens', 'exp', 'value', 'string', 'table', 'fndef' } local must_return = data.Set{ 'parens', 'exp', 'value', 'string', 'table', 'fndef' }
-- make sure there are no block levels statements in expression
local function validate_expression(block)
-- need to annotate blocks? how do I know where expressions are
end
local compiler_index = { local compiler_index = {
push = function(self) self._scope:push{} end, push = function(self) self._scope:push{} end,
pop = function(self) self._scope:pop() end, pop = function(self) self._scope:pop() end,
@ -264,25 +270,29 @@ local compiler_index = {
return table.concat(self:values(node), ", ") return table.concat(self:values(node), ", ")
end, end,
comprehension = function(self, node) -- need to get tmp name instead of using tmp
comprehension = function(self, node, return_value)
local _, exp, clauses = unpack(node) local _, exp, clauses = unpack(node)
local insert = { ("table.insert(tmp, %s)"):format(self:value(exp)) }
local action = return_value
and { ("table.insert(tmp, %s)"):format(self:value(exp)) }
or { self:stm(exp) }
for i = #clauses,1,-1 do for i = #clauses,1,-1 do
local c = clauses[i] local c = clauses[i]
if "for" == c[1] then if "for" == c[1] then
local _, names, iter = unpack(c) local _, names, iter = unpack(c)
insert = { action = {
("for %s in %s do"):format(self:name_list(names), self:value(iter)), ("for %s in %s do"):format(self:name_list(names), self:value(iter)),
insert, action,
"end" "end"
} }
elseif "when" == c[1] then elseif "when" == c[1] then
local _, when = unpack(c) local _, when = unpack(c)
insert = { action = {
("if %s then"):format(self:value(when)), ("if %s then"):format(self:value(when)),
insert, action,
"end" "end"
} }
else else
@ -290,13 +300,17 @@ local compiler_index = {
end end
end end
if return_value then
return self:pretty{ return self:pretty{
"(function()", "(function()",
{ "local tmp = {}", }, { "local tmp = {}", },
insert, action,
{ "return tmp" }, { "return tmp" },
"end)()" "end)()"
} }
else
return self:pretty(action)
end
end, end,
-- returns list of compiled statements -- returns list of compiled statements
@ -430,7 +444,7 @@ local compiler_index = {
return delim..inner..(delim_end or delim) return delim..inner..(delim_end or delim)
end, end,
value = function(self, node, ...) value = function(self, node, return_value, ...)
if return_value == nil then return_value = true end if return_value == nil then return_value = true end
if type(node) == "table" then if type(node) == "table" then
@ -438,7 +452,7 @@ local compiler_index = {
if not fn then if not fn then
error("Unknown op: "..tostring(node[1])) error("Unknown op: "..tostring(node[1]))
end end
return fn(self, node, ...) return fn(self, node, return_value, ...)
end end
return node return node

View File

@ -191,6 +191,23 @@ local build_grammar = wrap(function()
return stm return stm
end end
local function wrap_decorator(stm, dec)
if not dec then return stm end
local arg = {stm, dec}
if dec[1] == "if" then
local _, cond, fail = unpack(dec)
if fail then fail = {"else", {fail}} end
stm = {"if", cond, {stm}, fail}
elseif dec[1] == "comprehension" then
local _, clauses = unpack(dec)
stm = {"comprehension", stm, clauses}
end
return stm
end
local function check_lua_string(str, pos, right, left) local function check_lua_string(str, pos, right, left)
return #left == #right return #left == #right
end end
@ -201,8 +218,11 @@ local build_grammar = wrap(function()
Block = Ct(Line * (Break^1 * Line)^0), Block = Ct(Line * (Break^1 * Line)^0),
Line = Cmt(Indent, check_indent) * Statement + _Space * Comment, Line = Cmt(Indent, check_indent) * Statement + _Space * Comment,
Statement = (Import + If + While + Exp * Space) * Statement = (Import + If + While + Exp * Space) * (
(key"if" * Exp * (key"else" * Exp)^-1 * Space / mark"if")^-1 / wrap_if, -- statement decorators
key"if" * Exp * (key"else" * Exp)^-1 * Space / mark"if" +
CompInner / mark"comprehension"
)^-1 / wrap_decorator,
Body = Break * InBlock + Ct(Statement), Body = Break * InBlock + Ct(Statement),
@ -225,7 +245,9 @@ local build_grammar = wrap(function()
Ct((key"for" * Ct(NameList) * key"in" * Exp / mark"for") * CompClause^0) * Ct((key"for" * Ct(NameList) * key"in" * Exp / mark"for") * CompClause^0) *
sym"]" / mark"comprehension", sym"]" / mark"comprehension",
CompClause = key"for" * Ct(NameList) * key"in" * Exp / mark"for" + key"when" * Exp / mark"when", CompInner = Ct(CompFor * CompClause^0),
CompFor = key"for" * Ct(NameList) * key"in" * Exp / mark"for",
CompClause = CompFor + key"when" * Exp / mark"when",
Assign = Ct(AssignableList) * sym"=" * Ct(TableBlock + ExpList) / mark"assign", Assign = Ct(AssignableList) * sym"=" * Ct(TableBlock + ExpList) / mark"assign",

View File

@ -30,3 +30,12 @@ dump [{x, y} for x in range 5 when x > 2 for y in range 5]
things = [x + y for x in range 10 when x > 5 for y in range 10 when y > 7] things = [x + y for x in range 10 when x > 5 for y in range 10 when y > 7]
print x,y for x in ipairs{1,2,4} for y in ipairs{1,2,3} when x != 2
print "hello", x for x in items
[x for x in x]
x = [x for x in x]
print x,y for x in ipairs{1,2,4} for y in ipairs{1,2,3} when x != 2

View File

@ -131,3 +131,5 @@ y = not(5+5)
y = #"hello" y = #"hello"
x = #{#{},#{1},#{1,2}} x = #{#{},#{1},#{1,2}}

View File

@ -24,16 +24,12 @@ local mm = (function()
table.insert(tmp, self.x) table.insert(tmp, self.x)
end end
return tmp return tmp
end)(); end)()
(function()
local tmp = {}
for z in ipairs(items) do for z in ipairs(items) do
if z > 4 then if z > 4 then
table.insert(tmp, z) local _ = z
end end
end end
return tmp
end)()
local rad = (function() local rad = (function()
local tmp = {} local tmp = {}
for a in ipairs({ for a in ipairs({
@ -49,18 +45,14 @@ local rad = (function()
end end
end end
return tmp return tmp
end)(); end)()
(function()
local tmp = {}
for z in items do for z in items do
for j in list do for j in list do
if z > 4 then if z > 4 then
table.insert(tmp, z) _ = z
end end
end end
end end
return tmp
end)()
require("util") require("util")
local dump = function(x) print(util.dump(x)) end local dump = function(x) print(util.dump(x)) end
local range = function(count) local range = function(count)
@ -103,3 +95,30 @@ local things = (function()
end end
return tmp return tmp
end)() end)()
for x in ipairs({ 1, 2, 4 }) do
for y in ipairs({ 1, 2, 3 }) do
if x ~= 2 then
print(x, y)
end
end
end
for x in items do
print("hello", x)
end
for x in x do
_ = x
end
local x = (function()
local tmp = {}
for x in x do
table.insert(tmp, x)
end
return tmp
end)()
for x in ipairs({ 1, 2, 4 }) do
for y in ipairs({ 1, 2, 3 }) do
if x ~= 2 then
print(x, y)
end
end
end

View File

@ -71,8 +71,6 @@ x = -(function()
end)() end)()
if cool then if cool then
print("hello") print("hello")
else
_ = cool
end end
print("nutjob") print("nutjob")
if hello then if hello then
@ -81,7 +79,7 @@ end
if cool then if cool then
print("what") print("what")
else else
_ = cool _ = whack
end end
local arg = { ... } local arg = { ... }
x = function(...) dump({ ... }) end x = function(...) dump({ ... }) end