koatl 0.1.35__tar.gz → 0.1.37__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 (131) hide show
  1. {koatl-0.1.35 → koatl-0.1.37}/Cargo.lock +1 -1
  2. {koatl-0.1.35 → koatl-0.1.37}/PKG-INFO +1 -1
  3. {koatl-0.1.35 → koatl-0.1.37}/koatl/Cargo.toml +1 -1
  4. koatl-0.1.37/koatl/python/koatl/prelude/__init__.tl +60 -0
  5. {koatl-0.1.35 → koatl-0.1.37}/koatl/python/koatl/runtime/virtual.py +4 -4
  6. koatl-0.1.37/koatl/python/koatl/std/alg/__init__.tl +5 -0
  7. {koatl-0.1.35/koatl/python/koatl/prelude/functional → koatl-0.1.37/koatl/python/koatl/std/alg}/async.tl +1 -1
  8. {koatl-0.1.35/python/koatl/prelude/functional → koatl-0.1.37/koatl/python/koatl/std/alg}/env.tl +1 -1
  9. {koatl-0.1.35/python/koatl/prelude/functional → koatl-0.1.37/koatl/python/koatl/std/alg}/memo.tl +2 -5
  10. {koatl-0.1.35/koatl/python/koatl/prelude/functional → koatl-0.1.37/koatl/python/koatl/std/alg}/result.tl +2 -24
  11. koatl-0.1.37/koatl/python/koatl/std/data/__init__.tl +1 -0
  12. {koatl-0.1.35/python/koatl/prelude/functional → koatl-0.1.37/koatl/python/koatl/std/data}/list.tl +2 -5
  13. koatl-0.1.37/koatl/python/koatl/std/io.tl +3 -0
  14. koatl-0.1.35/python/koatl/prelude/iterable.tl → koatl-0.1.37/koatl/python/koatl/std/iter.tl +18 -9
  15. koatl-0.1.37/koatl/python/koatl/std/lazy_module.tl +33 -0
  16. koatl-0.1.35/koatl/python/koatl/prelude/regex.tl → koatl-0.1.37/koatl/python/koatl/std/re.tl +3 -15
  17. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/parser/src/ast.rs +7 -8
  18. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/parser/src/parser.rs +99 -60
  19. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/parser/src/util.rs +5 -33
  20. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/src/lib.rs +12 -1
  21. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/src/py/emit.rs +3 -3
  22. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/src/resolve_scopes.rs +118 -36
  23. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/src/transform.rs +103 -37
  24. koatl-0.1.37/python/koatl/prelude/__init__.tl +60 -0
  25. {koatl-0.1.35 → koatl-0.1.37}/python/koatl/runtime/virtual.py +4 -4
  26. koatl-0.1.37/python/koatl/std/alg/__init__.tl +5 -0
  27. {koatl-0.1.35/python/koatl/prelude/functional → koatl-0.1.37/python/koatl/std/alg}/async.tl +1 -1
  28. {koatl-0.1.35/koatl/python/koatl/prelude/functional → koatl-0.1.37/python/koatl/std/alg}/env.tl +1 -1
  29. {koatl-0.1.35/koatl/python/koatl/prelude/functional → koatl-0.1.37/python/koatl/std/alg}/memo.tl +2 -5
  30. {koatl-0.1.35/python/koatl/prelude/functional → koatl-0.1.37/python/koatl/std/alg}/result.tl +2 -24
  31. koatl-0.1.37/python/koatl/std/data/__init__.tl +1 -0
  32. {koatl-0.1.35/koatl/python/koatl/prelude/functional → koatl-0.1.37/python/koatl/std/data}/list.tl +2 -5
  33. koatl-0.1.37/python/koatl/std/io.tl +3 -0
  34. koatl-0.1.35/koatl/python/koatl/prelude/iterable.tl → koatl-0.1.37/python/koatl/std/iter.tl +18 -9
  35. koatl-0.1.37/python/koatl/std/lazy_module.tl +33 -0
  36. koatl-0.1.35/python/koatl/prelude/regex.tl → koatl-0.1.37/python/koatl/std/re.tl +3 -15
  37. koatl-0.1.35/koatl/python/koatl/prelude/__init__.tl +0 -6
  38. koatl-0.1.35/koatl/python/koatl/prelude/functional/__init__.tl +0 -26
  39. koatl-0.1.35/koatl/python/koatl/prelude/io.tl +0 -5
  40. koatl-0.1.35/python/koatl/prelude/__init__.tl +0 -6
  41. koatl-0.1.35/python/koatl/prelude/functional/__init__.tl +0 -26
  42. koatl-0.1.35/python/koatl/prelude/io.tl +0 -5
  43. {koatl-0.1.35 → koatl-0.1.37}/Cargo.toml +0 -0
  44. {koatl-0.1.35 → koatl-0.1.37}/README.md +0 -0
  45. {koatl-0.1.35 → koatl-0.1.37}/koatl/.github/workflows/CI.yml +0 -0
  46. {koatl-0.1.35 → koatl-0.1.37}/koatl/.gitignore +0 -0
  47. {koatl-0.1.35 → koatl-0.1.37}/koatl/LICENSE +0 -0
  48. {koatl-0.1.35 → koatl-0.1.37}/koatl/README.md +0 -0
  49. {koatl-0.1.35 → koatl-0.1.37}/koatl/python/koatl/__init__.py +0 -0
  50. {koatl-0.1.35 → koatl-0.1.37}/koatl/python/koatl/__main__.py +0 -0
  51. {koatl-0.1.35 → koatl-0.1.37}/koatl/python/koatl/cli.py +0 -0
  52. {koatl-0.1.35 → koatl-0.1.37}/koatl/python/koatl/notebook/__init__.py +0 -0
  53. {koatl-0.1.35 → koatl-0.1.37}/koatl/python/koatl/notebook/magic.py +0 -0
  54. {koatl-0.1.35 → koatl-0.1.37}/koatl/python/koatl/runtime/__init__.py +0 -0
  55. {koatl-0.1.35 → koatl-0.1.37}/koatl/python/koatl/runtime/classes.py +0 -0
  56. {koatl-0.1.35 → koatl-0.1.37}/koatl/python/koatl/runtime/helpers.py +0 -0
  57. {koatl-0.1.35 → koatl-0.1.37}/koatl/python/koatl/runtime/meta_finder.py +0 -0
  58. {koatl-0.1.35 → koatl-0.1.37}/koatl/python/koatl/runtime/record.py +0 -0
  59. /koatl-0.1.35/koatl/python/koatl/prelude/functional/algebra.tl → /koatl-0.1.37/koatl/python/koatl/std/alg/base.tl +0 -0
  60. {koatl-0.1.35 → koatl-0.1.37}/koatl/requirements.txt +0 -0
  61. {koatl-0.1.35 → koatl-0.1.37}/koatl/src/emit_py.rs +0 -0
  62. {koatl-0.1.35 → koatl-0.1.37}/koatl/src/lib.rs +0 -0
  63. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/coal.tl +0 -0
  64. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/containers.tl +0 -0
  65. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/data.txt +0 -0
  66. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/decorators.tl +0 -0
  67. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
  68. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/destructure.tl +0 -0
  69. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/escape_ident.tl +0 -0
  70. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/fstr.tl +0 -0
  71. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/functions.tl +0 -0
  72. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/generator.tl +0 -0
  73. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/if_expr.tl +0 -0
  74. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/imports.tl +0 -0
  75. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/loops.tl +0 -0
  76. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/match.tl +0 -0
  77. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/nary-list.tl +0 -0
  78. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/placeholder.tl +0 -0
  79. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/precedence.tl +0 -0
  80. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/record.tl +0 -0
  81. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/scopes.tl +0 -0
  82. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/semantic_whitespace.tl +0 -0
  83. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/short_circuit.tl +0 -0
  84. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/base/with.tl +0 -0
  85. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/prelude/async.tl +0 -0
  86. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/prelude/aug_assign.tl +0 -0
  87. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/prelude/env.tl +0 -0
  88. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/prelude/iterables.tl +0 -0
  89. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/prelude/list.tl +0 -0
  90. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/prelude/memo.tl +0 -0
  91. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/prelude/result.tl +0 -0
  92. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/prelude/slice.tl +0 -0
  93. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/prelude/try.tl +0 -0
  94. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/prelude/virtual.tl +0 -0
  95. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/util/__init__.py +0 -0
  96. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/util/module0.tl +0 -0
  97. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/util/module1.tl +0 -0
  98. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/e2e/util/module2.tl +0 -0
  99. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/parse/arith.tl +0 -0
  100. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/parse/assign.tl +0 -0
  101. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/parse/block-comments.tl +0 -0
  102. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/parse/deco.tl +0 -0
  103. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/parse/func.tl +0 -0
  104. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/parse/matches.tl +0 -0
  105. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/test_e2e.py +0 -0
  106. {koatl-0.1.35 → koatl-0.1.37}/koatl/tests/test_parse.py +0 -0
  107. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/Cargo.toml +0 -0
  108. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/parser/Cargo.toml +0 -0
  109. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/parser/src/lexer.rs +0 -0
  110. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/parser/src/lib.rs +0 -0
  111. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/src/inference.rs +0 -0
  112. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/src/main.rs +0 -0
  113. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/src/parse_timer.rs +0 -0
  114. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/src/parser.rs +0 -0
  115. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/src/py/ast.rs +0 -0
  116. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/src/py/mod.rs +0 -0
  117. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/src/py/util.rs +0 -0
  118. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/src/types.rs +0 -0
  119. {koatl-0.1.35 → koatl-0.1.37}/koatl-core/src/util.rs +0 -0
  120. {koatl-0.1.35 → koatl-0.1.37}/pyproject.toml +0 -0
  121. {koatl-0.1.35 → koatl-0.1.37}/python/koatl/__init__.py +0 -0
  122. {koatl-0.1.35 → koatl-0.1.37}/python/koatl/__main__.py +0 -0
  123. {koatl-0.1.35 → koatl-0.1.37}/python/koatl/cli.py +0 -0
  124. {koatl-0.1.35 → koatl-0.1.37}/python/koatl/notebook/__init__.py +0 -0
  125. {koatl-0.1.35 → koatl-0.1.37}/python/koatl/notebook/magic.py +0 -0
  126. {koatl-0.1.35 → koatl-0.1.37}/python/koatl/runtime/__init__.py +0 -0
  127. {koatl-0.1.35 → koatl-0.1.37}/python/koatl/runtime/classes.py +0 -0
  128. {koatl-0.1.35 → koatl-0.1.37}/python/koatl/runtime/helpers.py +0 -0
  129. {koatl-0.1.35 → koatl-0.1.37}/python/koatl/runtime/meta_finder.py +0 -0
  130. {koatl-0.1.35 → koatl-0.1.37}/python/koatl/runtime/record.py +0 -0
  131. /koatl-0.1.35/python/koatl/prelude/functional/algebra.tl → /koatl-0.1.37/python/koatl/std/alg/base.tl +0 -0
