list comprehension, self operator, all binary ops

This commit is contained in:
leaf corcoran 2011-05-27 21:27:59 -07:00
parent 08c3eee854
commit 1f821c19d4
4 changed files with 143 additions and 37 deletions

View File

@ -37,6 +37,20 @@ local compiler_index = {
self._indent = self._indent + amount self._indent = self._indent + amount
end, end,
pretty = function(self, tbl)
local out = {}
for _, line in ipairs(tbl) do
if type(line) == "table" then
self:indent(1)
table.insert(out, indent_char..self:pretty(line))
self:indent(-1)
else
table.insert(out, line)
end
end
return table.concat(out, "\n"..self:ichar())
end,
has_name = function(self, name) has_name = function(self, name)
for i = #self._scope,1,-1 do for i = #self._scope,1,-1 do
if self._scope[i][name] then return true end if self._scope[i][name] then return true end
@ -110,10 +124,13 @@ local compiler_index = {
local to_bind = {} local to_bind = {}
local final_names = {} local final_names = {}
for _, name in ipairs(names) do for _, name in ipairs(names) do
if type(name) == "table" then if ntype(name) == ":" then
name = name[2] name = self:value(name[2])
to_bind[name] = true to_bind[name] = true
else
name = self:value(name)
end end
table.insert(final_names, name) table.insert(final_names, name)
self:put_name(name) self:put_name(name)
end end
@ -211,6 +228,33 @@ local compiler_index = {
return ("while %s do\n%s\n%send"):format(self:value(cond), self:block(block, 1), ichr) return ("while %s do\n%s\n%send"):format(self:value(cond), self:block(block, 1), ichr)
end, end,
name_list = function(self, node)
return table.concat(self:values(node), ", ")
end,
comprehension = function(self, node)
local _, exp, names, iter, when = unpack(node)
local insert = ("table.insert(tmp, %s)"):format(self:value(exp))
if when then
insert = {
("if %s then"):format(self:value(when)), {
insert
}, "end"
}
end
return self:pretty{
"(function()", {
"local tmp = {}",
("for %s in %s do"):format(self:name_list(names), self:value(iter)),
type(insert) == "table" and insert or {insert},
"end",
"return tmp"
}, "end)()"
}
end,
block = function(self, node, inc) block = function(self, node, inc)
self:push() self:push()
if inc then self:indent(inc) end if inc then self:indent(inc) end
@ -302,6 +346,9 @@ local compiler_index = {
exp = function(self, node) exp = function(self, node)
local values = {} local values = {}
for i = 2, #node do for i = 2, #node do
if i % 2 == 1 and node[i] == "!=" then
node[i] = "~="
end
table.insert(values, self:value(node[i])) table.insert(values, self:value(node[i]))
end end
return table.concat(values, " ") return table.concat(values, " ")
@ -329,6 +376,11 @@ local compiler_index = {
return node return node
end, end,
self = function(self, node)
local _, val = unpack(node)
return "self."..self:value(val)
end,
-- a list of values -- a list of values
values = function(self, items, start) values = function(self, items, start)
start = start or 1 start = start or 1

View File

@ -124,6 +124,14 @@ local build_grammar = wrap(function()
return Space * word return Space * word
end end
local function op(word)
if word:match("^%w*$") then
keywords[word] = true
end
return Space * C(word)
end
local function sym(chars) local function sym(chars)
return Space * chars return Space * chars
end end
@ -160,6 +168,8 @@ local build_grammar = wrap(function()
return false return false
end end
local Name = sym"@" * Name / mark"self" + Name
-- make sure name is not a keyword -- make sure name is not a keyword
local Name = Cmt(Name, function(str, pos, name) local Name = Cmt(Name, function(str, pos, name)
if keywords[name] then return false end if keywords[name] then return false end
@ -187,7 +197,7 @@ local build_grammar = wrap(function()
OutBlock = Cmt("", pop_indent), OutBlock = Cmt("", pop_indent),
Import = key"import"* Ct(ImportNameList) * key"from" * Exp / mark"import", Import = key"import"* Ct(ImportNameList) * key"from" * Exp / mark"import",
ImportName = (Ct(C(sym":") * Name) + Name), ImportName = (Ct(sym":" / trim * Name) + Name),
ImportNameList = ImportName * (sym"," * ImportName)^0, ImportNameList = ImportName * (sym"," * ImportName)^0,
NameList = Name * (sym"," * Name)^0, NameList = Name * (sym"," * Name)^0,
@ -198,14 +208,24 @@ local build_grammar = wrap(function()
While = key"while" * Exp * key"do"^-1 * Body / mark"while", While = key"while" * Exp * key"do"^-1 * Body / mark"while",
Comprehension = sym"[" * Exp * key"for" * Ct(NameList) *
key"in" * Exp *
(key"when" * Exp)^-1 *
sym"]" / mark"comprehension",
Assign = Ct(AssignableList) * sym"=" * Ct(TableBlock + ExpList) / mark"assign", Assign = Ct(AssignableList) * sym"=" * Ct(TableBlock + ExpList) / mark"assign",
-- we can ignore precedence for now
OtherOps = op"or" + op"and" + op"<=" + op">=" + op"~=" + op"!=" + op"==" + op".." + op"<" + op">",
Assignable = Cmt(Chain, check_assignable) + Name, Assignable = Cmt(Chain, check_assignable) + Name,
AssignableList = Assignable * (sym"," * Assignable)^0, AssignableList = Assignable * (sym"," * Assignable)^0,
Exp = Ct(Term * (FactorOp * Term)^0) / flatten_or_mark"exp", Exp = Ct(Factor * (OtherOps * Factor)^0) / flatten_or_mark"exp",
Factor = Ct(Term * (FactorOp * Term)^0) / flatten_or_mark"exp",
Term = Ct(Value * (TermOp * Value)^0) / flatten_or_mark"exp", Term = Ct(Value * (TermOp * Value)^0) / flatten_or_mark"exp",
Value = TableLit + Value = TableLit +
Comprehension +
ColonChain + ColonChain +
Ct(KeyValueList) / mark"table" + Ct(KeyValueList) / mark"table" +
Assign + FunLit + String + Assign + FunLit + String +
@ -297,48 +317,17 @@ local build_grammar = wrap(function()
end) end)
local grammar = build_grammar()
-- parse a string -- parse a string
-- returns tree, or nil and error message -- returns tree, or nil and error message
function string(str) function string(str)
local g = build_grammar() local g = build_grammar()
return grammar:match(str) return g:match(str)
end end
local program = [[
if two_dads
do something
if yum
heckyes 23
print 2
print dadas
{1,2,3,4}
(a,b) ->
throw nuts
print 100
]]
local program = [[
hi = (a) -> print a
if true
hi 100
]]
local program3 = [[ local program3 = [[
-- hello -- hello
class Hello class Hello
@something = 2323 @something: 2323
hello: () -> hello: () ->
print 200 print 200

13
tests/inputs/lists.moon Normal file
View File

@ -0,0 +1,13 @@
hi = [x*2 for _, x in ipairs{1,2,3,4}]
items = {1,2,3,4,5,6}
mm = [@x for @x in ipairs items]
[z for z in ipairs items when z > 4]
rad = [{a} for a in ipairs {
1,2,3,4,5,6,
} when good_number a]

52
tests/outputs/lists.lua Normal file
View File

@ -0,0 +1,52 @@
local hi = (function()
local tmp = {}
for _, x in ipairs({
1,
2,
3,
4
}) do
table.insert(tmp, x * 2)
end
return tmp
end)()
local items = {
1,
2,
3,
4,
5,
6
}
local mm = (function()
local tmp = {}
for self.x in ipairs(items) do
table.insert(tmp, self.x)
end
return tmp
end)();
(function()
local tmp = {}
for z in ipairs(items) do
if z > 4 then
table.insert(tmp, z)
end
end
return tmp
end)()
local rad = (function()
local tmp = {}
for a in ipairs({
1,
2,
3,
4,
5,
6
}) do
if good_number(a) then
table.insert(tmp, { a })
end
end
return tmp
end)()