koatl 0.1.14__tar.gz → 0.1.15__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 (103) hide show
  1. {koatl-0.1.14 → koatl-0.1.15}/Cargo.lock +2 -1
  2. {koatl-0.1.14 → koatl-0.1.15}/PKG-INFO +1 -1
  3. {koatl-0.1.14 → koatl-0.1.15}/koatl/Cargo.toml +1 -1
  4. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/notebook/__init__.py +14 -5
  5. {koatl-0.1.14 → koatl-0.1.15/koatl}/python/koatl/prelude/functional/__init__.tl +2 -2
  6. {koatl-0.1.14 → koatl-0.1.15/koatl}/python/koatl/prelude/functional/async.tl +5 -4
  7. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/prelude/functional/reader.tl +3 -5
  8. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/prelude/iterable.tl +3 -3
  9. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/runtime/__init__.py +1 -0
  10. {koatl-0.1.14 → koatl-0.1.15/koatl}/python/koatl/runtime/helpers.py +3 -1
  11. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/runtime/meta_finder.py +1 -1
  12. {koatl-0.1.14 → koatl-0.1.15}/koatl/src/emit_py.rs +24 -11
  13. {koatl-0.1.14 → koatl-0.1.15}/koatl/src/lib.rs +1 -1
  14. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/coal.tl +5 -4
  15. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/if_expr.tl +1 -1
  16. koatl-0.1.15/koatl/tests/e2e/base/scopes.tl +49 -0
  17. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/semantic_whitespace.tl +2 -2
  18. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/test_e2e.py +26 -9
  19. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/Cargo.toml +1 -0
  20. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/parser/Cargo.toml +1 -1
  21. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/parser/src/ast.rs +56 -40
  22. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/parser/src/lexer.rs +2 -2
  23. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/parser/src/parser.rs +220 -153
  24. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/parser/src/util.rs +33 -36
  25. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/src/lib.rs +2 -2
  26. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/src/main.rs +1 -0
  27. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/src/py/ast.rs +19 -12
  28. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/src/py/emit.rs +16 -2
  29. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/src/py/util.rs +18 -2
  30. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/src/transform.rs +1595 -1186
  31. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/notebook/__init__.py +14 -5
  32. {koatl-0.1.14/koatl → koatl-0.1.15}/python/koatl/prelude/functional/__init__.tl +2 -2
  33. {koatl-0.1.14/koatl → koatl-0.1.15}/python/koatl/prelude/functional/async.tl +5 -4
  34. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/prelude/functional/reader.tl +3 -5
  35. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/prelude/iterable.tl +3 -3
  36. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/runtime/__init__.py +1 -0
  37. {koatl-0.1.14/koatl → koatl-0.1.15}/python/koatl/runtime/helpers.py +3 -1
  38. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/runtime/meta_finder.py +1 -1
  39. {koatl-0.1.14 → koatl-0.1.15}/Cargo.toml +0 -0
  40. {koatl-0.1.14 → koatl-0.1.15}/README.md +0 -0
  41. {koatl-0.1.14 → koatl-0.1.15}/koatl/.github/workflows/CI.yml +0 -0
  42. {koatl-0.1.14 → koatl-0.1.15}/koatl/.gitignore +0 -0
  43. {koatl-0.1.14 → koatl-0.1.15}/koatl/LICENSE +0 -0
  44. {koatl-0.1.14 → koatl-0.1.15}/koatl/README.md +0 -0
  45. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/__init__.py +0 -0
  46. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/__main__.py +0 -0
  47. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/cli.py +0 -0
  48. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/notebook/magic.py +0 -0
  49. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/prelude/__init__.tl +0 -0
  50. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/prelude/functional/async_util.py +0 -0
  51. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/prelude/functional/monad.tl +0 -0
  52. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/prelude/functional/result.tl +0 -0
  53. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/runtime/record.py +0 -0
  54. {koatl-0.1.14 → koatl-0.1.15}/koatl/python/koatl/runtime/virtual.py +0 -0
  55. {koatl-0.1.14 → koatl-0.1.15}/koatl/requirements.txt +0 -0
  56. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/containers.tl +0 -0
  57. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/decorators.tl +0 -0
  58. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
  59. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/destructure.tl +0 -0
  60. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/escape_ident.tl +0 -0
  61. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/fstr.tl +0 -0
  62. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/functions.tl +0 -0
  63. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/generator.tl +0 -0
  64. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/imports.tl +0 -0
  65. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/iterables.tl +0 -0
  66. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/loops.tl +0 -0
  67. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/match.tl +0 -0
  68. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/nary-list.tl +0 -0
  69. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/placeholder.tl +0 -0
  70. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/precedence.tl +0 -0
  71. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/slice.tl +0 -0
  72. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/base/try.tl +0 -0
  73. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/destructure.tl +0 -0
  74. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/prelude/async.tl +0 -0
  75. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/prelude/reader.tl +0 -0
  76. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/prelude/result.tl +0 -0
  77. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/prelude/virtual.tl +0 -0
  78. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/util/__init__.py +0 -0
  79. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/util/module0.tl +0 -0
  80. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/util/module1.tl +0 -0
  81. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/e2e/util/module2.tl +0 -0
  82. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/parse/arith.tl +0 -0
  83. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/parse/assign.tl +0 -0
  84. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/parse/deco.tl +0 -0
  85. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/parse/func.tl +0 -0
  86. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/parse/matches.tl +0 -0
  87. {koatl-0.1.14 → koatl-0.1.15}/koatl/tests/test_parse.py +0 -0
  88. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/parser/src/lib.rs +0 -0
  89. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/parser/tests/lexer.rs +0 -0
  90. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/src/linecol.rs +0 -0
  91. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/src/parser.rs +0 -0
  92. {koatl-0.1.14 → koatl-0.1.15}/koatl-core/src/py/mod.rs +0 -0
  93. {koatl-0.1.14 → koatl-0.1.15}/pyproject.toml +0 -0
  94. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/__init__.py +0 -0
  95. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/__main__.py +0 -0
  96. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/cli.py +0 -0
  97. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/notebook/magic.py +0 -0
  98. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/prelude/__init__.tl +0 -0
  99. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/prelude/functional/async_util.py +0 -0
  100. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/prelude/functional/monad.tl +0 -0
  101. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/prelude/functional/result.tl +0 -0
  102. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/runtime/record.py +0 -0
  103. {koatl-0.1.14 → koatl-0.1.15}/python/koatl/runtime/virtual.py +0 -0