@@ -99,7 +99,7 @@ checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
99
99
 
100
100
  [[package]]
101
101
  name = "koatl"
102
- version = "0.1.35"
102
+ version = "0.1.37"
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.35
3
+ Version: 0.1.37
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.35"
3
+ version = "0.1.37"
4
4
  edition = "2021"
5
5
 
6
6
  [lib]
@@ -0,0 +1,60 @@
1
+ import koatl.std.iter.Iterable
2
+
3
+ Extension.trait(Iterable)
4
+
5
+ import koatl.std.data.List
6
+
7
+ Extension.property(list, "len")& List.len.fget
8
+
9
+ import koatl.std.alg.*
10
+
11
+ Extension.property(object, "result")& self => Result(self)
12
+
13
+ __tl__.Ok = Ok
14
+ __tl__.Err = Err
15
+ __tl__.Result = Result
16
+
17
+ __tl__.op_coal = (x, f) =>
18
+ if x matches Result():
19
+ return x.coalesce(f)
20
+
21
+ if not koatl.std.alg.result.infer_ok(x):
22
+ return f()
23
+ return x
24
+
25
+ __tl__.op_map = (x, f) =>
26
+ if x matches Result():
27
+ return x.map(f)
28
+
29
+ if koatl.std.alg.result.infer_ok(x):
30
+ return f(x)
31
+ return x
32
+
33
+ __tl__.memo_value = Memo.value
34
+ __tl__.async_memo_value = AsyncMemo.value
35
+
36
+ import koatl.std.re.Pattern
37
+
38
+ Extension.method(str, "match")& (regex, str) => Pattern(regex).match(str)
39
+
40
+ # Note: the below methods have arguments in reverse order to Python's re module.
41
+ Extension.method(str, "matches")& (str, regex) => Pattern(regex).match(str)
42
+ Extension.method(str, "search")& (str, regex) => Pattern(regex).search(str)
43
+
44
+ import koatl.std.lazy_module.LazyModule
45
+
46
+ export Result, Ok, Err, Env, Memo, Async, AsyncMemo
47
+ export std = LazyModule("koatl.std")
48
+
49
+ ModuleProxy = class:
50
+ __init__ = (self) =>
51
+ self._modules = {}
52
+
53
+ __getattr__ = (self, attr) =>
54
+ if attr not in self._modules:
55
+ self._modules[attr] = LazyModule(attr)
56
+ return self._modules[attr]
57
+
58
+ __repr__ = self => f"ModuleProxy({self._modules})"
59
+
60
+ export mod = ModuleProxy()
@@ -1,14 +1,14 @@
1
1
  from functools import partial
