Skip to content

Commit 8fd0bee

Browse files
committed
New syntax for container comprehensions
1 parent 41391f5 commit 8fd0bee

File tree

87 files changed

+145
-108
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+145
-108
lines changed

docs/manual.md

+4-4

docs/why-pyxell.md

+6

lib/std.px

+7-7
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ func String_any(s: String, f: Char->Bool): Bool def
4444
return false
4545

4646
func String_filter(s: String, f: Char->Bool): String def
47-
return [c for c in s if f(c)].join()
47+
return [for c in s if f(c) yield c].join()
4848

4949
func String_map(s: String, f: Char->Char): String def
50-
return [f(c) for c in s].join()
50+
return [for c in s yield f(c)].join()
5151

5252
func String_fold<B>(s: String, f: Char->B->B, r: B): B def
5353
for c in s do
@@ -79,10 +79,10 @@ func Array_any<A>(a: [A], f: A->Bool = _): Bool def
7979
return false
8080

8181
func Array_filter<A>(a: [A], f: A->Bool): [A] def
82-
return [x for x in a if f(x)]
82+
return [for x in a if f(x) yield x]
8383

8484
func Array_map<A,B>(a: [A], f: A->B): [B] def
85-
return [f(x) for x in a]
85+
return [for x in a yield f(x)]
8686

8787
func Array_fold<A,B>(a: [A], f: A->B->B, r: B): B def
8888
for x in a do
@@ -114,10 +114,10 @@ func Set_any<A>(a: {A}, f: A->Bool = _): Bool def
114114
return false
115115

116116
func Set_filter<A>(a: {A}, f: A->Bool): {A} def
117-
return {x for x in a if f(x)}
117+
return {for x in a if f(x) yield x}
118118

119119
func Set_map<A,B>(a: {A}, f: A->B): {B} def
120-
return {f(x) for x in a}
120+
return {for x in a yield f(x)}
121121

122122
func Set_fold<A,B>(a: {A}, f: A->B->B, r: B): B def
123123
for x in a do
@@ -149,7 +149,7 @@ func Dict_any<A,B>(a: {A:B}, f: A*B->Bool): Bool def
149149
return false
150150

151151
func Dict_filter<A,B>(a: {A:B}, f: A*B->Bool): {A:B} def
152-
return {x.a: x.b for x in a if f(x)}
152+
return {for x in a if f(x) yield x.a: x.b}
153153

154154
func Dict_map<A,B,C,D>(a: {A:B}, f: A*B->C*D): {C:D} def
155155
r: {C:D}

src/parser.py

+23-11
Original file line numberDiff line numberDiff line change
@@ -427,8 +427,22 @@ def parse_expr_prefix_op(self, token):
427427
}
428428
if token.text in {'[', '{'}: # containers
429429
closing_bracket = chr(ord(token.text) + 2)
430-
items = []
430+
comprehensions = self.parse_comprehensions()
431431
kind = 'array'
432+
if comprehensions:
433+
exprs = [self.parse_expr()]
434+
if token.text == '{':
435+
kind = 'set'
436+
if self.match(':'):
437+
kind = 'dict'
438+
exprs.append(self.parse_expr())
439+
return {
440+
**self.expr_node('ExprComprehension', token),
441+
'kind': kind,
442+
'comprehensions': comprehensions,
443+
'exprs': (exprs, self.expect(closing_bracket))[0],
444+
}
445+
items = []
432446
if token.text == '{' and self.match(':'):
433447
kind = 'dict'
434448
else:
@@ -443,16 +457,6 @@ def parse_expr_prefix_op(self, token):
443457
elif kind == 'dict':
444458
items.append(self.parse_dict_item())
445459
if not self.match(','):
446-
if not self.check(closing_bracket) and len(items) == 1 and items[0]['node'] != 'DictSpread':
447-
comprehensions = []
448-
while self.check('for') or self.check('if'):
449-
comprehensions.append(self.parse_comprehension())
450-
return {
451-
**self.expr_node('ExprComprehension', token),
452-
'kind': kind,
453-
'exprs': items[0]['exprs'] if items[0]['node'] == 'DictPair' else items,
454-
'comprehensions': (comprehensions, self.expect(closing_bracket))[0],
455-
}
456460
break
457461
return {
458462
**self.expr_node('ExprCollection', token),
@@ -597,6 +601,14 @@ def parse_dict_item(self):
597601
'exprs': [self.parse_expr(), self.expect(':') and self.parse_expr()],
598602
}
599603

