koatl 0.1.41__tar.gz → 0.2.2__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 (144) hide show
  1. {koatl-0.1.41 → koatl-0.2.2}/Cargo.lock +9 -9
  2. koatl-0.2.2/Cargo.toml +3 -0
  3. {koatl-0.1.41 → koatl-0.2.2}/PKG-INFO +1 -1
  4. {koatl-0.1.41 → koatl-0.2.2}/koatl/Cargo.toml +1 -1
  5. {koatl-0.1.41 → koatl-0.2.2/koatl}/python/koatl/cli.py +15 -1
  6. {koatl-0.1.41 → koatl-0.2.2/koatl}/python/koatl/runtime/__init__.py +4 -3
  7. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/runtime/meta_finder.py +1 -1
  8. {koatl-0.1.41 → koatl-0.2.2/koatl}/python/koatl/std/alg/async.tl +1 -1
  9. {koatl-0.1.41 → koatl-0.2.2/koatl}/python/koatl/std/alg/do.tl +5 -5
  10. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/std/alg/env.tl +3 -3
  11. {koatl-0.1.41 → koatl-0.2.2/koatl}/python/koatl/std/alg/memo.tl +7 -8
  12. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/std/alg/result.tl +5 -5
  13. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/std/data/list.tl +3 -3
  14. koatl-0.2.2/koatl/python/koatl/std/io.tl +7 -0
  15. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/std/iter.tl +10 -6
  16. koatl-0.2.2/koatl/python/koatl/std/json.tl +34 -0
  17. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/std/lazy_module.tl +1 -1
  18. koatl-0.2.2/koatl/python/koatl/std/pickle.tl +10 -0
  19. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/std/trait.py +2 -2
  20. {koatl-0.1.41 → koatl-0.2.2}/koatl/src/emit_py.rs +1 -1
  21. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/match.tl +27 -12
  22. koatl-0.2.2/koatl/tests/e2e/prelude/try.tl +28 -0
  23. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/prelude/virtual.tl +2 -2
  24. koatl-0.2.2/koatl/tests/parse/matches.tl +2 -0
  25. {koatl-0.1.41 → koatl-0.2.2}/koatl-core/Cargo.toml +1 -1
  26. {koatl-0.1.41/koatl-core/parser → koatl-0.2.2/koatl-core}/src/ast.rs +5 -61
  27. koatl-0.1.41/koatl-core/parser/src/util.rs → koatl-0.2.2/koatl-core/src/ast_builder.rs +12 -5
  28. {koatl-0.1.41 → koatl-0.2.2}/koatl-core/src/inference.rs +17 -21
  29. {koatl-0.1.41 → koatl-0.2.2}/koatl-core/src/lib.rs +25 -15
  30. koatl-0.2.2/koatl-core/src/lift_cst.rs +663 -0
  31. {koatl-0.1.41 → koatl-0.2.2}/koatl-core/src/parse_timer.rs +10 -11
  32. {koatl-0.1.41 → koatl-0.2.2}/koatl-core/src/py/ast.rs +7 -1
  33. koatl-0.1.41/koatl-core/src/py/util.rs → koatl-0.2.2/koatl-core/src/py/ast_builder.rs +2 -1
  34. {koatl-0.1.41 → koatl-0.2.2}/koatl-core/src/py/emit.rs +15 -6
  35. {koatl-0.1.41 → koatl-0.2.2}/koatl-core/src/py/mod.rs +1 -1
  36. {koatl-0.1.41 → koatl-0.2.2}/koatl-core/src/resolve_scopes.rs +31 -38
  37. {koatl-0.1.41 → koatl-0.2.2}/koatl-core/src/transform.rs +52 -30
  38. {koatl-0.1.41 → koatl-0.2.2}/koatl-core/src/util.rs +1 -1
  39. {koatl-0.1.41/koatl-core/parser → koatl-0.2.2/koatl-parser}/Cargo.toml +1 -1
  40. koatl-0.2.2/koatl-parser/src/cst.rs +720 -0
  41. koatl-0.2.2/koatl-parser/src/lexer.rs +1683 -0
  42. {koatl-0.1.41/koatl-core/parser → koatl-0.2.2/koatl-parser}/src/lib.rs +3 -2
  43. koatl-0.2.2/koatl-parser/src/parser.rs +2398 -0
  44. koatl-0.2.2/koatl-parser/src/parser_error.rs +419 -0
  45. koatl-0.2.2/koatl-parser/src/simple_fmt.rs +743 -0
  46. {koatl-0.1.41/koatl → koatl-0.2.2}/python/koatl/cli.py +15 -1
  47. {koatl-0.1.41/koatl → koatl-0.2.2}/python/koatl/runtime/__init__.py +4 -3
  48. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/runtime/meta_finder.py +1 -1
  49. {koatl-0.1.41/koatl → koatl-0.2.2}/python/koatl/std/alg/async.tl +1 -1
  50. {koatl-0.1.41/koatl → koatl-0.2.2}/python/koatl/std/alg/do.tl +5 -5
  51. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/std/alg/env.tl +3 -3
  52. {koatl-0.1.41/koatl → koatl-0.2.2}/python/koatl/std/alg/memo.tl +7 -8
  53. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/std/alg/result.tl +5 -5
  54. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/std/data/list.tl +3 -3
  55. koatl-0.2.2/python/koatl/std/io.tl +7 -0
  56. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/std/iter.tl +10 -6
  57. koatl-0.2.2/python/koatl/std/json.tl +34 -0
  58. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/std/lazy_module.tl +1 -1
  59. koatl-0.2.2/python/koatl/std/pickle.tl +10 -0
  60. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/std/trait.py +2 -2
  61. koatl-0.1.41/Cargo.toml +0 -3
  62. koatl-0.1.41/koatl/python/koatl/std/io.tl +0 -3
  63. koatl-0.1.41/koatl/tests/e2e/prelude/try.tl +0 -29
  64. koatl-0.1.41/koatl/tests/parse/matches.tl +0 -2
  65. koatl-0.1.41/koatl-core/parser/src/lexer.rs +0 -1106
  66. koatl-0.1.41/koatl-core/parser/src/parser.rs +0 -1577
  67. koatl-0.1.41/koatl-core/src/parser.rs +0 -1
  68. koatl-0.1.41/python/koatl/std/io.tl +0 -3
  69. {koatl-0.1.41 → koatl-0.2.2}/README.md +0 -0
  70. {koatl-0.1.41 → koatl-0.2.2}/koatl/.github/workflows/CI.yml +0 -0
  71. {koatl-0.1.41 → koatl-0.2.2}/koatl/.gitignore +0 -0
  72. {koatl-0.1.41 → koatl-0.2.2}/koatl/LICENSE +0 -0
  73. {koatl-0.1.41 → koatl-0.2.2}/koatl/README.md +0 -0
  74. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/__init__.py +0 -0
  75. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/__main__.py +0 -0
  76. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/notebook/__init__.py +0 -0
  77. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/notebook/magic.py +0 -0
  78. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/prelude/__init__.tl +0 -0
  79. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/runtime/record.py +0 -0
  80. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/runtime/vattr.py +0 -0
  81. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/std/alg/__init__.tl +0 -0
  82. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/std/alg/base.tl +0 -0
  83. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/std/data/__init__.tl +0 -0
  84. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/std/data/record.tl +0 -0
  85. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/std/ext.tl +0 -0
  86. {koatl-0.1.41 → koatl-0.2.2}/koatl/python/koatl/std/re.tl +0 -0
  87. {koatl-0.1.41 → koatl-0.2.2}/koatl/requirements.txt +0 -0
  88. {koatl-0.1.41 → koatl-0.2.2}/koatl/src/lib.rs +0 -0
  89. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/containers.tl +0 -0
  90. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/data.txt +0 -0
  91. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/decorators.tl +0 -0
  92. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
  93. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/destructure.tl +0 -0
  94. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/escape_ident.tl +0 -0
  95. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/fstr.tl +0 -0
  96. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/functions.tl +0 -0
  97. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/generator.tl +0 -0
  98. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/if_expr.tl +0 -0
  99. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/loops.tl +0 -0
  100. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/nary-list.tl +0 -0
  101. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/placeholder.tl +0 -0
  102. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/precedence.tl +0 -0
  103. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/scopes.tl +0 -0
  104. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/semantic_whitespace.tl +0 -0
  105. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/short_circuit.tl +0 -0
  106. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/base/with.tl +0 -0
  107. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/prelude/async.tl +0 -0
  108. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/prelude/aug_assign.tl +0 -0
  109. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/prelude/coal.tl +0 -0
  110. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/prelude/env.tl +0 -0
  111. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/prelude/imports.tl +0 -0
  112. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/prelude/iterables.tl +0 -0
  113. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/prelude/list.tl +0 -0
  114. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/prelude/memo.tl +0 -0
  115. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/prelude/record.tl +0 -0
  116. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/prelude/result.tl +0 -0
  117. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/prelude/slice.tl +0 -0
  118. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/util/__init__.py +0 -0
  119. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/util/module0.tl +0 -0
  120. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/util/module1.tl +0 -0
  121. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/e2e/util/module2.tl +0 -0
  122. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/parse/arith.tl +0 -0
  123. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/parse/assign.tl +0 -0
  124. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/parse/block-comments.tl +0 -0
  125. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/parse/deco.tl +0 -0
  126. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/parse/func.tl +0 -0
  127. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/test_e2e.py +0 -0
  128. {koatl-0.1.41 → koatl-0.2.2}/koatl/tests/test_parse.py +0 -0
  129. {koatl-0.1.41 → koatl-0.2.2}/koatl-core/src/main.rs +0 -0
  130. {koatl-0.1.41 → koatl-0.2.2}/koatl-core/src/types.rs +0 -0
  131. {koatl-0.1.41 → koatl-0.2.2}/pyproject.toml +0 -0
  132. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/__init__.py +0 -0
  133. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/__main__.py +0 -0
  134. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/notebook/__init__.py +0 -0
  135. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/notebook/magic.py +0 -0
  136. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/prelude/__init__.tl +0 -0
  137. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/runtime/record.py +0 -0
  138. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/runtime/vattr.py +0 -0
  139. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/std/alg/__init__.tl +0 -0
  140. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/std/alg/base.tl +0 -0
  141. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/std/data/__init__.tl +0 -0
  142. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/std/data/record.tl +0 -0
  143. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/std/ext.tl +0 -0
  144. {koatl-0.1.41 → koatl-0.2.2}/python/koatl/std/re.tl +0 -0
