koatl 0.1.26__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.26 → koatl-0.1.27}/Cargo.lock +1 -1
- {koatl-0.1.26 → koatl-0.1.27}/PKG-INFO +1 -1
- {koatl-0.1.26 → koatl-0.1.27}/koatl/Cargo.toml +1 -1
- {koatl-0.1.26 → koatl-0.1.27}/koatl/src/emit_py.rs +28 -2
- {koatl-0.1.26 → 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.26 → 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.26 → koatl-0.1.27}/koatl/tests/e2e/prelude/memo.tl +17 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/prelude/reader.tl +1 -1
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/parser/src/ast.rs +3 -1
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/parser/src/lexer.rs +2 -1
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/parser/src/parser.rs +91 -64
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/parser/src/util.rs +2 -2
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/src/inference.rs +5 -1
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/src/py/ast.rs +1 -1
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/src/py/emit.rs +7 -2
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/src/py/util.rs +10 -1
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/src/resolve_scopes.rs +98 -105
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/src/transform.rs +192 -399
- {koatl-0.1.26 → koatl-0.1.27}/Cargo.toml +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/README.md +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/.github/workflows/CI.yml +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/.gitignore +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/LICENSE +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/README.md +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/__init__.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/__main__.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/cli.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/prelude/functional/__init__.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/prelude/functional/algebra.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/prelude/functional/async.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/prelude/functional/async_util.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/prelude/functional/list.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/prelude/functional/memo.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/prelude/functional/reader.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/prelude/functional/result.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/prelude/iterable.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/runtime/__init__.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/runtime/helpers.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/runtime/record.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/python/koatl/runtime/virtual.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/requirements.txt +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/src/lib.rs +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/coal.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/containers.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/decorators.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/escape_ident.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/fstr.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/functions.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/generator.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/if_expr.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/imports.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/loops.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/match.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/nary-list.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/placeholder.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/precedence.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/semantic_whitespace.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/base/short_circuit.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/destructure.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/prelude/async.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/prelude/iterables.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/prelude/list.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/prelude/result.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/prelude/slice.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/prelude/try.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/prelude/virtual.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/util/__init__.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/util/module0.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/util/module1.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/e2e/util/module2.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/parse/arith.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/parse/assign.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/parse/block-comments.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/parse/deco.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/parse/func.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/parse/matches.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/test_e2e.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl/tests/test_parse.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/Cargo.toml +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/parser/Cargo.toml +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/parser/src/lib.rs +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/parser/tests/lexer.rs +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/src/lib.rs +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/src/main.rs +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/src/parse_timer.rs +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/src/parser.rs +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/src/py/mod.rs +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/src/types.rs +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/koatl-core/src/util.rs +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/pyproject.toml +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/__init__.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/__main__.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/cli.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/prelude/functional/__init__.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/prelude/functional/algebra.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/prelude/functional/async.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/prelude/functional/async_util.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/prelude/functional/list.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/prelude/functional/memo.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/prelude/functional/reader.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/prelude/functional/result.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/prelude/iterable.tl +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/runtime/__init__.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/runtime/helpers.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/runtime/record.py +0 -0
- {koatl-0.1.26 → koatl-0.1.27}/python/koatl/runtime/virtual.py +0 -0
|
@@ -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
|
|
|
@@ -230,9 +220,9 @@ where
|
|
|
230
220
|
.map(|id| Expr::Literal(Literal::Str(id.value.0).spanned(id.span)))
|
|
231
221
|
.spanned_expr(),
|
|
232
222
|
literal.clone().map(Expr::Literal).spanned_expr(),
|
|
233
|
-
|
|
223
|
+
qualified_ident
|
|
234
224
|
.clone()
|
|
235
|
-
.
|
|
225
|
+
.delimited_by(symbol("("), symbol(")")),
|
|
236
226
|
))
|
|
237
227
|
.then_ignore(symbol(":"))
|
|
238
228
|
.then(pattern.clone())
|
|
@@ -275,6 +265,7 @@ where
|
|
|
275
265
|
let closed_pattern = choice((
|
|
276
266
|
literal_pattern,
|
|
277
267
|
class_pattern,
|
|
268
|
+
capture_pattern,
|
|
278
269
|
value_pattern.clone(),
|
|
279
270
|
group_pattern,
|
|
280
271
|
sequence_pattern,
|
|
@@ -476,12 +467,23 @@ where
|
|
|
476
467
|
})
|
|
477
468
|
}
|
|
478
469
|
|
|
479
|
-
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
|
+
>(
|
|
480
481
|
expr_or_inline_stmt_or_block: PBody,
|
|
481
482
|
nary_tuple: PTuple,
|
|
482
483
|
expr: PExpr,
|
|
483
484
|
ident: PIdent,
|
|
484
|
-
nary_pattern:
|
|
485
|
+
nary_pattern: PNaryPattern,
|
|
486
|
+
pattern: PPattern,
|
|
485
487
|
) -> (
|
|
486
488
|
impl Parser<'tokens, TInput, SStmt<'src>, TExtra<'tokens, 'src>> + Clone,
|
|
487
489
|
impl Parser<'tokens, TInput, SStmt<'src>, TExtra<'tokens, 'src>> + Clone,
|
|
@@ -492,6 +494,7 @@ where
|
|
|
492
494
|
PTuple: Parser<'tokens, TInput, SExpr<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
493
495
|
PExpr: Parser<'tokens, TInput, SExpr<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
494
496
|
PIdent: Parser<'tokens, TInput, SIdent<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
497
|
+
PNaryPattern: Parser<'tokens, TInput, SPattern<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
495
498
|
PPattern: Parser<'tokens, TInput, SPattern<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
496
499
|
{
|
|
497
500
|
let mut stmt = Recursive::<chumsky::recursive::Indirect<TInput, SStmt, TExtra>>::declare();
|
|
@@ -511,33 +514,55 @@ where
|
|
|
511
514
|
.map(|(decl, idents)| SStmtInner::Decl(idents, decl))
|
|
512
515
|
.boxed();
|
|
513
516
|
|
|
514
|
-
let
|
|
515
|
-
let inline_assign_lhs = expr.clone();
|
|
516
|
-
|
|
517
|
-
let assign_stmt = group((
|
|
517
|
+
let pattern_assign_stmt = group((
|
|
518
518
|
decl_mod.clone().or_not(),
|
|
519
|
-
|
|
519
|
+
nary_pattern.clone(),
|
|
520
520
|
symbol("=").ignore_then(nary_tuple.clone()),
|
|
521
521
|
))
|
|
522
|
-
.map(|(decl,
|
|
522
|
+
.map(|(decl, pat, rhs)| SStmtInner::PatternAssign(pat.indirect(), rhs.indirect(), decl))
|
|
523
523
|
.boxed();
|
|
524
524
|
|
|
525
|
-
let
|
|
525
|
+
let inline_pattern_assign_stmt = group((
|
|
526
526
|
decl_mod.clone().or_not(),
|
|
527
|
-
|
|
527
|
+
pattern.clone(),
|
|
528
528
|
symbol("=").ignore_then(expr.clone()),
|
|
529
529
|
))
|
|
530
|
-
.map(|(decl,
|
|
530
|
+
.map(|(decl, pat, rhs)| SStmtInner::PatternAssign(pat.indirect(), rhs.indirect(), decl))
|
|
531
531
|
.boxed();
|
|
532
532
|
|
|
533
|
-
let
|
|
534
|
-
.
|
|
535
|
-
.
|
|
536
|
-
.
|
|
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);
|
|
537
542
|
|
|
538
|
-
let
|
|
539
|
-
|
|
540
|
-
|
|
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
|
+
})
|
|
541
566
|
.boxed();
|
|
542
567
|
|
|
543
568
|
let while_stmt = just(Token::Kw("while"))
|
|
@@ -689,8 +714,8 @@ where
|
|
|
689
714
|
stmt.define(
|
|
690
715
|
choice((
|
|
691
716
|
decl_stmt.then_ignore(just(Token::Eol)),
|
|
717
|
+
pattern_assign_stmt.then_ignore(just(Token::Eol)),
|
|
692
718
|
assign_stmt.then_ignore(just(Token::Eol)),
|
|
693
|
-
expr_stmt.then_ignore(just(Token::Eol)),
|
|
694
719
|
while_stmt.clone().then_ignore(just(Token::Eol)),
|
|
695
720
|
for_stmt.clone().then_ignore(just(Token::Eol)),
|
|
696
721
|
return_stmt.then_ignore(just(Token::Eol)),
|
|
@@ -708,8 +733,8 @@ where
|
|
|
708
733
|
|
|
709
734
|
inline_stmt.define(
|
|
710
735
|
choice((
|
|
736
|
+
inline_pattern_assign_stmt,
|
|
711
737
|
inline_assign_stmt,
|
|
712
|
-
inline_expr_stmt,
|
|
713
738
|
while_stmt,
|
|
714
739
|
for_stmt,
|
|
715
740
|
inline_return_stmt,
|
|
@@ -861,6 +886,25 @@ where
|
|
|
861
886
|
.boxed();
|
|
862
887
|
// .memoized();
|
|
863
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
|
+
|
|
864
908
|
let mapping = enumeration(
|
|
865
909
|
choice((
|
|
866
910
|
symbol("**")
|
|
@@ -872,7 +916,7 @@ where
|
|
|
872
916
|
.map(|id| Expr::Literal(Literal::Str(id.value.0).spanned(id.span)))
|
|
873
917
|
.spanned_expr(),
|
|
874
918
|
literal_expr.clone(),
|
|
875
|
-
|
|
919
|
+
round_brackets.clone(),
|
|
876
920
|
))
|
|
877
921
|
.then_ignore(symbol(":"))
|
|
878
922
|
.then(expr.clone())
|
|
@@ -973,12 +1017,8 @@ where
|
|
|
973
1017
|
)
|
|
974
1018
|
.boxed();
|
|
975
1019
|
|
|
976
|
-
let (closed_pattern, as_pattern, nary_pattern) =
|
|
977
|
-
ident.clone(),
|
|
978
|
-
qualified_ident.clone(),
|
|
979
|
-
expr.clone(),
|
|
980
|
-
literal.clone(),
|
|
981
|
-
);
|
|
1020
|
+
let (closed_pattern, as_pattern, nary_pattern) =
|
|
1021
|
+
match_pattern(ident.clone(), qualified_ident.clone(), literal.clone());
|
|
982
1022
|
|
|
983
1023
|
let classic_match = just(Token::Kw("match"))
|
|
984
1024
|
.ignore_then(expr.clone())
|
|
@@ -990,17 +1030,6 @@ where
|
|
|
990
1030
|
.as_context()
|
|
991
1031
|
.boxed();
|
|
992
1032
|
|
|
993
|
-
let tuple = choice((
|
|
994
|
-
symbol("(")
|
|
995
|
-
.then(symbol(")"))
|
|
996
|
-
.map(|_| Expr::Tuple(vec![]))
|
|
997
|
-
.spanned_expr(),
|
|
998
|
-
nary_tuple
|
|
999
|
-
.clone()
|
|
1000
|
-
.delimited_by_with_eol(just(Token::Symbol("(")), just(Token::Symbol(")"))),
|
|
1001
|
-
))
|
|
1002
|
-
.boxed();
|
|
1003
|
-
|
|
1004
1033
|
enum ControlKw {
|
|
1005
1034
|
Await,
|
|
1006
1035
|
Yield,
|
|
@@ -1053,10 +1082,7 @@ where
|
|
|
1053
1082
|
list.clone(),
|
|
1054
1083
|
mapping,
|
|
1055
1084
|
fstr,
|
|
1056
|
-
|
|
1057
|
-
block
|
|
1058
|
-
.clone()
|
|
1059
|
-
.delimited_by_with_eol(symbol("("), symbol(")")),
|
|
1085
|
+
round_brackets.clone(),
|
|
1060
1086
|
))
|
|
1061
1087
|
.labelled("atom"),
|
|
1062
1088
|
);
|
|
@@ -1438,6 +1464,7 @@ where
|
|
|
1438
1464
|
expr.clone(),
|
|
1439
1465
|
ident.clone(),
|
|
1440
1466
|
nary_pattern.clone(),
|
|
1467
|
+
as_pattern.clone(),
|
|
1441
1468
|
);
|
|
1442
1469
|
|
|
1443
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>>),
|
|
@@ -572,10 +572,15 @@ impl SPyStmt<'_> {
|
|
|
572
572
|
expr.emit_to(ctx, LOW_PREC)?;
|
|
573
573
|
ctx.emit_endl();
|
|
574
574
|
}
|
|
575
|
-
PyStmt::Assign(target, value) => {
|
|
575
|
+
PyStmt::Assign(target, value, op) => {
|
|
576
576
|
ctx.emit_indent();
|
|
577
577
|
target.emit_to(ctx, LOW_PREC)?;
|
|
578
|
-
ctx.emit("
|
|
578
|
+
ctx.emit(" ");
|
|
579
|
+
if let Some(op) = op {
|
|
580
|
+
op.emit_to(ctx);
|
|
581
|
+
} else {
|
|
582
|
+
}
|
|
583
|
+
ctx.emit("= ");
|
|
579
584
|
value.emit_to(ctx, LOW_PREC)?;
|
|
580
585
|
ctx.emit_endl();
|
|
581
586
|
}
|
|
@@ -18,7 +18,16 @@ impl PyAstBuilder {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
pub fn assign<'src>(&self, target: SPyExpr<'src>, value: SPyExpr<'src>) -> SPyStmt<'src> {
|
|
21
|
-
(PyStmt::Assign(target, value), self.span).into()
|
|
21
|
+
(PyStmt::Assign(target, value, None), self.span).into()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
pub fn assign_modified<'src>(
|
|
25
|
+
&self,
|
|
26
|
+
target: SPyExpr<'src>,
|
|
27
|
+
value: SPyExpr<'src>,
|
|
28
|
+
op: Option<PyBinaryOp>,
|
|
29
|
+
) -> SPyStmt<'src> {
|
|
30
|
+
(PyStmt::Assign(target, value, op), self.span).into()
|
|
22
31
|
}
|
|
23
32
|
|
|
24
33
|
pub fn return_<'src>(&self, expr: SPyExpr<'src>) -> SPyStmt<'src> {
|