604+
def parse_comprehensions(self):
605+
comprehensions = []
606+
while self.check('for') or self.check('if'):
607+
comprehensions.append(self.parse_comprehension())
608+
if comprehensions:
609+
self.expect('yield')
610+
return comprehensions
611+
600612
def parse_comprehension(self):
601613
token = self.pop()
602614

test/bad/arrays/comprehension01.err

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
:2:18: Incompatible types `Int` and `Char`.
1+
:2:16: Incompatible types `Int` and `Char`.

test/bad/arrays/comprehension01.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
a = [x for x in 1..'c']
2+
a = [for x in 1..'c' yield x]

test/bad/arrays/comprehension02.err

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
:2:6: Undeclared identifier `y`.
1+
:2:27: Undeclared identifier `y`.

test/bad/arrays/comprehension02.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
a = [y for x in 1...5]
2+
a = [for x in 1...5 yield y]

test/bad/arrays/comprehension03.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11

2-
a = [x.toString() for x in 1...5]
2+
a = [for x in 1...5 yield x.toString()]
33
a[0] == 2

test/bad/arrays/comprehension04.err

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
:2:25: No implicit conversion from `Int` to `Bool`.
1+
:2:19: No implicit conversion from `Int` to `Bool`.

test/bad/arrays/comprehension04.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
[false for x in 2..1 if 0]
2+
[for x in 2..1 if 0 yield false]

test/bad/arrays/comprehension05.err

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
:2:3: Syntax error.
1+
:2:17: Syntax error.

test/bad/arrays/comprehension05.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
x for x in [true]
2+
for x in [true] yield x

test/bad/arrays/comprehension06.err

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
:2:23: No implicit conversion from `Bool` to `Int`.
1+
:2:21: No implicit conversion from `Bool` to `Int`.

test/bad/arrays/comprehension06.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
[x for x in 0...10 by true]
2+
[for x in 0...10 by true yield x]

test/bad/arrays/comprehension07.err

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
:2:8: Cannot unpack value of type `Char*Char*Char` into 2 values.
1+
:2:6: Cannot unpack value of type `Char*Char*Char` into 2 values.

test/bad/arrays/comprehension07.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
[x for x, y in 'a'..'b', 'c'..'d', 'e'..'f']
2+
[for x, y in 'a'..'b', 'c'..'d', 'e'..'f' yield x]

test/bad/arrays/comprehension08.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11

2-
[i for i in 0...10]
2+
[for i in 0...10 yield i]
33
print i

test/bad/arrays/comprehension09.err

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
:2:9: Cannot unpack value of type `String` into 2 values.
1+
:2:7: Cannot unpack value of type `String` into 2 values.

test/bad/arrays/comprehension09.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
[c for (a, b), c in [("d", true)]]
2+
[for (a, b), c in [("d", true)] yield x]

test/bad/arrays/comprehension10.err

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
:2:20: No implicit conversion from `Bool*Int` to `Bool`.
1+
:2:18: No implicit conversion from `Bool*Int` to `Bool`.

test/bad/arrays/comprehension10.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
[x for x in [0] if true, 1]
2+
[for x in [0] if true, 1 yield x]

test/bad/arrays/comprehension11.err

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
:2:10: Syntax error.
1+
:2:8: Syntax error.

test/bad/arrays/comprehension11.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
[x for x + 1 in [0]]
2+
[for x + 1 in [0] yield x]

test/bad/arrays/comprehension12.err

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:2:22: Invalid usage of an iterative expression.

test/bad/arrays/comprehension12.px

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
[for a in [[]] yield ...a]

test/bad/arrays/comprehension13.err

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:2:20: Syntax error.

test/bad/arrays/comprehension13.px

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
[for x in [] yield ]

test/bad/arrays/comprehension14.err

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:2:21: Syntax error.

test/bad/arrays/comprehension14.px

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
[for x in [] yield x, x]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:2:23: Syntax error.
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
{for d in [{:}] yield ...:d}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:2:20: Syntax error.
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
{for _ in [] yield :}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:2:24: Syntax error.
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
{for _ in [] yield 1: 2, 3}

test/bad/sets/comprehension01.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
{{i} for i in 1..0}
2+
{for i in 1..0 yield {i}}

test/good/arrays/cmp03.px

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ n = 1000000
33
n1 = n + 1
44
n2 = n + 2
55

6-
a = [x for x in 1..n]
6+
a = [for x in 1..n yield x]
77
print [[a, a]] == [[a, a]]
8-
print [[a + [n2]]] == [[[x for x in 1..n1]]]
9-
print [[a]] != [[[x for x in 1..n1]]]
10-
print [[a + [n1]]] != [[[x for x in 1..n1]]]
8+
print [[a + [n2]]] == [[[for x in 1..n1 yield x]]]
9+
print [[a]] != [[[for x in 1..n1 yield x]]]
10+
print [[a + [n1]]] != [[[for x in 1..n1 yield x]]]

