Skip to content
Browse files

table comprehensions support single expression that returns a pair

  • Loading branch information...
1 parent 867989b commit 14db695560a277d06882ecea2e29dbee8b550941 @leafo committed
Showing with 129 additions and 17 deletions.
  1. +13 −1 docs/reference.md
  2. +1 −1 moonscript/parse.lua
  3. +36 −11 moonscript/transform.lua
  4. +16 −4 moonscript/transform.moon
  5. +10 −0 tests/inputs/comprehension.moon
  6. +53 −0 tests/outputs/comprehension.lua
View
14 docs/reference.md
@@ -436,6 +436,18 @@ for a few numbers.
sqrts = {i, math.sqrt i for i in *numbers}
```
+The key-value tuple in a table comprehension can also come from a single
+expression, in which case the expression should return two values. The
+first is used as the key and the second is used as the value:
+
+In this example we convert an array of pairs to a table where the first item in
+the pair is the key and the second is the value.
+
+ ```moon
+ tuples = {{"hello", "world"}, {"foo", "bar"}}
+ tbl = {unpack tuple for tuple in *tuples}
+ ```
+
### Slicing
A special syntax is provided to restrict the items that are iterated over when
@@ -480,7 +492,7 @@ There are two for loop forms, just like in Lua. A numeric one and a generic one:
print key, value
```
-The slicing and `*` operators can be used, just like with table comprehensions:
+The slicing and `*` operators can be used, just like with comprehensions:
```moon
for item in *items[2,4]
View
2 moonscript/parse.lua
@@ -413,7 +413,7 @@ local build_grammar = wrap_env(function()
Comprehension = sym"[" * Exp * CompInner * sym"]" / mark"comprehension",
- TblComprehension = sym"{" * Exp * (sym"," * Exp)^-1 * CompInner * sym"}" / mark"tblcomprehension",
+ 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",
View
47 moonscript/transform.lua
@@ -1231,21 +1231,46 @@ Value = Transformer({
return a:wrap(node)
end,
tblcomprehension = function(self, node)
- local _, key_exp, value_exp, clauses = unpack(node)
+ local _, explist, clauses = unpack(node)
+ local key_exp, value_exp = unpack(explist)
local accum = NameProxy("tbl")
- local dest = build.chain({
- base = accum,
- {
- "index",
- key_exp
+ local inner
+ if value_exp then
+ local dest = build.chain({
+ base = accum,
+ {
+ "index",
+ key_exp
+ }
+ })
+ inner = {
+ build.assign_one(dest, value_exp)
}
- })
- local inner = build.assign_one(dest, value_exp)
+ else
+ local key_name, val_name = NameProxy("key"), NameProxy("val")
+ local dest = build.chain({
+ base = accum,
+ {
+ "index",
+ key_name
+ }
+ })
+ inner = {
+ build.assign({
+ names = {
+ key_name,
+ val_name
+ },
+ values = {
+ key_exp
+ }
+ }),
+ build.assign_one(dest, val_name)
+ }
+ end
return build.block_exp({
build.assign_one(accum, build.table()),
- construct_comprehension({
- inner
- }, clauses),
+ construct_comprehension(inner, clauses),
accum
})
end,
View
20 moonscript/transform.moon
@@ -654,15 +654,27 @@ Value = Transformer {
a\wrap node
tblcomprehension: (node) =>
- _, key_exp, value_exp, clauses = unpack node
+ _, explist, clauses = unpack node
+ key_exp, value_exp = unpack explist
accum = NameProxy "tbl"
- dest = build.chain { base: accum, {"index", key_exp} }
- inner = build.assign_one dest, value_exp
+
+ inner = if value_exp
+ dest = build.chain { base: accum, {"index", key_exp} }
+ { build.assign_one dest, value_exp }
+ else
+ -- If we only have single expression then
+ -- unpack the result into key and value
+ key_name, val_name = NameProxy"key", NameProxy"val"
+ dest = build.chain { base: accum, {"index", key_name} }
+ {
+ build.assign names: {key_name, val_name}, values: {key_exp}
+ build.assign_one dest, val_name
+ }
build.block_exp {
build.assign_one accum, build.table!
- construct_comprehension {inner}, clauses
+ construct_comprehension inner, clauses
accum
}
View
10 tests/inputs/comprehension.moon
@@ -1,4 +1,6 @@
+-- see lists.moon for list comprehension tests
+
items = {1,2,3,4,5,6}
out = {k,k*2 for k in items}
@@ -7,3 +9,11 @@ x = hello: "world", okay: 2323
copy = {k,v for k,v in pairs x when k != "okay"}
+--
+
+{ unpack(x) for x in yes }
+{ unpack(x) for x in *yes }
+
+{ xxxx for x in yes }
+{ unpack [a*i for i, a in ipairs x] for x in *{{1,2}, {3,4}} }
+
View
53 tests/outputs/comprehension.lua
@@ -25,4 +25,57 @@ local copy = (function()
end
end
return _tbl_0
+end)()
+local _ = (function()
+ local _tbl_0 = { }
+ for x in yes do
+ local _key_0, _val_0 = unpack(x)
+ _tbl_0[_key_0] = _val_0
+ end
+ return _tbl_0
+end)()
+_ = (function()
+ local _tbl_0 = { }
+ local _list_0 = yes
+ for _index_0 = 1, #_list_0 do
+ x = _list_0[_index_0]
+ local _key_0, _val_0 = unpack(x)
+ _tbl_0[_key_0] = _val_0
+ end
+ return _tbl_0
+end)()
+_ = (function()
+ local _tbl_0 = { }
+ for x in yes do
+ local _key_0, _val_0 = xxxx
+ _tbl_0[_key_0] = _val_0
+ end
+ return _tbl_0
+end)()
+_ = (function()
+ local _tbl_0 = { }
+ local _list_0 = {
+ {
+ 1,
+ 2
+ },
+ {
+ 3,
+ 4
+ }
+ }
+ for _index_0 = 1, #_list_0 do
+ x = _list_0[_index_0]
+ local _key_0, _val_0 = unpack((function()
+ local _accum_0 = { }
+ local _len_0 = 0
+ for i, a in ipairs(x) do
+ _len_0 = _len_0 + 1
+ _accum_0[_len_0] = a * i
+ end
+ return _accum_0
+ end)())
+ _tbl_0[_key_0] = _val_0
+ end
+ return _tbl_0
end)()

0 comments on commit 14db695

Please sign in to comment.
Something went wrong with that request. Please try again.