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.
- {koatl-0.1.14 → koatl-0.1.16}/Cargo.lock +2 -1
- {koatl-0.1.14 → koatl-0.1.16}/PKG-INFO +1 -1
- {koatl-0.1.14 → koatl-0.1.16}/koatl/Cargo.toml +1 -1
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/notebook/__init__.py +14 -5
- {koatl-0.1.14 → koatl-0.1.16/koatl}/python/koatl/prelude/functional/__init__.tl +2 -2
- {koatl-0.1.14 → koatl-0.1.16/koatl}/python/koatl/prelude/functional/async.tl +5 -4
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/prelude/functional/reader.tl +3 -5
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/prelude/iterable.tl +3 -3
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/runtime/__init__.py +1 -0
- {koatl-0.1.14 → koatl-0.1.16/koatl}/python/koatl/runtime/helpers.py +3 -1
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/runtime/meta_finder.py +1 -1
- {koatl-0.1.14 → koatl-0.1.16}/koatl/src/emit_py.rs +24 -11
- {koatl-0.1.14 → koatl-0.1.16}/koatl/src/lib.rs +1 -1
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/coal.tl +5 -4
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/fstr.tl +3 -3
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/if_expr.tl +1 -1
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/match.tl +1 -1
- koatl-0.1.16/koatl/tests/e2e/base/scopes.tl +92 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/semantic_whitespace.tl +2 -2
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/test_e2e.py +26 -9
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/Cargo.toml +1 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/Cargo.toml +1 -1
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/src/ast.rs +56 -40
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/src/lexer.rs +2 -2
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/src/parser.rs +220 -153
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/src/util.rs +43 -39
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/lib.rs +2 -2
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/main.rs +1 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/py/ast.rs +19 -12
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/py/emit.rs +16 -2
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/py/util.rs +18 -2
- koatl-0.1.16/koatl-core/src/transform.rs +3361 -0
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/notebook/__init__.py +14 -5
- {koatl-0.1.14/koatl → koatl-0.1.16}/python/koatl/prelude/functional/__init__.tl +2 -2
- {koatl-0.1.14/koatl → koatl-0.1.16}/python/koatl/prelude/functional/async.tl +5 -4
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/prelude/functional/reader.tl +3 -5
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/prelude/iterable.tl +3 -3
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/runtime/__init__.py +1 -0
- {koatl-0.1.14/koatl → koatl-0.1.16}/python/koatl/runtime/helpers.py +3 -1
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/runtime/meta_finder.py +1 -1
- koatl-0.1.14/koatl-core/src/transform.rs +0 -2651
- {koatl-0.1.14 → koatl-0.1.16}/Cargo.toml +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/README.md +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/.github/workflows/CI.yml +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/.gitignore +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/LICENSE +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/README.md +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/__init__.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/__main__.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/cli.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/prelude/functional/async_util.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/prelude/functional/monad.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/prelude/functional/result.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/runtime/record.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/python/koatl/runtime/virtual.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/requirements.txt +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/containers.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/decorators.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/destructure-for-and-fn.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/destructure.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/escape_ident.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/functions.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/generator.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/imports.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/iterables.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/loops.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/nary-list.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/placeholder.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/precedence.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/slice.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/base/try.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/destructure.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/prelude/async.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/prelude/reader.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/prelude/result.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/prelude/virtual.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/util/__init__.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/util/module0.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/util/module1.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/e2e/util/module2.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/parse/arith.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/parse/assign.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/parse/deco.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/parse/func.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/parse/matches.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl/tests/test_parse.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/src/lib.rs +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/parser/tests/lexer.rs +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/linecol.rs +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/parser.rs +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/koatl-core/src/py/mod.rs +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/pyproject.toml +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/__init__.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/__main__.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/cli.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/notebook/magic.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/prelude/__init__.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/prelude/functional/async_util.py +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/prelude/functional/monad.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/prelude/functional/result.tl +0 -0
- {koatl-0.1.14 → koatl-0.1.16}/python/koatl/runtime/record.py +0 -0
- {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.
|
|
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
|
|
|
@@ -21,14 +21,23 @@ def source_code_transformer(lines):
|
|
|
21
21
|
return lines
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
31
|
-
|
|
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
|
|
@@ -75,7 +75,9 @@ def do(f):
|
|
|
75
75
|
return e.value
|
|
76
76
|
|
|
77
77
|
try:
|
|
78
|
-
|
|
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="
|
|
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(
|
|
337
|
-
let arguments = args.emit_py(ctx)?;
|
|
338
|
-
let body_ast = body.emit_py(ctx)?;
|
|
339
|
-
let decorators = decorators.emit_py(ctx)?;
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
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(
|
|
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
|
-
"
|
|
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
|
-
|
|
4
|
-
assert_eq(
|
|
5
|
-
assert_eq(
|
|
6
|
-
assert_eq(
|
|
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
|
|
@@ -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" /
|
|
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
|
|
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=
|
|
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
|
-
|
|
50
|
-
|
|
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)
|