jaclang 0.7.9__py3-none-any.whl → 0.7.13__py3-none-any.whl
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.
Potentially problematic release.
This version of jaclang might be problematic. Click here for more details.
- jaclang/cli/cli.py +13 -3
- jaclang/compiler/absyntree.py +10 -2
- jaclang/compiler/parser.py +2 -1
- jaclang/compiler/passes/ir_pass.py +9 -0
- jaclang/compiler/passes/main/import_pass.py +15 -2
- jaclang/compiler/passes/main/pyast_gen_pass.py +238 -32
- jaclang/compiler/passes/main/pyast_load_pass.py +3 -1
- jaclang/compiler/passes/main/tests/test_import_pass.py +13 -0
- jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +2 -2
- jaclang/compiler/passes/main/tests/test_sub_node_pass.py +1 -3
- jaclang/compiler/passes/main/type_check_pass.py +0 -17
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +1 -2
- jaclang/compiler/tests/test_importer.py +1 -1
- jaclang/core/importer.py +233 -62
- jaclang/langserve/engine.py +182 -136
- jaclang/langserve/server.py +29 -7
- jaclang/langserve/tests/fixtures/base_module_structure.jac +28 -2
- jaclang/langserve/tests/fixtures/import_include_statements.jac +1 -1
- jaclang/langserve/tests/test_server.py +73 -66
- jaclang/langserve/utils.py +266 -0
- jaclang/plugin/default.py +7 -4
- jaclang/plugin/feature.py +3 -3
- jaclang/plugin/spec.py +3 -3
- jaclang/settings.py +1 -0
- jaclang/tests/fixtures/deep/one_lev.jac +6 -4
- jaclang/tests/fixtures/needs_import.jac +1 -1
- jaclang/tests/test_cli.py +7 -9
- jaclang/tests/test_language.py +9 -13
- jaclang/tests/test_man_code.py +8 -10
- jaclang/utils/helpers.py +3 -3
- jaclang/utils/test.py +8 -0
- {jaclang-0.7.9.dist-info → jaclang-0.7.13.dist-info}/METADATA +2 -2
- {jaclang-0.7.9.dist-info → jaclang-0.7.13.dist-info}/RECORD +35 -35
- {jaclang-0.7.9.dist-info → jaclang-0.7.13.dist-info}/WHEEL +0 -0
- {jaclang-0.7.9.dist-info → jaclang-0.7.13.dist-info}/entry_points.txt +0 -0
jaclang/cli/cli.py
CHANGED
|
@@ -92,22 +92,30 @@ def run(
|
|
|
92
92
|
base = base if base else "./"
|
|
93
93
|
mod = mod[:-4]
|
|
94
94
|
if filename.endswith(".jac"):
|
|
95
|
-
|
|
95
|
+
ret_module = jac_import(
|
|
96
96
|
target=mod,
|
|
97
97
|
base_path=base,
|
|
98
98
|
cachable=cache,
|
|
99
99
|
override_name="__main__" if main else None,
|
|
100
100
|
)
|
|
101
|
+
if ret_module is None:
|
|
102
|
+
loaded_mod = None
|
|
103
|
+
else:
|
|
104
|
+
(loaded_mod,) = ret_module
|
|
101
105
|
elif filename.endswith(".jir"):
|
|
102
106
|
with open(filename, "rb") as f:
|
|
103
107
|
ir = pickle.load(f)
|
|
104
|
-
|
|
108
|
+
ret_module = jac_import(
|
|
105
109
|
target=mod,
|
|
106
110
|
base_path=base,
|
|
107
111
|
cachable=cache,
|
|
108
112
|
override_name="__main__" if main else None,
|
|
109
113
|
mod_bundle=ir,
|
|
110
114
|
)
|
|
115
|
+
if ret_module is None:
|
|
116
|
+
loaded_mod = None
|
|
117
|
+
else:
|
|
118
|
+
(loaded_mod,) = ret_module
|
|
111
119
|
else:
|
|
112
120
|
print("Not a .jac file.")
|
|
113
121
|
return
|
|
@@ -243,7 +251,7 @@ def test(
|
|
|
243
251
|
|
|
244
252
|
jac test => jac test -d .
|
|
245
253
|
"""
|
|
246
|
-
Jac.run_test(
|
|
254
|
+
failcount = Jac.run_test(
|
|
247
255
|
filepath=filepath,
|
|
248
256
|
filter=filter,
|
|
249
257
|
xit=xit,
|
|
@@ -251,6 +259,8 @@ def test(
|
|
|
251
259
|
directory=directory,
|
|
252
260
|
verbose=verbose,
|
|
253
261
|
)
|
|
262
|
+
if failcount:
|
|
263
|
+
raise SystemExit(f"Tests failed: {failcount}")
|
|
254
264
|
|
|
255
265
|
|
|
256
266
|
@cmd_registry.register
|
jaclang/compiler/absyntree.py
CHANGED
|
@@ -916,9 +916,17 @@ class ModulePath(AstSymbolNode):
|
|
|
916
916
|
self.sub_module: Optional[Module] = None
|
|
917
917
|
|
|
918
918
|
name_spec = alias if alias else path[0] if path else None
|
|
919
|
+
|
|
920
|
+
AstNode.__init__(self, kid=kid)
|
|
921
|
+
if not name_spec:
|
|
922
|
+
pkg_name = self.loc.mod_path
|
|
923
|
+
for _ in range(self.level):
|
|
924
|
+
pkg_name = os.path.dirname(pkg_name)
|
|
925
|
+
pkg_name = pkg_name.split(os.sep)[-1]
|
|
926
|
+
name_spec = Name.gen_stub_from_node(self, pkg_name)
|
|
927
|
+
self.level += 1
|
|
919
928
|
if not isinstance(name_spec, Name):
|
|
920
929
|
raise ValueError("ModulePath should have a name spec. Impossible.")
|
|
921
|
-
AstNode.__init__(self, kid=kid)
|
|
922
930
|
AstSymbolNode.__init__(
|
|
923
931
|
self,
|
|
924
932
|
sym_name=name_spec.sym_name,
|
|
@@ -930,7 +938,7 @@ class ModulePath(AstSymbolNode):
|
|
|
930
938
|
def path_str(self) -> str:
|
|
931
939
|
"""Get path string."""
|
|
932
940
|
return ("." * self.level) + ".".join(
|
|
933
|
-
[p.value for p in self.path] if self.path else
|
|
941
|
+
[p.value for p in self.path] if self.path else [self.name_spec.sym_name]
|
|
934
942
|
)
|
|
935
943
|
|
|
936
944
|
def normalize(self, deep: bool = False) -> bool:
|
jaclang/compiler/parser.py
CHANGED
|
@@ -131,7 +131,8 @@ class JacParser(Pass):
|
|
|
131
131
|
def nu(self, node: ast.T) -> ast.T:
|
|
132
132
|
"""Update node."""
|
|
133
133
|
self.parse_ref.cur_node = node
|
|
134
|
-
self.parse_ref.node_list
|
|
134
|
+
if node not in self.parse_ref.node_list:
|
|
135
|
+
self.parse_ref.node_list.append(node)
|
|
135
136
|
return node
|
|
136
137
|
|
|
137
138
|
def start(self, kid: list[ast.Module]) -> ast.Module:
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"""Abstract class for IR Passes for Jac."""
|
|
2
2
|
|
|
3
|
+
import time
|
|
3
4
|
from typing import Optional, Type, TypeVar
|
|
4
5
|
|
|
5
6
|
import jaclang.compiler.absyntree as ast
|
|
6
7
|
from jaclang.compiler.passes.transform import Transform
|
|
8
|
+
from jaclang.settings import settings
|
|
7
9
|
from jaclang.utils.helpers import pascal_to_snake
|
|
8
10
|
|
|
9
11
|
T = TypeVar("T", bound=ast.AstNode)
|
|
@@ -17,6 +19,7 @@ class Pass(Transform[T]):
|
|
|
17
19
|
self.term_signal = False
|
|
18
20
|
self.prune_signal = False
|
|
19
21
|
self.ir: ast.AstNode = input_ir
|
|
22
|
+
self.time_taken = 0.0
|
|
20
23
|
Transform.__init__(self, input_ir, prior)
|
|
21
24
|
|
|
22
25
|
def before_pass(self) -> None:
|
|
@@ -104,11 +107,17 @@ class Pass(Transform[T]):
|
|
|
104
107
|
# Only performs passes on proper ASTs
|
|
105
108
|
if not isinstance(ir, ast.AstNode):
|
|
106
109
|
return ir
|
|
110
|
+
start_time = time.time()
|
|
107
111
|
self.before_pass()
|
|
108
112
|
if not isinstance(ir, ast.AstNode):
|
|
109
113
|
raise ValueError("Current node is not an AstNode.")
|
|
110
114
|
self.traverse(ir)
|
|
111
115
|
self.after_pass()
|
|
116
|
+
self.time_taken = time.time() - start_time
|
|
117
|
+
if settings.pass_timer:
|
|
118
|
+
print(
|
|
119
|
+
f"Time taken in {self.__class__.__name__}: {self.time_taken:.4f} seconds"
|
|
120
|
+
)
|
|
112
121
|
return self.ir
|
|
113
122
|
|
|
114
123
|
def traverse(self, node: ast.AstNode) -> ast.AstNode:
|
|
@@ -25,11 +25,14 @@ class JacImportPass(Pass):
|
|
|
25
25
|
def before_pass(self) -> None:
|
|
26
26
|
"""Run once before pass."""
|
|
27
27
|
self.import_table: dict[str, ast.Module] = {}
|
|
28
|
+
self.__py_imports: set[str] = set()
|
|
29
|
+
self.py_resolve_list: set[str] = set()
|
|
28
30
|
|
|
29
31
|
def enter_module(self, node: ast.Module) -> None:
|
|
30
32
|
"""Run Importer."""
|
|
31
33
|
self.cur_node = node
|
|
32
34
|
self.import_table[node.loc.mod_path] = node
|
|
35
|
+
self.__py_imports.clear()
|
|
33
36
|
self.__annex_impl(node)
|
|
34
37
|
self.terminate() # Turns off auto traversal for deliberate traversal
|
|
35
38
|
self.run_again = True
|
|
@@ -40,6 +43,10 @@ class JacImportPass(Pass):
|
|
|
40
43
|
self.process_import(node, i)
|
|
41
44
|
self.enter_module_path(i)
|
|
42
45
|
SubNodeTabPass(prior=self, input_ir=node)
|
|
46
|
+
|
|
47
|
+
for i in self.get_all_sub_nodes(node, ast.AtomTrailer):
|
|
48
|
+
self.enter_atom_trailer(i)
|
|
49
|
+
|
|
43
50
|
node.mod_deps = self.import_table
|
|
44
51
|
|
|
45
52
|
def process_import(self, node: ast.Module, i: ast.ModulePath) -> None:
|
|
@@ -50,6 +57,8 @@ class JacImportPass(Pass):
|
|
|
50
57
|
node=i,
|
|
51
58
|
mod_path=node.loc.mod_path,
|
|
52
59
|
)
|
|
60
|
+
elif lang == "py":
|
|
61
|
+
self.__py_imports.add(i.path_str)
|
|
53
62
|
|
|
54
63
|
def attach_mod_to_node(
|
|
55
64
|
self, node: ast.ModulePath | ast.ModuleItem, mod: ast.Module | None
|
|
@@ -122,6 +131,11 @@ class JacImportPass(Pass):
|
|
|
122
131
|
node.sub_module.name = node.alias.value
|
|
123
132
|
# Items matched during def/decl pass
|
|
124
133
|
|
|
134
|
+
def enter_atom_trailer(self, node: ast.AtomTrailer) -> None:
|
|
135
|
+
"""Iterate on AtomTrailer nodes to get python paths to resolve."""
|
|
136
|
+
if node.as_attr_list[0].sym_name in self.__py_imports:
|
|
137
|
+
self.py_resolve_list.add(".".join([i.sym_name for i in node.as_attr_list]))
|
|
138
|
+
|
|
125
139
|
def import_jac_module(self, node: ast.ModulePath, mod_path: str) -> None:
|
|
126
140
|
"""Import a module."""
|
|
127
141
|
self.cur_node = node # impacts error reporting
|
|
@@ -206,10 +220,9 @@ class PyImportPass(JacImportPass):
|
|
|
206
220
|
|
|
207
221
|
def before_pass(self) -> None:
|
|
208
222
|
"""Only run pass if settings are set to raise python."""
|
|
223
|
+
super().before_pass()
|
|
209
224
|
if not settings.py_raise:
|
|
210
225
|
self.terminate()
|
|
211
|
-
else:
|
|
212
|
-
return super().before_pass()
|
|
213
226
|
|
|
214
227
|
def process_import(self, node: ast.Module, i: ast.ModulePath) -> None:
|
|
215
228
|
"""Process an import."""
|
|
@@ -50,7 +50,15 @@ class PyastGenPass(Pass):
|
|
|
50
50
|
level=0,
|
|
51
51
|
),
|
|
52
52
|
jac_node=self.ir,
|
|
53
|
-
)
|
|
53
|
+
),
|
|
54
|
+
self.sync(
|
|
55
|
+
ast3.ImportFrom(
|
|
56
|
+
module="typing",
|
|
57
|
+
names=[self.sync(ast3.alias(name="TYPE_CHECKING", asname=None))],
|
|
58
|
+
level=0,
|
|
59
|
+
),
|
|
60
|
+
jac_node=self.ir,
|
|
61
|
+
),
|
|
54
62
|
]
|
|
55
63
|
|
|
56
64
|
def enter_node(self, node: ast.AstNode) -> None:
|
|
@@ -480,7 +488,7 @@ class PyastGenPass(Pass):
|
|
|
480
488
|
def exit_import(self, node: ast.Import) -> None:
|
|
481
489
|
"""Sub objects.
|
|
482
490
|
|
|
483
|
-
|
|
491
|
+
hint: SubTag[Name],
|
|
484
492
|
paths: list[ModulePath],
|
|
485
493
|
alias: Optional[Name],
|
|
486
494
|
items: Optional[SubNodeList[ModuleItem]],
|
|
@@ -488,12 +496,6 @@ class PyastGenPass(Pass):
|
|
|
488
496
|
doc: Optional[String],
|
|
489
497
|
sub_module: Optional[Module],
|
|
490
498
|
"""
|
|
491
|
-
py_nodes: list[ast3.AST] = []
|
|
492
|
-
|
|
493
|
-
if node.doc:
|
|
494
|
-
py_nodes.append(
|
|
495
|
-
self.sync(ast3.Expr(value=node.doc.gen.py_ast[0]), jac_node=node.doc)
|
|
496
|
-
)
|
|
497
499
|
path_alias: dict[str, Optional[str]] = (
|
|
498
500
|
{node.from_loc.path_str: None} if node.from_loc else {}
|
|
499
501
|
)
|
|
@@ -502,25 +504,75 @@ class PyastGenPass(Pass):
|
|
|
502
504
|
for item in node.items.items:
|
|
503
505
|
if isinstance(item, ast.ModuleItem):
|
|
504
506
|
imp_from[item.name.sym_name] = (
|
|
505
|
-
item.alias.sym_name if item.alias else
|
|
507
|
+
item.alias.sym_name if item.alias else None
|
|
506
508
|
)
|
|
507
509
|
elif isinstance(item, ast.ModulePath):
|
|
508
510
|
path_alias[item.path_str] = (
|
|
509
511
|
item.alias.sym_name if item.alias else None
|
|
510
512
|
)
|
|
511
513
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
for k in imp_from.
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
values.append(self.sync(ast3.Constant(value=v)))
|
|
518
|
-
|
|
514
|
+
item_keys = []
|
|
515
|
+
item_values = []
|
|
516
|
+
for k, v in imp_from.items():
|
|
517
|
+
item_keys.append(self.sync(ast3.Constant(value=k)))
|
|
518
|
+
item_values.append(self.sync(ast3.Constant(value=v)))
|
|
519
519
|
self.needs_jac_import()
|
|
520
|
-
|
|
520
|
+
path_named_value: str
|
|
521
|
+
py_nodes: list[ast3.AST] = []
|
|
522
|
+
typecheck_nodes: list[ast3.AST] = []
|
|
523
|
+
runtime_nodes: list[ast3.AST] = []
|
|
524
|
+
|
|
525
|
+
if node.doc:
|
|
521
526
|
py_nodes.append(
|
|
527
|
+
self.sync(ast3.Expr(value=node.doc.gen.py_ast[0]), jac_node=node.doc)
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
for path, alias in path_alias.items():
|
|
531
|
+
path_named_value = ("_jac_inc_" if node.is_absorb else "") + (
|
|
532
|
+
alias if alias else path
|
|
533
|
+
).lstrip(".").split(".")[0]
|
|
534
|
+
# target_named_value = ""
|
|
535
|
+
# for i in path.split("."):
|
|
536
|
+
# target_named_value += i if i else "."
|
|
537
|
+
# if i:
|
|
538
|
+
# break
|
|
539
|
+
runtime_nodes.append(
|
|
522
540
|
self.sync(
|
|
523
|
-
ast3.
|
|
541
|
+
ast3.Assign(
|
|
542
|
+
targets=(
|
|
543
|
+
[
|
|
544
|
+
self.sync(
|
|
545
|
+
ast3.Tuple(
|
|
546
|
+
elts=(
|
|
547
|
+
[
|
|
548
|
+
self.sync(
|
|
549
|
+
ast3.Name(
|
|
550
|
+
id=path_named_value,
|
|
551
|
+
ctx=ast3.Store(),
|
|
552
|
+
)
|
|
553
|
+
)
|
|
554
|
+
]
|
|
555
|
+
if not len(item_keys)
|
|
556
|
+
else []
|
|
557
|
+
+ [
|
|
558
|
+
self.sync(
|
|
559
|
+
ast3.Name(
|
|
560
|
+
id=(
|
|
561
|
+
v.value
|
|
562
|
+
if v.value
|
|
563
|
+
else k.value
|
|
564
|
+
),
|
|
565
|
+
ctx=ast3.Store(),
|
|
566
|
+
)
|
|
567
|
+
)
|
|
568
|
+
for k, v in zip(item_keys, item_values)
|
|
569
|
+
]
|
|
570
|
+
),
|
|
571
|
+
ctx=ast3.Store(),
|
|
572
|
+
)
|
|
573
|
+
)
|
|
574
|
+
]
|
|
575
|
+
),
|
|
524
576
|
value=self.sync(
|
|
525
577
|
ast3.Call(
|
|
526
578
|
func=self.sync(
|
|
@@ -532,7 +584,7 @@ class PyastGenPass(Pass):
|
|
|
532
584
|
ast3.keyword(
|
|
533
585
|
arg="target",
|
|
534
586
|
value=self.sync(
|
|
535
|
-
ast3.Constant(value=
|
|
587
|
+
ast3.Constant(value=path),
|
|
536
588
|
),
|
|
537
589
|
)
|
|
538
590
|
),
|
|
@@ -541,7 +593,8 @@ class PyastGenPass(Pass):
|
|
|
541
593
|
arg="base_path",
|
|
542
594
|
value=self.sync(
|
|
543
595
|
ast3.Name(
|
|
544
|
-
id="__file__",
|
|
596
|
+
id="__file__",
|
|
597
|
+
ctx=ast3.Load(),
|
|
545
598
|
)
|
|
546
599
|
),
|
|
547
600
|
)
|
|
@@ -580,7 +633,7 @@ class PyastGenPass(Pass):
|
|
|
580
633
|
ast3.keyword(
|
|
581
634
|
arg="mdl_alias",
|
|
582
635
|
value=self.sync(
|
|
583
|
-
ast3.Constant(value=
|
|
636
|
+
ast3.Constant(value=alias),
|
|
584
637
|
),
|
|
585
638
|
)
|
|
586
639
|
),
|
|
@@ -588,21 +641,170 @@ class PyastGenPass(Pass):
|
|
|
588
641
|
ast3.keyword(
|
|
589
642
|
arg="items",
|
|
590
643
|
value=self.sync(
|
|
591
|
-
ast3.Dict(
|
|
644
|
+
ast3.Dict(
|
|
645
|
+
keys=item_keys, values=item_values
|
|
646
|
+
),
|
|
592
647
|
),
|
|
593
648
|
)
|
|
594
649
|
),
|
|
595
650
|
],
|
|
596
651
|
)
|
|
597
|
-
)
|
|
652
|
+
),
|
|
598
653
|
),
|
|
654
|
+
),
|
|
655
|
+
)
|
|
656
|
+
if node.is_absorb:
|
|
657
|
+
absorb_exec = f"={path_named_value}.__dict__['"
|
|
658
|
+
runtime_nodes.append(
|
|
659
|
+
self.sync(
|
|
660
|
+
ast3.For(
|
|
661
|
+
target=self.sync(ast3.Name(id="i", ctx=ast3.Store())),
|
|
662
|
+
iter=self.sync(
|
|
663
|
+
ast3.IfExp(
|
|
664
|
+
test=self.sync(
|
|
665
|
+
ast3.Compare(
|
|
666
|
+
left=self.sync(ast3.Constant(value="__all__")),
|
|
667
|
+
ops=[self.sync(ast3.In())],
|
|
668
|
+
comparators=[
|
|
669
|
+
self.sync(
|
|
670
|
+
ast3.Attribute(
|
|
671
|
+
value=self.sync(
|
|
672
|
+
ast3.Name(
|
|
673
|
+
id=path_named_value,
|
|
674
|
+
ctx=ast3.Load(),
|
|
675
|
+
)
|
|
676
|
+
),
|
|
677
|
+
attr="__dict__",
|
|
678
|
+
ctx=ast3.Load(),
|
|
679
|
+
)
|
|
680
|
+
)
|
|
681
|
+
],
|
|
682
|
+
)
|
|
683
|
+
),
|
|
684
|
+
body=self.sync(
|
|
685
|
+
ast3.Attribute(
|
|
686
|
+
value=self.sync(
|
|
687
|
+
ast3.Name(
|
|
688
|
+
id=path_named_value, ctx=ast3.Load()
|
|
689
|
+
)
|
|
690
|
+
),
|
|
691
|
+
attr="__all__",
|
|
692
|
+
ctx=ast3.Load(),
|
|
693
|
+
)
|
|
694
|
+
),
|
|
695
|
+
orelse=self.sync(
|
|
696
|
+
ast3.Attribute(
|
|
697
|
+
value=self.sync(
|
|
698
|
+
ast3.Name(
|
|
699
|
+
id=path_named_value, ctx=ast3.Load()
|
|
700
|
+
)
|
|
701
|
+
),
|
|
702
|
+
attr="__dict__",
|
|
703
|
+
ctx=ast3.Load(),
|
|
704
|
+
)
|
|
705
|
+
),
|
|
706
|
+
)
|
|
707
|
+
),
|
|
708
|
+
body=[
|
|
709
|
+
self.sync(
|
|
710
|
+
ast3.If(
|
|
711
|
+
test=self.sync(
|
|
712
|
+
ast3.UnaryOp(
|
|
713
|
+
op=self.sync(ast3.Not()),
|
|
714
|
+
operand=self.sync(
|
|
715
|
+
ast3.Call(
|
|
716
|
+
func=self.sync(
|
|
717
|
+
ast3.Attribute(
|
|
718
|
+
value=self.sync(
|
|
719
|
+
ast3.Name(
|
|
720
|
+
id="i",
|
|
721
|
+
ctx=ast3.Load(),
|
|
722
|
+
)
|
|
723
|
+
),
|
|
724
|
+
attr="startswith",
|
|
725
|
+
ctx=ast3.Load(),
|
|
726
|
+
)
|
|
727
|
+
),
|
|
728
|
+
args=[
|
|
729
|
+
self.sync(
|
|
730
|
+
ast3.Constant(value="_")
|
|
731
|
+
)
|
|
732
|
+
],
|
|
733
|
+
keywords=[],
|
|
734
|
+
)
|
|
735
|
+
),
|
|
736
|
+
)
|
|
737
|
+
),
|
|
738
|
+
body=[
|
|
739
|
+
self.sync(
|
|
740
|
+
ast3.Expr(
|
|
741
|
+
value=self.sync(
|
|
742
|
+
ast3.Call(
|
|
743
|
+
func=self.sync(
|
|
744
|
+
ast3.Name(
|
|
745
|
+
id="exec",
|
|
746
|
+
ctx=ast3.Load(),
|
|
747
|
+
)
|
|
748
|
+
),
|
|
749
|
+
args=[
|
|
750
|
+
self.sync(
|
|
751
|
+
ast3.JoinedStr(
|
|
752
|
+
values=[
|
|
753
|
+
self.sync(
|
|
754
|
+
ast3.FormattedValue(
|
|
755
|
+
value=self.sync(
|
|
756
|
+
ast3.Name(
|
|
757
|
+
id="i",
|
|
758
|
+
ctx=ast3.Load(),
|
|
759
|
+
)
|
|
760
|
+
),
|
|
761
|
+
conversion=-1,
|
|
762
|
+
)
|
|
763
|
+
),
|
|
764
|
+
self.sync(
|
|
765
|
+
ast3.Constant(
|
|
766
|
+
value=absorb_exec
|
|
767
|
+
)
|
|
768
|
+
),
|
|
769
|
+
self.sync(
|
|
770
|
+
ast3.FormattedValue(
|
|
771
|
+
value=self.sync(
|
|
772
|
+
ast3.Name(
|
|
773
|
+
id="i",
|
|
774
|
+
ctx=ast3.Load(),
|
|
775
|
+
)
|
|
776
|
+
),
|
|
777
|
+
conversion=-1,
|
|
778
|
+
)
|
|
779
|
+
),
|
|
780
|
+
self.sync(
|
|
781
|
+
ast3.Constant(
|
|
782
|
+
value="']"
|
|
783
|
+
)
|
|
784
|
+
),
|
|
785
|
+
]
|
|
786
|
+
)
|
|
787
|
+
)
|
|
788
|
+
],
|
|
789
|
+
keywords=[],
|
|
790
|
+
)
|
|
791
|
+
)
|
|
792
|
+
)
|
|
793
|
+
)
|
|
794
|
+
],
|
|
795
|
+
orelse=[],
|
|
796
|
+
)
|
|
797
|
+
)
|
|
798
|
+
],
|
|
799
|
+
orelse=[],
|
|
800
|
+
)
|
|
599
801
|
)
|
|
600
802
|
)
|
|
601
803
|
if node.is_absorb:
|
|
602
804
|
source = node.items.items[0]
|
|
603
805
|
if not isinstance(source, ast.ModulePath):
|
|
604
806
|
raise self.ice()
|
|
605
|
-
|
|
807
|
+
typecheck_nodes.append(
|
|
606
808
|
self.sync(
|
|
607
809
|
py_node=ast3.ImportFrom(
|
|
608
810
|
module=(source.path_str.lstrip(".") if source else None),
|
|
@@ -612,15 +814,10 @@ class PyastGenPass(Pass):
|
|
|
612
814
|
jac_node=node,
|
|
613
815
|
)
|
|
614
816
|
)
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
# self.warning(
|
|
618
|
-
# "Includes import * in target module into current namespace."
|
|
619
|
-
# )
|
|
620
|
-
if not node.from_loc:
|
|
621
|
-
py_nodes.append(self.sync(ast3.Import(names=node.items.gen.py_ast)))
|
|
817
|
+
elif not node.from_loc:
|
|
818
|
+
typecheck_nodes.append(self.sync(ast3.Import(names=node.items.gen.py_ast)))
|
|
622
819
|
else:
|
|
623
|
-
|
|
820
|
+
typecheck_nodes.append(
|
|
624
821
|
self.sync(
|
|
625
822
|
ast3.ImportFrom(
|
|
626
823
|
module=(
|
|
@@ -633,6 +830,15 @@ class PyastGenPass(Pass):
|
|
|
633
830
|
)
|
|
634
831
|
)
|
|
635
832
|
)
|
|
833
|
+
py_nodes.append(
|
|
834
|
+
self.sync(
|
|
835
|
+
ast3.If(
|
|
836
|
+
test=self.sync(ast3.Name(id="TYPE_CHECKING", ctx=ast3.Load())),
|
|
837
|
+
body=typecheck_nodes,
|
|
838
|
+
orelse=runtime_nodes,
|
|
839
|
+
)
|
|
840
|
+
)
|
|
841
|
+
)
|
|
636
842
|
node.gen.py_ast = py_nodes
|
|
637
843
|
|
|
638
844
|
def exit_module_path(self, node: ast.ModulePath) -> None:
|
|
@@ -1507,11 +1507,13 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
1507
1507
|
pos_end=0,
|
|
1508
1508
|
)
|
|
1509
1509
|
)
|
|
1510
|
+
moddots = [self.operator(Tok.DOT, ".") for _ in range(node.level)]
|
|
1511
|
+
modparts = moddots + modpaths
|
|
1510
1512
|
path = ast.ModulePath(
|
|
1511
1513
|
path=modpaths,
|
|
1512
1514
|
level=node.level,
|
|
1513
1515
|
alias=None,
|
|
1514
|
-
kid=
|
|
1516
|
+
kid=modparts,
|
|
1515
1517
|
)
|
|
1516
1518
|
names = [self.convert(name) for name in node.names]
|
|
1517
1519
|
valid_names = []
|
|
@@ -49,3 +49,16 @@ class ImportPassPassTests(TestCase):
|
|
|
49
49
|
)
|
|
50
50
|
for i in state.ir.get_all_sub_nodes(ast.Module):
|
|
51
51
|
self.assertEqual(i.annexable_by, self.fixture_abs_path("autoimpl.jac"))
|
|
52
|
+
|
|
53
|
+
def test_py_resolve_list(self) -> None:
|
|
54
|
+
"""Basic test for pass."""
|
|
55
|
+
state: JacImportPass = jac_file_to_pass(
|
|
56
|
+
self.examples_abs_path("rpg_game/jac_impl/jac_impl_5/main.jac"),
|
|
57
|
+
JacImportPass,
|
|
58
|
+
)
|
|
59
|
+
self.assertGreater(len(state.py_resolve_list), 20)
|
|
60
|
+
self.assertIn("pygame.sprite.Sprite.__init__", state.py_resolve_list)
|
|
61
|
+
self.assertIn("pygame.mouse.get_pressed", state.py_resolve_list)
|
|
62
|
+
self.assertIn("pygame.K_SPACE", state.py_resolve_list)
|
|
63
|
+
self.assertIn("random.randint", state.py_resolve_list)
|
|
64
|
+
self.assertIn("pygame.font.Font", state.py_resolve_list)
|
|
@@ -36,7 +36,7 @@ class PyastGenPassTests(TestCaseMicroSuite, AstSyncTestMixin):
|
|
|
36
36
|
def test_hodge_podge(self) -> None:
|
|
37
37
|
"""Basic test for pass."""
|
|
38
38
|
code_gen = jac_file_to_pass(
|
|
39
|
-
self.
|
|
39
|
+
self.examples_abs_path("micro/hodge_podge.jac"),
|
|
40
40
|
target=PyastGenPass,
|
|
41
41
|
)
|
|
42
42
|
|
|
@@ -45,7 +45,7 @@ class PyastGenPassTests(TestCaseMicroSuite, AstSyncTestMixin):
|
|
|
45
45
|
def test_circle_py_ast(self) -> None:
|
|
46
46
|
"""Basic test for pass."""
|
|
47
47
|
code_gen = jac_file_to_pass(
|
|
48
|
-
self.
|
|
48
|
+
self.examples_abs_path("manual_code/circle.jac"),
|
|
49
49
|
target=PyastGenPass,
|
|
50
50
|
)
|
|
51
51
|
import ast as ast3
|
|
@@ -15,9 +15,7 @@ class SubNodePassTests(TestCase):
|
|
|
15
15
|
def test_sub_node_pass(self) -> None:
|
|
16
16
|
"""Basic test for pass."""
|
|
17
17
|
code_gen = jac_file_to_pass(
|
|
18
|
-
file_path=self.
|
|
19
|
-
"../../../../../../examples/manual_code/circle.jac"
|
|
20
|
-
),
|
|
18
|
+
file_path=self.examples_abs_path("manual_code/circle.jac"),
|
|
21
19
|
target=SubNodeTabPass,
|
|
22
20
|
)
|
|
23
21
|
for i in code_gen.ir.kid[1].kid:
|
|
@@ -94,29 +94,12 @@ class JacTypeCheckPass(Pass):
|
|
|
94
94
|
mypy_graph[module.name] = st
|
|
95
95
|
new_modules.append(st)
|
|
96
96
|
|
|
97
|
-
# def get_stub(mod: str) -> myab.BuildSource:
|
|
98
|
-
# """Get stub file path."""
|
|
99
|
-
# return myab.BuildSource(
|
|
100
|
-
# path=str(
|
|
101
|
-
# pathlib.Path(os.path.dirname(jaclang.__file__)).parent
|
|
102
|
-
# / "stubs"
|
|
103
|
-
# / "jaclang"
|
|
104
|
-
# / "plugin"
|
|
105
|
-
# / f"{mod}.pyi"
|
|
106
|
-
# ),
|
|
107
|
-
# module=f"jaclang.plugin.{mod}",
|
|
108
|
-
# )
|
|
109
|
-
|
|
110
97
|
graph = myab.load_graph(
|
|
111
98
|
[
|
|
112
99
|
myab.BuildSource(
|
|
113
100
|
path=str(self.__path / "typeshed" / "stdlib" / "builtins.pyi"),
|
|
114
101
|
module="builtins",
|
|
115
102
|
),
|
|
116
|
-
# get_stub("default"),
|
|
117
|
-
# get_stub("feature"),
|
|
118
|
-
# get_stub("spec"),
|
|
119
|
-
# get_stub("builtin"),
|
|
120
103
|
],
|
|
121
104
|
manager,
|
|
122
105
|
old_graph=mypy_graph,
|
|
@@ -18,10 +18,9 @@ class JacUnparseTests(TestCaseMicroSuite, AstSyncTestMixin):
|
|
|
18
18
|
|
|
19
19
|
def test_double_unparse(self) -> None:
|
|
20
20
|
"""Parse micro jac file."""
|
|
21
|
-
filename = "../../../../../../examples/manual_code/circle.jac"
|
|
22
21
|
try:
|
|
23
22
|
code_gen_pure = jac_file_to_pass(
|
|
24
|
-
self.
|
|
23
|
+
self.examples_abs_path("manual_code/circle.jac"),
|
|
25
24
|
target=PyastGenPass,
|
|
26
25
|
schedule=without_format,
|
|
27
26
|
)
|
|
@@ -17,7 +17,7 @@ class TestLoader(TestCase):
|
|
|
17
17
|
|
|
18
18
|
def test_import_basic_python(self) -> None:
|
|
19
19
|
"""Test basic self loading."""
|
|
20
|
-
h = jac_import("fixtures.hello_world", base_path=__file__)
|
|
20
|
+
(h,) = jac_import("fixtures.hello_world", base_path=__file__)
|
|
21
21
|
self.assertEqual(h.hello(), "Hello World!") # type: ignore
|
|
22
22
|
|
|
23
23
|
def test_modules_correct(self) -> None:
|