mirror of
https://github.com/leafo/moonscript.git
synced 2024-11-22 02:44:23 +00:00
added key,value table comprehensions
This commit is contained in:
parent
652e59c96c
commit
636c24258f
@ -281,10 +281,16 @@ same as the variable names, then the `:` prefix operator can be used:
|
|||||||
|
|
||||||
print_table :hair, :height
|
print_table :hair, :height
|
||||||
|
|
||||||
## Table Comprehensions
|
## Comprehensions
|
||||||
|
|
||||||
Table comprehensions provide a quick way to iterate over a table's values while
|
Compiling provide a convenient syntax for constructing a new table by iterating
|
||||||
applying a statement and accumulating the result.
|
over some existing object and applying an expression to its values. There are
|
||||||
|
two kinds of comprehensions: list comprehensions and table comprehensions. They
|
||||||
|
both produce Lua tables; _list comprehensions_ accumulate values into an
|
||||||
|
array-like table, and _table comprehensions_ let you set both the key and the
|
||||||
|
value on each iteration.
|
||||||
|
|
||||||
|
### List Comprehensions
|
||||||
|
|
||||||
The following creates a copy of the `items` table but with all the values
|
The following creates a copy of the `items` table but with all the values
|
||||||
doubled.
|
doubled.
|
||||||
@ -312,6 +318,33 @@ Using multiple `for` clauses is the same as using nested loops:
|
|||||||
|
|
||||||
points = [{x,y} for x in *x_coords for y in *y_coords]
|
points = [{x,y} for x in *x_coords for y in *y_coords]
|
||||||
|
|
||||||
|
### Table Comprehensions
|
||||||
|
|
||||||
|
The syntax for table comprehensions is very similar, differing by using `{` and
|
||||||
|
`}` and taking two values from each iteration.
|
||||||
|
|
||||||
|
This example copies the key-value table `thing`:
|
||||||
|
|
||||||
|
thing = {
|
||||||
|
color: "red"
|
||||||
|
name: "fast"
|
||||||
|
width: 123
|
||||||
|
}
|
||||||
|
|
||||||
|
thing_copy = {k,v for k,v in pairs thing}
|
||||||
|
|
||||||
|
Table comprehensions, like list comprehensions, also support multiple `for` and
|
||||||
|
`when` clauses`. In this example we use a `where` clause to prevent the value
|
||||||
|
associated with the `color` key from being copied.
|
||||||
|
|
||||||
|
no_color = {k,v for k,v in pairs thing when k != "color"}
|
||||||
|
|
||||||
|
The `*` operator is also supported. Here we create a square root look up table
|
||||||
|
for a few numbers.
|
||||||
|
|
||||||
|
numbers = {1,2,3,4}
|
||||||
|
sqrts = {i, math.sqrt i for i in *numbers}
|
||||||
|
|
||||||
### Slicing
|
### Slicing
|
||||||
|
|
||||||
A special syntax is provided to restrict the items that are iterated over when
|
A special syntax is provided to restrict the items that are iterated over when
|
||||||
|
@ -206,6 +206,35 @@ Transformer = (function()
|
|||||||
_base_0.__class = _class_0
|
_base_0.__class = _class_0
|
||||||
return _class_0
|
return _class_0
|
||||||
end)()
|
end)()
|
||||||
|
local construct_comprehension
|
||||||
|
construct_comprehension = function(inner, clauses)
|
||||||
|
local current_stms = inner
|
||||||
|
for _, clause in reversed(clauses) do
|
||||||
|
local t = clause[1]
|
||||||
|
if t == "for" then
|
||||||
|
local _, names, iter = unpack(clause)
|
||||||
|
current_stms = {
|
||||||
|
"foreach",
|
||||||
|
names,
|
||||||
|
iter,
|
||||||
|
current_stms
|
||||||
|
}
|
||||||
|
elseif t == "when" then
|
||||||
|
local _, cond = unpack(clause)
|
||||||
|
current_stms = {
|
||||||
|
"if",
|
||||||
|
cond,
|
||||||
|
current_stms
|
||||||
|
}
|
||||||
|
else
|
||||||
|
current_stms = error("Unknown comprehension clause: " .. t)
|
||||||
|
end
|
||||||
|
current_stms = {
|
||||||
|
current_stms
|
||||||
|
}
|
||||||
|
end
|
||||||
|
return current_stms[1]
|
||||||
|
end
|
||||||
Statement = Transformer({
|
Statement = Transformer({
|
||||||
assign = function(self, node)
|
assign = function(self, node)
|
||||||
local _, names, values = unpack(node)
|
local _, names, values = unpack(node)
|
||||||
@ -367,34 +396,7 @@ Statement = Transformer({
|
|||||||
exp
|
exp
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
local current_stms = action(exp)
|
return construct_comprehension(action(exp), clauses)
|
||||||
for _, clause in reversed(clauses) do
|
|
||||||
local t = clause[1]
|
|
||||||
if t == "for" then
|
|
||||||
local names, iter
|
|
||||||
_, names, iter = unpack(clause)
|
|
||||||
current_stms = {
|
|
||||||
"foreach",
|
|
||||||
names,
|
|
||||||
iter,
|
|
||||||
current_stms
|
|
||||||
}
|
|
||||||
elseif t == "when" then
|
|
||||||
local cond
|
|
||||||
_, cond = unpack(clause)
|
|
||||||
current_stms = {
|
|
||||||
"if",
|
|
||||||
cond,
|
|
||||||
current_stms
|
|
||||||
}
|
|
||||||
else
|
|
||||||
current_stms = error("Unknown comprehension clause: " .. t)
|
|
||||||
end
|
|
||||||
current_stms = {
|
|
||||||
current_stms
|
|
||||||
}
|
|
||||||
end
|
|
||||||
return current_stms[1]
|
|
||||||
end,
|
end,
|
||||||
["if"] = function(self, node, ret)
|
["if"] = function(self, node, ret)
|
||||||
if ret then
|
if ret then
|
||||||
@ -820,6 +822,25 @@ Value = Transformer({
|
|||||||
end)
|
end)
|
||||||
return a:wrap(node)
|
return a:wrap(node)
|
||||||
end,
|
end,
|
||||||
|
tblcomprehension = function(self, node)
|
||||||
|
local _, key_exp, value_exp, clauses = unpack(node)
|
||||||
|
local accum = NameProxy("tbl")
|
||||||
|
local dest = build.chain({
|
||||||
|
base = accum,
|
||||||
|
{
|
||||||
|
"index",
|
||||||
|
key_exp
|
||||||
|
}
|
||||||
|
})
|
||||||
|
local inner = build.assign_one(dest, value_exp)
|
||||||
|
return build.block_exp({
|
||||||
|
build.assign_one(accum, build.table()),
|
||||||
|
construct_comprehension({
|
||||||
|
inner
|
||||||
|
}, clauses),
|
||||||
|
accum
|
||||||
|
})
|
||||||
|
end,
|
||||||
fndef = function(self, node)
|
fndef = function(self, node)
|
||||||
smart_node(node)
|
smart_node(node)
|
||||||
node.body = apply_to_last(node.body, implicitly_return(self))
|
node.body = apply_to_last(node.body, implicitly_return(self))
|
||||||
|
@ -108,6 +108,22 @@ class Transformer
|
|||||||
can_transform: (node) =>
|
can_transform: (node) =>
|
||||||
@transformers[ntype node] != nil
|
@transformers[ntype node] != nil
|
||||||
|
|
||||||
|
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 = {current_stms}
|
||||||
|
|
||||||
|
current_stms[1]
|
||||||
|
|
||||||
Statement = Transformer {
|
Statement = Transformer {
|
||||||
assign: (node) =>
|
assign: (node) =>
|
||||||
_, names, values = unpack node
|
_, names, values = unpack node
|
||||||
@ -185,23 +201,8 @@ Statement = Transformer {
|
|||||||
|
|
||||||
comprehension: (node, action) =>
|
comprehension: (node, action) =>
|
||||||
_, exp, clauses = unpack node
|
_, exp, clauses = unpack node
|
||||||
|
|
||||||
action = action or (exp) -> {exp}
|
action = action or (exp) -> {exp}
|
||||||
|
construct_comprehension action(exp), clauses
|
||||||
current_stms = action exp
|
|
||||||
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 = {current_stms}
|
|
||||||
|
|
||||||
current_stms[1]
|
|
||||||
|
|
||||||
-- handle cascading return decorator
|
-- handle cascading return decorator
|
||||||
if: (node, ret) =>
|
if: (node, ret) =>
|
||||||
@ -428,6 +429,7 @@ class Accumulator
|
|||||||
default_accumulator = (node) =>
|
default_accumulator = (node) =>
|
||||||
Accumulator!\convert node
|
Accumulator!\convert node
|
||||||
|
|
||||||
|
|
||||||
implicitly_return = (scope) ->
|
implicitly_return = (scope) ->
|
||||||
fn = (stm) ->
|
fn = (stm) ->
|
||||||
t = ntype stm
|
t = ntype stm
|
||||||
@ -451,6 +453,19 @@ Value = Transformer {
|
|||||||
a\mutate_body {exp}, false
|
a\mutate_body {exp}, false
|
||||||
a\wrap node
|
a\wrap node
|
||||||
|
|
||||||
|
tblcomprehension: (node) =>
|
||||||
|
_, key_exp, value_exp, clauses = unpack node
|
||||||
|
|
||||||
|
accum = NameProxy "tbl"
|
||||||
|
dest = build.chain { base: accum, {"index", key_exp} }
|
||||||
|
inner = build.assign_one dest, value_exp
|
||||||
|
|
||||||
|
build.block_exp {
|
||||||
|
build.assign_one accum, build.table!
|
||||||
|
construct_comprehension {inner}, clauses
|
||||||
|
accum
|
||||||
|
}
|
||||||
|
|
||||||
fndef: (node) =>
|
fndef: (node) =>
|
||||||
smart_node node
|
smart_node node
|
||||||
node.body = apply_to_last node.body, implicitly_return self
|
node.body = apply_to_last node.body, implicitly_return self
|
||||||
|
@ -173,6 +173,9 @@ build = setmetatable({
|
|||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
table = function(tbl)
|
table = function(tbl)
|
||||||
|
if tbl == nil then
|
||||||
|
tbl = { }
|
||||||
|
end
|
||||||
return {
|
return {
|
||||||
"table",
|
"table",
|
||||||
tbl
|
tbl
|
||||||
|
@ -94,7 +94,7 @@ build = setmetatable {
|
|||||||
names: {name}
|
names: {name}
|
||||||
values: {value}
|
values: {value}
|
||||||
}
|
}
|
||||||
table: (tbl) ->
|
table: (tbl={}) ->
|
||||||
{"table", tbl}
|
{"table", tbl}
|
||||||
block_exp: (body) ->
|
block_exp: (body) ->
|
||||||
{"block_exp", body}
|
{"block_exp", body}
|
||||||
|
9
tests/inputs/comprehension.moon
Normal file
9
tests/inputs/comprehension.moon
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
items = {1,2,3,4,5,6}
|
||||||
|
out = {k,k*2 for k in items}
|
||||||
|
|
||||||
|
|
||||||
|
x = hello: "world", okay: 2323
|
||||||
|
|
||||||
|
copy = {k,v for k,v in pairs x when k != "okay"}
|
||||||
|
|
28
tests/outputs/comprehension.lua
Normal file
28
tests/outputs/comprehension.lua
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
local items = {
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6
|
||||||
|
}
|
||||||
|
local out = (function()
|
||||||
|
local _tbl_0 = { }
|
||||||
|
for k in items do
|
||||||
|
_tbl_0[k] = k * 2
|
||||||
|
end
|
||||||
|
return _tbl_0
|
||||||
|
end)()
|
||||||
|
local x = {
|
||||||
|
hello = "world",
|
||||||
|
okay = 2323
|
||||||
|
}
|
||||||
|
local copy = (function()
|
||||||
|
local _tbl_0 = { }
|
||||||
|
for k, v in pairs(x) do
|
||||||
|
if k ~= "okay" then
|
||||||
|
_tbl_0[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return _tbl_0
|
||||||
|
end)()
|
Loading…
Reference in New Issue
Block a user