2
2
  from itertools import count
3
3
  from types import SimpleNamespace
4
- from .._rs import fast_vget, fast_vset, fast_vset_trait
4
+ from koatl._rs import fast_vget, fast_vset, fast_vset_trait
5
5
 
6
6
 
7
7
  def vget(obj, name, ignore_traits=False):
8
8
  try:
9
9
  return getattr(obj, name)
10
- except AttributeError:
11
- pass
10
+ except AttributeError as e:
11
+ orig_err = e
12
12
 
13
13
  # special case for iter - this could be implemented using types and trait vtbls
14
14
  # but this is simpler and probably faster
@@ -38,7 +38,7 @@ def vget(obj, name, ignore_traits=False):
38
38
 
39
39
  return partial(v, obj)
40
40
 
41
- raise AttributeError(f"'{type(obj).__name__}' object has no v-attribute '{name}'")
41
+ raise orig_err
42
42
 
43
43
 
44
44
  def vhas(obj, name, ignore_traits=False):
@@ -0,0 +1,5 @@
1
+ export import .base.*
2
+ export import .async.*
3
+ export import .env.*
4
+ export import .memo.*
5
+ export import .result.*
@@ -1,7 +1,7 @@
1
1
  import functools.wraps
2
2
  import asyncio
3
3
 