@@ -99,7 +99,7 @@ checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
99
99
 
100
100
  [[package]]
101
101
  name = "koatl"
102
- version = "0.1.41"
102
+ version = "0.2.2"
103
103
  dependencies = [
104
104
  "ariadne",
105
105
  "koatl-core",
@@ -112,11 +112,18 @@ name = "koatl-core"
112
112
  version = "0.1.0"
113
113
  dependencies = [
114
114
  "ariadne",
115
+ "koatl-parser",
115
116
  "once_cell",
116
- "parser",
117
117
  "slotmap",
118
118
  ]
119
119
 
120
+ [[package]]
121
+ name = "koatl-parser"
122
+ version = "0.1.0"
123
+ dependencies = [
124
+ "chumsky",
125
+ ]
126
+
120
127
  [[package]]
121
128
  name = "libc"
122
129
  version = "0.2.174"
@@ -144,13 +151,6 @@ version = "1.21.3"
144
151
  source = "registry+https://github.com/rust-lang/crates.io-index"
145
152
  checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
146
153
 
147
- [[package]]
148
- name = "parser"
149
- version = "0.1.0"
150
- dependencies = [
151
- "chumsky",
152
- ]
153
-
154
154
  [[package]]
155
155
  name = "portable-atomic"
156
156
  version = "1.11.1"
koatl-0.2.2/Cargo.toml ADDED
@@ -0,0 +1,3 @@
1
+ [workspace]
2
+ members = ["koatl-parser", "koatl-core", "koatl"]
3
+ resolver = "3"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: koatl
3
- Version: 0.1.41
3
+ Version: 0.2.2
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.41"
3
+ version = "0.2.2"
4
4
  edition = "2021"
5
5
 
6
6
  [lib]
@@ -9,9 +9,23 @@ def transpile_from_source(source, mode="script", script_path="<string>"):
9
9
 
10
10
  def run_from_source(source, mode="script", script_path="<string>"):
11
11
  from koatl import transpile
12
+ import ast
12
13
 
13
14
  transpiled_code = transpile(source, mode=mode, filename=str(script_path))
14
- code_obj = compile(transpiled_code, script_path, "exec")
15
+
16
+ try:
17
+ code_obj = compile(transpiled_code, script_path, "exec")
18
+ except Exception as e:
19
+
20
+ class Visitor(ast.NodeVisitor):
21
+ def generic_visit(self, node):
22
+ if hasattr(node, "lineno"):
23
+ if node.lineno > node.end_lineno:
24
+ print(f"Error: {node.lineno} > {node.end_lineno} for {node}")
25
+ super().generic_visit(node)
26
+
27
+ Visitor().visit(transpiled_code)
28
+ raise
15
29
 
16
30
  script_globals = {"__name__": "__main__"}
17
31
 
@@ -3,7 +3,8 @@ import importlib
3
3
  from types import SimpleNamespace
4
4
 
5
5
  from koatl.runtime.record import Record
6
- from . import meta_finder, vattr
6
+ from . import meta_finder
7
+ from .vattr import vhas, vget
7
8
 
8
9
  meta_finder.install_hook()
9
10
 
@@ -42,6 +43,6 @@ __tl__ = SimpleNamespace(
42
43
  #
43
44
  set_exports=set_exports,
44
45
  #
45
- vget=vattr.vget,
46
- vhas=vattr.vhas,
46
+ vget=vget,
47
+ vhas=vhas,
47
48
  )
@@ -52,7 +52,7 @@ class TlLoader(Loader):
52
52
  self.filepath,
53
53
  )
