koatl 0.1.20__tar.gz → 0.1.22__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.20 → koatl-0.1.22}/Cargo.lock +1 -1
- {koatl-0.1.20 → koatl-0.1.22}/PKG-INFO +1 -1
- {koatl-0.1.20 → koatl-0.1.22}/koatl/Cargo.toml +1 -1
- {koatl-0.1.20 → koatl-0.1.22/koatl}/python/koatl/prelude/functional/memo.tl +23 -14
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/runtime/helpers.py +1 -1
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/Cargo.toml +4 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/parser/src/ast.rs +0 -1
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/parser/src/parser.rs +251 -211
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/src/inference.rs +0 -1
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/src/main.rs +0 -2
- koatl-0.1.22/koatl-core/src/parse_timer.rs +35 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/src/resolve_scopes.rs +0 -15
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/src/transform.rs +22 -14
- {koatl-0.1.20/koatl → koatl-0.1.22}/python/koatl/prelude/functional/memo.tl +23 -14
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/runtime/helpers.py +1 -1
- {koatl-0.1.20 → koatl-0.1.22}/Cargo.toml +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/README.md +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/.github/workflows/CI.yml +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/.gitignore +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/LICENSE +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/README.md +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/__init__.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/__main__.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/cli.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/prelude/functional/__init__.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/prelude/functional/async.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/prelude/functional/async_util.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/prelude/functional/monad.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/prelude/functional/reader.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/prelude/functional/result.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/prelude/iterable.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/runtime/__init__.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/runtime/record.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/python/koatl/runtime/virtual.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/requirements.txt +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/src/emit_py.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/src/lib.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/coal.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/containers.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/decorators.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/destructure.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/escape_ident.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/fstr.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/functions.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/generator.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/if_expr.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/imports.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/loops.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/match.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/nary-list.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/placeholder.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/precedence.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/scopes.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/semantic_whitespace.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/slice.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/base/try.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/destructure.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/prelude/async.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/prelude/iterables.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/prelude/memo.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/prelude/reader.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/prelude/result.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/prelude/virtual.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/util/__init__.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/util/module0.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/util/module1.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/e2e/util/module2.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/parse/arith.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/parse/assign.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/parse/block-comments.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/parse/deco.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/parse/func.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/parse/matches.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/test_e2e.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl/tests/test_parse.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/parser/Cargo.toml +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/parser/src/lexer.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/parser/src/lib.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/parser/src/util.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/parser/tests/lexer.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/src/lib.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/src/parser.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/src/py/ast.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/src/py/emit.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/src/py/mod.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/src/py/util.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/src/types.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/koatl-core/src/util.rs +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/pyproject.toml +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/__init__.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/__main__.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/cli.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/prelude/functional/__init__.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/prelude/functional/async.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/prelude/functional/async_util.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/prelude/functional/monad.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/prelude/functional/reader.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/prelude/functional/result.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/prelude/iterable.tl +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/runtime/__init__.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/runtime/record.py +0 -0
- {koatl-0.1.20 → koatl-0.1.22}/python/koatl/runtime/virtual.py +0 -0
|
@@ -8,37 +8,46 @@ export Memo = class(Monad):
|
|
|
8
8
|
__init__ = self =>
|
|
9
9
|
self.cache = defaultdict(dict)
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
__repr__ = self => f"Memo.Cache({self.cache})"
|
|
12
|
+
|
|
13
|
+
try_get = (self, name, deps) =>
|
|
14
|
+
try self.cache[name][deps] except KeyError()
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
update = (self, name, deps, value) =>
|
|
16
17
|
self.cache[name][deps] = value
|
|
17
18
|
value
|
|
18
19
|
|
|
19
|
-
__repr__ = self => f"Memo.Cache({self.cache})"
|
|
20
|
-
|
|
21
20
|
__init__ = (self, f) => self.f = f
|
|
22
21
|
|
|
23
22
|
__repr__ = self => f"Memo(...)"
|
|
24
23
|
|
|
25
24
|
value = staticmethod& (id, deps, f) =>
|
|
26
|
-
Memo(ctx =>
|
|
25
|
+
Memo(ctx =>
|
|
26
|
+
if ctx.try_get(id, tuple(deps)) matches Ok() as value:
|
|
27
|
+
return value
|
|
28
|
+
|
|
29
|
+
ctx.update(id, tuple(deps), f())
|
|
30
|
+
)
|
|
27
31
|
|
|
28
32
|
fn = staticmethod& f => wraps(f)& (*args, **kwargs) =>
|
|
29
33
|
let id = f"{f.__module__}.{f.__qualname__}"
|
|
30
34
|
let deps = (tuple(args), tuple(kwargs.items()))
|
|
31
35
|
|
|
32
36
|
Memo(ctx =>
|
|
33
|
-
ctx.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
if ctx.try_get(id, deps) matches Ok() as value:
|
|
38
|
+
return value
|
|
39
|
+
|
|
40
|
+
let v = f(*args, **kwargs)
|
|
41
|
+
if v matches Memo():
|
|
42
|
+
v = v.run(ctx)
|
|
43
|
+
|
|
44
|
+
ctx.update(id, deps, v)
|
|
39
45
|
)
|
|
40
46
|
|
|
41
|
-
run = (self, ctx=
|
|
47
|
+
run = (self, ctx=None) =>
|
|
48
|
+
if ctx === None:
|
|
49
|
+
ctx = Memo.Cache()
|
|
50
|
+
self.f(ctx)
|
|
42
51
|
|
|
43
52
|
pure = staticmethod& value => Memo(ctx => value)
|
|
44
53
|
|
|
@@ -76,7 +76,7 @@ def do(f):
|
|
|
76
76
|
|
|
77
77
|
try:
|
|
78
78
|
# TODO: this is a workaround to avoid recursion.
|
|
79
|
-
# is it possible to
|
|
79
|
+
# is it possible to derive bind_gen directly from bind_once?
|
|
80
80
|
|
|
81
81
|
return vget(m, "bind_gen")(gen)
|
|
82
82
|
except (NotImplementedError, AttributeError):
|
|
@@ -131,6 +131,7 @@ pub fn match_pattern<'tokens, 'src: 'tokens, TInput, PIdent, PQualIdent, PExpr,
|
|
|
131
131
|
) -> (
|
|
132
132
|
impl Parser<'tokens, TInput, SPattern<'src>, TExtra<'tokens, 'src>> + Clone,
|
|
133
133
|
impl Parser<'tokens, TInput, SPattern<'src>, TExtra<'tokens, 'src>> + Clone,
|
|
134
|
+
impl Parser<'tokens, TInput, SPattern<'src>, TExtra<'tokens, 'src>> + Clone,
|
|
134
135
|
)
|
|
135
136
|
where
|
|
136
137
|
TInput: ValueInput<'tokens, Token = Token<'src>, Span = Span>,
|
|
@@ -311,7 +312,7 @@ where
|
|
|
311
312
|
|
|
312
313
|
pattern.define(
|
|
313
314
|
choice((
|
|
314
|
-
as_pattern,
|
|
315
|
+
as_pattern.clone(),
|
|
315
316
|
value_pattern,
|
|
316
317
|
closed_pattern.clone(),
|
|
317
318
|
symbol("_")
|
|
@@ -323,6 +324,7 @@ where
|
|
|
323
324
|
|
|
324
325
|
(
|
|
325
326
|
closed_pattern.labelled("pattern").as_context(),
|
|
327
|
+
as_pattern.labelled("pattern").as_context(),
|
|
326
328
|
nary_sequence_pattern.labelled("pattern").as_context(),
|
|
327
329
|
)
|
|
328
330
|
}
|
|
@@ -475,6 +477,245 @@ where
|
|
|
475
477
|
})
|
|
476
478
|
}
|
|
477
479
|
|
|
480
|
+
pub fn statement<'tokens, 'src: 'tokens, TInput, PBody, PTuple, PExpr, PIdent, PPattern>(
|
|
481
|
+
expr_or_inline_stmt_or_block: PBody,
|
|
482
|
+
nary_tuple: PTuple,
|
|
483
|
+
expr: PExpr,
|
|
484
|
+
ident: PIdent,
|
|
485
|
+
nary_pattern: PPattern,
|
|
486
|
+
) -> (
|
|
487
|
+
impl Parser<'tokens, TInput, SStmt<'src>, TExtra<'tokens, 'src>> + Clone,
|
|
488
|
+
impl Parser<'tokens, TInput, SStmt<'src>, TExtra<'tokens, 'src>> + Clone,
|
|
489
|
+
)
|
|
490
|
+
where
|
|
491
|
+
TInput: ValueInput<'tokens, Token = Token<'src>, Span = Span>,
|
|
492
|
+
PBody: Parser<'tokens, TInput, SExpr<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
493
|
+
PTuple: Parser<'tokens, TInput, SExpr<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
494
|
+
PExpr: Parser<'tokens, TInput, SExpr<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
495
|
+
PIdent: Parser<'tokens, TInput, SIdent<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
496
|
+
PPattern: Parser<'tokens, TInput, SPattern<'src>, TExtra<'tokens, 'src>> + Clone + 'tokens,
|
|
497
|
+
{
|
|
498
|
+
let mut stmt = Recursive::<chumsky::recursive::Indirect<TInput, SStmt, TExtra>>::declare();
|
|
499
|
+
let mut inline_stmt =
|
|
500
|
+
Recursive::<chumsky::recursive::Indirect<TInput, SStmt, TExtra>>::declare();
|
|
501
|
+
|
|
502
|
+
let decl_mod = choice((
|
|
503
|
+
just(Token::Kw("export")).to(DeclType::Export),
|
|
504
|
+
just(Token::Kw("global")).to(DeclType::Global),
|
|
505
|
+
just(Token::Kw("let")).to(DeclType::Let),
|
|
506
|
+
just(Token::Kw("const")).to(DeclType::Const),
|
|
507
|
+
));
|
|
508
|
+
|
|
509
|
+
let decl_stmt = decl_mod
|
|
510
|
+
.clone()
|
|
511
|
+
.then(ident.clone().separated_by(symbol(",")).collect())
|
|
512
|
+
.map(|(decl, idents)| SStmtInner::Decl(idents, decl))
|
|
513
|
+
.boxed();
|
|
514
|
+
|
|
515
|
+
let assign_lhs = nary_tuple.clone();
|
|
516
|
+
let inline_assign_lhs = expr.clone();
|
|
517
|
+
|
|
518
|
+
let assign_stmt = group((
|
|
519
|
+
decl_mod.clone().or_not(),
|
|
520
|
+
assign_lhs.clone(),
|
|
521
|
+
symbol("=").ignore_then(nary_tuple.clone()),
|
|
522
|
+
))
|
|
523
|
+
.map(|(decl, lhs, rhs)| SStmtInner::Assign(lhs.indirect(), rhs.indirect(), decl))
|
|
524
|
+
.boxed();
|
|
525
|
+
|
|
526
|
+
let inline_assign_stmt = group((
|
|
527
|
+
decl_mod.clone().or_not(),
|
|
528
|
+
inline_assign_lhs.clone(),
|
|
529
|
+
symbol("=").ignore_then(expr.clone()),
|
|
530
|
+
))
|
|
531
|
+
.map(|(decl, lhs, rhs)| SStmtInner::Assign(lhs.indirect(), rhs.indirect(), decl))
|
|
532
|
+
.boxed();
|
|
533
|
+
|
|
534
|
+
let expr_stmt = assign_lhs
|
|
535
|
+
.clone()
|
|
536
|
+
.map(|x| SStmtInner::Expr(x.indirect()))
|
|
537
|
+
.boxed();
|
|
538
|
+
|
|
539
|
+
let inline_expr_stmt = inline_assign_lhs
|
|
540
|
+
.clone()
|
|
541
|
+
.map(|x| SStmtInner::Expr(x.indirect()))
|
|
542
|
+
.boxed();
|
|
543
|
+
|
|
544
|
+
let while_stmt = just(Token::Kw("while"))
|
|
545
|
+
.ignore_then(expr.clone())
|
|
546
|
+
.then_ignore(just(START_BLOCK))
|
|
547
|
+
.then(expr_or_inline_stmt_or_block.clone())
|
|
548
|
+
.map(|(cond, body)| SStmtInner::While(cond.indirect(), body.indirect()))
|
|
549
|
+
.labelled("while statement")
|
|
550
|
+
.boxed();
|
|
551
|
+
|
|
552
|
+
let except_block = just(Token::Eol)
|
|
553
|
+
.then(just(Token::Kw("except")))
|
|
554
|
+
.ignore_then(nary_pattern.clone().or_not())
|
|
555
|
+
.boxed()
|
|
556
|
+
.then(just(START_BLOCK).ignore_then(expr_or_inline_stmt_or_block.clone()))
|
|
557
|
+
.map(|(pattern, body)| SMatchCase {
|
|
558
|
+
pattern: pattern.map(|x| x.indirect()),
|
|
559
|
+
guard: None,
|
|
560
|
+
body: body.indirect(),
|
|
561
|
+
})
|
|
562
|
+
.labelled("except block")
|
|
563
|
+
.boxed();
|
|
564
|
+
|
|
565
|
+
let finally_block = one_of([Token::Eol])
|
|
566
|
+
.then(just(Token::Kw("finally")))
|
|
567
|
+
.then(just(START_BLOCK))
|
|
568
|
+
.ignore_then(expr_or_inline_stmt_or_block.clone())
|
|
569
|
+
.labelled("finally block")
|
|
570
|
+
.boxed();
|
|
571
|
+
|
|
572
|
+
let try_stmt = just(Token::Kw("try"))
|
|
573
|
+
.then(just(START_BLOCK))
|
|
574
|
+
.ignore_then(group((
|
|
575
|
+
expr_or_inline_stmt_or_block.clone(),
|
|
576
|
+
except_block.repeated().collect(),
|
|
577
|
+
finally_block.or_not(),
|
|
578
|
+
)))
|
|
579
|
+
.map(|(body, excepts, finally)| {
|
|
580
|
+
SStmtInner::Try(body.indirect(), excepts, finally.map(|x| x.indirect()))
|
|
581
|
+
})
|
|
582
|
+
.labelled("try statement")
|
|
583
|
+
.boxed();
|
|
584
|
+
|
|
585
|
+
let for_stmt = just(Token::Kw("for"))
|
|
586
|
+
.ignore_then(group((
|
|
587
|
+
nary_pattern.clone().then_ignore(just(Token::Kw("in"))),
|
|
588
|
+
expr.clone().then_ignore(just(START_BLOCK)),
|
|
589
|
+
expr_or_inline_stmt_or_block.clone(),
|
|
590
|
+
)))
|
|
591
|
+
.map(|(decl, iter, body)| {
|
|
592
|
+
SStmtInner::For(decl.indirect(), iter.indirect(), body.indirect())
|
|
593
|
+
})
|
|
594
|
+
.labelled("for statement")
|
|
595
|
+
.boxed();
|
|
596
|
+
|
|
597
|
+
let return_stmt = just(Token::Kw("return"))
|
|
598
|
+
.ignore_then(nary_tuple.clone())
|
|
599
|
+
.map(|x| SStmtInner::Return(x.indirect()))
|
|
600
|
+
.labelled("return statement")
|
|
601
|
+
.boxed();
|
|
602
|
+
|
|
603
|
+
let inline_return_stmt = just(Token::Kw("return"))
|
|
604
|
+
.ignore_then(expr.clone())
|
|
605
|
+
.map(|x| SStmtInner::Return(x.indirect()))
|
|
606
|
+
.labelled("inline return statement")
|
|
607
|
+
.boxed();
|
|
608
|
+
|
|
609
|
+
let assert_stmt = just(Token::Ident("assert"))
|
|
610
|
+
.ignore_then(expr.clone())
|
|
611
|
+
.then(symbol(",").ignore_then(expr.clone()).or_not())
|
|
612
|
+
.map(|(x, y)| SStmtInner::Assert(x.indirect(), y.map(|y| y.indirect())))
|
|
613
|
+
.labelled("assert statement")
|
|
614
|
+
.boxed();
|
|
615
|
+
|
|
616
|
+
let raise_stmt = just(Token::Kw("raise"))
|
|
617
|
+
.ignore_then(nary_tuple.clone().or_not())
|
|
618
|
+
.map(|x| SStmtInner::Raise(x.map(|x| x.indirect())))
|
|
619
|
+
.labelled("raise statement")
|
|
620
|
+
.boxed();
|
|
621
|
+
|
|
622
|
+
let inline_raise_stmt = just(Token::Kw("raise"))
|
|
623
|
+
.ignore_then(expr.clone().or_not())
|
|
624
|
+
.map(|x| SStmtInner::Raise(x.map(|x| x.indirect())))
|
|
625
|
+
.labelled("inline raise statement")
|
|
626
|
+
.boxed();
|
|
627
|
+
|
|
628
|
+
let break_stmt = just(Token::Kw("break"))
|
|
629
|
+
.map(|_| SStmtInner::Break)
|
|
630
|
+
.labelled("break statement")
|
|
631
|
+
.boxed();
|
|
632
|
+
|
|
633
|
+
let continue_stmt = just(Token::Kw("continue"))
|
|
634
|
+
.map(|_| SStmtInner::Continue)
|
|
635
|
+
.labelled("continue statement")
|
|
636
|
+
.boxed();
|
|
637
|
+
|
|
638
|
+
let import_stmt = just(Token::Kw("export"))
|
|
639
|
+
.to(1)
|
|
640
|
+
.or_not()
|
|
641
|
+
.then_ignore(just(Token::Kw("import")))
|
|
642
|
+
.then(group((
|
|
643
|
+
symbol(".").repeated().count(),
|
|
644
|
+
ident
|
|
645
|
+
.clone()
|
|
646
|
+
.then_ignore(symbol("."))
|
|
647
|
+
.repeated()
|
|
648
|
+
.collect()
|
|
649
|
+
.boxed(),
|
|
650
|
+
choice((
|
|
651
|
+
enumeration(
|
|
652
|
+
ident
|
|
653
|
+
.clone()
|
|
654
|
+
.then(just(Token::Kw("as")).ignore_then(ident.clone()).or_not()),
|
|
655
|
+
symbol(","),
|
|
656
|
+
)
|
|
657
|
+
.delimited_by_with_eol(symbol("("), symbol(")"))
|
|
658
|
+
.map(ImportList::Leaves)
|
|
659
|
+
.boxed(),
|
|
660
|
+
just(Token::Symbol("*")).map(|_| ImportList::Star),
|
|
661
|
+
ident
|
|
662
|
+
.clone()
|
|
663
|
+
.then(just(Token::Kw("as")).ignore_then(ident.clone()).or_not())
|
|
664
|
+
.map(|x| ImportList::Leaves(vec![x]))
|
|
665
|
+
.boxed(),
|
|
666
|
+
))
|
|
667
|
+
.boxed(),
|
|
668
|
+
)))
|
|
669
|
+
.map(|(reexport, (level, trunk, import_list))| {
|
|
670
|
+
SStmtInner::Import(ImportStmt {
|
|
671
|
+
trunk,
|
|
672
|
+
imports: import_list,
|
|
673
|
+
level,
|
|
674
|
+
reexport: reexport.is_some(),
|
|
675
|
+
})
|
|
676
|
+
})
|
|
677
|
+
.labelled("import statement")
|
|
678
|
+
.boxed();
|
|
679
|
+
|
|
680
|
+
stmt.define(
|
|
681
|
+
choice((
|
|
682
|
+
decl_stmt.then_ignore(just(Token::Eol)),
|
|
683
|
+
assign_stmt.then_ignore(just(Token::Eol)),
|
|
684
|
+
expr_stmt.then_ignore(just(Token::Eol)),
|
|
685
|
+
while_stmt.clone().then_ignore(just(Token::Eol)),
|
|
686
|
+
for_stmt.clone().then_ignore(just(Token::Eol)),
|
|
687
|
+
return_stmt.then_ignore(just(Token::Eol)),
|
|
688
|
+
assert_stmt.then_ignore(just(Token::Eol)),
|
|
689
|
+
raise_stmt.then_ignore(just(Token::Eol)),
|
|
690
|
+
break_stmt.clone().then_ignore(just(Token::Eol)),
|
|
691
|
+
continue_stmt.clone().then_ignore(just(Token::Eol)),
|
|
692
|
+
import_stmt.then_ignore(just(Token::Eol)),
|
|
693
|
+
try_stmt.then_ignore(just(Token::Eol)),
|
|
694
|
+
))
|
|
695
|
+
.labelled("statement")
|
|
696
|
+
.map_with(|x, e| x.spanned(e.span()))
|
|
697
|
+
.boxed(),
|
|
698
|
+
);
|
|
699
|
+
|
|
700
|
+
inline_stmt.define(
|
|
701
|
+
choice((
|
|
702
|
+
inline_assign_stmt,
|
|
703
|
+
inline_expr_stmt,
|
|
704
|
+
while_stmt,
|
|
705
|
+
for_stmt,
|
|
706
|
+
inline_return_stmt,
|
|
707
|
+
inline_raise_stmt,
|
|
708
|
+
break_stmt,
|
|
709
|
+
continue_stmt,
|
|
710
|
+
))
|
|
711
|
+
.labelled("inline-statement")
|
|
712
|
+
.map_with(|x, e| x.spanned(e.span()))
|
|
713
|
+
.boxed(),
|
|
714
|
+
);
|
|
715
|
+
|
|
716
|
+
(stmt, inline_stmt)
|
|
717
|
+
}
|
|
718
|
+
|
|
478
719
|
pub fn parser<'tokens, 'src: 'tokens, TInput>()
|
|
479
720
|
-> impl Parser<'tokens, TInput, SExpr<'src>, TExtra<'tokens, 'src>> + Clone
|
|
480
721
|
where
|
|
@@ -483,6 +724,7 @@ where
|
|
|
483
724
|
let mut stmt = Recursive::<chumsky::recursive::Indirect<TInput, SStmt, TExtra>>::declare();
|
|
484
725
|
let mut inline_stmt =
|
|
485
726
|
Recursive::<chumsky::recursive::Indirect<TInput, SStmt, TExtra>>::declare();
|
|
727
|
+
|
|
486
728
|
let mut atom = Recursive::<chumsky::recursive::Indirect<TInput, SExpr, TExtra>>::declare();
|
|
487
729
|
let mut expr = Recursive::<chumsky::recursive::Indirect<TInput, SExpr, TExtra>>::declare();
|
|
488
730
|
let mut unary = Recursive::<chumsky::recursive::Indirect<TInput, SExpr, TExtra>>::declare();
|
|
@@ -722,7 +964,7 @@ where
|
|
|
722
964
|
)
|
|
723
965
|
.boxed();
|
|
724
966
|
|
|
725
|
-
let (closed_pattern, nary_pattern) = match_pattern(
|
|
967
|
+
let (closed_pattern, as_pattern, nary_pattern) = match_pattern(
|
|
726
968
|
ident.clone(),
|
|
727
969
|
qualified_ident.clone(),
|
|
728
970
|
expr.clone(),
|
|
@@ -1113,7 +1355,7 @@ where
|
|
|
1113
1355
|
.then(
|
|
1114
1356
|
just(Token::Ident("matches"))
|
|
1115
1357
|
.ignore_then(just(Token::Kw("not")).to(0).or_not())
|
|
1116
|
-
.then(
|
|
1358
|
+
.then(as_pattern.clone())
|
|
1117
1359
|
.or_not(),
|
|
1118
1360
|
)
|
|
1119
1361
|
.map_with(|(expr, matches_part), e| {
|
|
@@ -1181,218 +1423,16 @@ where
|
|
|
1181
1423
|
binary6.labelled("expression").as_context().boxed(), // .memoized(),
|
|
1182
1424
|
);
|
|
1183
1425
|
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
let decl_mod = choice((
|
|
1187
|
-
just(Token::Kw("export")).to(DeclType::Export),
|
|
1188
|
-
just(Token::Kw("global")).to(DeclType::Global),
|
|
1189
|
-
just(Token::Kw("let")).to(DeclType::Let),
|
|
1190
|
-
just(Token::Kw("const")).to(DeclType::Const),
|
|
1191
|
-
));
|
|
1192
|
-
|
|
1193
|
-
let decl_stmt = decl_mod
|
|
1194
|
-
.clone()
|
|
1195
|
-
.then(ident.clone().separated_by(symbol(",")).collect())
|
|
1196
|
-
.map(|(decl, idents)| SStmtInner::Decl(idents, decl))
|
|
1197
|
-
.boxed();
|
|
1198
|
-
|
|
1199
|
-
let assign_stmt = group((
|
|
1200
|
-
decl_mod.clone().or_not(),
|
|
1426
|
+
let (stmt_, inline_stmt_) = statement(
|
|
1427
|
+
expr_or_inline_stmt_or_block.clone(),
|
|
1201
1428
|
nary_tuple.clone(),
|
|
1202
|
-
symbol("=").ignore_then(nary_tuple.clone()),
|
|
1203
|
-
))
|
|
1204
|
-
.map(|(decl, lhs, rhs)| SStmtInner::Assign(lhs.indirect(), rhs.indirect(), decl))
|
|
1205
|
-
.boxed();
|
|
1206
|
-
|
|
1207
|
-
let inline_assign_stmt = group((
|
|
1208
|
-
decl_mod.clone().or_not(),
|
|
1209
1429
|
expr.clone(),
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
.map(|(decl, lhs, rhs)| SStmtInner::Assign(lhs.indirect(), rhs.indirect(), decl))
|
|
1213
|
-
.boxed();
|
|
1214
|
-
|
|
1215
|
-
let expr_stmt = nary_tuple
|
|
1216
|
-
.clone()
|
|
1217
|
-
.map(|x| SStmtInner::Expr(x.indirect()))
|
|
1218
|
-
.boxed();
|
|
1219
|
-
|
|
1220
|
-
let inline_expr_stmt = expr.clone().map(|x| SStmtInner::Expr(x.indirect())).boxed();
|
|
1221
|
-
|
|
1222
|
-
let while_stmt = just(Token::Kw("while"))
|
|
1223
|
-
.ignore_then(expr.clone())
|
|
1224
|
-
.then_ignore(just(START_BLOCK))
|
|
1225
|
-
.then(expr_or_inline_stmt_or_block.clone())
|
|
1226
|
-
.map(|(cond, body)| SStmtInner::While(cond.indirect(), body.indirect()))
|
|
1227
|
-
.labelled("while statement")
|
|
1228
|
-
.boxed();
|
|
1229
|
-
|
|
1230
|
-
let except_block = just(Token::Eol)
|
|
1231
|
-
.then(just(Token::Kw("except")))
|
|
1232
|
-
.ignore_then(nary_pattern.clone().or_not())
|
|
1233
|
-
.boxed()
|
|
1234
|
-
.then(just(START_BLOCK).ignore_then(expr_or_inline_stmt_or_block.clone()))
|
|
1235
|
-
.map(|(pattern, body)| SMatchCase {
|
|
1236
|
-
pattern: pattern.map(|x| x.indirect()),
|
|
1237
|
-
guard: None,
|
|
1238
|
-
body: body.indirect(),
|
|
1239
|
-
})
|
|
1240
|
-
.labelled("except block")
|
|
1241
|
-
.boxed();
|
|
1242
|
-
|
|
1243
|
-
let finally_block = one_of([Token::Eol])
|
|
1244
|
-
.then(just(Token::Kw("finally")))
|
|
1245
|
-
.then(just(START_BLOCK))
|
|
1246
|
-
.ignore_then(expr_or_inline_stmt_or_block.clone())
|
|
1247
|
-
.labelled("finally block")
|
|
1248
|
-
.boxed();
|
|
1249
|
-
|
|
1250
|
-
let try_stmt = just(Token::Kw("try"))
|
|
1251
|
-
.then(just(START_BLOCK))
|
|
1252
|
-
.ignore_then(group((
|
|
1253
|
-
expr_or_inline_stmt_or_block.clone(),
|
|
1254
|
-
except_block.repeated().collect(),
|
|
1255
|
-
finally_block.or_not(),
|
|
1256
|
-
)))
|
|
1257
|
-
.map(|(body, excepts, finally)| {
|
|
1258
|
-
SStmtInner::Try(body.indirect(), excepts, finally.map(|x| x.indirect()))
|
|
1259
|
-
})
|
|
1260
|
-
.labelled("try statement")
|
|
1261
|
-
.boxed();
|
|
1262
|
-
|
|
1263
|
-
let for_stmt = just(Token::Kw("for"))
|
|
1264
|
-
.ignore_then(group((
|
|
1265
|
-
nary_pattern.clone().then_ignore(just(Token::Kw("in"))),
|
|
1266
|
-
expr.clone().then_ignore(just(START_BLOCK)),
|
|
1267
|
-
expr_or_inline_stmt_or_block.clone(),
|
|
1268
|
-
)))
|
|
1269
|
-
.map(|(decl, iter, body)| {
|
|
1270
|
-
SStmtInner::For(decl.indirect(), iter.indirect(), body.indirect())
|
|
1271
|
-
})
|
|
1272
|
-
.labelled("for statement")
|
|
1273
|
-
.boxed();
|
|
1274
|
-
|
|
1275
|
-
let return_stmt = just(Token::Kw("return"))
|
|
1276
|
-
.ignore_then(nary_tuple.clone())
|
|
1277
|
-
.map(|x| SStmtInner::Return(x.indirect()))
|
|
1278
|
-
.labelled("return statement")
|
|
1279
|
-
.boxed();
|
|
1280
|
-
|
|
1281
|
-
let inline_return_stmt = just(Token::Kw("return"))
|
|
1282
|
-
.ignore_then(expr.clone())
|
|
1283
|
-
.map(|x| SStmtInner::Return(x.indirect()))
|
|
1284
|
-
.labelled("inline return statement")
|
|
1285
|
-
.boxed();
|
|
1286
|
-
|
|
1287
|
-
let assert_stmt = just(Token::Ident("assert"))
|
|
1288
|
-
.ignore_then(expr.clone())
|
|
1289
|
-
.then(symbol(",").ignore_then(expr.clone()).or_not())
|
|
1290
|
-
.map(|(x, y)| SStmtInner::Assert(x.indirect(), y.map(|y| y.indirect())))
|
|
1291
|
-
.labelled("assert statement")
|
|
1292
|
-
.boxed();
|
|
1293
|
-
|
|
1294
|
-
let raise_stmt = just(Token::Kw("raise"))
|
|
1295
|
-
.ignore_then(nary_tuple.clone().or_not())
|
|
1296
|
-
.map(|x| SStmtInner::Raise(x.map(|x| x.indirect())))
|
|
1297
|
-
.labelled("raise statement")
|
|
1298
|
-
.boxed();
|
|
1299
|
-
|
|
1300
|
-
let inline_raise_stmt = just(Token::Kw("raise"))
|
|
1301
|
-
.ignore_then(expr.clone().or_not())
|
|
1302
|
-
.map(|x| SStmtInner::Raise(x.map(|x| x.indirect())))
|
|
1303
|
-
.labelled("inline raise statement")
|
|
1304
|
-
.boxed();
|
|
1305
|
-
|
|
1306
|
-
let break_stmt = just(Token::Kw("break"))
|
|
1307
|
-
.map(|_| SStmtInner::Break)
|
|
1308
|
-
.labelled("break statement")
|
|
1309
|
-
.boxed();
|
|
1310
|
-
|
|
1311
|
-
let continue_stmt = just(Token::Kw("continue"))
|
|
1312
|
-
.map(|_| SStmtInner::Continue)
|
|
1313
|
-
.labelled("continue statement")
|
|
1314
|
-
.boxed();
|
|
1315
|
-
|
|
1316
|
-
let import_stmt = just(Token::Kw("export"))
|
|
1317
|
-
.to(1)
|
|
1318
|
-
.or_not()
|
|
1319
|
-
.then_ignore(just(Token::Kw("import")))
|
|
1320
|
-
.then(group((
|
|
1321
|
-
symbol(".").repeated().count(),
|
|
1322
|
-
ident
|
|
1323
|
-
.clone()
|
|
1324
|
-
.then_ignore(symbol("."))
|
|
1325
|
-
.repeated()
|
|
1326
|
-
.collect()
|
|
1327
|
-
.boxed(),
|
|
1328
|
-
choice((
|
|
1329
|
-
enumeration(
|
|
1330
|
-
ident
|
|
1331
|
-
.clone()
|
|
1332
|
-
.then(just(Token::Kw("as")).ignore_then(ident.clone()).or_not()),
|
|
1333
|
-
symbol(","),
|
|
1334
|
-
)
|
|
1335
|
-
.delimited_by_with_eol(symbol("("), symbol(")"))
|
|
1336
|
-
.map(ImportList::Leaves)
|
|
1337
|
-
.boxed(),
|
|
1338
|
-
just(Token::Symbol("*")).map(|_| ImportList::Star),
|
|
1339
|
-
ident
|
|
1340
|
-
.clone()
|
|
1341
|
-
.then(just(Token::Kw("as")).ignore_then(ident.clone()).or_not())
|
|
1342
|
-
.map(|x| ImportList::Leaves(vec![x]))
|
|
1343
|
-
.boxed(),
|
|
1344
|
-
))
|
|
1345
|
-
.boxed(),
|
|
1346
|
-
)))
|
|
1347
|
-
.map(|(reexport, (level, trunk, import_list))| {
|
|
1348
|
-
SStmtInner::Import(ImportStmt {
|
|
1349
|
-
trunk,
|
|
1350
|
-
imports: import_list,
|
|
1351
|
-
level,
|
|
1352
|
-
reexport: reexport.is_some(),
|
|
1353
|
-
})
|
|
1354
|
-
})
|
|
1355
|
-
.labelled("import statement")
|
|
1356
|
-
.boxed();
|
|
1357
|
-
|
|
1358
|
-
let module_stmt = just(Token::Kw("module")).map(|_| SStmtInner::Module);
|
|
1359
|
-
|
|
1360
|
-
stmt.define(
|
|
1361
|
-
choice((
|
|
1362
|
-
decl_stmt.then_ignore(just(Token::Eol)),
|
|
1363
|
-
assign_stmt.then_ignore(just(Token::Eol)),
|
|
1364
|
-
expr_stmt.then_ignore(just(Token::Eol)),
|
|
1365
|
-
module_stmt.then_ignore(just(Token::Eol)),
|
|
1366
|
-
while_stmt.clone().then_ignore(just(Token::Eol)),
|
|
1367
|
-
for_stmt.clone().then_ignore(just(Token::Eol)),
|
|
1368
|
-
return_stmt.then_ignore(just(Token::Eol)),
|
|
1369
|
-
assert_stmt.then_ignore(just(Token::Eol)),
|
|
1370
|
-
raise_stmt.then_ignore(just(Token::Eol)),
|
|
1371
|
-
break_stmt.clone().then_ignore(just(Token::Eol)),
|
|
1372
|
-
continue_stmt.clone().then_ignore(just(Token::Eol)),
|
|
1373
|
-
import_stmt.then_ignore(just(Token::Eol)),
|
|
1374
|
-
try_stmt.then_ignore(just(Token::Eol)),
|
|
1375
|
-
))
|
|
1376
|
-
.labelled("statement")
|
|
1377
|
-
.map_with(|x, e| x.spanned(e.span()))
|
|
1378
|
-
.boxed(),
|
|
1430
|
+
ident.clone(),
|
|
1431
|
+
nary_pattern.clone(),
|
|
1379
1432
|
);
|
|
1380
1433
|
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
inline_assign_stmt,
|
|
1384
|
-
inline_expr_stmt,
|
|
1385
|
-
while_stmt,
|
|
1386
|
-
for_stmt,
|
|
1387
|
-
inline_return_stmt,
|
|
1388
|
-
inline_raise_stmt,
|
|
1389
|
-
break_stmt,
|
|
1390
|
-
continue_stmt,
|
|
1391
|
-
))
|
|
1392
|
-
.labelled("inline-statement")
|
|
1393
|
-
.map_with(|x, e| x.spanned(e.span()))
|
|
1394
|
-
.boxed(),
|
|
1395
|
-
);
|
|
1434
|
+
stmt.define(stmt_.labelled("statement").boxed());
|
|
1435
|
+
inline_stmt.define(inline_stmt_.labelled("inline-statement").boxed());
|
|
1396
1436
|
|
|
1397
1437
|
block.labelled("program")
|
|
1398
1438
|
}
|
|
@@ -53,7 +53,6 @@ impl<'src, 'ast> SStmtExt<'src, 'ast> for Indirect<SStmt<'src>> {
|
|
|
53
53
|
}
|
|
54
54
|
Stmt::Raise(..) | Stmt::Return(..) | Stmt::Break | Stmt::Continue => Type::Bottom,
|
|
55
55
|
Stmt::Import(..) => Type::NoReturn,
|
|
56
|
-
Stmt::Module => Type::NoReturn,
|
|
57
56
|
Stmt::Decl(..) => Type::NoReturn,
|
|
58
57
|
}
|
|
59
58
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
use std::time::Instant;
|
|
2
|
+
|
|
3
|
+
use koatl_core::parse_tl;
|
|
4
|
+
|
|
5
|
+
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
6
|
+
let filename = std::env::args().nth(1).ok_or("Missing filename argument")?;
|
|
7
|
+
let src = std::fs::read_to_string(&filename).unwrap();
|
|
8
|
+
|
|
9
|
+
let now = Instant::now();
|
|
10
|
+
|
|
11
|
+
let n = 1000;
|
|
12
|
+
|
|
13
|
+
for _ in 0..n {
|
|
14
|
+
match parse_tl(&src) {
|
|
15
|
+
Ok(_) => {}
|
|
16
|
+
Err(errs) => {
|
|
17
|
+
errs.0.into_iter().for_each(|e| {
|
|
18
|
+
eprintln!("Error: {}", e.message);
|
|
19
|
+
if let Some(span) = e.span {
|
|
20
|
+
eprintln!("At span: {:?}", span);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
return Err("Parsing failed".into());
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
println!(
|
|
29
|
+
"Parsed {} in {}us",
|
|
30
|
+
filename,
|
|
31
|
+
now.elapsed().as_nanos() as f64 / 1000.0 / n as f64
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
Ok(())
|
|
35
|
+
}
|
|
@@ -213,13 +213,6 @@ impl<'src> ResolveState<'src> {
|
|
|
213
213
|
let placeholder_ctx = self.placeholder_stack.pop().unwrap();
|
|
214
214
|
|
|
215
215
|
if placeholder_ctx.activated {
|
|
216
|
-
if ph_fn_ctx.is_async || ph_fn_ctx.is_generator || ph_fn_ctx.is_do {
|
|
217
|
-
self.errors.extend(simple_err(
|
|
218
|
-
"Await, bind, and yield are not allowed in placeholder functions",
|
|
219
|
-
placeholder_ctx.span,
|
|
220
|
-
));
|
|
221
|
-
}
|
|
222
|
-
|
|
223
216
|
ph_fn_ctx.is_placeholder = true;
|
|
224
217
|
|
|
225
218
|
ph_fn_ctx.arg_names.push(placeholder_ctx.arg_decl);
|
|
@@ -1323,13 +1316,6 @@ impl<'src> SExprExt<'src> for Indirect<SExpr<'src>> {
|
|
|
1323
1316
|
|
|
1324
1317
|
let fn_ctx = state.fn_stack.pop().unwrap();
|
|
1325
1318
|
|
|
1326
|
-
if fn_ctx.is_async || fn_ctx.is_generator || fn_ctx.is_do {
|
|
1327
|
-
state.errors.extend(simple_err(
|
|
1328
|
-
"Memo expressions cannot be async, generator, or do",
|
|
1329
|
-
span,
|
|
1330
|
-
));
|
|
1331
|
-
}
|
|
1332
|
-
|
|
1333
1319
|
state.memo_captures.insert(inner.as_ref().into(), fn_ctx);
|
|
1334
1320
|
|
|
1335
1321
|
Expr::Memo(inner)
|
|
@@ -1555,7 +1541,6 @@ impl<'src> SStmtExt<'src> for Indirect<SStmt<'src>> {
|
|
|
1555
1541
|
Stmt::Import(import_stmt)
|
|
1556
1542
|
}
|
|
1557
1543
|
Stmt::Break => Stmt::Break,
|
|
1558
|
-
Stmt::Module => Stmt::Module,
|
|
1559
1544
|
Stmt::Continue => Stmt::Continue,
|
|
1560
1545
|
};
|
|
1561
1546
|
|
|
@@ -15,6 +15,7 @@ use crate::{
|
|
|
15
15
|
use once_cell::sync::Lazy;
|
|
16
16
|
use parser::ast::*;
|
|
17
17
|
use slotmap::SlotMap;
|
|
18
|
+
use std::hash::{Hash, Hasher};
|
|
18
19
|
|
|
19
20
|
static PY_KWS: &[&str] = &[
|
|
20
21
|
"and", "as", "assert", "break", "class", "continue", "def", "del", "elif", "else", "except",
|
|
@@ -1978,12 +1979,6 @@ impl<'src> SStmtExt<'src> for SStmt<'src> {
|
|
|
1978
1979
|
pre.push(a.import(aliases));
|
|
1979
1980
|
};
|
|
1980
1981
|
}
|
|
1981
|
-
Stmt::Module => {
|
|
1982
|
-
return Err(simple_err(
|
|
1983
|
-
"Module statements are not allowed in the transform phase",
|
|
1984
|
-
span,
|
|
1985
|
-
));
|
|
1986
|
-
}
|
|
1987
1982
|
};
|
|
1988
1983
|
|
|
1989
1984
|
Ok(pre)
|
|
@@ -2285,20 +2280,26 @@ impl<'src, 'ast> SExprExt<'src, 'ast> for SExpr<'src> {
|
|
|
2285
2280
|
|
|
2286
2281
|
let callback = pre.bind(make_fn_exp(
|
|
2287
2282
|
ctx,
|
|
2288
|
-
FnDef::PyFnDef(vec![], py_body,
|
|
2283
|
+
FnDef::PyFnDef(vec![], py_body, memo_captures.is_do, memo_captures.is_async),
|
|
2289
2284
|
&span,
|
|
2290
2285
|
)?);
|
|
2291
2286
|
|
|
2292
2287
|
let linecol = ctx.line_cache.linecol(span.start);
|
|
2293
2288
|
|
|
2294
|
-
a.
|
|
2289
|
+
let memo_call = a.call(
|
|
2295
2290
|
a.tl_builtin("memo"),
|
|
2296
2291
|
vec![
|
|
2297
|
-
PyCallItem::Arg(
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2292
|
+
PyCallItem::Arg(a.str(format!(
|
|
2293
|
+
"{}:{}:{}:{:08x}",
|
|
2294
|
+
ctx.filename,
|
|
2295
|
+
linecol.0,
|
|
2296
|
+
linecol.1,
|
|
2297
|
+
{
|
|
2298
|
+
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
|
2299
|
+
ctx.source[span.start..span.end].hash(&mut hasher);
|
|
2300
|
+
hasher.finish() as u32
|
|
2301
|
+
}
|
|
2302
|
+
))),
|
|
2302
2303
|
PyCallItem::Arg(
|
|
2303
2304
|
a.tuple(
|
|
2304
2305
|
nonlocals
|
|
@@ -2310,7 +2311,14 @@ impl<'src, 'ast> SExprExt<'src, 'ast> for SExpr<'src> {
|
|
|
2310
2311
|
),
|
|
2311
2312
|
PyCallItem::Arg(callback),
|
|
2312
2313
|
],
|
|
2313
|
-
)
|
|
2314
|
+
);
|
|
2315
|
+
|
|
2316
|
+
if memo_captures.is_do {
|
|
2317
|
+
// TODO should we really automatically bind a monadic expression for convenience?
|
|
2318
|
+
a.yield_(a.yield_(memo_call))
|
|
2319
|
+
} else {
|
|
2320
|
+
a.yield_(memo_call)
|
|
2321
|
+
}
|
|
2314
2322
|
}
|
|
2315
2323
|
Expr::Await(expr) => a.await_(pre.bind(expr.transform(ctx)?)),
|
|
2316
2324
|
Expr::Yield(expr) => a.yield_(pre.bind(expr.transform(ctx)?)),
|
|
@@ -8,37 +8,46 @@ export Memo = class(Monad):
|
|
|
8
8
|
__init__ = self =>
|
|
9
9
|
self.cache = defaultdict(dict)
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
__repr__ = self => f"Memo.Cache({self.cache})"
|
|
12
|
+
|
|
13
|
+
try_get = (self, name, deps) =>
|
|
14
|
+
try self.cache[name][deps] except KeyError()
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
update = (self, name, deps, value) =>
|
|
16
17
|
self.cache[name][deps] = value
|
|
17
18
|
value
|
|
18
19
|
|
|
19
|
-
__repr__ = self => f"Memo.Cache({self.cache})"
|
|
20
|
-
|
|
21
20
|
__init__ = (self, f) => self.f = f
|
|
22
21
|
|
|
23
22
|
__repr__ = self => f"Memo(...)"
|
|
24
23
|
|
|
25
24
|
value = staticmethod& (id, deps, f) =>
|
|
26
|
-
Memo(ctx =>
|
|
25
|
+
Memo(ctx =>
|
|
26
|
+
if ctx.try_get(id, tuple(deps)) matches Ok() as value:
|
|
27
|
+
return value
|
|
28
|
+
|
|
29
|
+
ctx.update(id, tuple(deps), f())
|
|
30
|
+
)
|
|
27
31
|
|
|
28
32
|
fn = staticmethod& f => wraps(f)& (*args, **kwargs) =>
|
|
29
33
|
let id = f"{f.__module__}.{f.__qualname__}"
|
|
30
34
|
let deps = (tuple(args), tuple(kwargs.items()))
|
|
31
35
|
|
|
32
36
|
Memo(ctx =>
|
|
33
|
-
ctx.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
if ctx.try_get(id, deps) matches Ok() as value:
|
|
38
|
+
return value
|
|
39
|
+
|
|
40
|
+
let v = f(*args, **kwargs)
|
|
41
|
+
if v matches Memo():
|
|
42
|
+
v = v.run(ctx)
|
|
43
|
+
|
|
44
|
+
ctx.update(id, deps, v)
|
|
39
45
|
)
|
|
40
46
|
|
|
41
|
-
run = (self, ctx=
|
|
47
|
+
run = (self, ctx=None) =>
|
|
48
|
+
if ctx === None:
|
|
49
|
+
ctx = Memo.Cache()
|
|
50
|
+
self.f(ctx)
|
|
42
51
|
|
|
43
52
|
pure = staticmethod& value => Memo(ctx => value)
|
|
44
53
|
|
|
@@ -76,7 +76,7 @@ def do(f):
|
|
|
76
76
|
|
|
77
77
|
try:
|
|
78
78
|
# TODO: this is a workaround to avoid recursion.
|
|
79
|
-
# is it possible to
|
|
79
|
+
# is it possible to derive bind_gen directly from bind_once?
|
|
80
80
|
|
|
81
81
|
return vget(m, "bind_gen")(gen)
|
|
82
82
|
except (NotImplementedError, AttributeError):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|