koatl 0.1.14__tar.gz → 0.1.16__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 (104) hide show
  1. {koatl-0.1.14 → koatl-0.1.16}/Cargo.lock +2 -1
  2. {koatl-0.1.14 → koatl-0.1.16}/PKG-INFO +1 -1
  3. {koatl-0.1.14 → koatl-0.1.16}/koatl/Cargo.toml +1 -1
  4. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/notebook/__init__.py +14 -5
  5. {koatl-0.1.14 → koatl-0.1.16/koatl}/python/koatl/prelude/functional/__init__.tl +2 -2
  6. {koatl-0.1.14 → koatl-0.1.16/koatl}/python/koatl/prelude/functional/async.tl +5 -4
  7. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/prelude/functional/reader.tl +3 -5
  8. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/prelude/iterable.tl +3 -3
  9. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/runtime/__init__.py +1 -0
  10. {koatl-0.1.14 → koatl-0.1.16/koatl}/python/koatl/runtime/helpers.py +3 -1
  11. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/runtime/meta_finder.py +1 -1
  12. {koatl-0.1.14 → koatl-0.1.16}/koatl/src/emit_py.rs +24 -11
  13. {koatl-0.1.14 → koatl-0.1.16}/koatl/src/lib.rs +1 -1
  14. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/coal.tl +5 -4
  15. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/fstr.tl +3 -3
  16. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/if_expr.tl +1 -1
  17. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/match.tl +1 -1
  18. koatl-0.1.16/koatl/tests/e2e/base/scopes.tl +92 -0
  19. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/semantic_whitespace.tl +2 -2
  20. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/test_e2e.py +26 -9
  21. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/Cargo.toml +1 -0
  22. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/Cargo.toml +1 -1
  23. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/src/ast.rs +56 -40
  24. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/src/lexer.rs +2 -2
  25. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/src/parser.rs +220 -153
  26. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/src/util.rs +43 -39
  27. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/lib.rs +2 -2
  28. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/main.rs +1 -0
  29. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/py/ast.rs +19 -12
  30. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/py/emit.rs +16 -2
  31. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/py/util.rs +18 -2
  32. koatl-0.1.16/koatl-core/src/transform.rs +3361 -0
  33. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/notebook/__init__.py +14 -5
  34. {koatl-0.1.14/koatl → koatl-0.1.16}/python/koatl/prelude/functional/__init__.tl +2 -2
  35. {koatl-0.1.14/koatl → koatl-0.1.16}/python/koatl/prelude/functional/async.tl +5 -4
  36. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/prelude/functional/reader.tl +3 -5
  37. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/prelude/iterable.tl +3 -3
  38. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/runtime/__init__.py +1 -0
  39. {koatl-0.1.14/koatl → koatl-0.1.16}/python/koatl/runtime/helpers.py +3 -1
  40. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/runtime/meta_finder.py +1 -1
  41. koatl-0.1.14/koatl-core/src/transform.rs +0 -2651
  42. {koatl-0.1.14 → koatl-0.1.16}/Cargo.toml +0 -0
  43. {koatl-0.1.14 → koatl-0.1.16}/README.md +0 -0
  44. {koatl-0.1.14 → koatl-0.1.16}/koatl/.github/workflows/CI.yml +0 -0
  45. {koatl-0.1.14 → koatl-0.1.16}/koatl/.gitignore +0 -0
  46. {koatl-0.1.14 → koatl-0.1.16}/koatl/LICENSE +0 -0
  47. {koatl-0.1.14 → koatl-0.1.16}/koatl/README.md +0 -0
  48. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/__init__.py +0 -0
  49. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/__main__.py +0 -0
  50. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/cli.py +0 -0
  51. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/notebook/magic.py +0 -0
  52. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/prelude/__init__.tl +0 -0
  53. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/prelude/functional/async_util.py +0 -0
  54. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/prelude/functional/monad.tl +0 -0
  55. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/prelude/functional/result.tl +0 -0
  56. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/runtime/record.py +0 -0
  57. {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/runtime/virtual.py +0 -0
  58. {koatl-0.1.14 → koatl-0.1.16}/koatl/requirements.txt +0 -0
  59. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/containers.tl +0 -0
  60. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/decorators.tl +0 -0
  61. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
  62. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/destructure.tl +0 -0
  63. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/escape_ident.tl +0 -0
  64. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/functions.tl +0 -0
  65. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/generator.tl +0 -0
  66. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/imports.tl +0 -0
  67. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/iterables.tl +0 -0
  68. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/loops.tl +0 -0
  69. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/nary-list.tl +0 -0
  70. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/placeholder.tl +0 -0
  71. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/precedence.tl +0 -0
  72. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/slice.tl +0 -0
  73. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/try.tl +0 -0
  74. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/destructure.tl +0 -0
  75. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/prelude/async.tl +0 -0
  76. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/prelude/reader.tl +0 -0
  77. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/prelude/result.tl +0 -0
  78. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/prelude/virtual.tl +0 -0
  79. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/util/__init__.py +0 -0
  80. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/util/module0.tl +0 -0
  81. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/util/module1.tl +0 -0
  82. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/util/module2.tl +0 -0
  83. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/parse/arith.tl +0 -0
  84. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/parse/assign.tl +0 -0
  85. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/parse/deco.tl +0 -0
  86. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/parse/func.tl +0 -0
  87. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/parse/matches.tl +0 -0
  88. {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/test_parse.py +0 -0
  89. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/src/lib.rs +0 -0
  90. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/tests/lexer.rs +0 -0
  91. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/linecol.rs +0 -0
  92. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/parser.rs +0 -0
  93. {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/py/mod.rs +0 -0
  94. {koatl-0.1.14 → koatl-0.1.16}/pyproject.toml +0 -0
  95. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/__init__.py +0 -0
  96. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/__main__.py +0 -0
  97. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/cli.py +0 -0
  98. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/notebook/magic.py +0 -0
  99. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/prelude/__init__.tl +0 -0
  100. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/prelude/functional/async_util.py +0 -0
  101. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/prelude/functional/monad.tl +0 -0
  102. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/prelude/functional/result.tl +0 -0
  103. {koatl-0.1.14 → koatl-0.1.16}/python/koatl/runtime/record.py +0 -0
  104. {koatl-0.1.14 → koatl-0.1.16}/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.16"
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.16
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.16"
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
@@ -11,9 +11,9 @@ fstr = f"x = {(y => y)(x)}"
11
11
  assert_eq(fstr, "x = 1")
12
12
 
13
13
  fstr = f"={
14
- a = 1
15
- b = 2
16
- c = 3
14
+ let a = 1
15
+ let b = 2
16
+ let c = 3
17
17
  a * b * c
18
18
  }="
19
19
  assert_eq(fstr, "=6=")
@@ -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)
@@ -71,6 +71,6 @@ assert_eq(
71
71
 
72
72
  x = 1
73
73
  assert_eq([1, 2, 3] matches [1, 2, 3], True)
74
- assert_eq([1, 2, 3] matches [.x, y, 3], True)
74
+ assert_eq([1, 2, 3] matches [.x, _, 3], True)
75
75
 
76
76
  assert_eq(try 1 matches 1, True)
@@ -0,0 +1,92 @@
1
+ import util.assert_eq
2
+
3
+ #-
4
+ Note: many of the tests in this file are inside temporary functions;
5
+ this is because the global scope is special in Python.
6
+ -#
7
+
8
+
9
+
10
+ # Scope variables shouldn't escape
11
+
12
+ test = 1
13
+ if True:
14
+ test = 2
15
+ assert_eq(test, 2)
16
+ let test = 3
17
+ assert_eq(test, 3)
18
+ test = 4
19
+ assert_eq(test, 4)
20
+ assert_eq(test, 2)
21
+
22
+ # Nested scopes should identify captures properly
23
+
24
+ test = 1
25
+ f = () =>
26
+ test = 2
27
+ let g = () =>
28
+ test = 3
29
+ g()
30
+ assert_eq(test, 3)
31
+ f()
32
+ assert_eq(test, 3)
33
+
34
+ # ...but should also not leak variables
35
+
36
+ test = 1
37
+ f = () =>
38
+ test = 2
39
+ let g = () =>
40
+ let test = 3
41
+ g()
42
+ assert_eq(test, 2)
43
+ f()
44
+ assert_eq(test, 2)
45
+
46
+ # Arguments should shadow all other variables
47
+
48
+ test = 0
49
+ f = test =>
50
+ test = 1
51
+ assert_eq(test, 1)
52
+ f(1)
53
+ assert_eq(test, 0)
54
+
55
+ # Assignment lhs should be lifted into function body scope
56
+
57
+ f = () =>
58
+ let g = 1
59
+ let g = () => g = 2
60
+ g()
61
+ assert_eq(g, 2)
62
+ f()
63
+
64
+ # Recursion should work
65
+
66
+ a = () =>
67
+ let fib = n => n < 2 then 1 else fib(n - 1) + fib(n - 2)
68
+ assert_eq(fib(5), 8)
69
+ a()
70
+
71
+ # Classes should work
72
+
73
+ f = () =>
74
+ let A = class:
75
+ B = 2
76
+
77
+ f = (self, x=B) =>
78
+ x
79
+
80
+ assert_eq(A.B, 2)
81
+ assert_eq(A().f(), 2)
82
+ f()
83
+
84
+ f = () =>
85
+ let A = class:
86
+ f = self =>
87
+ # this should now resolve to the class itself
88
+ A = 2
89
+
90
+ A().f()
91
+ assert_eq(A, 2)
92
+ f()
@@ -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"] }