54
54
 
55
- if module.__name__.startswith("koatl.prelude"):
55
+ if module.__name__.startswith("koatl"):
56
56
  transpiled_code = transpile(
57
57
  source_code, mode="no_prelude", filename=self.filepath
58
58
  )
@@ -31,7 +31,7 @@ export Async = class(MonadOnce):
31
31
  self = gen.send(yield from self.__await__())
32
32
  if not hasattr(self, "__await__"):
33
33
  raise ValueError(f"Expected the binder to return an Awaitable, but got {type(self).__name__}")
34
- except StopIteration(value=value):
34
+ except StopIteration(value=value) =>
35
35
  return value
36
36
 
37
37
  pure = staticmethod& x => Async.from_generator_fn& () =>
@@ -7,10 +7,10 @@ export do = f => wraps(f)& (*args, **kwargs) =>
7
7
  let m
8
8
  try:
9
9
  m = gen.send(None)
10
- except StopIteration() as e:
10
+ except StopIteration() as e =>
11
11
  raise ValueError(
12
12
  "Returning before `@` is not allowed. "
13
- "Use `return @MonadType.pure(value)` instead."
13
+ + "Use `return @MonadType.pure(value)` instead."
14
14
  )
15
15
 
16
16
  try:
@@ -18,17 +18,17 @@ export do = f => wraps(f)& (*args, **kwargs) =>
18
18
  # is it possible to derive bind_gen directly from bind_once?