@@ -99,7 +99,7 @@ checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
99
99
 
100
100
  [[package]]
101
101
  name = "koatl"
102
- version = "0.1.14"
102
+ version = "0.1.15"
103
103
  dependencies = [
104
104
  "ariadne",
105
105
  "koatl-core",
@@ -112,6 +112,7 @@ name = "koatl-core"
112
112
  version = "0.1.0"
113
113
  dependencies = [
114
114
  "ariadne",
115
+ "once_cell",
115
116
  "parser",
116
117
  ]
117
118
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: koatl
3
- Version: 0.1.14
3
+ Version: 0.1.15
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.14"
3
+ version = "0.1.15"
4
4
  edition = "2021"
5
5
 
6
6
  [lib]
@@ -21,14 +21,23 @@ def source_code_transformer(lines):
21
21
  return lines
22
22
 
23
23
 
24
- def import_prelude(namespace):
25
- exec("from koatl.runtime import *", namespace)
26
- exec("from koatl.prelude import *", namespace)
24
+ def try_import_prelude(namespace):
25
+ try:
26
+ exec("from koatl.runtime import *", namespace)
27
+ exec("from koatl.prelude import *", namespace)
28
+ except Exception as e:
29
+ import traceback
30
+
31
+ print(
32
+ "There was an error importing the Koatl prelude. Some features may not work."
33
+ )
34
+ traceback.print_exc()
27
35
 
28
36
 
29
37
  def load_ipython_extension(ipython):
30
- import_prelude(ipython.user_ns)
31
- print("koatl enabled")
38
+ print("Switched notebook to Koatl.")
39
+
40
+ try_import_prelude(ipython.user_ns)
32
41
 
33
42
  ttm = ipython.input_transformer_manager
34
43
 
@@ -9,8 +9,8 @@ export Fn = class:
9
9
  [] => raise ValueError("At least one function is required for composition")
10
10
  [f] => f
11
11
  [*fs] =>
12
- composed = (*args, **kwargs) =>
13
- value = fs[-1](*args, **kwargs)
12
+ let composed = (*args, **kwargs) =>
13
+ let value = fs[-1](*args, **kwargs)
14
14
  for f in fs[..-1..-1]:
15
15
  value = f(value)
16
16
  value
@@ -1,8 +1,10 @@
1
1
  import functools.wraps
2
2
  import asyncio
3
+
3
4
  import .async_util
5
+ import .monad.Monad
4
6
 
5
- export Async = class:
7
+ export Async = class(Monad):
6
8
  __init__ = (self, awaitable) => self.generator = awaitable.__await__()
7
9
 
8
10
  __await__ = self => self.generator
@@ -10,14 +12,14 @@ export Async = class:
10
12
  __repr__ = self => "Async(...)"
11
13
 
12
14
  from_generator_fn = staticmethod& (generator_fn, *args, **kwargs) =>
13
- m = object.__new__(Async)
15
+ let m = object.__new__(Async)
14
16
  m.generator = generator_fn(*args, **kwargs)
15
17
  return m
16
18
 
17
19
  run = self => asyncio.run(async_util.to_coro(self))
18
20
 
19
21
  bind_once = (self, f) => Async.from_generator_fn& () =>
20
- result = f(yield from self.__await__())
22
+ let result = f(yield from self.__await__())
21
23
 
22
24
  if hasattr(result, "__await__"):
23
25
  return yield from result.__await__()
@@ -25,7 +27,6 @@ export Async = class:
25
27
  return result
26
28
 
27
29
  bind_gen = (self, gen) => Async.from_generator_fn& () =>
28
- nonlocal self = self
29
30
  try:
30
31
  while True:
31
32
  self = gen.send(yield from self.__await__())
@@ -1,6 +1,7 @@
1
1
  import functools.wraps
2
+ import .monad.Monad
2
3
 
3
- export Reader = class:
4
+ export Reader = class(Monad):
4
5
  __init__ = (self, fn) => self.fn = fn
5
6
 
6
7
  __repr__ = self => "Reader(...)"
@@ -8,16 +9,13 @@ export Reader = class:
8
9
  run = (self, ctx) => self.fn(ctx)
9
10
 
10
11
  bind_once = (self, f) => Reader& ctx =>
11
- v = f(self.fn(ctx))
12
+ let v = f(self.fn(ctx))
12
13
  if v matches Reader():
13
14
  v.fn(ctx)
14
15
  else:
15
16
  v
16
17
 
17
- # TODO: this is a workaround to avoid recursion.
18
- # how to get bind_gen directly from bind_once?
19
18
  bind_gen = (self, gen) => Reader& ctx =>
20
- nonlocal self = self
21
19
  try:
22
20
  while True:
23
21
  self = gen.send(self.fn(ctx))
@@ -13,7 +13,7 @@ methods = {
13
13
  yield from f(i)
14
14
 
15
15
  fold: (x, init, f) =>
16
- acc = init
16
+ let acc = init
17
17
  for i in x:
18
18
  acc = f(acc, i)
19
19
  acc
@@ -25,7 +25,7 @@ methods = {
25
25
  return None
26
26
 
27
27
  last: (x, f) =>
28
- result = None
28
+ let result = None
29
29
  for i in x:
30
30
  if f(i):
31
31
  result = i
@@ -38,7 +38,7 @@ methods = {
38
38
  raise IndexError("Index out of range")
39
39
 
40
40
  sum: x =>
41
- acc = 0
41
+ let acc = 0
42
42
  for i in x:
43
43
  acc = acc + i
44
44
  acc
@@ -22,6 +22,7 @@ from .helpers import *
22
22
 
23
23
 
24
24
  __tl__ = SimpleNamespace(
25
+ slice=slice,
25
26
  vget=virtual.vget,
26
27
  vhas=virtual.vhas,
27
28
  unpack_record=helpers.unpack_record,
@@ -75,7 +75,9 @@ def do(f):
75
75
  return e.value
76
76
 
77
77
  try:
78
- print(m, gen)
78
+ # TODO: this is a workaround to avoid recursion.
79
+ # is it possible to get bind_gen directly from bind_once?
80
+
79
81
  return vget(m, "bind_gen")(gen)
80
82
  except (NotImplementedError, AttributeError):
81
83
  return vget(m, "bind_once")(recurse)
@@ -54,7 +54,7 @@ class TlLoader(Loader):
54
54
 
55
55
  if module.__name__.startswith("koatl.prelude"):
56
56
  transpiled_code = transpile(
57
- source_code, mode="prelude", filename=self.filepath
57
+ source_code, mode="no_prelude", filename=self.filepath
58
58
  )
59
59
  else:
60
60
  transpiled_code = transpile(
@@ -333,18 +333,31 @@ impl<'src> PyStmtExt<'src> for SPyStmt<'src> {
333
333
  &self.tl_span,
334
334
  )
335
335
  }
336
- PyStmt::FnDef(name, args, body, decorators) => {
337
- let arguments = args.emit_py(ctx)?;
338
- let body_ast = body.emit_py(ctx)?;
339
- let decorators = decorators.emit_py(ctx)?;
340
-
341
- ctx.ast_node(
342
- "FunctionDef",
343
- (name.as_ref(), arguments, body_ast, decorators),
344
- &self.tl_span,
345
- )
336
+ PyStmt::FnDef(fndef) => {
337
+ let arguments = fndef.args.emit_py(ctx)?;
338
+ let body_ast = fndef.body.emit_py(ctx)?;
339
+ let decorators = fndef.decorators.emit_py(ctx)?;
340
+
341
+ if fndef.async_ {
342
+ ctx.ast_node(
343
+ "AsyncFunctionDef",
344
+ (fndef.name.as_ref(), arguments, body_ast, decorators),
345
+ &self.tl_span,
346
+ )
347
+ } else {
348
+ ctx.ast_node(
349
+ "FunctionDef",
350
+ (fndef.name.as_ref(), arguments, body_ast, decorators),
351
+ &self.tl_span,
352
+ )
353
+ }
346
354
  }
347
- PyStmt::ClassDef(name, bases, body, decorators) => {
355
+ PyStmt::ClassDef(PyClassDef {
356
+ name,
357
+ bases,
358
+ body,
359
+ decorators,
360
+ }) => {
348
361
  let mut bases_ast = Vec::new();
349
362
  let mut keywords_ast = Vec::new();
350
363
 
@@ -14,7 +14,7 @@ use pyo3::{
14
14
  fn get_option(mode: &str) -> PyResult<TranspileOptions> {
15
15
  Ok(match mode {
16
16
  "module" => TranspileOptions::module(),
17
- "prelude" => TranspileOptions::prelude(),
17
+ "no_prelude" => TranspileOptions::no_prelude(),
18
18
  "interactive" => TranspileOptions::interactive(),
19
19
  "script" => TranspileOptions::script(),
20
20
  _ => {
@@ -1,9 +1,10 @@
1
1
  import util.assert_eq
2
2
 
3
- assert_eq(None?(1)?(2), None)
4
- assert_eq(None?[1]?.a, None)
5
- assert_eq(None?.a, None)
6
- assert_eq(None?.(a), None)
3
+ none = None
4
+ assert_eq(none?(1)?(2), None)
5
+ assert_eq(none?[1]?.a, None)
6
+ assert_eq(none?.a, None)
7
+ assert_eq(none?.(a), None)
7
8
 
8
9
  obj = (class:
9
10
  a = 1
@@ -10,7 +10,7 @@ assert_eq(a, 1)
10
10
  a = if False:
11
11
  2 * 4
12
12
  else:
13
- x = 4 * 8
13
+ let x = 4 * 8
14
14
  x * 2
15
15
 
16
16
  assert_eq(a, 4 * 8 * 2)
@@ -0,0 +1,49 @@
1
+ import util.assert_eq
2
+
3
+ test = 1
4
+ if True:
5
+ test = 2
6
+ assert_eq(test, 2)
7
+
8
+ let test = 3
9
+ assert_eq(test, 3)
10
+
11
+ test = 4
12
+ assert_eq(test, 4)
13
+
14
+ assert_eq(test, 2)
15
+
16
+ f = () =>
17
+ let test = 5
18
+ assert_eq(test, 5)
19
+
20
+ f()
21
+ assert_eq(test, 2)
22
+
23
+ f = () =>
24
+ test = 5
25
+ let g = () =>
26
+ test = 6
27
+ g()
28
+ assert_eq(test, 6)
29
+
30
+ f()
31
+
32
+
33
+ f = () =>
34
+ test = 5
35
+ let g = () =>
36
+ let test = 6
37
+ g()
38
+ assert_eq(test, 5)
39
+
40
+ f()
41
+
42
+ test = 0
43
+
44
+ f = test =>
45
+ test = 1
46
+ assert_eq(test, 1)
47
+
48
+ f(1)
49
+ assert_eq(test, 0)
@@ -64,7 +64,7 @@ assert_eq([
64
64
  apply = (x, y) => x(y)
65
65
  assert_eq(apply(
66
66
  x =>
67
- y = x * 2
67
+ let y = x * 2
68
68
  y * 2
69
69
  8
70
70
  ), 8 * 2 * 2)
@@ -72,7 +72,7 @@ assert_eq(apply(
72
72
  assert_eq(
73
73
  apply(
74
74
  x =>
75
- y = x * 2
75
+ let y = x * 2
76
76
  y * 2
77
77
  8
78
78
  )
@@ -6,10 +6,9 @@ from pathlib import Path
6
6
  sys.path.append(str(Path(__file__).parent / "e2e"))
7
7
 
8
8
 
9
- def get_test_data():
9
+ def get_test_data(dirs):
10
10
  data_dirs = [
11
- Path(__file__).parent / "e2e" / "base",
12
- Path(__file__).parent / "e2e" / "prelude",
11
+ Path(__file__).parent / "e2e" / dirs,
13
12
  ]
14
13
 
15
14
  test_cases = []
@@ -20,13 +19,32 @@ def get_test_data():
20
19
  return test_cases
21
20
 
22
21
 
23
- @pytest.mark.parametrize("test_file", get_test_data())
24
- def test_e2e_native_emit(test_file):
22
+ @pytest.mark.parametrize("test_file", get_test_data("base"))
23
+ def test_e2e_native_emit_base(test_file):
24
+ e2e_native_emit(test_file, "no_prelude")
25
+
26
+
27
+ @pytest.mark.parametrize("test_file", get_test_data("prelude"))
28
+ def test_e2e_native_emit_prelude(test_file):
29
+ e2e_native_emit(test_file, "script")
30
+
31
+
32
+ @pytest.mark.parametrize("test_file", get_test_data("base"))
33
+ def test_e2e_base(test_file):
34
+ e2e(test_file, "no_prelude")
35
+
36
+
37
+ @pytest.mark.parametrize("test_file", get_test_data("prelude"))
38
+ def test_e2e_prelude(test_file):
39
+ e2e(test_file, "script")
40
+
41
+
42
+ def e2e_native_emit(test_file, mode):
25
43
  import linecache
26
44
 
27
45
  with open(test_file, "r") as f:
28
46
  source = f.read()
29
- source, source_map = koatl.transpile_raw(source, mode="script")
47
+ source, source_map = koatl.transpile_raw(source, mode=mode)
30
48
 
31
49
  global_dict = {}
32
50
 
@@ -46,6 +64,5 @@ def test_e2e_native_emit(test_file):
46
64
  print("end", test_file)
47
65
 
48
66
 
49
- @pytest.mark.parametrize("test_file", get_test_data())
50
- def test_e2e(test_file):
51
- koatl.cli.run_from_path(test_file, mode="script")
67
+ def e2e(test_file, mode):
68
+ koatl.cli.run_from_path(test_file, mode=mode)
@@ -6,3 +6,4 @@ edition = "2024"
6
6
  [dependencies]
7
7
  ariadne = "0.5.1"
8
8
  parser = { path = "parser" }
9
+ once_cell = "1.19.0"
@@ -4,4 +4,4 @@ version = "0.1.0"
4
4
  edition = "2024"
5
5
 
6
6
  [dependencies]
7
- chumsky = "0.10.1"
7
+ chumsky = { version="0.10.1", features=["memoization"] }
@@ -1,9 +1,10 @@
1
- use std::borrow::Cow;
1
+ use std::{borrow::Cow, rc::Rc};
2
2
 
3
3
  use chumsky::span::SimpleSpan;
4
4
 
5
5
  pub type Span = SimpleSpan<usize, ()>;
6
6
  pub type Spanned<T> = (T, Span);
7
+ pub type Indirect<T> = Rc<T>;
7
8
 
8
9
  #[derive(Debug, Copy, Clone)]
9
10
  pub enum BinaryOp {
@@ -40,7 +41,15 @@ pub enum UnaryOp {
40
41
  Bind,
41
42
  }
42
43
 
43
- pub type Ident<'a> = Cow<'a, str>;
44
+ #[derive(Debug, Clone, Eq, PartialEq, Hash)]
45
+ pub struct Ident<'a>(pub Cow<'a, str>);
46
+
47
+ impl<'a> From<Cow<'a, str>> for Ident<'a> {
48
+ fn from(value: Cow<'a, str>) -> Self {
49
+ Ident(value)
50
+ }
51
+ }
52
+
44
53
  pub type SIdent<'a> = Spanned<Ident<'a>>;
45
54
 
46
55
  #[derive(Debug, Clone)]
@@ -62,24 +71,26 @@ pub struct ImportStmt<'a> {
62
71
  }
63
72
 
64
73
  #[derive(Debug, Clone, Copy, PartialEq)]
65
- pub enum AssignModifier {
74
+ pub enum DeclType {
66
75
  Export,
67
76
  Global,
68
- Nonlocal,
77
+ Let,
78
+ Const,
69
79
  }
70
80
 
71
81
  // TODO should these be cows
72
82
  #[derive(Debug, Clone)]
73
83
  pub enum Stmt<'a> {
74
84
  Module,
75
- Assign(SExpr<'a>, SExpr<'a>, Vec<AssignModifier>),
85
+ Decl(Vec<SIdent<'a>>, DeclType),
86
+ Assign(SExpr<'a>, SExpr<'a>, Option<DeclType>),
76
87
  Expr(SExpr<'a>),
77
88
 
78
89
  Return(SExpr<'a>),
79
90
  While(SExpr<'a>, SExpr<'a>),
80
91
  For(SPattern<'a>, SExpr<'a>, SExpr<'a>),
81
92
  Import(ImportStmt<'a>),
82
- Try(SExpr<'a>, Vec<MatchCase<'a>>, Option<SExpr<'a>>),
93
+ Try(SExpr<'a>, Vec<Indirect<MatchCase<'a>>>, Option<SExpr<'a>>),
83
94
  Assert(SExpr<'a>, Option<SExpr<'a>>),
84
95
  Raise(Option<SExpr<'a>>),
85
96
  Break,
@@ -101,7 +112,7 @@ pub type SLiteral<'a> = Spanned<Literal<'a>>;
101
112
 
102
113
  #[derive(Debug, Clone)]
103
114
  pub struct FmtExpr<'a> {
104
- pub block: SExpr<'a>,
115
+ pub expr: SExpr<'a>,
105
116
  pub fmt: Option<Ident<'a>>,
106
117
  }
107
118
 
@@ -132,7 +143,7 @@ pub type SCallItem<'a> = Spanned<CallItem<'a>>;
132
143
 
133
144
  #[derive(Debug, Clone)]
134
145
  pub enum ArgDefItem<'a> {
135
- Arg(SPattern<'a>, Option<SExpr<'a>>),
146
+ Arg(ISPattern<'a>, Option<SExpr<'a>>),
136
147
  ArgSpread(SIdent<'a>),
137
148
  KwargSpread(SIdent<'a>),
138
149
  }
@@ -141,7 +152,7 @@ pub type SArgItem<'a> = Spanned<ArgDefItem<'a>>;
141
152
 
142
153
  #[derive(Debug, Clone)]
143
154
  pub struct MatchCase<'src> {
144
- pub pattern: Option<SPattern<'src>>,
155
+ pub pattern: Option<Indirect<SPattern<'src>>>,
145
156
  pub guard: Option<SExpr<'src>>,
146
157
  pub body: SExpr<'src>,
147
158
  }
@@ -155,41 +166,45 @@ pub enum Expr<'a> {
155
166
  List(Vec<ListItem<'a>>),
156
167
  Mapping(Vec<MappingItem<'a>>),
157
168
  Slice(
158
- Option<Box<SExpr<'a>>>,
159
- Option<Box<SExpr<'a>>>,
160
- Option<Box<SExpr<'a>>>,
169
+ Option<Indirect<SExpr<'a>>>,
170
+ Option<Indirect<SExpr<'a>>>,
171
+ Option<Indirect<SExpr<'a>>>,
161
172
  ),
162
173
 
163
- Unary(UnaryOp, Box<SExpr<'a>>),
164
- Binary(BinaryOp, Box<SExpr<'a>>, Box<SExpr<'a>>),
174
+ Unary(UnaryOp, Indirect<SExpr<'a>>),
175
+ Binary(BinaryOp, Indirect<SExpr<'a>>, Indirect<SExpr<'a>>),
165
176
 
166
- Await(Box<SExpr<'a>>),
167
- Yield(Box<SExpr<'a>>),
168
- YieldFrom(Box<SExpr<'a>>),
177
+ Await(Indirect<SExpr<'a>>),
178
+ Yield(Indirect<SExpr<'a>>),
179
+ YieldFrom(Indirect<SExpr<'a>>),
169
180
 
170
- If(Box<SExpr<'a>>, Box<SExpr<'a>>, Option<Box<SExpr<'a>>>),
171
- Match(Box<SExpr<'a>>, Vec<MatchCase<'a>>),
172
- Matches(Box<SExpr<'a>>, Box<SPattern<'a>>),
173
- Class(Vec<SCallItem<'a>>, Box<SExpr<'a>>),
181
+ If(
182
+ Indirect<SExpr<'a>>,
183
+ Indirect<SExpr<'a>>,
184
+ Option<Indirect<SExpr<'a>>>,
185
+ ),
186
+ Match(Indirect<SExpr<'a>>, Vec<Indirect<MatchCase<'a>>>),
187
+ Matches(Indirect<SExpr<'a>>, ISPattern<'a>),
188
+ Class(Vec<SCallItem<'a>>, Indirect<SExpr<'a>>),
174
189
 
175
- Call(Box<SExpr<'a>>, Vec<SCallItem<'a>>),
176
- Subscript(Box<SExpr<'a>>, Vec<ListItem<'a>>),
177
- RawAttribute(Box<SExpr<'a>>, SIdent<'a>),
178
- ScopedAttribute(Box<SExpr<'a>>, Box<SExpr<'a>>),
179
- Attribute(Box<SExpr<'a>>, SIdent<'a>),
190
+ Call(Indirect<SExpr<'a>>, Vec<SCallItem<'a>>),
191
+ Subscript(Indirect<SExpr<'a>>, Vec<ListItem<'a>>),
192
+ RawAttribute(Indirect<SExpr<'a>>, SIdent<'a>),
193
+ ScopedAttribute(Indirect<SExpr<'a>>, Indirect<SExpr<'a>>),
194
+ Attribute(Indirect<SExpr<'a>>, SIdent<'a>),
180
195
 
181
- MappedCall(Box<SExpr<'a>>, Vec<SCallItem<'a>>),
182
- MappedSubscript(Box<SExpr<'a>>, Vec<ListItem<'a>>),
183
- MappedRawAttribute(Box<SExpr<'a>>, SIdent<'a>),
184
- MappedScopedAttribute(Box<SExpr<'a>>, Box<SExpr<'a>>),
185
- MappedAttribute(Box<SExpr<'a>>, SIdent<'a>),
196
+ MappedCall(Indirect<SExpr<'a>>, Vec<SCallItem<'a>>),
197
+ MappedSubscript(Indirect<SExpr<'a>>, Vec<ListItem<'a>>),
198
+ MappedRawAttribute(Indirect<SExpr<'a>>, SIdent<'a>),
199
+ MappedScopedAttribute(Indirect<SExpr<'a>>, Indirect<SExpr<'a>>),
200
+ MappedAttribute(Indirect<SExpr<'a>>, SIdent<'a>),
186
201
 
187
- Checked(Box<SExpr<'a>>, Option<Box<SPattern<'a>>>),
202
+ Checked(Indirect<SExpr<'a>>, Option<ISPattern<'a>>),
188
203
 
189
- Fn(Vec<ArgDefItem<'a>>, Box<SExpr<'a>>),
204
+ Fn(Vec<ArgDefItem<'a>>, Indirect<SExpr<'a>>),
190
205
  Fstr(Spanned<String>, Vec<(SFmtExpr<'a>, Spanned<String>)>),
191
206
 
192
- Decorated(Box<SExpr<'a>>, Box<SExpr<'a>>),
207
+ Decorated(Indirect<SExpr<'a>>, Indirect<SExpr<'a>>),
193
208
 
194
209
  Block(Vec<SStmt<'a>>),
195
210
  }
@@ -198,29 +213,29 @@ pub type SExpr<'a> = Spanned<Expr<'a>>;
198
213
 
199
214
  #[derive(Debug, Clone)]
200
215
  pub enum PatternSequenceItem<'a> {
201
- Item(SPattern<'a>),
216
+ Item(ISPattern<'a>),
202
217
  Spread(Option<SIdent<'a>>),
203
218
  }
204
219
 
205
220
  #[derive(Debug, Clone)]
206
221
  pub enum PatternMappingItem<'a> {
207
222
  Ident(SIdent<'a>),
208
- Item(SExpr<'a>, SPattern<'a>),
223
+ Item(SExpr<'a>, ISPattern<'a>),
209
224
  Spread(Option<SIdent<'a>>),
210
225
  }
211
226
 
212
227
  #[derive(Debug, Clone)]
213
228
  pub enum PatternClassItem<'a> {
214
- Item(SPattern<'a>),
215
- Kw(SIdent<'a>, SPattern<'a>),
229
+ Item(ISPattern<'a>),
230
+ Kw(SIdent<'a>, ISPattern<'a>),
216
231
  }
217
232
 
218
233
  #[derive(Debug, Clone)]
219
234
  pub enum Pattern<'a> {
220
235
  Capture(Option<SIdent<'a>>),
221
236
  Value(SExpr<'a>),
222
- As(Box<SPattern<'a>>, SIdent<'a>),
223
- Or(Vec<SPattern<'a>>),
237
+ As(ISPattern<'a>, SIdent<'a>),
238
+ Or(Vec<ISPattern<'a>>),
224
239
  Literal(SLiteral<'a>),
225
240
  Sequence(Vec<PatternSequenceItem<'a>>),
226
241
  Mapping(Vec<PatternMappingItem<'a>>),
@@ -228,3 +243,4 @@ pub enum Pattern<'a> {
228
243
  }
229
244
 
230
245
  pub type SPattern<'a> = Spanned<Pattern<'a>>;
246
+ pub type ISPattern<'a> = Indirect<SPattern<'a>>;
@@ -139,8 +139,8 @@ where
139
139
  fn new(input: &'input mut InputRef<'src, 'parse, TInput, TExtra<'src>>) -> Self {
140
140
  static KEYWORDS: &[&str] = &[
141
141
  "match", "if", "then", "else", "import", "export", "as", "class", "while", "for", "in",
142
- "break", "continue", "with", "yield", "global", "nonlocal", "return", "raise", "try",
143
- "except", "finally", "and", "or", "not", "await",
142
+ "break", "continue", "with", "yield", "global", "return", "raise", "try", "except",
143
+ "finally", "and", "or", "not", "await", "let", "const",
144
144
  ];
145
145
 
146
146
  let keywords = HashSet::<String>::from_iter(KEYWORDS.iter().map(|s| s.to_string()));