4
- import .MonadOnce
4
+ import .base.MonadOnce
5
5
 
6
6
  export Async = class(MonadOnce):
7
7
  __init__ = (self, awaitable) => self.generator = awaitable.__await__()
@@ -1,5 +1,5 @@
1
1
  import functools.wraps
2
- import .MonadOnce
2
+ import .base.MonadOnce
3
3
 
4
4
  export Env = class(MonadOnce):
5
5
  __slots__ = ("f",)
@@ -1,7 +1,7 @@
1
1
  import collections.defaultdict
2
2
  import functools.wraps
3
3
 
4
- import .algebra.(MonadOnce, Identity)
4
+ import .base.(MonadOnce, Identity)
5
5
  import .result.(Result, Ok, Err)
6
6
  import .async.(Async)
7
7
 
@@ -181,7 +181,4 @@ export AsyncMemo = class(MonadOnce):
181
181
 
182
182
  except StopIteration(value=value):
183
183
  return value
184
- )
185
-
186
- __tl__.memo_value = Memo.value
187
- __tl__.async_memo_value = AsyncMemo.value
184
+ )
@@ -1,5 +1,5 @@
1
1
  import functools.wraps
2
- import .algebra.(Identity, MonadOnce)
2
+ import .base.(Identity, MonadOnce)
3
3
 
4
4
  infer_ok = x =>
5
5
  x match:
@@ -158,26 +158,4 @@ export Err = class(Result):
158
158
  if self.value matches BaseException():
159
159
  raise self.value
160
160
  raise ValueError(f"Expected Ok, got {repr(self)}")
161
- coalesce = (self, f) => f()
162
-
163
- Extension.property(object, "result")& self => Result
164
-
165
- __tl__.Ok = Ok
166
- __tl__.Err = Err
167
- __tl__.Result = Result
168
-
169
- __tl__.op_coal = (x, f) =>
170
- if x matches Result():
171
- return x.coalesce(f)
172
-
173
- if not infer_ok(x):
174
- return f()
175
- return x
176
-
177
- __tl__.op_map = (x, f) =>
178
- if x matches Result():
179
- return x.map(f)
180
-
181
- if infer_ok(x):
182
- return f(x)
183
- return x
161
+ coalesce = (self, f) => f()
@@ -0,0 +1 @@
1
+ export import .list.List
@@ -1,6 +1,6 @@
1
1
  import itertools