test/good/arrays/comprehension01.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

2-
a = [x for x in 1..5]
2+
a = [for x in 1..5 yield x]
33
print a.length
44
print a[0], a[1], a[4]

test/good/arrays/comprehension02.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

2-
a = [c.toString() for c in 'A'...'D']
2+
a = [for c in 'A'...'D' yield c.toString()]
33
print a.length
44
print a[0], a[2] == "C"

test/good/arrays/comprehension03.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

2-
a = [d+c for d in -2...5 for c in 'i'..'k']
2+
a = [for d in -2...5 for c in 'i'..'k' yield d+c]
33
print a.length
44
print a[0], a[5], a[-1]

test/good/arrays/comprehension04.px

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11

2-
print [not true for x in 1...10^^6 if x %% 2].length
3-
print [x for x in 1...10^^7 if not x %% 2][1234567]
2+
print [for x in 1...10^^6 if x %% 2 yield not true].length
3+
print [for x in 1...10^^7 if not x %% 2 yield x][1234567]

test/good/arrays/comprehension05.px

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
n = 13
3-
p = [[x, y, z] for x in 1..n for y in 1..n for z in 1..n
4-
if x^2 + y^2 == z^2 and x <= y <= z]
3+
p = [for x in 1..n for y in 1..n for z in 1..n
4+
if x^2 + y^2 == z^2 and x <= y <= z
5+
yield [x, y, z]]
56
print p

test/good/arrays/comprehension06.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

2-
a = [(x, y) for x in 1..10 by 2 if x > 3 for y in x...0 by -3 if y < 10]
2+
a = [for x in 1..10 by 2 if x > 3 for y in x...0 by -3 if y < 10 yield (x, y)]
33
for x in a do
44
print x

test/good/arrays/comprehension07.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

22
a = [2, 3, 4, 5]
33
b = [7, 4, 1, 5]
4-
c = [i + min(x, y) for x, y, i in a, b, 1...]
4+
c = [for x, y, i in a, b, 1... yield i + min(x, y)]
55
print c

test/good/arrays/comprehension08.px

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11

22
n = 0
33
for x in 1..100 do
4-
a = [x for x in 1..n]
4+
a = [for x in 1..n yield x]
55
l1 = a.length
6-
b = [x for x in 1..n]
6+
b = [for x in 1..n yield x]
77
l2 = a.length
88
if l1 != 0 or l2 != 0 do
99
print false

test/good/arrays/comprehension09.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

2-
a = [x/y for x in 1.0..2.0 for y in 2.0...6.0 by 2.0]
2+
a = [for x in 1.0..2.0 for y in 2.0...6.0 by 2.0 yield x/y]
33
for x in a do
44
print x

test/good/arrays/comprehension10.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
print [[[z for z in y..y] for y in 1..x] for x in 5...1 by -1 if x < 4]
2+
print [for x in 5...1 by -1 if x < 4 yield [for y in 1..x yield [for z in y..y yield z]]]

test/good/arrays/comprehension11.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

22
i = 0
33
c = false
4-
print ["{i}{c}" for i in ["I"] for i, c in 1..2, 'a'..'b']
4+
print [for i in ["I"] for i, c in 1..2, 'a'..'b' yield "{i}{c}"]
55
print i, c

test/good/arrays/comprehension12.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
print [x for x in [1, 2][::-1]]
2+
print [for x in [1, 2][::-1] yield x]

test/good/arrays/comprehension13.px

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11

2-
print [not x for x in false..true]
3-
print [x for x in true...false by -2]
2+
print [for x in false..true yield not x]
3+
print [for x in true...false by -2 yield x]

test/good/arrays/comprehension14.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
print [t for t in 0... by -1, 'w'..'z' by 2]
2+
print [for t in 0... by -1, 'w'..'z' by 2 yield t]

test/good/arrays/comprehension15.px

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11

2-
a: [Float] = [x*10^^15 for x in 2..4]
2+
a: [Float] = [for x in 2..4 yield x*10^^15]
33
print a

test/good/arrays/comprehension16.px

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11

2-
print ['a' if 2 + 2 < 4]
3-
print [c if true for c in 'b'..'c']
2+
print [if 2 + 2 < 4 yield 'a']
3+
print [if true for c in 'b'..'c' yield c]

0 commit comments

Comments
 (0)