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.
Files changed (117) hide show
  1. {koatl-0.1.25 → koatl-0.1.26}/Cargo.lock +1 -1
  2. {koatl-0.1.25 → koatl-0.1.26}/PKG-INFO +1 -1
  3. {koatl-0.1.25 → koatl-0.1.26}/koatl/Cargo.toml +1 -1
  4. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/prelude/functional/__init__.tl +1 -1
  5. koatl-0.1.26/koatl/python/koatl/prelude/functional/algebra.tl +46 -0
  6. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/prelude/functional/async.tl +3 -3
  7. {koatl-0.1.25 → koatl-0.1.26/koatl}/python/koatl/prelude/functional/list.tl +1 -1
  8. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/prelude/functional/memo.tl +3 -5
  9. {koatl-0.1.25 → koatl-0.1.26/koatl}/python/koatl/prelude/functional/reader.tl +2 -2
  10. {koatl-0.1.25 → koatl-0.1.26/koatl}/python/koatl/prelude/functional/result.tl +2 -2
  11. {koatl-0.1.25 → koatl-0.1.26/koatl}/python/koatl/runtime/virtual.py +2 -1
  12. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/src/parser.rs +0 -1
  13. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/py/emit.rs +2 -6
  14. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/resolve_scopes.rs +14 -15
  15. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/transform.rs +5 -8
  16. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/prelude/functional/__init__.tl +1 -1
  17. koatl-0.1.26/python/koatl/prelude/functional/algebra.tl +46 -0
  18. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/prelude/functional/async.tl +3 -3
  19. {koatl-0.1.25/koatl → koatl-0.1.26}/python/koatl/prelude/functional/list.tl +1 -1
  20. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/prelude/functional/memo.tl +3 -5
  21. {koatl-0.1.25/koatl → koatl-0.1.26}/python/koatl/prelude/functional/reader.tl +2 -2
  22. {koatl-0.1.25/koatl → koatl-0.1.26}/python/koatl/prelude/functional/result.tl +2 -2
  23. {koatl-0.1.25/koatl → koatl-0.1.26}/python/koatl/runtime/virtual.py +2 -1
  24. koatl-0.1.25/koatl/python/koatl/prelude/functional/monad.tl +0 -21
  25. koatl-0.1.25/python/koatl/prelude/functional/monad.tl +0 -21
  26. {koatl-0.1.25 → koatl-0.1.26}/Cargo.toml +0 -0
  27. {koatl-0.1.25 → koatl-0.1.26}/README.md +0 -0
  28. {koatl-0.1.25 → koatl-0.1.26}/koatl/.github/workflows/CI.yml +0 -0
  29. {koatl-0.1.25 → koatl-0.1.26}/koatl/.gitignore +0 -0
  30. {koatl-0.1.25 → koatl-0.1.26}/koatl/LICENSE +0 -0
  31. {koatl-0.1.25 → koatl-0.1.26}/koatl/README.md +0 -0
  32. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/__init__.py +0 -0
  33. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/__main__.py +0 -0
  34. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/cli.py +0 -0
  35. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/notebook/__init__.py +0 -0
  36. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/notebook/magic.py +0 -0
  37. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/prelude/__init__.tl +0 -0
  38. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/prelude/functional/async_util.py +0 -0
  39. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/prelude/iterable.tl +0 -0
  40. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/runtime/__init__.py +0 -0
  41. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/runtime/helpers.py +0 -0
  42. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/runtime/meta_finder.py +0 -0
  43. {koatl-0.1.25 → koatl-0.1.26}/koatl/python/koatl/runtime/record.py +0 -0
  44. {koatl-0.1.25 → koatl-0.1.26}/koatl/requirements.txt +0 -0
  45. {koatl-0.1.25 → koatl-0.1.26}/koatl/src/emit_py.rs +0 -0
  46. {koatl-0.1.25 → koatl-0.1.26}/koatl/src/lib.rs +0 -0
  47. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/coal.tl +0 -0
  48. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/containers.tl +0 -0
  49. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/decorators.tl +0 -0
  50. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
  51. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/destructure.tl +0 -0
  52. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/escape_ident.tl +0 -0
  53. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/fstr.tl +0 -0
  54. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/functions.tl +0 -0
  55. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/generator.tl +0 -0
  56. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/if_expr.tl +0 -0
  57. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/imports.tl +0 -0
  58. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/loops.tl +0 -0
  59. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/match.tl +0 -0
  60. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/nary-list.tl +0 -0
  61. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/placeholder.tl +0 -0
  62. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/precedence.tl +0 -0
  63. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/scopes.tl +0 -0
  64. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/semantic_whitespace.tl +0 -0
  65. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/base/short_circuit.tl +0 -0
  66. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/destructure.tl +0 -0
  67. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/async.tl +0 -0
  68. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/iterables.tl +0 -0
  69. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/list.tl +0 -0
  70. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/memo.tl +0 -0
  71. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/reader.tl +0 -0
  72. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/result.tl +0 -0
  73. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/slice.tl +0 -0
  74. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/try.tl +0 -0
  75. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/prelude/virtual.tl +0 -0
  76. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/util/__init__.py +0 -0
  77. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/util/module0.tl +0 -0
  78. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/util/module1.tl +0 -0
  79. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/e2e/util/module2.tl +0 -0
  80. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/parse/arith.tl +0 -0
  81. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/parse/assign.tl +0 -0
  82. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/parse/block-comments.tl +0 -0
  83. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/parse/deco.tl +0 -0
  84. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/parse/func.tl +0 -0
  85. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/parse/matches.tl +0 -0
  86. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/test_e2e.py +0 -0
  87. {koatl-0.1.25 → koatl-0.1.26}/koatl/tests/test_parse.py +0 -0
  88. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/Cargo.toml +0 -0
  89. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/Cargo.toml +0 -0
  90. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/src/ast.rs +0 -0
  91. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/src/lexer.rs +0 -0
  92. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/src/lib.rs +0 -0
  93. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/src/util.rs +0 -0
  94. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/parser/tests/lexer.rs +0 -0
  95. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/inference.rs +0 -0
  96. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/lib.rs +0 -0
  97. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/main.rs +0 -0
  98. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/parse_timer.rs +0 -0
  99. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/parser.rs +0 -0
  100. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/py/ast.rs +0 -0
  101. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/py/mod.rs +0 -0
  102. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/py/util.rs +0 -0
  103. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/types.rs +0 -0
  104. {koatl-0.1.25 → koatl-0.1.26}/koatl-core/src/util.rs +0 -0
  105. {koatl-0.1.25 → koatl-0.1.26}/pyproject.toml +0 -0
  106. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/__init__.py +0 -0
  107. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/__main__.py +0 -0
  108. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/cli.py +0 -0
  109. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/notebook/__init__.py +0 -0
  110. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/notebook/magic.py +0 -0
  111. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/prelude/__init__.tl +0 -0
  112. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/prelude/functional/async_util.py +0 -0
  113. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/prelude/iterable.tl +0 -0
  114. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/runtime/__init__.py +0 -0
  115. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/runtime/helpers.py +0 -0
  116. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/runtime/meta_finder.py +0 -0
  117. {koatl-0.1.25 → koatl-0.1.26}/python/koatl/runtime/record.py +0 -0
