koatl 0.1.33__tar.gz → 0.1.35__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {koatl-0.1.33 → koatl-0.1.35}/Cargo.lock +1 -1
- {koatl-0.1.33 → koatl-0.1.35}/PKG-INFO +1 -1
- {koatl-0.1.33 → koatl-0.1.35}/koatl/Cargo.toml +1 -1
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/prelude/functional/algebra.tl +4 -4
- {koatl-0.1.33 → koatl-0.1.35/koatl}/python/koatl/prelude/functional/result.tl +1 -1
- {koatl-0.1.33 → koatl-0.1.35/koatl}/python/koatl/prelude/iterable.tl +64 -14
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/runtime/classes.py +5 -4
- {koatl-0.1.33 → koatl-0.1.35/koatl}/python/koatl/runtime/record.py +10 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/runtime/virtual.py +1 -1
- {koatl-0.1.33 → koatl-0.1.35}/koatl/src/emit_py.rs +3 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/coal.tl +1 -1
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/prelude/try.tl +2 -2
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/prelude/virtual.tl +1 -1
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/parser/src/ast.rs +9 -5
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/parser/src/lexer.rs +40 -18
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/parser/src/parser.rs +37 -23
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/src/py/ast.rs +4 -1
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/src/py/emit.rs +43 -18
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/src/py/util.rs +1 -1
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/src/resolve_scopes.rs +1 -1
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/src/transform.rs +10 -6
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/prelude/functional/algebra.tl +4 -4
- {koatl-0.1.33/koatl → koatl-0.1.35}/python/koatl/prelude/functional/result.tl +1 -1
- {koatl-0.1.33/koatl → koatl-0.1.35}/python/koatl/prelude/iterable.tl +64 -14
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/runtime/classes.py +5 -4
- {koatl-0.1.33/koatl → koatl-0.1.35}/python/koatl/runtime/record.py +10 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/runtime/virtual.py +1 -1
- {koatl-0.1.33 → koatl-0.1.35}/Cargo.toml +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/README.md +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/.github/workflows/CI.yml +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/.gitignore +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/LICENSE +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/README.md +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/__init__.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/__main__.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/cli.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/prelude/functional/__init__.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/prelude/functional/async.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/prelude/functional/env.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/prelude/functional/list.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/prelude/functional/memo.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/prelude/io.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/prelude/regex.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/runtime/__init__.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/runtime/helpers.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/requirements.txt +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/src/lib.rs +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/containers.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/data.txt +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/decorators.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/destructure.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/escape_ident.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/fstr.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/functions.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/generator.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/if_expr.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/imports.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/loops.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/match.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/nary-list.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/placeholder.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/precedence.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/record.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/scopes.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/semantic_whitespace.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/short_circuit.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/base/with.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/prelude/async.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/prelude/aug_assign.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/prelude/env.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/prelude/iterables.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/prelude/list.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/prelude/memo.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/prelude/result.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/prelude/slice.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/util/__init__.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/util/module0.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/util/module1.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/e2e/util/module2.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/parse/arith.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/parse/assign.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/parse/block-comments.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/parse/deco.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/parse/func.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/parse/matches.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/test_e2e.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl/tests/test_parse.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/Cargo.toml +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/parser/Cargo.toml +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/parser/src/lib.rs +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/parser/src/util.rs +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/src/inference.rs +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/src/lib.rs +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/src/main.rs +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/src/parse_timer.rs +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/src/parser.rs +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/src/py/mod.rs +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/src/types.rs +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/koatl-core/src/util.rs +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/pyproject.toml +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/__init__.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/__main__.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/cli.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/prelude/functional/__init__.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/prelude/functional/async.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/prelude/functional/env.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/prelude/functional/list.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/prelude/functional/memo.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/prelude/io.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/prelude/regex.tl +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/runtime/__init__.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/runtime/helpers.py +0 -0
- {koatl-0.1.33 → koatl-0.1.35}/python/koatl/runtime/meta_finder.py +0 -0
|
@@ -8,9 +8,9 @@ export Monad = class(Trait):
|
|
|
8
8
|
"""
|
|
9
9
|
__slots__ = ()
|
|
10
10
|
|
|
11
|
-
bind =
|
|
11
|
+
bind = Trait.abstract& (self, f) => None
|
|
12
12
|
|
|
13
|
-
pure = staticmethod&
|
|
13
|
+
pure = staticmethod& Trait.abstract& value => None
|
|
14
14
|
|
|
15
15
|
# Automatically generated implementations.
|
|
16
16
|
map = (self, f) => self.bind(x => self.pure(f(x)))
|
|
@@ -33,7 +33,7 @@ export MonadOnce = class(Monad, Trait):
|
|
|
33
33
|
__slots__ = ()
|
|
34
34
|
|
|
35
35
|
# The default implementation required for `@` syntax that should be overridden by subclasses.
|
|
36
|
-
bind_once =
|
|
36
|
+
bind_once = Trait.abstract& (self, f) => None
|
|
37
37
|
|
|
38
38
|
# An optional, optimized implementation of `bind` that skips deep recursion.
|
|
39
39
|
# TODO: can this be automatically generated from bind_once?
|
|
@@ -69,4 +69,4 @@ export Traversable = class(Trait):
|
|
|
69
69
|
"""
|
|
70
70
|
__slots__ = ()
|
|
71
71
|
|
|
72
|
-
traverse =
|
|
72
|
+
traverse = Trait.abstract& (self, f) => None
|
|
@@ -160,7 +160,7 @@ export Err = class(Result):
|
|
|
160
160
|
raise ValueError(f"Expected Ok, got {repr(self)}")
|
|
161
161
|
coalesce = (self, f) => f()
|
|
162
162
|
|
|
163
|
-
Extension.property(object, "result")& Result
|
|
163
|
+
Extension.property(object, "result")& self => Result
|
|
164
164
|
|
|
165
165
|
__tl__.Ok = Ok
|
|
166
166
|
__tl__.Err = Err
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import itertools
|
|
2
2
|
import builtins
|
|
3
|
-
import .functional.(Traversable, Ok, Err, Memo, Async, AsyncMemo)
|
|
3
|
+
import .functional.(Traversable, Ok, Err, Memo, Async, AsyncMemo, Result)
|
|
4
4
|
|
|
5
5
|
export Iterable = Extension.trait& class(Traversable, Trait):
|
|
6
|
-
iter =
|
|
6
|
+
iter = Trait.abstract& self => None
|
|
7
7
|
|
|
8
8
|
skip = (self, n) =>
|
|
9
9
|
let it = self.iter
|
|
@@ -50,6 +50,22 @@ export Iterable = Extension.trait& class(Traversable, Trait):
|
|
|
50
50
|
|
|
51
51
|
filter = (self, f) => builtins.filter(f, self.iter)
|
|
52
52
|
|
|
53
|
+
filter_map = (self, f=None) =>
|
|
54
|
+
let impl = () =>
|
|
55
|
+
if f === None:
|
|
56
|
+
for i in self.iter:
|
|
57
|
+
if Result(i) matches Ok(value):
|
|
58
|
+
yield value
|
|
59
|
+
else:
|
|
60
|
+
for i in self.iter:
|
|
61
|
+
if Result(f(i)) matches Ok(value):
|
|
62
|
+
yield value
|
|
63
|
+
|
|
64
|
+
impl.__name__ = f"filter_map"
|
|
65
|
+
impl.__qualname__ = f"Iterable.filter_map"
|
|
66
|
+
|
|
67
|
+
impl()
|
|
68
|
+
|
|
53
69
|
flat_map = (self, f) => itertools.chain.from_iterable(self.map(f))
|
|
54
70
|
|
|
55
71
|
reverse = self => reversed(list(self.iter))
|
|
@@ -59,8 +75,16 @@ export Iterable = Extension.trait& class(Traversable, Trait):
|
|
|
59
75
|
|
|
60
76
|
copy = self => itertools.tee(self.iter)
|
|
61
77
|
|
|
62
|
-
|
|
63
|
-
|
|
78
|
+
count = (self, f=None) =>
|
|
79
|
+
let acc = 0
|
|
80
|
+
if f === None:
|
|
81
|
+
for _ in self:
|
|
82
|
+
acc += 1
|
|
83
|
+
else:
|
|
84
|
+
for i in self:
|
|
85
|
+
if f(i):
|
|
86
|
+
acc += 1
|
|
87
|
+
acc
|
|
64
88
|
|
|
65
89
|
fold = (self, init, f) =>
|
|
66
90
|
let acc = init
|
|
@@ -163,30 +187,56 @@ export Iterable = Extension.trait& class(Traversable, Trait):
|
|
|
163
187
|
raise ValueError("mean of empty iterable")
|
|
164
188
|
acc / count
|
|
165
189
|
|
|
166
|
-
max = self =>
|
|
190
|
+
max = (self, key=None) =>
|
|
167
191
|
let it = self.iter
|
|
168
|
-
let v
|
|
192
|
+
let v, m
|
|
169
193
|
try:
|
|
170
194
|
v = next(it)
|
|
195
|
+
if key === None:
|
|
196
|
+
m = v
|
|
197
|
+
else:
|
|
198
|
+
m = key(v)
|
|
171
199
|
except StopIteration(value=value):
|
|
172
200
|
raise ValueError("max of empty iterable")
|
|
173
201
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
202
|
+
|
|
203
|
+
if key === None:
|
|
204
|
+
for i in it:
|
|
205
|
+
if i > m:
|
|
206
|
+
v = i
|
|
207
|
+
m = i
|
|
208
|
+
else:
|
|
209
|
+
for i in it:
|
|
210
|
+
let ki = key(i)
|
|
211
|
+
if ki > m:
|
|
212
|
+
v = i
|
|
213
|
+
m = ki
|
|
214
|
+
|
|
177
215
|
v
|
|
178
216
|
|
|
179
|
-
min = self =>
|
|
217
|
+
min = (self, key=None) =>
|
|
180
218
|
let it = self.iter
|
|
181
|
-
let v
|
|
219
|
+
let v, m
|
|
182
220
|
try:
|
|
183
221
|
v = next(it)
|
|
222
|
+
if key === None:
|
|
223
|
+
m = v
|
|
224
|
+
else:
|
|
225
|
+
m = key(v)
|
|
184
226
|
except StopIteration(value=value):
|
|
185
227
|
raise ValueError("min of empty iterable")
|
|
186
228
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
229
|
+
if key === None:
|
|
230
|
+
for i in it:
|
|
231
|
+
if i < m:
|
|
232
|
+
v = i
|
|
233
|
+
m = i
|
|
234
|
+
else:
|
|
235
|
+
for i in it:
|
|
236
|
+
let ki = key(i)
|
|
237
|
+
if ki < m:
|
|
238
|
+
v = i
|
|
239
|
+
m = ki
|
|
190
240
|
v
|
|
191
241
|
|
|
192
242
|
list = self =>
|
|
@@ -40,6 +40,7 @@ class MappingMeta(type):
|
|
|
40
40
|
return [(k, v) for k, v in inspect.getmembers(self) if not k.startswith("_")]
|
|
41
41
|
|
|
42
42
|
|
|
43
|
+
# A utility base class to inherit from to enable __getitem__ method lookup on types and thus destructuring.
|
|
43
44
|
class Class(metaclass=MappingMeta):
|
|
44
45
|
pass
|
|
45
46
|
|
|
@@ -104,9 +105,9 @@ class Trait(metaclass=TraitMeta):
|
|
|
104
105
|
fn._property = True
|
|
105
106
|
return property(fn)
|
|
106
107
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
@staticmethod
|
|
109
|
+
def abstract(value):
|
|
110
|
+
return abc.abstractmethod(value)
|
|
110
111
|
|
|
111
112
|
|
|
112
|
-
__all__ = ["Class", "Trait"
|
|
113
|
+
__all__ = ["Class", "Trait"]
|
|
@@ -21,6 +21,16 @@ class Record(dict):
|
|
|
21
21
|
|
|
22
22
|
return attr
|
|
23
23
|
|
|
24
|
+
def __hash__(self):
|
|
25
|
+
return hash(tuple(sorted(self.items())))
|
|
26
|
+
|
|
27
|
+
def __eq__(self, other):
|
|
28
|
+
return super().__eq__(other)
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def len(self):
|
|
32
|
+
return len(self)
|
|
33
|
+
|
|
24
34
|
@staticmethod
|
|
25
35
|
def method(fn):
|
|
26
36
|
fn._method = True
|
|
@@ -7,7 +7,7 @@ from .._rs import fast_vget, fast_vset, fast_vset_trait
|
|
|
7
7
|
def vget(obj, name, ignore_traits=False):
|
|
8
8
|
try:
|
|
9
9
|
return getattr(obj, name)
|
|
10
|
-
except:
|
|
10
|
+
except AttributeError:
|
|
11
11
|
pass
|
|
12
12
|
|
|
13
13
|
# special case for iter - this could be implemented using types and trait vtbls
|
|
@@ -553,6 +553,7 @@ impl<'src> PyExprExt<'src> for SPyExpr<'src> {
|
|
|
553
553
|
PyBinaryOp::Sub => Some("Sub"),
|
|
554
554
|
PyBinaryOp::Mult => Some("Mult"),
|
|
555
555
|
PyBinaryOp::Div => Some("Div"),
|
|
556
|
+
PyBinaryOp::FloorDiv => Some("FloorDiv"),
|
|
556
557
|
PyBinaryOp::Mod => Some("Mod"),
|
|
557
558
|
PyBinaryOp::Pow => Some("Pow"),
|
|
558
559
|
_ => None,
|
|
@@ -596,6 +597,8 @@ impl<'src> PyExprExt<'src> for SPyExpr<'src> {
|
|
|
596
597
|
PyBinaryOp::Neq => Some("NotEq"),
|
|
597
598
|
PyBinaryOp::Is => Some("Is"),
|
|
598
599
|
PyBinaryOp::Nis => Some("IsNot"),
|
|
600
|
+
PyBinaryOp::In => Some("In"),
|
|
601
|
+
PyBinaryOp::Nin => Some("NotIn"),
|
|
599
602
|
_ => None,
|
|
600
603
|
};
|
|
601
604
|
|
|
@@ -15,7 +15,7 @@ assert_eq(x.a, 1)
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
SomeTrait = Extension.trait& class(Trait):
|
|
18
|
-
required_method =
|
|
18
|
+
required_method = Trait.abstract& self => ()
|
|
19
19
|
|
|
20
20
|
derived_method = self => self.required_method()
|
|
21
21
|
derived_property = Trait.property& self => self.required_method()
|
|
@@ -35,11 +35,15 @@ pub enum BinaryOp {
|
|
|
35
35
|
Add,
|
|
36
36
|
Sub,
|
|
37
37
|
Mul,
|
|
38
|
-
Mod,
|
|
39
38
|
MatMul,
|
|
40
39
|
Div,
|
|
41
40
|
Exp,
|
|
42
41
|
|
|
42
|
+
FloorDiv,
|
|
43
|
+
Mod,
|
|
44
|
+
|
|
45
|
+
In,
|
|
46
|
+
Nin,
|
|
43
47
|
Lt,
|
|
44
48
|
Leq,
|
|
45
49
|
Gt,
|
|
@@ -138,9 +142,9 @@ pub enum Stmt<'a, TTree: Tree> {
|
|
|
138
142
|
}
|
|
139
143
|
|
|
140
144
|
#[derive(Debug, Clone)]
|
|
141
|
-
pub struct FmtExpr<
|
|
145
|
+
pub struct FmtExpr<TTree: Tree> {
|
|
142
146
|
pub expr: TTree::Expr,
|
|
143
|
-
pub fmt: Option<
|
|
147
|
+
pub fmt: Option<TTree::Expr>,
|
|
144
148
|
}
|
|
145
149
|
|
|
146
150
|
#[derive(Debug, Clone)]
|
|
@@ -229,7 +233,7 @@ pub enum Expr<'a, TTree: Tree> {
|
|
|
229
233
|
Block(Vec<TTree::Stmt>),
|
|
230
234
|
|
|
231
235
|
Fn(Vec<ArgDefItem<'a, TTree>>, TTree::Expr),
|
|
232
|
-
Fstr(Spanned<String>, Vec<(FmtExpr<
|
|
236
|
+
Fstr(Spanned<String>, Vec<(FmtExpr<TTree>, Spanned<String>)>),
|
|
233
237
|
|
|
234
238
|
// these are removed during desugaring
|
|
235
239
|
Decorated(TTree::Expr, TTree::Expr),
|
|
@@ -347,4 +351,4 @@ pub type SMappingItem<'a> = MappingItem<STree<'a>>;
|
|
|
347
351
|
pub type SMatchCase<'a> = MatchCase<STree<'a>>;
|
|
348
352
|
pub type SCallItem<'a> = CallItem<'a, STree<'a>>;
|
|
349
353
|
pub type SArgDefItem<'a> = ArgDefItem<'a, STree<'a>>;
|
|
350
|
-
pub type SFmtExpr<'a> = FmtExpr<
|
|
354
|
+
pub type SFmtExpr<'a> = FmtExpr<STree<'a>>;
|
|
@@ -5,7 +5,10 @@ use chumsky::{
|
|
|
5
5
|
label::LabelError,
|
|
6
6
|
prelude::*,
|
|
7
7
|
};
|
|
8
|
-
use std::{
|
|
8
|
+
use std::{
|
|
9
|
+
collections::HashSet,
|
|
10
|
+
fmt::{self},
|
|
11
|
+
};
|
|
9
12
|
|
|
10
13
|
use crate::ast::{Span, Spannable, Spanned};
|
|
11
14
|
|
|
@@ -321,7 +324,7 @@ where
|
|
|
321
324
|
fn parse_symbol(&mut self) -> TResult<'src, Spanned<Token<'src>>> {
|
|
322
325
|
const POLYGRAMS: &[&str] = &[
|
|
323
326
|
"+=", "-=", "*=", "/=", "|=", "??=", "===", "<=>", "=>", "..", "==", "<>", "<=", ">=",
|
|
324
|
-
"//", "**", "??", ".=",
|
|
327
|
+
"//", "**", "??", ".=", "::",
|
|
325
328
|
];
|
|
326
329
|
const MONOGRAMS: &str = "[](){}<>.,;:!?@$%^&*+-=|\\/`~";
|
|
327
330
|
|
|
@@ -612,23 +615,13 @@ where
|
|
|
612
615
|
}
|
|
613
616
|
}
|
|
614
617
|
|
|
615
|
-
fn
|
|
618
|
+
fn parse_fstr_inner(&mut self, ending: &str, verbatim: bool) -> TResult<'src, TokenList<'src>> {
|
|
616
619
|
let mut marker = self.cursor();
|
|
617
|
-
|
|
618
|
-
if verbatim {
|
|
619
|
-
self.parse_seq("f\"\"\"")?;
|
|
620
|
-
} else {
|
|
621
|
-
self.parse_seq("f\"")?;
|
|
622
|
-
}
|
|
623
|
-
|
|
624
620
|
let mut tokens = vec![];
|
|
625
621
|
let mut current_str = String::new();
|
|
626
622
|
|
|
627
623
|
loop {
|
|
628
|
-
if self
|
|
629
|
-
.try_parse(|x| x.parse_seq(if verbatim { "\"\"\"" } else { "\"" }))
|
|
630
|
-
.is_ok()
|
|
631
|
-
{
|
|
624
|
+
if self.look_ahead(|x| x.parse_seq(ending)).is_ok() {
|
|
632
625
|
if tokens.len() == 0 {
|
|
633
626
|
tokens.push(Token::FstrBegin(current_str).spanned(self.span_since(&marker)));
|
|
634
627
|
} else {
|
|
@@ -667,12 +660,19 @@ where
|
|
|
667
660
|
|
|
668
661
|
self.parse_nonsemantic()?;
|
|
669
662
|
let _ = self.try_parse(|x| x.parse_newline());
|
|
670
|
-
|
|
671
663
|
let sexpr = self.try_parse(|x| x.parse_block(0, NewBlockType::BeginInput))?;
|
|
672
|
-
|
|
673
664
|
let _ = self.try_parse(|x| x.parse_newline());
|
|
674
|
-
|
|
675
|
-
self.
|
|
665
|
+
|
|
666
|
+
self.parse_indentation()?;
|
|
667
|
+
|
|
668
|
+
marker = self.cursor();
|
|
669
|
+
let mut format_tokens = vec![];
|
|
670
|
+
if self.try_parse(|x| x.parse_seq("!")).is_ok() {
|
|
671
|
+
format_tokens.push(Token::Symbol("!").spanned(self.span_since(&marker)));
|
|
672
|
+
format_tokens.extend(self.parse_fstr_inner("}", verbatim)?);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
self.parse_seq("}")?;
|
|
676
676
|
|
|
677
677
|
tokens.push(Token::Indent.spanned(Span::new(
|
|
678
678
|
sexpr.span.context,
|
|
@@ -687,6 +687,7 @@ where
|
|
|
687
687
|
sexpr.span.context,
|
|
688
688
|
sexpr.span.end..sexpr.span.end,
|
|
689
689
|
)));
|
|
690
|
+
tokens.extend(format_tokens);
|
|
690
691
|
|
|
691
692
|
marker = self.cursor();
|
|
692
693
|
|
|
@@ -703,6 +704,20 @@ where
|
|
|
703
704
|
}
|
|
704
705
|
}
|
|
705
706
|
|
|
707
|
+
fn parse_fstr(&mut self, verbatim: bool) -> TResult<'src, TokenList<'src>> {
|
|
708
|
+
if verbatim {
|
|
709
|
+
self.parse_seq("f\"\"\"")?;
|
|
710
|
+
let inner = self.parse_fstr_inner("\"\"\"", true)?;
|
|
711
|
+
self.parse_seq("\"\"\"")?;
|
|
712
|
+
return Ok(inner);
|
|
713
|
+
} else {
|
|
714
|
+
self.parse_seq("f\"")?;
|
|
715
|
+
let inner = self.parse_fstr_inner("\"", false)?;
|
|
716
|
+
self.parse_seq("\"")?;
|
|
717
|
+
return Ok(inner);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
706
721
|
fn parse_str_start(&mut self) -> TResult<'src, ()> {
|
|
707
722
|
let start = self.cursor();
|
|
708
723
|
|
|
@@ -818,6 +833,13 @@ where
|
|
|
818
833
|
break;
|
|
819
834
|
}
|
|
820
835
|
|
|
836
|
+
if let Token::Symbol("!") = &tok.value {
|
|
837
|
+
// Format specifier delimiter; end block.
|
|
838
|
+
self.input.rewind(saved);
|
|
839
|
+
end_block = true;
|
|
840
|
+
break;
|
|
841
|
+
}
|
|
842
|
+
|
|
821
843
|
if let Token::Symbol(s) = &tok.value {
|
|
822
844
|
let char = s.chars().next().unwrap_or('\0');
|
|
823
845
|
if OPEN_DELIMS.contains(&char) {
|
|
@@ -525,6 +525,8 @@ where
|
|
|
525
525
|
symbol("-=").to(BinaryOp::Sub),
|
|
526
526
|
symbol("*=").to(BinaryOp::Mul),
|
|
527
527
|
symbol("/=").to(BinaryOp::Div),
|
|
528
|
+
symbol("//=").to(BinaryOp::FloorDiv),
|
|
529
|
+
symbol("%=").to(BinaryOp::Mod),
|
|
528
530
|
symbol("|=").to(BinaryOp::Pipe),
|
|
529
531
|
symbol("??=").to(BinaryOp::Coalesce),
|
|
530
532
|
))
|
|
@@ -543,6 +545,7 @@ where
|
|
|
543
545
|
SStmtInner::Expr(lhs.indirect())
|
|
544
546
|
}
|
|
545
547
|
})
|
|
548
|
+
.labelled("assignment")
|
|
546
549
|
.boxed();
|
|
547
550
|
|
|
548
551
|
let inline_assign_stmt = group((expr.clone(), assign_op.clone().then(expr.clone()).or_not()))
|
|
@@ -553,6 +556,7 @@ where
|
|
|
553
556
|
SStmtInner::Expr(lhs.indirect())
|
|
554
557
|
}
|
|
555
558
|
})
|
|
559
|
+
.labelled("assignment")
|
|
556
560
|
.boxed();
|
|
557
561
|
|
|
558
562
|
let while_stmt = just(Token::Kw("while"))
|
|
@@ -955,27 +959,32 @@ where
|
|
|
955
959
|
}
|
|
956
960
|
.map_with(|x, e| x.spanned(e.span()));
|
|
957
961
|
|
|
958
|
-
let fstr =
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
(
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
962
|
+
let mut fstr = Recursive::<chumsky::recursive::Indirect<TInput, SExpr, TExtra>>::declare();
|
|
963
|
+
|
|
964
|
+
fstr.define(
|
|
965
|
+
fstr_begin
|
|
966
|
+
.then(
|
|
967
|
+
expr_or_block
|
|
968
|
+
.clone()
|
|
969
|
+
.then(symbol("!").ignore_then(fstr.clone()).or_not())
|
|
970
|
+
.then(fstr_continue)
|
|
971
|
+
.map(|((block, fmt), cont)| {
|
|
972
|
+
(
|
|
973
|
+
FmtExpr {
|
|
974
|
+
expr: block.indirect(),
|
|
975
|
+
fmt: fmt.map(|x| x.indirect()),
|
|
976
|
+
},
|
|
977
|
+
cont,
|
|
978
|
+
)
|
|
979
|
+
})
|
|
980
|
+
.repeated()
|
|
981
|
+
.collect::<Vec<_>>(),
|
|
982
|
+
)
|
|
983
|
+
.map(|(begin, parts)| SExprInner::Fstr(begin, parts))
|
|
984
|
+
.spanned_expr()
|
|
985
|
+
.labelled("f-string")
|
|
986
|
+
.boxed(),
|
|
987
|
+
);
|
|
979
988
|
|
|
980
989
|
let class_ = just(Token::Kw("class"))
|
|
981
990
|
.ignore_then(
|
|
@@ -1183,7 +1192,7 @@ where
|
|
|
1183
1192
|
.labelled("then-attribute")
|
|
1184
1193
|
.boxed();
|
|
1185
1194
|
|
|
1186
|
-
let raw_attr = symbol("
|
|
1195
|
+
let raw_attr = symbol("::")
|
|
1187
1196
|
.ignore_then(ident.clone())
|
|
1188
1197
|
.map(Postfix::RawAttribute)
|
|
1189
1198
|
.labelled("raw-attribute")
|
|
@@ -1307,6 +1316,7 @@ where
|
|
|
1307
1316
|
select! {
|
|
1308
1317
|
Token::Symbol("*") => BinaryOp::Mul,
|
|
1309
1318
|
Token::Symbol("/") => BinaryOp::Div,
|
|
1319
|
+
Token::Symbol("//") => BinaryOp::FloorDiv,
|
|
1310
1320
|
Token::Symbol("%") => BinaryOp::Mod,
|
|
1311
1321
|
Token::Symbol("@") => BinaryOp::MatMul,
|
|
1312
1322
|
},
|
|
@@ -1325,6 +1335,7 @@ where
|
|
|
1325
1335
|
let binary3 = make_binary_op(
|
|
1326
1336
|
binary2.clone(),
|
|
1327
1337
|
select! {
|
|
1338
|
+
Token::Kw("in") => BinaryOp::In,
|
|
1328
1339
|
Token::Symbol("<") => BinaryOp::Lt,
|
|
1329
1340
|
Token::Symbol("<=") => BinaryOp::Leq,
|
|
1330
1341
|
Token::Symbol(">") => BinaryOp::Gt,
|
|
@@ -1333,7 +1344,10 @@ where
|
|
|
1333
1344
|
Token::Symbol("<>") => BinaryOp::Neq,
|
|
1334
1345
|
Token::Symbol("===") => BinaryOp::Is,
|
|
1335
1346
|
Token::Symbol("<=>") => BinaryOp::Nis,
|
|
1336
|
-
}
|
|
1347
|
+
}
|
|
1348
|
+
.or(just(Token::Kw("not"))
|
|
1349
|
+
.then(just(Token::Kw("in")))
|
|
1350
|
+
.to(BinaryOp::Nin)),
|
|
1337
1351
|
false,
|
|
1338
1352
|
);
|
|
1339
1353
|
|
|
@@ -146,6 +146,7 @@ pub enum PyBinaryOp {
|
|
|
146
146
|
Mult,
|
|
147
147
|
Div,
|
|
148
148
|
Mod,
|
|
149
|
+
FloorDiv,
|
|
149
150
|
Pow,
|
|
150
151
|
MatMult,
|
|
151
152
|
|
|
@@ -160,6 +161,8 @@ pub enum PyBinaryOp {
|
|
|
160
161
|
Geq,
|
|
161
162
|
Is,
|
|
162
163
|
Nis,
|
|
164
|
+
In,
|
|
165
|
+
Nin,
|
|
163
166
|
}
|
|
164
167
|
|
|
165
168
|
#[derive(Debug, Clone)]
|
|
@@ -200,7 +203,7 @@ pub enum PyDictItem<'a> {
|
|
|
200
203
|
#[derive(Debug, Clone)]
|
|
201
204
|
pub enum PyFstrPart<'a> {
|
|
202
205
|
Str(PyIdent<'a>),
|
|
203
|
-
Expr(SPyExpr<'a>, Option<
|
|
206
|
+
Expr(SPyExpr<'a>, Option<SPyExpr<'a>>),
|
|
204
207
|
}
|
|
205
208
|
|
|
206
209
|
#[derive(Debug, Clone)]
|