19
19
 
20
20
  return m.bind_gen(gen)
21
- except AttributeError():
21
+ except AttributeError() =>
22
22
  None
23
23
 
24
24
  let recurse = v =>
25
25
  try:
26
26
  m = gen.send(v)
27
27
  return m.bind_once(recurse)
28
- except StopIteration() as e:
28
+ except StopIteration() as e =>
29
29
  return m.pure(e.value)
30
30
 
31
31
  try:
32
32
  return m.bind_once(recurse)
33
- except AttributeError():
33
+ except AttributeError() =>
34
34
  raise ValueError("@ can only be used with an object that has `bind_once`.")
@@ -26,7 +26,7 @@ export Env = class(MonadOnce):
26
26
 
27
27
  bind_once = (self, f) => Env& ctx =>
28
28
  let v = f(self.f(ctx))
29
- if v matches not Env():
29
+ if v not matches Env():
30
30
  raise ValueError(f"Expected the binder to return an Env, but got {type(v)}")
31
31
 
32
32
  v.f(ctx)
@@ -35,9 +35,9 @@ export Env = class(MonadOnce):
35
35
  try:
36
36
  while True:
37
37
  self = gen.send(self.f(ctx))
38
- if self matches not Env():
38
+ if self not matches Env():
39
39
  raise ValueError(f"Expected the binder to return an Env, but got {type(self)}")