@@ -99,7 +99,7 @@ checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
99
99
 
100
100
  [[package]]
101
101
  name = "koatl"
102
- version = "0.1.25"
102
+ version = "0.1.26"
103
103
  dependencies = [
104
104
  "ariadne",
105
105
  "koatl-core",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: koatl
3
- Version: 0.1.25
3
+ Version: 0.1.26
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "koatl"
3
- version = "0.1.25"
3
+ version = "0.1.26"
4
4
  edition = "2021"
5
5
 
6
6
  [lib]
@@ -1,4 +1,4 @@
1
- export import .monad.*
1
+ export import .algebra.*
2
2
  export import .result.*
3
3
  export import .async.*
4
4
  export import .reader.*
@@ -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 .monad.Monad
5
+ import .MonadOnce
6
6
 
7
- export Async = class(Monad):
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
- #- TODO: Why is asyncio.gather eager? -#
42
+ # TODO: Why is asyncio.gather eager?
43
43
  gather = staticmethod& (*args) => Async.from_generator_fn& () => yield from asyncio.gather(*args)
@@ -1,7 +1,7 @@
1
1
  import collections.UserList
2
2
  import itertools
3
3
 
4
- import .monad.Monad
4
+ import .Monad
5
5
  import ..iterable.Iterable
6
6
 
7
7
  export List = class(UserList, Monad):
@@ -1,18 +1,16 @@
1
1
  import collections.defaultdict
2
2
  import functools.wraps
3
3
  import .result.(Result, Ok)
4
- import .Monad
4
+ import .MonadOnce
5
5
 
6
- export Memo = class(Monad):
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,7 +1,7 @@
1
1
  import functools.wraps
2
- import .monad.Monad
2
+ import .MonadOnce
3
3
 
4
- export Reader = class(Monad):
4
+ export Reader = class(MonadOnce):
5
5
  __init__ = (self, fn) => self.fn = fn
6
6
 
7
7
  __repr__ = self => "Reader(...)"
@@ -1,8 +1,8 @@
1
1
  import functools.wraps
2
- import .monad.Monad
3
2
  import koatl.runtime.virtual.register_global_attr
3
+ import .algebra.MonadOnce
4
4
 
5
- export Result = class:
5
+ export Result = class(MonadOnce):
6
6
  __slots__ = ()
7
7
  __match_args__ = ("value",)
8
8
 
@@ -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
- (type,),
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
- set_prec(-0.5);
467
- ctx.emit_indent();
465
+ ctx.emit("(");
468
466
  ctx.emit("await ");
469
467
  expr.emit_to(ctx, LOW_PREC)?;
470
- ctx.emit_endl();
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(ScopeKey::null());
84
+ let mut root_scope = Scope::new(None);
86
85
  root_scope.is_global = true;
87
86
 
88
- let err_scope = Scope::new(ScopeKey::null());
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(ScopeKey::null());
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
- // TODO make this option
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::{Key, 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
- if scope.parent.is_null() {
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
- scope = &ctx.scopes[scope.parent];
2484
+
2485
+ scope = &ctx.scopes[parent];
2489
2486
  }
2490
2487
 
2491
2488
  if scope.is_global || scope.is_class {
@@ -1,4 +1,4 @@
1
- export import .monad.*
1
+ export import .algebra.*
2
2
  export import .result.*
3
3
  export import .async.*
4
4
  export import .reader.*
@@ -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 .monad.Monad
5
+ import .MonadOnce
6
6
 
7
- export Async = class(Monad):
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
- #- TODO: Why is asyncio.gather eager? -#
42
+ # TODO: Why is asyncio.gather eager?
43
43
  gather = staticmethod& (*args) => Async.from_generator_fn& () => yield from asyncio.gather(*args)
@@ -1,7 +1,7 @@
1
1
  import collections.UserList
2
2
  import itertools
3
3
 
4
- import .monad.Monad
4
+ import .Monad
5
5
  import ..iterable.Iterable
6
6
 
7
7
  export List = class(UserList, Monad):
@@ -1,18 +1,16 @@
1
1
  import collections.defaultdict
2
2
  import functools.wraps
3
3
  import .result.(Result, Ok)
4
- import .Monad
4
+ import .MonadOnce
5
5
 
6
- export Memo = class(Monad):
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,7 +1,7 @@
1
1
  import functools.wraps
2
- import .monad.Monad
2
+ import .MonadOnce
3
3
 
4
- export Reader = class(Monad):
4
+ export Reader = class(MonadOnce):
5
5
  __init__ = (self, fn) => self.fn = fn
6
6
 
7
7
  __repr__ = self => "Reader(...)"
@@ -1,8 +1,8 @@
1
1
  import functools.wraps
2
- import .monad.Monad
3
2
  import koatl.runtime.virtual.register_global_attr
3
+ import .algebra.MonadOnce
4
4
 
5
- export Result = class:
5
+ export Result = class(MonadOnce):
6
6
  __slots__ = ()
7
7
  __match_args__ = ("value",)
8
8
 
@@ -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
- (type,),
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