2
2
 
3
- import .Monad
3
+ import koatl.std.alg.Monad
4
4
 
5
5
  export List = class(Monad):
6
6
  __new__ = (cls, *args, **kwargs) => raise ValueError(
@@ -19,7 +19,4 @@ export List = class(Monad):
19
19
 
20
20
  pure = staticmethod& x => [x]
21
21
 
22
- len = property& self => len(self)
23
-
24
-
25
- Extension.property(list, "len")& List.len.fget
22
+ len = property& self => len(self)
@@ -0,0 +1,3 @@
1
+ export read_file = (filename) =>
2
+ with desc = open(filename, "r"):
3
+ desc.read()
@@ -1,8 +1,9 @@
1
1
  import itertools
2
2
  import builtins
3
- import .functional.(Traversable, Ok, Err, Memo, Async, AsyncMemo, Result)
3
+ import .alg.(Traversable, Ok, Err, Memo, Async, AsyncMemo, Result)
4
4
 
5
- export Iterable = Extension.trait& class(Traversable, Trait):
5
+
6
+ export Iterable = class(Traversable, Trait):
6
7
  iter = Trait.abstract& self => None
7
8
 
8
9
  skip = (self, n) =>
@@ -11,6 +12,16 @@ export Iterable = Extension.trait& class(Traversable, Trait):
11
12
  next(it, None)
12
13
  it
13
14
 
15
+ skip_while = (self, f) =>
16
+ let it = self.iter
17
+ while True:
18
+ try:
19
+ let value = next(it)
20
+ if not f(value):
21
+ return Iterable.chain([value], it)
22
+ except StopIteration():
23
+ return it
24
+
14
25
  take = (self, n) =>
15
26
  let impl = () =>
16
27
  let it = self.iter
@@ -70,7 +81,7 @@ export Iterable = Extension.trait& class(Traversable, Trait):
70
81
 
71
82
  reverse = self => reversed(list(self.iter))
72
83
 
73
- sort = (self, key=None, reverse=False) =>
84
+ sorted = (self, key=None, reverse=False) =>
74
85
  sorted(self.iter, key=key, reverse=reverse)
75
86
 
76
87
  copy = self => itertools.tee(self.iter)
@@ -99,19 +110,19 @@ export Iterable = Extension.trait& class(Traversable, Trait):
99
110
  acc[i] = value
100
111
  acc
101
112
 
102
- group_by = (self, f) =>
113
+ group_by = (self, f=None) =>
103
114
  let acc = dict()
104
115
  for i in self:
105
- let key = f(i)
116
+ let key = f === None then i else f(i)
106
117
  if not acc.__contains__(key):
107
118
  acc[key] = []
108
119
  acc[key].append(i)
109
120
  acc
110
121
 
111
- count_by = (self, f) =>
122
+ count_by = (self, f=None) =>
112
123
  let acc = dict()
113
124
  for i in self:
114
- let key = f(i)
125
+ let key = f === None then i else f(i)
115
126
  if not acc.__contains__(key):
116
127
  acc[key] = 0
117
128
  acc[key] += 1
@@ -249,8 +260,6 @@ export Iterable = Extension.trait& class(Traversable, Trait):
249
260
  Record(self.iter)
250
261
 
251
262
  traverse = (self, f=None) =>
252
- import .functional.(Async, Result)
253
-
254
263
  if f === None:
255
264
  f = x => x
256
265
 
@@ -0,0 +1,33 @@
1
+ import importlib
2
+ import collections
3
+
4
+ export LazyModule = class:
5
+ __init__ = (self, name) =>
6
+ self._name = name
7
+ self._module = None
8
+ self._submodules = {}
9
+
10
+ __getattr__ = (self, attr) =>
11
+ try:
12
+ if self._module === None:
13
+ self._module = importlib.import_module(self._name)
14
+
15
+ if hasattr(self._module, "__path__"):
16
+ if attr not in self._submodules:
17
+ self._submodules[attr] =
18
+ if importlib.util.find_spec(f"{self._name}.{attr}", self._module.__path__):
19
+ LazyModule(f"{self._name}.{attr}")
20
+ else:
21
+ None
22
+
23
+ if self._submodules[attr] <=> None:
24
+ return self._submodules[attr]
25
+
26
+ if hasattr(self._module, attr):
27
+ return getattr(self._module, attr)
28
+ except e:
29
+ raise ValueError(str(e))
30
+
31
+ raise AttributeError(f"Module '{self._name}' has no attribute '{attr}'")
32
+
33
+ __repr__ = self => f"LazyModule({self._name})"
@@ -1,8 +1,8 @@
1
1
  import re
2
2
  import collections
3
- import .functional.Result
3
+ import .alg.Result
4
4
 
5
- export Regex = class:
5
+ export Pattern = class:
6
6
  __slots__ = ("pattern",)
7
7
 
8
8
  __init__ = (self, pattern) =>
@@ -45,16 +45,4 @@ export Regex = class:
45
45
 
46
46
  match = property& self => self._match.group(0)
47
47
 
48
- __repr__ = self => f"Match({self._match})"
49
-
50
-
51
- Extension.method(str, "match")& (regex, str) => Regex(regex).match(str)
52
-
53
-
54
- # Note: the below methods have arguments in reverse order to Python's re module.
55
-
56
- Extension.method(str, "matches")& (str, regex) =>
57
- Regex(regex).match(str)
58
-
59
- Extension.method(str, "search")& (str, regex) =>
60
- Regex(regex).search(str)
48
+ __repr__ = self => f"Match({self._match})"
@@ -97,21 +97,20 @@ pub enum Literal<'a> {
97
97
  pub type SLiteral<'a> = Spanned<Literal<'a>>;
98
98
 
99
99
  #[derive(Debug, Clone)]
100
- pub enum ImportList<'a> {
101
- // ident, alias
102
- Leaves(Vec<(SIdent<'a>, Option<SIdent<'a>>)>),
100
+ pub enum ImportLeaf<'a> {
101
+ Multi(Vec<ImportTree<'a>>),
102
+ Single(SIdent<'a>, Option<SIdent<'a>>),
103
+ This(Option<SIdent<'a>>),
103
104
  Star,
104
105
  }
105
106
 
106
107
  #[derive(Debug, Clone)]
107
- pub struct ImportStmt<'a> {
108
+ pub struct ImportTree<'a> {
108
109
  pub trunk: Vec<SIdent<'a>>,
109
- pub imports: ImportList<'a>,
110
+ pub leaf: Spanned<ImportLeaf<'a>>,
110
111
 
111
112
  // number of dots prepending the trunk
112
113
  pub level: usize,
113
-
114
- pub reexport: bool,
115
114
  }
116
115
 
117
116
  #[derive(Debug, Clone, Copy, PartialEq)]
@@ -133,7 +132,7 @@ pub enum Stmt<'a, TTree: Tree> {
133
132
  Return(TTree::Expr),
134
133
  While(TTree::Expr, TTree::Expr),
135
134
  For(TTree::Pattern, TTree::Expr, TTree::Expr),
136
- Import(ImportStmt<'a>),
135
+ Import(ImportTree<'a>, bool),
137
136
  Try(TTree::Expr, Vec<MatchCase<TTree>>, Option<TTree::Expr>),
138
137
  Raise(Option<TTree::Expr>),
139
138
 
@@ -646,55 +646,62 @@ where
646
646
  .labelled("continue statement")
647
647
  .boxed();
648
648
 
649
+ let import_item = recursive(|import_item| {
650
+ // TODO this looks extremely cursed
651
+ let level = symbol("..")
652
+ .to(2)
653
+ .repeated()
654
+ .foldr(
655
+ symbol(".")
656
+ .or_not()
657
+ .map(|x| if x.is_some() { 1 } else { 0 }),
658
+ |acc, sum| acc + sum,
659
+ )
660
+ .boxed();
661
+
662
+ let prefix = ident
663
+ .clone()
664
+ .then_ignore(symbol("."))
665
+ .repeated()
666
+ .collect()
667
+ .boxed();
668
+
669
+ choice((
670
+ group((
671
+ level,
672
+ prefix,
673
+ choice((
674
+ enumeration(import_item.clone(), symbol(","))
675
+ .delimited_by_with_eol(symbol("("), symbol(")"))
676
+ .map(ImportLeaf::Multi),
677
+ ident
678
+ .clone()
679
+ .then(just(Token::Kw("as")).ignore_then(ident.clone()).or_not())
680
+ .map(|(item, name)| ImportLeaf::Single(item, name)),
681
+ symbol("*").map(|_| ImportLeaf::Star),
682
+ )),
683
+ ))
684
+ .map_with(|(level, prefix, choice), e| ImportTree {
685
+ trunk: prefix,
686
+ level: level,
687
+ leaf: choice.spanned(e.span()),
688
+ }),
689
+ symbol(".")
690
+ .ignore_then(just(Token::Kw("as")).ignore_then(ident.clone()).or_not())
691
+ .map_with(|alias, e| ImportTree {
692
+ trunk: vec![],
693
+ level: 0,
694
+ leaf: ImportLeaf::This(alias).spanned(e.span()),
695
+ }),
696
+ ))
697
+ });
698
+
649
699
  let import_stmt = just(Token::Kw("export"))
650
700
  .to(1)
651
701
  .or_not()
652
702
  .then_ignore(just(Token::Kw("import")))
653
- .then(group((
654
- // TODO this looks extremely cursed
655
- symbol("..")
656
- .to(2)
657
- .repeated()
658
- .foldr(
659
- symbol(".")
660
- .or_not()
661
- .map(|x| if x.is_some() { 1 } else { 0 }),
662
- |acc, sum| acc + sum,
663
- )
664
- .boxed(),
665
- ident
666
- .clone()
667
- .then_ignore(symbol("."))
668
- .repeated()
669
- .collect()
670
- .boxed(),
671
- choice((
672
- enumeration(
673
- ident
674
- .clone()
675
- .then(just(Token::Kw("as")).ignore_then(ident.clone()).or_not()),
676
- symbol(","),
677
- )
678
- .delimited_by_with_eol(symbol("("), symbol(")"))
679
- .map(ImportList::Leaves)
680
- .boxed(),
681
- just(Token::Symbol("*")).map(|_| ImportList::Star),
682
- ident
683
- .clone()
684
- .then(just(Token::Kw("as")).ignore_then(ident.clone()).or_not())
685
- .map(|x| ImportList::Leaves(vec![x]))
686
- .boxed(),
687
- ))
688
- .boxed(),
689
- )))
690
- .map(|(reexport, (level, trunk, import_list))| {
691
- SStmtInner::Import(ImportStmt {
692
- trunk,
693
- imports: import_list,
694
- level,
695
- reexport: reexport.is_some(),
696
- })
697
- })
703
+ .then(import_item)
704
+ .map(|(reexport, tree)| SStmtInner::Import(tree, reexport.is_some()))
698
705
  .labelled("import statement")
699
706
  .boxed();
700
707
 
@@ -745,8 +752,7 @@ where
745
752
  let mut expr = Recursive::<chumsky::recursive::Indirect<TInput, SExpr, TExtra>>::declare();
746
753
  let mut unary = Recursive::<chumsky::recursive::Indirect<TInput, SExpr, TExtra>>::declare();
747
754
  let mut cases = Recursive::<chumsky::recursive::Indirect<TInput, _, TExtra>>::declare();
748
- let mut below_pipe =
749
- Recursive::<chumsky::recursive::Indirect<TInput, SExpr, TExtra>>::declare();
755
+ let mut below_fn = Recursive::<chumsky::recursive::Indirect<TInput, SExpr, TExtra>>::declare();
750
756
 
751
757
  let stmts = stmt
752
758
  .clone()
@@ -1134,6 +1140,7 @@ where
1134
1140
 
1135
1141
  enum Postfix<'a> {
1136
1142
  Call(Vec<CallItem<'a, STree<'a>>>),
1143
+ MethodCall(SIdent<'a>, Vec<CallItem<'a, STree<'a>>>),
1137
1144
  Subscript(Vec<ListItem<STree<'a>>>),
1138
1145
  Attribute(SIdent<'a>),
1139
1146
  ScopedAttribute(SExpr<'a>),
@@ -1181,6 +1188,12 @@ where
1181
1188
  .labelled("subscript")
1182
1189
  .boxed();
1183
1190
 
1191
+ let method_call = symbol(".")
1192
+ .ignore_then(ident.clone())
1193
+ .then(call_args.clone())
1194
+ .map(|(ident, args)| Postfix::MethodCall(ident, args))
1195
+ .labelled("method-call");
1196
+
1184
1197
  let attribute = symbol(".")
1185
1198
  .ignore_then(ident.clone())
1186
1199
  .map(Postfix::Attribute)
@@ -1204,12 +1217,25 @@ where
1204
1217
  symbol("?")
1205
1218
  .to(1)
1206
1219
  .or_not()
1207
- .then(choice((call, subscript, attribute, then, raw_attr)))
1220
+ .then(choice((
1221
+ call,
1222
+ subscript,
1223
+ method_call,
1224
+ attribute,
1225
+ then,
1226
+ raw_attr,
1227
+ )))
1208
1228
  .repeated(),
1209
1229
  |expr, (coal, op), e| -> SExpr {
1210
1230
  if coal.is_none() {
1211
1231
  match op {
1212
1232
  Postfix::Call(args) => Expr::Call(expr.indirect(), args),
1233
+ Postfix::MethodCall(name, args) => Expr::Call(
1234
+ Expr::Attribute(expr.indirect(), name)
1235
+ .spanned(e.span())
1236
+ .indirect(),
1237
+ args,
1238
+ ),
1213
1239
  Postfix::Subscript(args) => Expr::Subscript(expr.indirect(), args),
1214
1240
  Postfix::RawAttribute(attr) => Expr::RawAttribute(expr.indirect(), attr),
1215
1241
  Postfix::ScopedAttribute(rhs) => {
@@ -1220,6 +1246,12 @@ where
1220
1246
  } else {
1221
1247
  match op {
1222
1248
  Postfix::Call(args) => Expr::MappedCall(expr.indirect(), args),
1249
+ Postfix::MethodCall(name, args) => Expr::MappedCall(
1250
+ Expr::MappedAttribute(expr.indirect(), name)
1251
+ .spanned(e.span())
1252
+ .indirect(),
1253
+ args,
1254
+ ),
1223
1255
  Postfix::Subscript(args) => Expr::MappedSubscript(expr.indirect(), args),
1224
1256
  Postfix::RawAttribute(attr) => {
1225
1257
  Expr::MappedRawAttribute(expr.indirect(), attr)
@@ -1374,17 +1406,10 @@ where
1374
1406
  .boxed(),
1375
1407
  );
1376
1408
 
1377
- let fn_ = function(
1378
- expr_or_inline_stmt_or_block.clone(),
1379
- ident.clone(),
1380
- expr.clone(),
1381
- closed_pattern.clone(),
1382
- );
1383
-
1384
1409
  not_or_try.define(choice((not, checked, binary3.clone())));
1385
1410
 
1386
1411
  let binary4 = make_binary_op(
1387
- choice((fn_, not_or_try)),
1412
+ not_or_try,
1388
1413
  select! {
1389
1414
  Token::Symbol("??") => BinaryOp::Coalesce,
1390
1415
  },
@@ -1429,7 +1454,7 @@ where
1429
1454
 
1430
1455
  let (match_, cases_) = match_expr(
1431
1456
  slices,
1432
- binary3,
1457
+ below_fn.clone(),
1433
1458
  nary_pattern.clone(),
1434
1459
  expr_or_inline_stmt_or_block.clone(),
1435
1460
  );
@@ -1465,12 +1490,19 @@ where
1465
1490
  matches,
1466
1491
  select! {
1467
1492
  Token::Kw("and") => BinaryOp::And,
1493
+ },
1494
+ false,
1495
+ );
1496
+
1497
+ let binary6 = make_binary_op(
1498
+ binary5,
1499
+ select! {
1468
1500
  Token::Kw("or") => BinaryOp::Or,
1469
1501
  },
1470
1502
  false,
1471
1503
  );
1472
1504
 
1473
- let if_ = binary5
1505
+ let if_ = binary6
1474
1506
  .then(
1475
1507
  group((
1476
1508
  just(Token::Kw("then"))
@@ -1494,10 +1526,17 @@ where
1494
1526
  }
1495
1527
  });
1496
1528
 
1497
- below_pipe.define(if_);
1529
+ below_fn.define(if_);
1530
+
1531
+ let fn_ = function(
1532
+ expr_or_inline_stmt_or_block.clone(),
1533
+ ident.clone(),
1534
+ expr.clone(),
1535
+ closed_pattern.clone(),
1536
+ );
1498
1537
 
1499
1538
  let binary6 = make_binary_op(
1500
- below_pipe.clone(),
1539
+ choice((fn_, below_fn)),
1501
1540
  select! {
1502
1541
  Token::Symbol("|") => BinaryOp::Pipe,
1503
1542
  },