40
- except StopIteration(value=value):
40
+ except StopIteration(value=value) =>
41
41
  return value
42
42
 
43
43
  NoKey = object()
@@ -24,7 +24,7 @@ export Memo = class(MonadOnce):
24
24
 
25
25
  __repr__ = self => f"Memo.Cache({self.cache})"
26
26
 
27
- try_get = (self, name, deps) => try self.cache[name][deps] except KeyError()
27
+ try_get = (self, name, deps) => check self.cache[name][deps] except KeyError()
28
28
 
29
29
  update = (self, name, deps, value) =>
30
30
  self.cache[name][deps] = value
@@ -88,7 +88,7 @@ export Memo = class(MonadOnce):
88
88
  bind_once = (self, f) => Memo(ctx =>
89
89
  let value = f(self.f(ctx))
90
90
 
91
- if value matches not Memo():
91
+ if value not matches Memo():
92
92
  raise ValueError(f"Expected the binder to return a Memo, but got {type(value)}")
93
93
 
94
94
  return value.f(ctx)
@@ -100,10 +100,9 @@ export Memo = class(MonadOnce):
100
100
  let inner = self.f(ctx)
101
101
  self = gen.send(inner)
102
102
 
103
- if self matches not Memo():
103
+ if self not matches Memo():
104
104
  raise ValueError(f"Expected the binder to return a Memo, but got {type(value)}")
105
-
106
- except StopIteration(value=value):
105
+ except StopIteration(value=value) =>
107
106
  return value
108
107
  )
109
108
 
@@ -164,7 +163,7 @@ export AsyncMemo = class(MonadOnce):
164
163
  bind_once = (self, f) => AsyncMemo(ctx =>
165
164
  let value = f(@self.f(ctx))
166
165
 
167
- if value matches not AsyncMemo():
166
+ if value not matches AsyncMemo():
168
167
  raise ValueError(f"Expected the binder to return a Memo, but got {type(value)}")
169
168
 
170
169
  return value.f(ctx)
@@ -176,9 +175,9 @@ export AsyncMemo = class(MonadOnce):
176
175
  let inner = @self.f(ctx)
177
176
  self = gen.send(inner)
178
177
 
179
- if self matches not AsyncMemo():
178
+ if self not matches AsyncMemo():
180
179
  raise ValueError(f"Expected the binder to return a Memo, but got {type(value)}")
181
180
 
182
- except StopIteration(value=value):
181
+ except StopIteration(value=value) =>
183
182
  return value
184
183
  )
@@ -5,7 +5,7 @@ infer_ok = x =>
5
5
  x match:
6
6
  None => False
7
7
  BaseException() => False
8
- default True
8
+ _ => True
9
9
 
10
10
  op_coal = (x, f) =>
11
11
  if x matches Result():
