koatl 0.1.25__tar.gz → 0.1.26__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.26}/Cargo.lock +1 -1
- {koatl-0.1.25 → koatl-0.1.26}/PKG-INFO +1 -1
- {koatl-0.1.25 → koatl-0.1.26}/koatl/Cargo.toml +1 -1
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/prelude/functional/__init__.tl +1 -1
- koatl-0.1.26/koatl/python/koatl/prelude/functional/algebra.tl +46 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/prelude/functional/async.tl +3 -3
- {koatl-0.1.25 → koatl-0.1.26/koatl}/python/koatl/prelude/functional/list.tl +1 -1
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/prelude/functional/memo.tl +3 -5
- {koatl-0.1.25 → koatl-0.1.26/koatl}/python/koatl/prelude/functional/reader.tl +2 -2
- {koatl-0.1.25 → koatl-0.1.26/koatl}/python/koatl/prelude/functional/result.tl +2 -2
- {koatl-0.1.25 → koatl-0.1.26/koatl}/python/koatl/runtime/virtual.py +2 -1
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/src/parser.rs +0 -1
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/py/emit.rs +2 -6
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/resolve_scopes.rs +14 -15
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/transform.rs +5 -8
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/prelude/functional/__init__.tl +1 -1
- koatl-0.1.26/python/koatl/prelude/functional/algebra.tl +46 -0
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/prelude/functional/async.tl +3 -3
- {koatl-0.1.25/koatl → koatl-0.1.26}/python/koatl/prelude/functional/list.tl +1 -1
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/prelude/functional/memo.tl +3 -5
- {koatl-0.1.25/koatl → koatl-0.1.26}/python/koatl/prelude/functional/reader.tl +2 -2
- {koatl-0.1.25/koatl → koatl-0.1.26}/python/koatl/prelude/functional/result.tl +2 -2
- {koatl-0.1.25/koatl → koatl-0.1.26}/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.26}/Cargo.toml +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/README.md +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/.github/workflows/CI.yml +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/.gitignore +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/LICENSE +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/README.md +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/__main__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/cli.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/prelude/functional/async_util.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/prelude/iterable.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/runtime/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/runtime/helpers.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/runtime/record.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/requirements.txt +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/src/emit_py.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/src/lib.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/coal.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/containers.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/decorators.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/destructure.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/escape_ident.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/fstr.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/functions.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/generator.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/if_expr.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/imports.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/loops.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/match.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/nary-list.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/placeholder.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/precedence.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/scopes.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/semantic_whitespace.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/short_circuit.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/destructure.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/async.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/iterables.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/list.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/memo.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/reader.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/result.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/slice.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/try.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/virtual.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/util/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/util/module0.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/util/module1.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/util/module2.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/parse/arith.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/parse/assign.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/parse/block-comments.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/parse/deco.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/parse/func.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/parse/matches.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/test_e2e.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/test_parse.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/Cargo.toml +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/Cargo.toml +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/src/ast.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/src/lexer.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/src/lib.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/src/util.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/tests/lexer.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/inference.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/lib.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/main.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/parse_timer.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/parser.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/py/ast.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/py/mod.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/py/util.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/types.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/util.rs +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/pyproject.toml +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/__main__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/cli.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/notebook/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/prelude/functional/async_util.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/prelude/iterable.tl +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/runtime/__init__.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/runtime/helpers.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/python/koatl/runtime/meta_finder.py +0 -0
- {koatl-0.1.25 → koatl-0.1.26}/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
|
|
|
@@ -210,7 +210,6 @@ where
|
|
|
210
210
|
if items.len() == 1 && last_comma.is_none() {
|
|
211
211
|
let item = items.into_iter().next().unwrap();
|
|
212
212
|
if let PatternSequenceItem::Item(inner) = item {
|
|
213
|
-
// TODO ???
|
|
214
213
|
inner.extract()
|
|
215
214
|
} else {
|
|
216
215
|
Pattern::Sequence(vec![item]).spanned(e.span())
|
|
@@ -456,21 +456,18 @@ impl SPyExpr<'_> {
|
|
|
456
456
|
ctx.emit("]");
|
|
457
457
|
}
|
|
458
458
|
PyExpr::Yield(expr) => {
|
|
459
|
-
set_prec(-0.5);
|
|
460
459
|
ctx.emit("(");
|
|
461
460
|
ctx.emit("yield ");
|
|
462
461
|
expr.emit_to(ctx, LOW_PREC)?;
|
|
463
462
|
ctx.emit(")");
|
|
464
463
|
}
|
|
465
464
|
PyExpr::Await(expr) => {
|
|
466
|
-
|
|
467
|
-
ctx.emit_indent();
|
|
465
|
+
ctx.emit("(");
|
|
468
466
|
ctx.emit("await ");
|
|
469
467
|
expr.emit_to(ctx, LOW_PREC)?;
|
|
470
|
-
ctx.
|
|
468
|
+
ctx.emit(")");
|
|
471
469
|
}
|
|
472
470
|
PyExpr::YieldFrom(expr) => {
|
|
473
|
-
set_prec(-0.5); // TODO is this precedence correct?
|
|
474
471
|
ctx.emit("(");
|
|
475
472
|
ctx.emit("yield from ");
|
|
476
473
|
expr.emit_to(ctx, LOW_PREC)?;
|
|
@@ -511,7 +508,6 @@ impl SPyExpr<'_> {
|
|
|
511
508
|
}
|
|
512
509
|
}
|
|
513
510
|
PyExpr::IfExpr(cond, if_, else_) => {
|
|
514
|
-
// TODO precedence here?
|
|
515
511
|
ctx.emit("(");
|
|
516
512
|
if_.emit_to(ctx, LOW_PREC)?;
|
|
517
513
|
ctx.emit(" if ");
|
|
@@ -2,7 +2,6 @@ use std::collections::HashMap;
|
|
|
2
2
|
use std::collections::HashSet;
|
|
3
3
|
use std::fmt::Display;
|
|
4
4
|
|
|
5
|
-
use slotmap::Key;
|
|
6
5
|
use slotmap::SlotMap;
|
|
7
6
|
use slotmap::new_key_type;
|
|
8
7
|
|
|
@@ -82,10 +81,10 @@ fn top_scope_and_key<'src, 'state>(
|
|
|
82
81
|
#[allow(dead_code)]
|
|
83
82
|
impl<'src> ResolveState<'src> {
|
|
84
83
|
fn new(source: &'src str) -> Self {
|
|
85
|
-
let mut root_scope = Scope::new(
|
|
84
|
+
let mut root_scope = Scope::new(None);
|
|
86
85
|
root_scope.is_global = true;
|
|
87
86
|
|
|
88
|
-
let err_scope = Scope::new(
|
|
87
|
+
let err_scope = Scope::new(None);
|
|
89
88
|
|
|
90
89
|
let mut scopes = SlotMap::with_key();
|
|
91
90
|
let root_scope_key = scopes.insert(root_scope);
|
|
@@ -203,7 +202,7 @@ impl<'src> ResolveState<'src> {
|
|
|
203
202
|
where
|
|
204
203
|
F: FnOnce(&mut ResolveState<'src>) -> Indirect<SExpr<'src>>,
|
|
205
204
|
{
|
|
206
|
-
let mut dummy_scope = Scope::new(
|
|
205
|
+
let mut dummy_scope = Scope::new(None);
|
|
207
206
|
dummy_scope.is_fn = true;
|
|
208
207
|
|
|
209
208
|
let temp_scope_key = self.scopes.insert(dummy_scope);
|
|
@@ -480,8 +479,7 @@ impl Display for Declaration<'_> {
|
|
|
480
479
|
|
|
481
480
|
#[derive(Debug)]
|
|
482
481
|
pub struct Scope {
|
|
483
|
-
|
|
484
|
-
pub parent: ScopeKey,
|
|
482
|
+
pub parent: Option<ScopeKey>,
|
|
485
483
|
|
|
486
484
|
pub locals: Vec<DeclarationKey>,
|
|
487
485
|
|
|
@@ -511,7 +509,7 @@ impl Display for Scope {
|
|
|
511
509
|
}
|
|
512
510
|
|
|
513
511
|
impl Scope {
|
|
514
|
-
fn new(parent: ScopeKey) -> Scope {
|
|
512
|
+
fn new(parent: Option<ScopeKey>) -> Scope {
|
|
515
513
|
Self {
|
|
516
514
|
parent,
|
|
517
515
|
locals: Vec::new(),
|
|
@@ -821,7 +819,7 @@ fn pattern_scoped<'src>(
|
|
|
821
819
|
state: &mut ResolveState<'src>,
|
|
822
820
|
pattern: Indirect<SPattern<'src>>,
|
|
823
821
|
) -> (Indirect<SPattern<'src>>, ScopeKey, PatternMeta<'src>) {
|
|
824
|
-
let scope = Scope::new(state.top_scope_key());
|
|
822
|
+
let scope = Scope::new(Some(state.top_scope_key()));
|
|
825
823
|
let scope_key = state.scopes.insert(scope);
|
|
826
824
|
|
|
827
825
|
let (pattern, meta) = pattern.traverse(state);
|
|
@@ -996,7 +994,7 @@ impl<'src> SExprExt<'src> for Indirect<SExpr<'src>> {
|
|
|
996
994
|
new_stmts
|
|
997
995
|
} else {
|
|
998
996
|
let parent = state.top_scope_key();
|
|
999
|
-
let scope = state.scopes.insert(Scope::new(parent));
|
|
997
|
+
let scope = state.scopes.insert(Scope::new(Some(parent)));
|
|
1000
998
|
state
|
|
1001
999
|
.scoped(scope, |state| {
|
|
1002
1000
|
let mut new_stmts = Vec::new();
|
|
@@ -1091,7 +1089,7 @@ impl<'src> SExprExt<'src> for Indirect<SExpr<'src>> {
|
|
|
1091
1089
|
(Some(pattern), scope)
|
|
1092
1090
|
} else {
|
|
1093
1091
|
let parent = state.top_scope_key();
|
|
1094
|
-
(None, state.scopes.insert(Scope::new(parent)))
|
|
1092
|
+
(None, state.scopes.insert(Scope::new(Some(parent))))
|
|
1095
1093
|
};
|
|
1096
1094
|
|
|
1097
1095
|
SMatchCase {
|
|
@@ -1109,7 +1107,7 @@ impl<'src> SExprExt<'src> for Indirect<SExpr<'src>> {
|
|
|
1109
1107
|
Expr::Class(bases, body) => {
|
|
1110
1108
|
let bases = traverse_call_items(state, bases);
|
|
1111
1109
|
|
|
1112
|
-
let mut scope = Scope::new(state.top_scope_key());
|
|
1110
|
+
let mut scope = Scope::new(Some(state.top_scope_key()));
|
|
1113
1111
|
scope.is_class = true;
|
|
1114
1112
|
let scope = state.scopes.insert(scope);
|
|
1115
1113
|
|
|
@@ -1122,7 +1120,7 @@ impl<'src> SExprExt<'src> for Indirect<SExpr<'src>> {
|
|
|
1122
1120
|
Expr::Fn(arg_def_items, body) => {
|
|
1123
1121
|
let mut decls = vec![];
|
|
1124
1122
|
|
|
1125
|
-
let mut scope = Scope::new(state.top_scope_key());
|
|
1123
|
+
let mut scope = Scope::new(Some(state.top_scope_key()));
|
|
1126
1124
|
scope.is_fn = true;
|
|
1127
1125
|
let scope = state.scopes.insert(scope);
|
|
1128
1126
|
|
|
@@ -1402,7 +1400,7 @@ impl<'src> SExprExt<'src> for Indirect<SExpr<'src>> {
|
|
|
1402
1400
|
Expr::Memo(inner) => {
|
|
1403
1401
|
state.set_do(span);
|
|
1404
1402
|
|
|
1405
|
-
let mut scope = Scope::new(state.top_scope_key());
|
|
1403
|
+
let mut scope = Scope::new(Some(state.top_scope_key()));
|
|
1406
1404
|
// TODO it's confusing that we need to
|
|
1407
1405
|
// set scope.is_fn = true all the time in order
|
|
1408
1406
|
// for captures to be found properly.
|
|
@@ -1574,7 +1572,7 @@ impl<'src> SStmtExt<'src> for Indirect<SStmt<'src>> {
|
|
|
1574
1572
|
(Some(pattern), scope)
|
|
1575
1573
|
} else {
|
|
1576
1574
|
let parent = state.top_scope_key();
|
|
1577
|
-
(None, state.scopes.insert(Scope::new(parent)))
|
|
1575
|
+
(None, state.scopes.insert(Scope::new(Some(parent))))
|
|
1578
1576
|
};
|
|
1579
1577
|
|
|
1580
1578
|
let body = state
|
|
@@ -1612,7 +1610,8 @@ impl<'src> SStmtExt<'src> for Indirect<SStmt<'src>> {
|
|
|
1612
1610
|
|
|
1613
1611
|
match &import_stmt.imports {
|
|
1614
1612
|
ImportList::Star => {
|
|
1615
|
-
// TODO
|
|
1613
|
+
// TODO can this be improved?
|
|
1614
|
+
|
|
1616
1615
|
let base_module = import_stmt
|
|
1617
1616
|
.trunk
|
|
1618
1617
|
.iter()
|
|
@@ -14,7 +14,7 @@ use crate::{
|
|
|
14
14
|
};
|
|
15
15
|
use once_cell::sync::Lazy;
|
|
16
16
|
use parser::ast::*;
|
|
17
|
-
use slotmap::
|
|
17
|
+
use slotmap::SlotMap;
|
|
18
18
|
use std::hash::{Hash, Hasher};
|
|
19
19
|
|
|
20
20
|
static PY_KWS: &[&str] = &[
|
|
@@ -845,9 +845,6 @@ impl<'src, 'ast> SPatternExt<'src, 'ast> for SPattern<'src> {
|
|
|
845
845
|
ctx: &mut TlCtx<'src, 'ast>,
|
|
846
846
|
info: &PatternInfo,
|
|
847
847
|
) -> TlResult<WithPre<'src, SPyPattern<'src>>> {
|
|
848
|
-
// TODO avoid python syntaxerror by verifying that all branches in Or bind the same name
|
|
849
|
-
// also check for no patterns after default pattern
|
|
850
|
-
|
|
851
848
|
let mut pre = PyBlock::new();
|
|
852
849
|
|
|
853
850
|
let pattern = &self.value;
|
|
@@ -2322,7 +2319,6 @@ impl<'src, 'ast> SExprExt<'src, 'ast> for SExpr<'src> {
|
|
|
2322
2319
|
|
|
2323
2320
|
let memo_call = a.call(
|
|
2324
2321
|
if memo_captures.is_do {
|
|
2325
|
-
// TODO is there any better solution?
|
|
2326
2322
|
a.tl_builtin("bind_memo_value")
|
|
2327
2323
|
} else {
|
|
2328
2324
|
a.tl_builtin("memo_value")
|
|
@@ -2478,14 +2474,15 @@ fn py_fn_bindings<'src, 'ast>(
|
|
|
2478
2474
|
for capture in memo_captures.captures.iter() {
|
|
2479
2475
|
let mut scope = &ctx.scopes[ctx.declarations[*capture].scope];
|
|
2480
2476
|
loop {
|
|
2481
|
-
|
|
2477
|
+
let Some(parent) = scope.parent else {
|
|
2482
2478
|
break;
|
|
2483
|
-
}
|
|
2479
|
+
};
|
|
2484
2480
|
|
|
2485
2481
|
if scope.is_fn || scope.is_class || scope.is_global {
|
|
2486
2482
|
break;
|
|
2487
2483
|
}
|
|
2488
|
-
|
|
2484
|
+
|
|
2485
|
+
scope = &ctx.scopes[parent];
|
|
2489
2486
|
}
|
|
2490
2487
|
|
|
2491
2488
|
if scope.is_global || scope.is_class {
|
|
@@ -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
|
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
|
|
3
|
-
# TODO: this should be really called MonadOnce.
|
|
4
|
-
export Monad = class(abc.ABC):
|
|
5
|
-
__slots__ = ()
|
|
6
|
-
|
|
7
|
-
# The default implementation required for `@` syntax that should be overridden by subclasses.
|
|
8
|
-
bind_once = abc.abstractmethod& (self, f) => None
|
|
9
|
-
|
|
10
|
-
pure = staticmethod& abc.abstractmethod& value => None
|
|
11
|
-
|
|
12
|
-
# Automatically given by bind_once.
|
|
13
|
-
bind = (self, f) => self.bind_once(f)
|
|
14
|
-
|
|
15
|
-
# An optional, optimized implementation of `bind` that skips deep recursion.
|
|
16
|
-
# TODO: can this be automatically generated?
|
|
17
|
-
# bind_gen = (self, gen) => ...
|
|
18
|
-
|
|
19
|
-
# Automatically generated implementations.
|
|
20
|
-
map = (self, f) => self.bind(x => self.pure(f(x)))
|
|
21
|
-
apply = (self, f) => self.bind(x => f.map(fn => fn(x)))
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
|
|
3
|
-
# TODO: this should be really called MonadOnce.
|
|
4
|
-
export Monad = class(abc.ABC):
|
|
5
|
-
__slots__ = ()
|
|
6
|
-
|
|
7
|
-
# The default implementation required for `@` syntax that should be overridden by subclasses.
|
|
8
|
-
bind_once = abc.abstractmethod& (self, f) => None
|
|
9
|
-
|
|
10
|
-
pure = staticmethod& abc.abstractmethod& value => None
|
|
11
|
-
|
|
12
|
-
# Automatically given by bind_once.
|
|
13
|
-
bind = (self, f) => self.bind_once(f)
|
|
14
|
-
|
|
15
|
-
# An optional, optimized implementation of `bind` that skips deep recursion.
|
|
16
|
-
# TODO: can this be automatically generated?
|
|
17
|
-
# bind_gen = (self, gen) => ...
|
|
18
|
-
|
|
19
|
-
# Automatically generated implementations.
|
|
20
|
-
map = (self, f) => self.bind(x => self.pure(f(x)))
|
|
21
|
-
apply = (self, f) => self.bind(x => f.map(fn => fn(x)))
|
|
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
|