koatl 0.1.25__tar.gz → 0.1.27__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.25 → koatl-0.1.27}/Cargo.lock +1 -1
- {koatl-0.1.25 → koatl-0.1.27}/PKG-INFO +1 -1
- {koatl-0.1.25 → koatl-0.1.27}/koatl/Cargo.toml +1 -1
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/prelude/functional/__init__.tl +1 -1
- koatl-0.1.27/koatl/python/koatl/prelude/functional/algebra.tl +46 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/prelude/functional/async.tl +3 -3
- {koatl-0.1.25 → koatl-0.1.27/koatl}/python/koatl/prelude/functional/list.tl +1 -1
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/prelude/functional/memo.tl +3 -5
- {koatl-0.1.25 → koatl-0.1.27/koatl}/python/koatl/prelude/functional/reader.tl +2 -2
- {koatl-0.1.25 → koatl-0.1.27/koatl}/python/koatl/prelude/functional/result.tl +2 -2
- {koatl-0.1.25 → koatl-0.1.27/koatl}/python/koatl/runtime/virtual.py +2 -1
- {koatl-0.1.25 → koatl-0.1.27}/koatl/src/emit_py.rs +28 -2
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/destructure.tl +1 -7
- koatl-0.1.27/koatl/tests/e2e/base/record.tl +24 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/scopes.tl +12 -0
- koatl-0.1.27/koatl/tests/e2e/prelude/aug_assign.tl +13 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/prelude/memo.tl +17 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/prelude/reader.tl +1 -1
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/parser/src/ast.rs +3 -1
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/parser/src/lexer.rs +2 -1
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/parser/src/parser.rs +91 -65
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/parser/src/util.rs +2 -2
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/src/inference.rs +5 -1
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/src/py/ast.rs +1 -1
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/src/py/emit.rs +9 -8
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/src/py/util.rs +10 -1
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/src/resolve_scopes.rs +112 -120
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/src/transform.rs +197 -407
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/prelude/functional/__init__.tl +1 -1
- koatl-0.1.27/python/koatl/prelude/functional/algebra.tl +46 -0
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/prelude/functional/async.tl +3 -3
- {koatl-0.1.25/koatl → koatl-0.1.27}/python/koatl/prelude/functional/list.tl +1 -1
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/prelude/functional/memo.tl +3 -5
- {koatl-0.1.25/koatl → koatl-0.1.27}/python/koatl/prelude/functional/reader.tl +2 -2
- {koatl-0.1.25/koatl → koatl-0.1.27}/python/koatl/prelude/functional/result.tl +2 -2
- {koatl-0.1.25/koatl → koatl-0.1.27}/python/koatl/runtime/virtual.py +2 -1
- koatl-0.1.25/koatl/python/koatl/prelude/functional/monad.tl +0 -21
- koatl-0.1.25/python/koatl/prelude/functional/monad.tl +0 -21
- {koatl-0.1.25 → koatl-0.1.27}/Cargo.toml +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/README.md +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/.github/workflows/CI.yml +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/.gitignore +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/LICENSE +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/README.md +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/__main__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/cli.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/prelude/functional/async_util.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/prelude/iterable.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/runtime/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/runtime/helpers.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/python/koatl/runtime/record.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/requirements.txt +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/src/lib.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/coal.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/containers.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/decorators.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/escape_ident.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/fstr.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/functions.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/generator.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/if_expr.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/imports.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/loops.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/match.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/nary-list.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/placeholder.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/precedence.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/semantic_whitespace.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/base/short_circuit.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/destructure.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/prelude/async.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/prelude/iterables.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/prelude/list.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/prelude/result.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/prelude/slice.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/prelude/try.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/prelude/virtual.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/util/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/util/module0.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/util/module1.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/e2e/util/module2.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/parse/arith.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/parse/assign.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/parse/block-comments.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/parse/deco.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/parse/func.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/parse/matches.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/test_e2e.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl/tests/test_parse.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/Cargo.toml +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/parser/Cargo.toml +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/parser/src/lib.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/parser/tests/lexer.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/src/lib.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/src/main.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/src/parse_timer.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/src/parser.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/src/py/mod.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/src/types.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/koatl-core/src/util.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/pyproject.toml +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/__main__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/cli.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/prelude/functional/async_util.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/prelude/iterable.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/runtime/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/runtime/helpers.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.1.25 → koatl-0.1.27}/python/koatl/runtime/record.py +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
|
|
3
|
+
export Monad = class(abc.ABC):
|
|
4
|
+
"""
|
|
5
|
+
Abstract base class for monads.
|
|
6
|
+
|
|
7
|
+
Subclasses must implement `bind` and `pure`.
|
|
8
|
+
Automatically provides standard monadic operations: bind_once, map, and apply.
|
|
9
|
+
"""
|
|
10
|
+
__slots__ = ()
|
|
11
|
+
|
|
12
|
+
bind = abc.abstractmethod& (self, f) => None
|
|
13
|
+
|
|
14
|
+
pure = staticmethod& abc.abstractmethod& value => None
|
|
15
|
+
|
|
16
|
+
# Automatically generated implementations.
|
|
17
|
+
map = (self, f) => self.bind(x => self.pure(f(x)))
|
|
18
|
+
apply = (self, f) => self.bind(x => f.map(fn => fn(x)))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# TODO: should this inherit from Monad?
|
|
22
|
+
export MonadOnce = class(abc.ABC):
|
|
23
|
+
"""
|
|
24
|
+
Abstract base class for single-use monads.
|
|
25
|
+
|
|
26
|
+
A MonadOnce can only be bound once, which is suitable for
|
|
27
|
+
use with Python generators that cannot be cloned or reused.
|
|
28
|
+
|
|
29
|
+
Subclasses must implement `bind_once` and `pure`.
|
|
30
|
+
Automatically provides (likely suboptimal) standard monadic operations: bind, map, and apply.
|
|
31
|
+
"""
|
|
32
|
+
__slots__ = ()
|
|
33
|
+
|
|
34
|
+
# The default implementation required for `@` syntax that should be overridden by subclasses.
|
|
35
|
+
bind_once = abc.abstractmethod& (self, f) => None
|
|
36
|
+
|
|
37
|
+
pure = staticmethod& abc.abstractmethod& value => None
|
|
38
|
+
|
|
39
|
+
# An optional, optimized implementation of `bind` that skips deep recursion.
|
|
40
|
+
# TODO: can this be automatically generated from bind_once?
|
|
41
|
+
# bind_gen = (self, gen) => ...
|
|
42
|
+
|
|
43
|
+
# Automatically generated implementations.
|
|
44
|
+
bind = (self, f) => self.bind_once(f)
|
|
45
|
+
map = (self, f) => self.bind(x => self.pure(f(x)))
|
|
46
|
+
apply = (self, f) => self.bind(x => f.map(fn => fn(x)))
|
|
@@ -2,9 +2,9 @@ import functools.wraps
|
|
|
2
2
|
import asyncio
|
|
3
3
|
|
|
4
4
|
import .async_util
|
|
5
|
-
import .
|
|
5
|
+
import .MonadOnce
|
|
6
6
|
|
|
7
|
-
export Async = class(
|
|
7
|
+
export Async = class(MonadOnce):
|
|
8
8
|
__init__ = (self, awaitable) => self.generator = awaitable.__await__()
|
|
9
9
|
|
|
10
10
|
__await__ = self => self.generator
|
|
@@ -39,5 +39,5 @@ export Async = class(Monad):
|
|
|
39
39
|
|
|
40
40
|
sleep = staticmethod& x => Async(asyncio.sleep(x))
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
# TODO: Why is asyncio.gather eager?
|
|
43
43
|
gather = staticmethod& (*args) => Async.from_generator_fn& () => yield from asyncio.gather(*args)
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import collections.defaultdict
|
|
2
2
|
import functools.wraps
|
|
3
3
|
import .result.(Result, Ok)
|
|
4
|
-
import .
|
|
4
|
+
import .MonadOnce
|
|
5
5
|
|
|
6
|
-
export Memo = class(
|
|
6
|
+
export Memo = class(MonadOnce):
|
|
7
7
|
Cache = class:
|
|
8
8
|
__init__ = self =>
|
|
9
9
|
self.cache = defaultdict(dict)
|
|
10
10
|
|
|
11
11
|
__repr__ = self => f"Memo.Cache({self.cache})"
|
|
12
12
|
|
|
13
|
-
try_get = (self, name, deps) =>
|
|
14
|
-
# TODO should try operator return a Result directly?
|
|
15
|
-
Result(try self.cache[name][deps] except KeyError())
|
|
13
|
+
try_get = (self, name, deps) => try self.cache[name][deps] except KeyError()
|
|
16
14
|
|
|
17
15
|
update = (self, name, deps, value) =>
|
|
18
16
|
self.cache[name][deps] = value
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import abc
|
|
1
2
|
from functools import partial
|
|
2
3
|
from itertools import count
|
|
3
4
|
from types import new_class
|
|
@@ -105,7 +106,7 @@ def Trait(module, name, methods, *, requires=[]):
|
|
|
105
106
|
|
|
106
107
|
meta = type(
|
|
107
108
|
f"{name}Meta",
|
|
108
|
-
(
|
|
109
|
+
(abc.ABCMeta,),
|
|
109
110
|
{"__instancecheck__": instancecheck, "__module__": "types"},
|
|
110
111
|
)
|
|
111
112
|
|
|
@@ -279,10 +279,36 @@ impl<'src> PyStmtExt<'src> for SPyStmt<'src> {
|
|
|
279
279
|
.collect();
|
|
280
280
|
ctx.ast_node("Match", (subject_ast, cases_ast?), &self.tl_span)
|
|
281
281
|
}
|
|
282
|
-
PyStmt::Assign(target, value) => {
|
|
282
|
+
PyStmt::Assign(target, value, op) => {
|
|
283
283
|
let target_ast = target.emit_py(ctx)?;
|
|
284
284
|
let value_ast = value.emit_py(ctx)?;
|
|
285
|
-
|
|
285
|
+
|
|
286
|
+
if let Some(op) = op {
|
|
287
|
+
let py_op = match op {
|
|
288
|
+
PyBinaryOp::Add => "Add",
|
|
289
|
+
PyBinaryOp::Sub => "Sub",
|
|
290
|
+
PyBinaryOp::Mult => "Mult",
|
|
291
|
+
PyBinaryOp::Div => "Div",
|
|
292
|
+
_ => {
|
|
293
|
+
return Err(PyTlErr {
|
|
294
|
+
message: format!(
|
|
295
|
+
"Unsupported augmented assignment operator: {:?}",
|
|
296
|
+
op
|
|
297
|
+
),
|
|
298
|
+
py_err: None,
|
|
299
|
+
span: Some(self.tl_span),
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
ctx.ast_node(
|
|
305
|
+
"AugAssign",
|
|
306
|
+
(target_ast, ctx.ast_cls(py_op, ())?, value_ast),
|
|
307
|
+
&self.tl_span,
|
|
308
|
+
)
|
|
309
|
+
} else {
|
|
310
|
+
ctx.ast_node("Assign", ([target_ast], value_ast), &self.tl_span)
|
|
311
|
+
}
|
|
286
312
|
}
|
|
287
313
|
PyStmt::Return(expr) => {
|
|
288
314
|
let expr_ast = expr.emit_py(ctx)?;
|
|
@@ -48,11 +48,5 @@ assert_eq([a, b, c], ["a", [2, 3], {2: "2", 3: "3"}])
|
|
|
48
48
|
{a, **b} = {a: 42, b: 43}
|
|
49
49
|
assert_eq([a, b], [42, {b: 43}])
|
|
50
50
|
|
|
51
|
-
a, *b, c = 1, 2, 3, 4
|
|
52
|
-
assert_eq([a, b, c], [1, (2, 3), 4])
|
|
53
|
-
|
|
54
51
|
a, [*b], c, *d = 1, [2, 3], 4, 5, 6
|
|
55
|
-
assert_eq([a, b, c, d], [1, [2, 3], 4,
|
|
56
|
-
|
|
57
|
-
# destructuring modules
|
|
58
|
-
{assert_eq} = util
|
|
52
|
+
assert_eq([a, b, c, d], [1, [2, 3], 4, [5, 6]])
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import util.assert_eq
|
|
2
|
+
|
|
3
|
+
assert_eq(
|
|
4
|
+
{a: 0}.keys() | list
|
|
5
|
+
["a"]
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
assert_eq(
|
|
9
|
+
{(): 0}.keys() | list
|
|
10
|
+
[()]
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
assert_eq(
|
|
14
|
+
{(1): 0}.keys() | list
|
|
15
|
+
[1]
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
assert_eq(
|
|
19
|
+
{(
|
|
20
|
+
let x = 1
|
|
21
|
+
x
|
|
22
|
+
): 0}.keys() | list
|
|
23
|
+
[1]
|
|
24
|
+
)
|
|
@@ -89,4 +89,16 @@ f = () =>
|
|
|
89
89
|
|
|
90
90
|
A().f()
|
|
91
91
|
assert_eq(A, 2)
|
|
92
|
+
f()
|
|
93
|
+
|
|
94
|
+
# Shadowing should work
|
|
95
|
+
f = () =>
|
|
96
|
+
let x = 1
|
|
97
|
+
let x = x + 1
|
|
98
|
+
assert_eq(x, 2)
|
|
99
|
+
|
|
100
|
+
# but recursion should also work
|
|
101
|
+
let x = 3
|
|
102
|
+
let x = () => x.__name__
|
|
103
|
+
assert_eq(type(x()), str)
|
|
92
104
|
f()
|
|
@@ -29,3 +29,20 @@ assert_eq(f(10).run(ctx), 20)
|
|
|
29
29
|
assert_eq(f(5).run(ctx), 10)
|
|
30
30
|
assert_eq(f(5).run(ctx), 10)
|
|
31
31
|
assert_eq(counts, 2)
|
|
32
|
+
|
|
33
|
+
# Indirect dependencies should be tracked as well.
|
|
34
|
+
|
|
35
|
+
counts = 0
|
|
36
|
+
|
|
37
|
+
f = (x, y) =>
|
|
38
|
+
memo:
|
|
39
|
+
counts = counts + 1
|
|
40
|
+
let other = () => y
|
|
41
|
+
x * other()
|
|
42
|
+
|
|
43
|
+
ctx = Memo.Cache()
|
|
44
|
+
assert_eq(f(10, 20).run(ctx), 200)
|
|
45
|
+
assert_eq(f(10, 20).run(ctx), 200)
|
|
46
|
+
assert_eq(f(10, 30).run(ctx), 300)
|
|
47
|
+
assert_eq(f(10, 30).run(ctx), 300)
|
|
48
|
+
assert_eq(counts, 2)
|
|
@@ -121,7 +121,9 @@ pub enum DeclType {
|
|
|
121
121
|
#[derive(Debug, Clone)]
|
|
122
122
|
pub enum Stmt<'a, TTree: Tree> {
|
|
123
123
|
Decl(Vec<SIdent<'a>>, DeclType),
|
|
124
|
-
Assign(TTree::Expr, TTree::Expr, Option<
|
|
124
|
+
Assign(TTree::Expr, TTree::Expr, Option<BinaryOp>),
|
|
125
|
+
PatternAssign(TTree::Pattern, TTree::Expr, Option<DeclType>),
|
|
126
|
+
|
|
125
127
|
Expr(TTree::Expr),
|
|
126
128
|
|
|
127
129
|
Return(TTree::Expr),
|
|
@@ -272,7 +272,8 @@ where
|
|
|
272
272
|
|
|
273
273
|
fn parse_symbol(&mut self) -> TResult<'src, Spanned<Token<'src>>> {
|
|
274
274
|
const POLYGRAMS: &[&str] = &[
|
|
275
|
-
"
|
|
275
|
+
"+=", "-=", "*=", "/=", "|=", "??=", "===", "<=>", "=>", "..", "==", "<>", "<=", ">=",
|
|
276
|
+
"//", "**", "??", ".=",
|
|
276
277
|
];
|
|
277
278
|
const MONOGRAMS: &str = "[](){}<>.,;:!?@$%^&*+-=|\\/`~";
|
|
278
279
|
|
|
@@ -123,10 +123,9 @@ where
|
|
|
123
123
|
just(Token::Symbol(symbol))
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
pub fn match_pattern<'tokens, 'src: 'tokens, TInput, PIdent, PQualIdent,
|
|
126
|
+
pub fn match_pattern<'tokens, 'src: 'tokens, TInput, PIdent, PQualIdent, PLiteral>(
|
|
127
127
|
ident: PIdent,
|
|
128
128
|
qualified_ident: PQualIdent,
|
|
129
|
-
sexpr: PExpr,
|
|
130
129
|
literal: PLiteral,
|
|
131
130
|
) -> (
|
|
132
131
|
impl Parser<'tokens, TInput, SPattern<'src>, TExtra<'tokens, 'src>> + Clone,
|
|
@@ -137,7 +136,6 @@ where
|
|
|
137
136
|
TInput: ValueInput<'tokens, Token = Token<'src>, Span = Span>,
|
|
138
137
|
PIdent: Parser<'tokens, TInput, SIdent<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
139
138
|
PQualIdent: Parser<'tokens, TInput, SExpr<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
140
|
-
PExpr: Parser<'tokens, TInput, SExpr<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
141
139
|
PLiteral: Parser<'tokens, TInput, SLiteral<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
142
140
|
{
|
|
143
141
|
let mut pattern =
|
|
@@ -153,24 +151,16 @@ where
|
|
|
153
151
|
if id.value.0 == "_" { None } else { Some(id) }
|
|
154
152
|
}
|
|
155
153
|
|
|
154
|
+
let capture_pattern = ident
|
|
155
|
+
.clone()
|
|
156
|
+
.map(to_wildcard)
|
|
157
|
+
.map(Pattern::Capture)
|
|
158
|
+
.spanned_pattern()
|
|
159
|
+
.boxed();
|
|
160
|
+
|
|
156
161
|
let value_pattern = symbol(".")
|
|
157
|
-
.
|
|
158
|
-
.
|
|
159
|
-
.then(qualified_ident.clone())
|
|
160
|
-
.try_map(|(q, value), _e| {
|
|
161
|
-
Ok(if let Expr::RawAttribute(..) = value.value {
|
|
162
|
-
Pattern::Value(value.indirect())
|
|
163
|
-
} else if q.is_some() {
|
|
164
|
-
Pattern::Value(value.indirect())
|
|
165
|
-
} else if let Expr::Ident(id) = value.value {
|
|
166
|
-
Pattern::Capture(to_wildcard(id))
|
|
167
|
-
} else {
|
|
168
|
-
return Err(Rich::custom(
|
|
169
|
-
value.span,
|
|
170
|
-
"Internal error: value pattern must be an identifier or attribute",
|
|
171
|
-
));
|
|
172
|
-
})
|
|
173
|
-
})
|
|
162
|
+
.ignore_then(qualified_ident.clone())
|
|
163
|
+
.map(|value| Pattern::Value(value.indirect()))
|
|
174
164
|
.spanned_pattern()
|
|
175
165
|
.boxed();
|
|
176
166
|
|
|
@@ -210,7 +200,6 @@ where
|
|
|
210
200
|
if items.len() == 1 && last_comma.is_none() {
|
|
211
201
|
let item = items.into_iter().next().unwrap();
|
|
212
202
|
if let PatternSequenceItem::Item(inner) = item {
|
|
213
|
-
// TODO ???
|
|
214
203
|
inner.extract()
|
|
215
204
|
} else {
|
|
216
205
|
Pattern::Sequence(vec![item]).spanned(e.span())
|
|
@@ -231,9 +220,9 @@ where
|
|
|
231
220
|
.map(|id| Expr::Literal(Literal::Str(id.value.0).spanned(id.span)))
|
|
232
221
|
.spanned_expr(),
|
|
233
222
|
literal.clone().map(Expr::Literal).spanned_expr(),
|
|
234
|
-
|
|
223
|
+
qualified_ident
|
|
235
224
|
.clone()
|
|
236
|
-
.
|
|
225
|
+
.delimited_by(symbol("("), symbol(")")),
|
|
237
226
|
))
|
|
238
227
|
.then_ignore(symbol(":"))
|
|
239
228
|
.then(pattern.clone())
|
|
@@ -276,6 +265,7 @@ where
|
|
|
276
265
|
let closed_pattern = choice((
|
|
277
266
|
literal_pattern,
|
|
278
267
|
class_pattern,
|
|
268
|
+
capture_pattern,
|
|
279
269
|
value_pattern.clone(),
|
|
280
270
|
group_pattern,
|
|
281
271
|
sequence_pattern,
|
|
@@ -477,12 +467,23 @@ where
|
|
|
477
467
|
})
|
|
478
468
|
}
|
|
479
469
|
|
|
480
|
-
pub fn statement<
|
|
470
|
+
pub fn statement<
|
|
471
|
+
'tokens,
|
|
472
|
+
'src: 'tokens,
|
|
473
|
+
TInput,
|
|
474
|
+
PBody,
|
|
475
|
+
PTuple,
|
|
476
|
+
PExpr,
|
|
477
|
+
PIdent,
|
|
478
|
+
PNaryPattern,
|
|
479
|
+
PPattern,
|
|
480
|
+
>(
|
|
481
481
|
expr_or_inline_stmt_or_block: PBody,
|
|
482
482
|
nary_tuple: PTuple,
|
|
483
483
|
expr: PExpr,
|
|
484
484
|
ident: PIdent,
|
|
485
|
-
nary_pattern:
|
|
485
|
+
nary_pattern: PNaryPattern,
|
|
486
|
+
pattern: PPattern,
|
|
486
487
|
) -> (
|
|
487
488
|
impl Parser<'tokens, TInput, SStmt<'src>, TExtra<'tokens, 'src>> + Clone,
|
|
488
489
|
impl Parser<'tokens, TInput, SStmt<'src>, TExtra<'tokens, 'src>> + Clone,
|
|
@@ -493,6 +494,7 @@ where
|
|
|
493
494
|
PTuple: Parser<'tokens, TInput, SExpr<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
494
495
|
PExpr: Parser<'tokens, TInput, SExpr<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
495
496
|
PIdent: Parser<'tokens, TInput, SIdent<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
497
|
+
PNaryPattern: Parser<'tokens, TInput, SPattern<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
496
498
|
PPattern: Parser<'tokens, TInput, SPattern<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
497
499
|
{
|
|
498
500
|
let mut stmt = Recursive::<chumsky::recursive::Indirect<TInput, SStmt, TExtra>>::declare();
|
|
@@ -512,33 +514,55 @@ where
|
|
|
512
514
|
.map(|(decl, idents)| SStmtInner::Decl(idents, decl))
|
|
513
515
|
.boxed();
|
|
514
516
|
|
|
515
|
-
let
|
|
516
|
-
let inline_assign_lhs = expr.clone();
|
|
517
|
-
|
|
518
|
-
let assign_stmt = group((
|
|
517
|
+
let pattern_assign_stmt = group((
|
|
519
518
|
decl_mod.clone().or_not(),
|
|
520
|
-
|
|
519
|
+
nary_pattern.clone(),
|
|
521
520
|
symbol("=").ignore_then(nary_tuple.clone()),
|
|
522
521
|
))
|
|
523
|
-
.map(|(decl,
|
|
522
|
+
.map(|(decl, pat, rhs)| SStmtInner::PatternAssign(pat.indirect(), rhs.indirect(), decl))
|
|
524
523
|
.boxed();
|
|
525
524
|
|
|
526
|
-
let
|
|
525
|
+
let inline_pattern_assign_stmt = group((
|
|
527
526
|
decl_mod.clone().or_not(),
|
|
528
|
-
|
|
527
|
+
pattern.clone(),
|
|
529
528
|
symbol("=").ignore_then(expr.clone()),
|
|
530
529
|
))
|
|
531
|
-
.map(|(decl,
|
|
530
|
+
.map(|(decl, pat, rhs)| SStmtInner::PatternAssign(pat.indirect(), rhs.indirect(), decl))
|
|
532
531
|
.boxed();
|
|
533
532
|
|
|
534
|
-
let
|
|
535
|
-
.
|
|
536
|
-
.
|
|
537
|
-
.
|
|
533
|
+
let aug_op = choice((
|
|
534
|
+
symbol("+=").to(BinaryOp::Add),
|
|
535
|
+
symbol("-=").to(BinaryOp::Sub),
|
|
536
|
+
symbol("*=").to(BinaryOp::Mul),
|
|
537
|
+
symbol("/=").to(BinaryOp::Div),
|
|
538
|
+
symbol("|=").to(BinaryOp::Pipe),
|
|
539
|
+
symbol("??=").to(BinaryOp::Coalesce),
|
|
540
|
+
))
|
|
541
|
+
.map(Some);
|
|
538
542
|
|
|
539
|
-
let
|
|
540
|
-
|
|
541
|
-
|
|
543
|
+
let assign_op = choice((aug_op, symbol("=").to(None)));
|
|
544
|
+
|
|
545
|
+
let assign_stmt = group((
|
|
546
|
+
nary_tuple.clone(),
|
|
547
|
+
assign_op.clone().then(nary_tuple.clone()).or_not(),
|
|
548
|
+
))
|
|
549
|
+
.map(|(lhs, rhs)| {
|
|
550
|
+
if let Some((op, rhs)) = rhs {
|
|
551
|
+
SStmtInner::Assign(lhs.indirect(), rhs.indirect(), op)
|
|
552
|
+
} else {
|
|
553
|
+
SStmtInner::Expr(lhs.indirect())
|
|
554
|
+
}
|
|
555
|
+
})
|
|
556
|
+
.boxed();
|
|
557
|
+
|
|
558
|
+
let inline_assign_stmt = group((expr.clone(), assign_op.clone().then(expr.clone()).or_not()))
|
|
559
|
+
.map(|(lhs, rhs)| {
|
|
560
|
+
if let Some((op, rhs)) = rhs {
|
|
561
|
+
SStmtInner::Assign(lhs.indirect(), rhs.indirect(), op)
|
|
562
|
+
} else {
|
|
563
|
+
SStmtInner::Expr(lhs.indirect())
|
|
564
|
+
}
|
|
565
|
+
})
|
|
542
566
|
.boxed();
|
|
543
567
|
|
|
544
568
|
let while_stmt = just(Token::Kw("while"))
|
|
@@ -690,8 +714,8 @@ where
|
|
|
690
714
|
stmt.define(
|
|
691
715
|
choice((
|
|
692
716
|
decl_stmt.then_ignore(just(Token::Eol)),
|
|
717
|
+
pattern_assign_stmt.then_ignore(just(Token::Eol)),
|
|
693
718
|
assign_stmt.then_ignore(just(Token::Eol)),
|
|
694
|
-
expr_stmt.then_ignore(just(Token::Eol)),
|
|
695
719
|
while_stmt.clone().then_ignore(just(Token::Eol)),
|
|
696
720
|
for_stmt.clone().then_ignore(just(Token::Eol)),
|
|
697
721
|
return_stmt.then_ignore(just(Token::Eol)),
|
|
@@ -709,8 +733,8 @@ where
|
|
|
709
733
|
|
|
710
734
|
inline_stmt.define(
|
|
711
735
|
choice((
|
|
736
|
+
inline_pattern_assign_stmt,
|
|
712
737
|
inline_assign_stmt,
|
|
713
|
-
inline_expr_stmt,
|
|
714
738
|
while_stmt,
|
|
715
739
|
for_stmt,
|
|
716
740
|
inline_return_stmt,
|
|
@@ -862,6 +886,25 @@ where
|
|
|
862
886
|
.boxed();
|
|
863
887
|
// .memoized();
|
|
864
888
|
|
|
889
|
+
let tuple = choice((
|
|
890
|
+
symbol("(")
|
|
891
|
+
.then(symbol(")"))
|
|
892
|
+
.map(|_| Expr::Tuple(vec![]))
|
|
893
|
+
.spanned_expr(),
|
|
894
|
+
nary_tuple
|
|
895
|
+
.clone()
|
|
896
|
+
.delimited_by_with_eol(just(Token::Symbol("(")), just(Token::Symbol(")"))),
|
|
897
|
+
))
|
|
898
|
+
.boxed();
|
|
899
|
+
|
|
900
|
+
let round_brackets = choice((
|
|
901
|
+
tuple.clone(),
|
|
902
|
+
block
|
|
903
|
+
.clone()
|
|
904
|
+
.delimited_by_with_eol(symbol("("), symbol(")")),
|
|
905
|
+
))
|
|
906
|
+
.boxed();
|
|
907
|
+
|
|
865
908
|
let mapping = enumeration(
|
|
866
909
|
choice((
|
|
867
910
|
symbol("**")
|
|
@@ -873,7 +916,7 @@ where
|
|
|
873
916
|
.map(|id| Expr::Literal(Literal::Str(id.value.0).spanned(id.span)))
|
|
874
917
|
.spanned_expr(),
|
|
875
918
|
literal_expr.clone(),
|
|
876
|
-
|
|
919
|
+
round_brackets.clone(),
|
|
877
920
|
))
|
|
878
921
|
.then_ignore(symbol(":"))
|
|
879
922
|
.then(expr.clone())
|
|
@@ -974,12 +1017,8 @@ where
|
|
|
974
1017
|
)
|
|
975
1018
|
.boxed();
|
|
976
1019
|
|
|
977
|
-
let (closed_pattern, as_pattern, nary_pattern) =
|
|
978
|
-
ident.clone(),
|
|
979
|
-
qualified_ident.clone(),
|
|
980
|
-
expr.clone(),
|
|
981
|
-
literal.clone(),
|
|
982
|
-
);
|
|
1020
|
+
let (closed_pattern, as_pattern, nary_pattern) =
|
|
1021
|
+
match_pattern(ident.clone(), qualified_ident.clone(), literal.clone());
|
|
983
1022
|
|
|
984
1023
|
let classic_match = just(Token::Kw("match"))
|
|
985
1024
|
.ignore_then(expr.clone())
|
|
@@ -991,17 +1030,6 @@ where
|
|
|
991
1030
|
.as_context()
|
|
992
1031
|
.boxed();
|
|
993
1032
|
|
|
994
|
-
let tuple = choice((
|
|
995
|
-
symbol("(")
|
|
996
|
-
.then(symbol(")"))
|
|
997
|
-
.map(|_| Expr::Tuple(vec![]))
|
|
998
|
-
.spanned_expr(),
|
|
999
|
-
nary_tuple
|
|
1000
|
-
.clone()
|
|
1001
|
-
.delimited_by_with_eol(just(Token::Symbol("(")), just(Token::Symbol(")"))),
|
|
1002
|
-
))
|
|
1003
|
-
.boxed();
|
|
1004
|
-
|
|
1005
1033
|
enum ControlKw {
|
|
1006
1034
|
Await,
|
|
1007
1035
|
Yield,
|
|
@@ -1054,10 +1082,7 @@ where
|
|
|
1054
1082
|
list.clone(),
|
|
1055
1083
|
mapping,
|
|
1056
1084
|
fstr,
|
|
1057
|
-
|
|
1058
|
-
block
|
|
1059
|
-
.clone()
|
|
1060
|
-
.delimited_by_with_eol(symbol("("), symbol(")")),
|
|
1085
|
+
round_brackets.clone(),
|
|
1061
1086
|
))
|
|
1062
1087
|
.labelled("atom"),
|
|
1063
1088
|
);
|
|
@@ -1439,6 +1464,7 @@ where
|
|
|
1439
1464
|
expr.clone(),
|
|
1440
1465
|
ident.clone(),
|
|
1441
1466
|
nary_pattern.clone(),
|
|
1467
|
+
as_pattern.clone(),
|
|
1442
1468
|
);
|
|
1443
1469
|
|
|
1444
1470
|
stmt.define(stmt_.labelled("statement").boxed());
|
|
@@ -33,9 +33,9 @@ impl AstBuilder {
|
|
|
33
33
|
&self,
|
|
34
34
|
target: impl Into<Indirect<SExpr<'src>>>,
|
|
35
35
|
value: impl Into<Indirect<SExpr<'src>>>,
|
|
36
|
-
|
|
36
|
+
aug_op: Option<BinaryOp>,
|
|
37
37
|
) -> SStmt<'src> {
|
|
38
|
-
Stmt::Assign(target.into(), value.into(),
|
|
38
|
+
Stmt::Assign(target.into(), value.into(), aug_op).spanned(self.span)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
pub fn return_<'src>(&self, expr: impl IntoIndirect<SExpr<'src>>) -> SStmt<'src> {
|
|
@@ -22,7 +22,11 @@ impl<'src, 'ast> SStmtExt<'src, 'ast> for Indirect<SStmt<'src>> {
|
|
|
22
22
|
fn traverse(&'ast self, ctx: &mut InferenceCtx<'src, '_>) -> Type {
|
|
23
23
|
match &self.value {
|
|
24
24
|
Stmt::Expr(expr) => expr.traverse(ctx),
|
|
25
|
-
Stmt::
|
|
25
|
+
Stmt::PatternAssign(_lhs, rhs, _decl_type) => {
|
|
26
|
+
rhs.traverse(ctx);
|
|
27
|
+
Type::NoReturn
|
|
28
|
+
}
|
|
29
|
+
Stmt::Assign(lhs, rhs, _op) => {
|
|
26
30
|
lhs.traverse(ctx);
|
|
27
31
|
rhs.traverse(ctx);
|
|
28
32
|
Type::NoReturn
|
|
@@ -66,7 +66,7 @@ pub enum PyStmt<'a> {
|
|
|
66
66
|
Expr(SPyExpr<'a>),
|
|
67
67
|
If(SPyExpr<'a>, PyBlock<'a>, Option<PyBlock<'a>>),
|
|
68
68
|
Match(SPyExpr<'a>, Vec<PyMatchCase<'a>>),
|
|
69
|
-
Assign(SPyExpr<'a>, SPyExpr<'a>),
|
|
69
|
+
Assign(SPyExpr<'a>, SPyExpr<'a>, Option<PyBinaryOp>),
|
|
70
70
|
Return(SPyExpr<'a>),
|
|
71
71
|
Raise(Option<SPyExpr<'a>>),
|
|
72
72
|
Assert(SPyExpr<'a>, Option<SPyExpr<'a>>),
|