@@ -42,7 +42,7 @@ export Result = class(MonadOnce):
42
42
  """
43
43
  try:
44
44
  return Ok(f())
45
- except BaseException() as e:
45
+ except BaseException() as e =>
46
46
  return Err(e)
47
47
 
48
48
  bind_once = (self, f) =>
@@ -50,7 +50,7 @@ export Result = class(MonadOnce):
50
50
  return self
51
51
 
52
52
  let value = f(self.value)
53
- if value matches not Result():
53
+ if value not matches Result():
54
54
  raise ValueError(f"Expected the binder to return a Result, but got {type(value)}")
55
55
  value
56
56
 
@@ -61,9 +61,9 @@ export Result = class(MonadOnce):
61
61
  return self
62
62
 
63
63
  self = gen.send(self.value)
64
- if self matches not Result():
64
+ if self not matches Result():
65
65
  raise ValueError(f"Expected the binder to return a Result, but got {type(self)}")
66
- except StopIteration(value=value):
66
+ except StopIteration(value=value) =>
67
67
  return Result(value)
68
68
 
69
69
  pure = staticmethod& x => Ok(x)
@@ -5,14 +5,14 @@ import koatl.std.alg.Monad
5
5
  export List = class(Monad):
6
6
  __new__ = (cls, *args, **kwargs) => raise ValueError(
7
7
  "List cannot be instantiated directly. "
8
- "Use [] or list()."
8
+ + "Use [] or list()."
9
9
  )
10
10
 
11
11
  bind_once = (self, f) =>
12
12
  raise NotImplementedError(
13
13
  "List may not be bound using @ "
14
- "due to generator limitations. "
15
- "Wrap in Ok to use the Result monad."
14
+ + "due to generator limitations. "
15
+ + "Wrap in Ok to use the Result monad."
16
16
  )
17
17
 
18
18
  bind = (self, f) => List(self.flat_map(f))
@@ -0,0 +1,7 @@
1
+ export read_file = (filename, binary=False) =>
2
+ with desc = open(filename, binary then "rb" else "r"):
3
+ desc.read()
4
+
5
+ export write_file = (filename, content, binary=False) =>
6
+ with desc = open(filename, binary then "wb" else "w"):
7
+ desc.write(content)
@@ -1,6 +1,7 @@
1
1
  import itertools
2
2
  import builtins
3
3
 
4
+ import koatl.std.data.Record
4
5
  import koatl.std.trait.Trait
5
6
  import .alg.(Traversable, Ok, Err, Memo, Async, AsyncMemo, Result)
6
7
 
@@ -20,7 +21,7 @@ export Iterable = class(Traversable, Trait):
20
21
  let value = next(it)
21
22
  if not f(value):
22
23
  return Iterable.chain([value], it)
23
- except StopIteration():
24
+ except StopIteration() =>
24
25
  return it
25
26
 
26
27
  take = (self, n) =>
@@ -29,7 +30,7 @@ export Iterable = class(Traversable, Trait):
29
30
  for _ in ..n:
30
31
  try:
31
32
  yield next(it)
32
- except StopIteration(value=value):
33
+ except StopIteration(value=value) =>
33
34
  return value
34
35
 
35
36
  impl.__name__ = f"take"
@@ -52,6 +53,9 @@ export Iterable = class(Traversable, Trait):
52
53
  chain = (self, *others) =>
53
54
  itertools.chain(self.iter, *others.map($.iter))
54
55
 
56
+ product = (self, *others) =>
57
+ itertools.product(self.iter, *others.map($.iter))
58
+
55
59
  zip = (self, *others) =>
56
60
  zip(self.iter, *others.map($.iter))
57
61
 
@@ -148,7 +152,7 @@ export Iterable = class(Traversable, Trait):
148
152
  return Err()
149
153
 
150
154
  first = self =>
151
- (try next(self.iter)).map_err(_ => None)
155
+ (check next(self.iter)).map_err(_ => None)
152
156
 
153
157
  last = (self, f) =>
154
158
  let result = Err()
@@ -208,7 +212,7 @@ export Iterable = class(Traversable, Trait):
208
212
  m = v
209
213
  else:
210
214
  m = key(v)
211
- except StopIteration(value=value):
215
+ except StopIteration(value=value) =>
212
216
  raise ValueError("max of empty iterable")
213
217
 
214
218
 
@@ -235,7 +239,7 @@ export Iterable = class(Traversable, Trait):
235
239
  m = v
236
240
  else:
237
241
  m = key(v)
238
- except StopIteration(value=value):
242
+ except StopIteration(value=value) =>
239
243
  raise ValueError("min of empty iterable")
240
244
 
241
245
  if key === None:
@@ -268,7 +272,7 @@ export Iterable = class(Traversable, Trait):
268
272
  let v
269
273
  try:
270
274
  v = next(it)
271
- except StopIteration():
275
+ except StopIteration() =>
272
276
  return []
273
277
 
274
278
  let m = f(v)
@@ -0,0 +1,34 @@
1
+ import json
2
+ import koatl.std.io
3
+ import koatl.std.data.Record
4
+
5
+ export JSONEncoder = class(json.JSONEncoder):
6
+ default = (self, o) =>
7
+ o match:
8
+ Record() => o.__dict__
9
+ default => super().default(o)
10
+
11
+ export JSONDecoder = class(json.JSONDecoder):
12
+ __init__ = (self, **kwargs) =>
13
+ let object_hook = d =>
14
+ d match:
15
+ dict() => Record(d)
16
+ default => d
17
+
18
+ super().__init__(object_hook=object_hook, **kwargs)
19
+
20
+ export parse = json_str => JSONDecoder().decode(json_str)
21
+
22
+ export stringify = (obj, **kwargs) => JSONEncoder(**kwargs).encode(obj)
23
+
24
+ export pretty = obj => stringify(obj, indent=2)
25
+
26
+ export compact = obj => stringify(obj, separators=(",", ":"))
27
+
28
+ export read_file = filename =>
29
+ let s = io.read_file(filename)
30
+ parse(s)
31
+
32
+ export write_file = (filename, obj, indent=2, sort_keys=True) =>
33
+ let s = stringify(obj, indent=indent, sort_keys=sort_keys)
34
+ io.write_file(filename, s)
@@ -25,7 +25,7 @@ export LazyModule = class:
25
25
 
26
26
  if hasattr(self._module, attr):
27
27
  return getattr(self._module, attr)
28
- except e:
28
+ except e =>
29
29
  raise ValueError(str(e))
30
30
 
31
31
  raise AttributeError(f"Module '{self._name}' has no attribute '{attr}'")
@@ -0,0 +1,10 @@
1
+ import pickle
2
+ import koatl.std.io
3
+
4
+ export write_file = (filename, obj, protocol=None) =>
5
+ with f = open(filename, "wb"):
6
+ pickle.dump(obj, f, protocol=protocol ?? pickle.DEFAULT_PROTOCOL)
7
+
8
+ export load_file = filename =>
9
+ with f = open(filename, "rb"):
10
+ pickle.load(f)
@@ -2,7 +2,7 @@ import abc
2
2
  import collections
3
3
  import inspect
4
4
 
5
- from koatl.prelude import __tl__
5
+ from koatl.runtime import vhas
6
6
 
7
7
 
8
8
  @collections.abc.Mapping.register
@@ -90,7 +90,7 @@ class TraitMeta(MappingMeta):
90
90
  # Check if the exact class has _trait_reqs, in which case it's a trait.
91
91
  if "_trait_reqs" in cls.__dict__:
92
92
  for req in cls._trait_reqs:
93
- if not __tl__.vhas(instance, req):
93
+ if not vhas(instance, req):
94
94
  return False
95
95
 
96
96
  return True
@@ -1,4 +1,4 @@
1
- use koatl_core::{parser::ast::*, py::ast::*, util::LineColCache};
1
+ use koatl_core::{py::ast::*, util::LineColCache, Span};
2
2
 
3
3
  use pyo3::{
4
4
  call::PyCallArgs,
@@ -1,28 +1,36 @@
1
1
  import util.assert_eq
2
2
 
3
3
  # parsing test
4
- 1 match 1 if False => 2 default 3
4
+ 1 match:
5
+ 1 if False => 2
6
+ _ => 3
5
7
 
6
8
  assert_eq(
7
- 1 match 1 if False => 2 default 3,
9
+ 1 match:
10
+ 1 if False => 2
11
+ _ => 3
8
12
  3
9
13
  )
10
14
 
11
15
  assert_eq(
12
- 1 match 1 if False => 2 else _ => 3,
16
+ 1 match:
17
+ 1 if False => 2
18
+ _ => 3
13
19
  3
14
20
  )
15
21
 
16
22
  x = 1
17
23
  assert_eq(
18
- 1 match .x => 2 default 3,
24
+ 1 match:
25
+ .x => 2
26
+ _ => 3
19
27
  2
20
28
  )
21
29
 
22
30
  assert_eq(
23
31
  1 match:
24
32
  .x => 2
25
- default 3
33
+ _ => 3
26
34
  2
27
35
  )
28
36
 
@@ -34,7 +42,7 @@ assert_eq(
34
42
  )
35
43
 
36
44
  assert_eq(
37
- match 1:
45
+ 1 match:
38
46
  .x => 2
39
47
  _ => 3
40
48
  2
@@ -42,29 +50,36 @@ assert_eq(
42
50
 
43
51
  x = 1
44
52
  assert_eq(
45
- 2 match .x => 2 default 3
53
+ 2 match:
54
+ .x => 2
55
+ _ => 3
46
56
  3
47
57
  )
48
58
 
49
59
  assert_eq(
50
- 2 match x => 2
60
+ 2 match:
61
+ x => 2
51
62
  2
52
63
  )
53
64
 
54
65
  assert_eq(
55
- [1, 2, 3] match [3, *x] => x default 123
66
+ [1, 2, 3] match:
67
+ [3, *x] => x
68
+ _ => 123
56
69
  123
57
70
  )
58
71
 
59
72
  assert_eq(
60
- [1, 2, 3] match [1, *x] => x default 123
73
+ [1, 2, 3] match:
74
+ [1, *x] => x
75
+ _ => 123
61
76
  [2, 3] | list
62
77
  )
63
78
 
64
79
  assert_eq(
65
80
  [1, 2, 3] match:
66
81
  [1, *x] => x
67
- default:
82
+ _ =>
68
83
  123
69
84
  [2, 3] | list
70
85
  )
@@ -79,7 +94,7 @@ f = () =>
79
94
  else:
80
95
  raise
81
96
 
82
- if [1, 2, 3] matches not [1, 2, x]:
97
+ if [1, 2, 3] not matches [1, 2, x]:
83
98
  raise
84
99
  else:
85
100
  assert_eq(x, 3)
@@ -0,0 +1,28 @@
1
+ import util.assert_eq
2
+
3
+ # precedence
4
+ assert_eq(check 1 ?? 2, 1)
5
+ assert_eq(check z ?? 2, 2)
6
+ assert_eq(check z matches Err(NameError()), True)
7
+ assert_eq(check z ?? check 1 ?? 2, 1)
8
+ assert_eq(check z ?? check None ?? 2, None)
9
+ assert_eq(check z ?? Err(None) ?? 2, 2)
10
+
11
+ err_type = NameError
12
+ assert_eq(check a except err_type() matches Err(), True)
13
+
14
+ # handlers
15
+ assert_eq(check 1 except ValueError() ?? 2, 1)
16
+ assert_eq(check a except NameError() ?? 2, 2)
17
+ assert_eq(check a except (ValueError() | NameError()) ?? 2, 2)
18
+
19
+ try:
20
+ check a except (ValueError() | StopIteration())
21
+ raise
22
+ except _ =>
23
+ None
24
+
25
+ assert_eq(check 1 matches Ok(1), True)
26
+
27
+ assert_eq((check 5)?.($+1), Ok(6))
28
+ assert_eq((check x)?.($+1) matches Err(), True)
@@ -28,5 +28,5 @@ assert_eq(None.some_global_prop, ())
28
28
  assert_eq({required_method: Record.method& self => 42}.derived_method(), 42)
29
29
  assert_eq({required_method: Record.method& self => 42}.derived_property, 42)
30
30
 
31
- assert_eq((try "asdf".derived_method).ok, False)
32
- assert_eq((try "asdf".derived_prop).ok, False)
31
+ assert_eq((check "asdf".derived_method).ok, False)
32
+ assert_eq((check "asdf".derived_prop).ok, False)
@@ -0,0 +1,2 @@
1
+ 1 matches 1
2
+ 1 not matches 1
@@ -5,7 +5,7 @@ edition = "2024"
5
5
 
6
6
  [dependencies]
7
7
  ariadne = "0.5.1"
8
- parser = { path = "parser" }
8
+ koatl-parser = { path = "../koatl-parser" }
9
9
  once_cell = "1.19.0"
10
10
  slotmap = "1.0.7"
11
11