add numeric for loop comprehensions/decorator, fixes #45

This commit is contained in:
leaf corcoran 2013-01-12 15:09:17 -08:00
parent c4217982e0
commit 0cf96b97f6
8 changed files with 177 additions and 30 deletions

View File

@ -415,6 +415,12 @@ Using multiple `for` clauses is the same as using nested loops:
points = [{x,y} for x in *x_coords for y in *y_coords]
```
Numeric for loops can also be used in comprehensions:
```moon
evens = [i for i=1,100 when i % 2 == 0]
```
### Table Comprehensions
The syntax for table comprehensions is very similar, only differing by using `{` and

View File

@ -447,9 +447,10 @@ local build_grammar = wrap_env(function()
TblComprehension = sym"{" * Ct(Exp * (sym"," * Exp)^-1) * CompInner * sym"}" / mark"tblcomprehension",
CompInner = Ct(CompFor * CompClause^0),
CompFor = key"for" * Ct(NameList) * key"in" * (sym"*" * Exp / mark"unpack" + Exp) / mark"for",
CompClause = CompFor + key"when" * Exp / mark"when",
CompInner = Ct((CompForEach + CompFor) * CompClause^0),
CompForEach = key"for" * Ct(NameList) * key"in" * (sym"*" * Exp / mark"unpack" + Exp) / mark"foreach",
CompFor = key "for" * Name * sym"=" * Ct(Exp * sym"," * Exp * (sym"," * Exp)^-1) / mark"for",
CompClause = CompFor + CompForEach + key"when" * Exp / mark"when",
Assign = sym"=" * (Ct(With + If + Switch) + Ct(TableBlock + ExpListLow)) / mark"assign",
Update = ((sym"..=" + sym"+=" + sym"-=" + sym"*=" + sym"/=" + sym"%=" + sym"or=" + sym"and=") / trim) * Exp / mark"update",

View File

@ -66,12 +66,16 @@ apply_to_last = function(stms, fn)
local _accum_0 = { }
local _len_0 = 1
for i, stm in ipairs(stms) do
local _value_0
if i == last_exp_id then
_accum_0[_len_0] = fn(stm)
_value_0 = fn(stm)
else
_accum_0[_len_0] = stm
_value_0 = stm
end
if _value_0 ~= nil then
_accum_0[_len_0] = _value_0
_len_0 = _len_0 + 1
end
_len_0 = _len_0 + 1
end
return _accum_0
end)()
@ -291,9 +295,25 @@ construct_comprehension = function(inner, clauses)
local current_stms = inner
for _, clause in reversed(clauses) do
local t = clause[1]
if t == "for" then
local _exp_0 = t
if "for" == _exp_0 then
local name, bounds
do
local _obj_0 = clause
_, name, bounds = _obj_0[1], _obj_0[2], _obj_0[3]
end
current_stms = {
"for",
name,
bounds,
current_stms
}
elseif "foreach" == _exp_0 then
local names, iter
_, names, iter = unpack(clause)
do
local _obj_0 = clause
_, names, iter = _obj_0[1], _obj_0[2], _obj_0[3]
end
current_stms = {
"foreach",
names,
@ -302,9 +322,12 @@ construct_comprehension = function(inner, clauses)
},
current_stms
}
elseif t == "when" then
elseif "when" == _exp_0 then
local cond
_, cond = unpack(clause)
do
local _obj_0 = clause
_, cond = _obj_0[1], _obj_0[2]
end
current_stms = {
"if",
cond,
@ -440,15 +463,19 @@ local Statement = Transformer({
local _list_0 = names
for _index_0 = 1, #_list_0 do
local name = _list_0[_index_0]
local _value_0
if type(name) == "table" then
_accum_0[_len_0] = name
_value_0 = name
else
_accum_0[_len_0] = {
_value_0 = {
"dot",
name
}
end
_len_0 = _len_0 + 1
if _value_0 ~= nil then
_accum_0[_len_0] = _value_0
_len_0 = _len_0 + 1
end
end
return _accum_0
end)()
@ -458,8 +485,11 @@ local Statement = Transformer({
local _list_0 = names
for _index_0 = 1, #_list_0 do
local name = _list_0[_index_0]
_accum_0[_len_0] = type(name) == "table" and name[2] or name
_len_0 = _len_0 + 1
local _value_0 = type(name) == "table" and name[2] or name
if _value_0 ~= nil then
_accum_0[_len_0] = _value_0
_len_0 = _len_0 + 1
end
end
return _accum_0
end)()
@ -681,17 +711,21 @@ local Statement = Transformer({
local _accum_0 = { }
local _len_0 = 1
for i, name in ipairs(node.names) do
local _value_0
if ntype(name) == "table" then
do
local _with_0 = NameProxy("des")
local proxy = _with_0
insert(destructures, destructure.build_assign(name, proxy))
_accum_0[_len_0] = _with_0
_value_0 = _with_0
end
else
_accum_0[_len_0] = name
_value_0 = name
end
if _value_0 ~= nil then
_accum_0[_len_0] = _value_0
_len_0 = _len_0 + 1
end
_len_0 = _len_0 + 1
end
return _accum_0
end)()
@ -872,8 +906,10 @@ local Statement = Transformer({
else
_value_0 = tuple
end
_accum_0[_len_0] = _value_0
_len_0 = _len_0 + 1
if _value_0 ~= nil then
_accum_0[_len_0] = _value_0
_len_0 = _len_0 + 1
end
_continue_0 = true
until true
if not _continue_0 then

View File

@ -140,14 +140,19 @@ construct_comprehension = (inner, clauses) ->
current_stms = inner
for _, clause in reversed clauses
t = clause[1]
current_stms = if t == "for"
_, names, iter = unpack clause
{"foreach", names, {iter}, current_stms}
elseif t == "when"
_, cond = unpack clause
{"if", cond, current_stms}
else
error "Unknown comprehension clause: "..t
current_stms = switch t
when "for"
{_, name, bounds} = clause
{"for", name, bounds, current_stms}
when "foreach"
{_, names, iter} = clause
{"foreach", names, {iter}, current_stms}
when "when"
{_, cond} = clause
{"if", cond, current_stms}
else
error "Unknown comprehension clause: "..t
current_stms = {current_stms}
current_stms[1]

View File

@ -17,3 +17,17 @@ copy = {k,v for k,v in pairs x when k != "okay"}
{ xxxx for x in yes }
{ unpack [a*i for i, a in ipairs x] for x in *{{1,2}, {3,4}} }
--
n1 = [i for i=1,10]
n2 = [i for i=1,10 when i % 2 == 1]
aa = [{x,y} for x=1,10 for y=5,14]
bb = [y for thing in y for i=1,10]
cc = [y for i=1,10 for thing in y]
dd = [y for i=1,10 when cool for thing in y when x > 3 when c + 3]
{"hello", "world" for i=1,10}
nil

View File

@ -104,6 +104,7 @@ x = -[x for x in x]
print "hello" if cool
print "hello" unless cool
print "hello" unless 1212 and 3434 -- hello
print "hello" for i=1,10
print "nutjob"

View File

@ -52,7 +52,7 @@ _ = (function()
end
return _tbl_0
end)()
return (function()
_ = (function()
local _tbl_0 = { }
local _list_0 = {
{
@ -78,4 +78,85 @@ return (function()
_tbl_0[_key_0] = _val_0
end
return _tbl_0
end)()
end)()
local n1 = (function()
local _accum_0 = { }
local _len_0 = 1
for i = 1, 10 do
_accum_0[_len_0] = i
_len_0 = _len_0 + 1
end
return _accum_0
end)()
local n2 = (function()
local _accum_0 = { }
local _len_0 = 1
for i = 1, 10 do
if i % 2 == 1 then
_accum_0[_len_0] = i
_len_0 = _len_0 + 1
end
end
return _accum_0
end)()
local aa = (function()
local _accum_0 = { }
local _len_0 = 1
for x = 1, 10 do
for y = 5, 14 do
_accum_0[_len_0] = {
x,
y
}
_len_0 = _len_0 + 1
end
end
return _accum_0
end)()
local bb = (function()
local _accum_0 = { }
local _len_0 = 1
for thing in y do
for i = 1, 10 do
_accum_0[_len_0] = y
_len_0 = _len_0 + 1
end
end
return _accum_0
end)()
local cc = (function()
local _accum_0 = { }
local _len_0 = 1
for i = 1, 10 do
for thing in y do
_accum_0[_len_0] = y
_len_0 = _len_0 + 1
end
end
return _accum_0
end)()
local dd = (function()
local _accum_0 = { }
local _len_0 = 1
for i = 1, 10 do
if cool then
for thing in y do
if x > 3 then
if c + 3 then
_accum_0[_len_0] = y
_len_0 = _len_0 + 1
end
end
end
end
end
return _accum_0
end)()
_ = (function()
local _tbl_0 = { }
for i = 1, 10 do
_tbl_0["hello"] = "world"
end
return _tbl_0
end)()
return nil

View File

@ -107,6 +107,9 @@ end
if not (1212 and 3434) then
print("hello")
end
for i = 1, 10 do
print("hello")
end
print("nutjob")
if hello then
_ = 343