jaclang 0.7.0__py3-none-any.whl → 0.7.2__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/compiler/absyntree.py +53 -50
- jaclang/compiler/compile.py +21 -0
- jaclang/compiler/passes/main/__init__.py +2 -2
- jaclang/compiler/passes/main/def_impl_match_pass.py +10 -8
- jaclang/compiler/passes/main/def_use_pass.py +14 -7
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +20 -1
- jaclang/compiler/passes/main/import_pass.py +60 -11
- jaclang/compiler/passes/main/pyast_gen_pass.py +65 -4
- jaclang/compiler/passes/main/pyast_load_pass.py +2 -1
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +6 -1
- jaclang/compiler/passes/main/pyout_pass.py +3 -1
- jaclang/compiler/passes/main/schedules.py +4 -3
- jaclang/compiler/passes/main/tests/fixtures/incautoimpl.jac +7 -0
- jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +4 -4
- jaclang/compiler/passes/main/tests/test_import_pass.py +21 -0
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
- jaclang/compiler/passes/tool/jac_formatter_pass.py +14 -2
- jaclang/compiler/passes/tool/tests/fixtures/doc_string.jac +15 -0
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +7 -5
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +1 -2
- jaclang/compiler/symtable.py +21 -1
- jaclang/core/aott.py +107 -11
- jaclang/core/construct.py +171 -5
- jaclang/core/llms/anthropic.py +31 -2
- jaclang/core/llms/base.py +3 -3
- jaclang/core/llms/groq.py +4 -1
- jaclang/core/llms/huggingface.py +4 -1
- jaclang/core/llms/ollama.py +4 -1
- jaclang/core/llms/openai.py +6 -2
- jaclang/core/llms/togetherai.py +4 -1
- jaclang/langserve/engine.py +193 -121
- jaclang/langserve/server.py +35 -6
- jaclang/langserve/tests/fixtures/circle.jac +73 -0
- jaclang/langserve/tests/fixtures/circle_err.jac +73 -0
- jaclang/langserve/tests/fixtures/circle_pure.impl.jac +32 -0
- jaclang/langserve/tests/fixtures/circle_pure.jac +34 -0
- jaclang/langserve/tests/fixtures/circle_pure_err.impl.jac +32 -0
- jaclang/langserve/tests/fixtures/circle_pure_err.jac +34 -0
- jaclang/langserve/tests/test_server.py +156 -1
- jaclang/langserve/utils.py +127 -2
- jaclang/plugin/default.py +25 -83
- jaclang/plugin/feature.py +10 -12
- jaclang/plugin/tests/test_features.py +0 -33
- jaclang/settings.py +1 -0
- jaclang/tests/fixtures/byllmissue.jac +3 -0
- jaclang/tests/fixtures/hash_init_check.jac +17 -0
- jaclang/tests/fixtures/math_question.jpg +0 -0
- jaclang/tests/fixtures/nosigself.jac +19 -0
- jaclang/tests/fixtures/type_info.jac +1 -1
- jaclang/tests/fixtures/walker_override.jac +21 -0
- jaclang/tests/fixtures/with_llm_vision.jac +25 -0
- jaclang/tests/test_cli.py +1 -1
- jaclang/tests/test_language.py +61 -11
- jaclang/utils/helpers.py +3 -5
- jaclang/utils/test.py +1 -1
- jaclang/utils/treeprinter.py +19 -2
- {jaclang-0.7.0.dist-info → jaclang-0.7.2.dist-info}/METADATA +3 -2
- {jaclang-0.7.0.dist-info → jaclang-0.7.2.dist-info}/RECORD +60 -48
- jaclang/core/memory.py +0 -48
- jaclang/core/shelve_storage.py +0 -55
- {jaclang-0.7.0.dist-info → jaclang-0.7.2.dist-info}/WHEEL +0 -0
- {jaclang-0.7.0.dist-info → jaclang-0.7.2.dist-info}/entry_points.txt +0 -0
jaclang/compiler/absyntree.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import ast as ast3
|
|
6
|
+
import os
|
|
6
7
|
from hashlib import md5
|
|
7
8
|
from types import EllipsisType
|
|
8
9
|
from typing import Any, Callable, Generic, Optional, Sequence, Type, TypeVar
|
|
@@ -31,7 +32,6 @@ class AstNode:
|
|
|
31
32
|
self.kid: list[AstNode] = [x.set_parent(self) for x in kid]
|
|
32
33
|
self.sym_tab: Optional[SymbolTable] = None
|
|
33
34
|
self._sub_node_tab: dict[type, list[AstNode]] = {}
|
|
34
|
-
self._typ: type = type(None)
|
|
35
35
|
self.gen: CodeGenTarget = CodeGenTarget()
|
|
36
36
|
self.meta: dict[str, str] = {}
|
|
37
37
|
self.loc: CodeLocInfo = CodeLocInfo(*self.resolve_tok_range())
|
|
@@ -111,11 +111,15 @@ class AstNode:
|
|
|
111
111
|
|
|
112
112
|
return Pass.get_all_sub_nodes(node=self, typ=typ, brute_force=brute_force)
|
|
113
113
|
|
|
114
|
-
def
|
|
114
|
+
def find_parent_of_type(self, typ: Type[T]) -> Optional[T]:
|
|
115
115
|
"""Get parent of type."""
|
|
116
116
|
from jaclang.compiler.passes import Pass
|
|
117
117
|
|
|
118
|
-
|
|
118
|
+
return Pass.has_parent_of_type(node=self, typ=typ)
|
|
119
|
+
|
|
120
|
+
def parent_of_type(self, typ: Type[T]) -> T:
|
|
121
|
+
"""Get parent of type."""
|
|
122
|
+
ret = self.find_parent_of_type(typ)
|
|
119
123
|
if isinstance(ret, typ):
|
|
120
124
|
return ret
|
|
121
125
|
else:
|
|
@@ -178,6 +182,8 @@ class AstSymbolNode(AstNode):
|
|
|
178
182
|
self.sym_link: Optional[Symbol] = None
|
|
179
183
|
self.sym_name: str = sym_name
|
|
180
184
|
self.sym_name_node = sym_name_node
|
|
185
|
+
if isinstance(self.sym_name_node, NameSpec):
|
|
186
|
+
self.sym_name_node.name_of = self
|
|
181
187
|
self.sym_type: SymbolType = sym_type
|
|
182
188
|
self.sym_info: SymbolInfo = SymbolInfo()
|
|
183
189
|
self.py_ctx_func: Type[ast3.AST] = ast3.Load
|
|
@@ -258,8 +264,11 @@ class WalkerStmtOnlyNode(AstNode):
|
|
|
258
264
|
class AstImplOnlyNode(AstNode):
|
|
259
265
|
"""ImplOnly node type for Jac Ast."""
|
|
260
266
|
|
|
261
|
-
def __init__(
|
|
267
|
+
def __init__(
|
|
268
|
+
self, target: ArchRefChain, body: SubNodeList, decl_link: Optional[AstNode]
|
|
269
|
+
) -> None:
|
|
262
270
|
"""Initialize impl only node."""
|
|
271
|
+
self.target = target
|
|
263
272
|
self.body = body
|
|
264
273
|
self.decl_link = decl_link
|
|
265
274
|
|
|
@@ -304,6 +313,10 @@ class CodeBlockStmt(AstNode):
|
|
|
304
313
|
class NameSpec(AtomExpr, EnumBlockStmt):
|
|
305
314
|
"""NameSpec node type for Jac Ast."""
|
|
306
315
|
|
|
316
|
+
def __init__(self) -> None:
|
|
317
|
+
"""Initialize name spec node."""
|
|
318
|
+
self.name_of: AstSymbolNode = self
|
|
319
|
+
|
|
307
320
|
|
|
308
321
|
class ArchSpec(ElementStmt, CodeBlockStmt, AstSymbolNode, AstDocNode, AstSemStrNode):
|
|
309
322
|
"""ArchSpec node type for Jac Ast."""
|
|
@@ -392,7 +405,7 @@ class Module(AstDocNode):
|
|
|
392
405
|
body: Sequence[ElementStmt | String | EmptyToken],
|
|
393
406
|
is_imported: bool,
|
|
394
407
|
kid: Sequence[AstNode],
|
|
395
|
-
|
|
408
|
+
stub_only: bool = False,
|
|
396
409
|
registry: Optional[SemRegistry] = None,
|
|
397
410
|
) -> None:
|
|
398
411
|
"""Initialize whole program node."""
|
|
@@ -400,13 +413,37 @@ class Module(AstDocNode):
|
|
|
400
413
|
self.source = source
|
|
401
414
|
self.body = body
|
|
402
415
|
self.is_imported = is_imported
|
|
416
|
+
self.stub_only = stub_only
|
|
403
417
|
self.impl_mod: list[Module] = []
|
|
404
|
-
self.test_mod =
|
|
418
|
+
self.test_mod: list[Module] = []
|
|
405
419
|
self.mod_deps: dict[str, Module] = {}
|
|
406
420
|
self.registry = registry
|
|
407
421
|
AstNode.__init__(self, kid=kid)
|
|
408
422
|
AstDocNode.__init__(self, doc=doc)
|
|
409
423
|
|
|
424
|
+
@property
|
|
425
|
+
def annexable_by(self) -> Optional[str]:
|
|
426
|
+
"""Get annexable by."""
|
|
427
|
+
if not self.stub_only and self.loc.mod_path.endswith("impl.jac"):
|
|
428
|
+
head_mod_name = self.name.split(".")[0]
|
|
429
|
+
potential_path = os.path.join(
|
|
430
|
+
os.path.dirname(self.loc.mod_path),
|
|
431
|
+
f"{head_mod_name}.jac",
|
|
432
|
+
)
|
|
433
|
+
if os.path.exists(potential_path):
|
|
434
|
+
return potential_path
|
|
435
|
+
if os.path.split(os.path.dirname(self.loc.mod_path))[-1].endswith(".impl"):
|
|
436
|
+
head_mod_name = os.path.split(os.path.dirname(self.loc.mod_path))[
|
|
437
|
+
-1
|
|
438
|
+
].split(".")[0]
|
|
439
|
+
potential_path = os.path.join(
|
|
440
|
+
os.path.dirname(os.path.dirname(self.loc.mod_path)),
|
|
441
|
+
f"{head_mod_name}.jac",
|
|
442
|
+
)
|
|
443
|
+
if os.path.exists(potential_path):
|
|
444
|
+
return potential_path
|
|
445
|
+
return None
|
|
446
|
+
|
|
410
447
|
def normalize(self, deep: bool = False) -> bool:
|
|
411
448
|
"""Normalize module node."""
|
|
412
449
|
res = True
|
|
@@ -701,10 +738,12 @@ class ModuleItem(AstSymbolNode):
|
|
|
701
738
|
name: Name,
|
|
702
739
|
alias: Optional[Name],
|
|
703
740
|
kid: Sequence[AstNode],
|
|
741
|
+
sub_module: Optional[Module] = None,
|
|
704
742
|
) -> None:
|
|
705
743
|
"""Initialize module item node."""
|
|
706
744
|
self.name = name
|
|
707
745
|
self.alias = alias
|
|
746
|
+
self.sub_module = sub_module
|
|
708
747
|
AstNode.__init__(self, kid=kid)
|
|
709
748
|
AstSymbolNode.__init__(
|
|
710
749
|
self,
|
|
@@ -839,7 +878,6 @@ class ArchDef(ArchSpec, AstImplOnlyNode):
|
|
|
839
878
|
decl_link: Optional[Architype] = None,
|
|
840
879
|
) -> None:
|
|
841
880
|
"""Initialize arch def node."""
|
|
842
|
-
self.target = target
|
|
843
881
|
AstNode.__init__(self, kid=kid)
|
|
844
882
|
AstSymbolNode.__init__(
|
|
845
883
|
self,
|
|
@@ -849,7 +887,7 @@ class ArchDef(ArchSpec, AstImplOnlyNode):
|
|
|
849
887
|
)
|
|
850
888
|
AstDocNode.__init__(self, doc=doc)
|
|
851
889
|
ArchSpec.__init__(self, decorators=decorators)
|
|
852
|
-
AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
|
|
890
|
+
AstImplOnlyNode.__init__(self, target=target, body=body, decl_link=decl_link)
|
|
853
891
|
|
|
854
892
|
def normalize(self, deep: bool = False) -> bool:
|
|
855
893
|
"""Normalize arch def node."""
|
|
@@ -950,7 +988,6 @@ class EnumDef(ArchSpec, AstImplOnlyNode):
|
|
|
950
988
|
decl_link: Optional[Enum] = None,
|
|
951
989
|
) -> None:
|
|
952
990
|
"""Initialize arch def node."""
|
|
953
|
-
self.target = target
|
|
954
991
|
AstNode.__init__(self, kid=kid)
|
|
955
992
|
AstSymbolNode.__init__(
|
|
956
993
|
self,
|
|
@@ -960,7 +997,7 @@ class EnumDef(ArchSpec, AstImplOnlyNode):
|
|
|
960
997
|
)
|
|
961
998
|
AstDocNode.__init__(self, doc=doc)
|
|
962
999
|
ArchSpec.__init__(self, decorators=decorators)
|
|
963
|
-
AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
|
|
1000
|
+
AstImplOnlyNode.__init__(self, target=target, body=body, decl_link=decl_link)
|
|
964
1001
|
|
|
965
1002
|
def normalize(self, deep: bool = False) -> bool:
|
|
966
1003
|
"""Normalize enum def node."""
|
|
@@ -1000,7 +1037,7 @@ class Ability(
|
|
|
1000
1037
|
is_static: bool,
|
|
1001
1038
|
is_abstract: bool,
|
|
1002
1039
|
access: Optional[SubTag[Token]],
|
|
1003
|
-
signature:
|
|
1040
|
+
signature: FuncSignature | EventSignature,
|
|
1004
1041
|
body: Optional[SubNodeList[CodeBlockStmt] | AbilityDef | FuncCall],
|
|
1005
1042
|
kid: Sequence[AstNode],
|
|
1006
1043
|
semstr: Optional[String] = None,
|
|
@@ -1027,16 +1064,6 @@ class Ability(
|
|
|
1027
1064
|
AstDocNode.__init__(self, doc=doc)
|
|
1028
1065
|
AstAsyncNode.__init__(self, is_async=is_async)
|
|
1029
1066
|
|
|
1030
|
-
@property
|
|
1031
|
-
def is_method(self) -> bool:
|
|
1032
|
-
"""Check if is method."""
|
|
1033
|
-
check = isinstance(self.parent, SubNodeList) and isinstance(
|
|
1034
|
-
self.parent.parent, Architype
|
|
1035
|
-
)
|
|
1036
|
-
if check:
|
|
1037
|
-
self.sym_type = SymbolType.METHOD
|
|
1038
|
-
return check
|
|
1039
|
-
|
|
1040
1067
|
@property
|
|
1041
1068
|
def is_func(self) -> bool:
|
|
1042
1069
|
"""Check if is func."""
|
|
@@ -1119,7 +1146,6 @@ class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
|
|
|
1119
1146
|
decl_link: Optional[Ability] = None,
|
|
1120
1147
|
) -> None:
|
|
1121
1148
|
"""Initialize ability def node."""
|
|
1122
|
-
self.target = target
|
|
1123
1149
|
self.signature = signature
|
|
1124
1150
|
self.decorators = decorators
|
|
1125
1151
|
AstNode.__init__(self, kid=kid)
|
|
@@ -1130,7 +1156,7 @@ class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
|
|
|
1130
1156
|
sym_type=SymbolType.IMPL,
|
|
1131
1157
|
)
|
|
1132
1158
|
AstDocNode.__init__(self, doc=doc)
|
|
1133
|
-
AstImplOnlyNode.__init__(self, body=body, decl_link=decl_link)
|
|
1159
|
+
AstImplOnlyNode.__init__(self, target=target, body=body, decl_link=decl_link)
|
|
1134
1160
|
|
|
1135
1161
|
def normalize(self, deep: bool = False) -> bool:
|
|
1136
1162
|
"""Normalize ability def node."""
|
|
@@ -1152,14 +1178,6 @@ class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
|
|
|
1152
1178
|
self.set_kids(nodes=new_kid)
|
|
1153
1179
|
return res
|
|
1154
1180
|
|
|
1155
|
-
@property
|
|
1156
|
-
def is_method(self) -> bool:
|
|
1157
|
-
"""Check if is method."""
|
|
1158
|
-
return (
|
|
1159
|
-
len(self.target.archs) > 1
|
|
1160
|
-
and self.target.archs[-2].arch.name != Tok.ABILITY_OP
|
|
1161
|
-
)
|
|
1162
|
-
|
|
1163
1181
|
|
|
1164
1182
|
class FuncSignature(AstSemStrNode):
|
|
1165
1183
|
"""FuncSignature node type for Jac Ast."""
|
|
@@ -1197,13 +1215,6 @@ class FuncSignature(AstSemStrNode):
|
|
|
1197
1215
|
self.set_kids(nodes=new_kid)
|
|
1198
1216
|
return res
|
|
1199
1217
|
|
|
1200
|
-
@property
|
|
1201
|
-
def is_method(self) -> bool:
|
|
1202
|
-
"""Check if is method."""
|
|
1203
|
-
return (isinstance(self.parent, Ability) and self.parent.is_method) or (
|
|
1204
|
-
isinstance(self.parent, AbilityDef) and self.parent.is_method
|
|
1205
|
-
)
|
|
1206
|
-
|
|
1207
1218
|
@property
|
|
1208
1219
|
def is_static(self) -> bool:
|
|
1209
1220
|
"""Check if is static."""
|
|
@@ -1256,17 +1267,6 @@ class EventSignature(AstSemStrNode):
|
|
|
1256
1267
|
self.set_kids(nodes=new_kid)
|
|
1257
1268
|
return res
|
|
1258
1269
|
|
|
1259
|
-
@property
|
|
1260
|
-
def is_method(self) -> bool:
|
|
1261
|
-
"""Check if is method."""
|
|
1262
|
-
if (isinstance(self.parent, Ability) and self.parent.is_method) or (
|
|
1263
|
-
isinstance(self.parent, AbilityDef)
|
|
1264
|
-
and isinstance(self.parent.decl_link, Ability)
|
|
1265
|
-
and self.parent.decl_link.is_method
|
|
1266
|
-
):
|
|
1267
|
-
return True
|
|
1268
|
-
return False
|
|
1269
|
-
|
|
1270
1270
|
|
|
1271
1271
|
class ArchRefChain(AstNode):
|
|
1272
1272
|
"""Arch ref list node type for Jac Ast."""
|
|
@@ -1428,7 +1428,7 @@ class HasVar(AstSymbolNode, AstTypedVarNode, AstSemStrNode):
|
|
|
1428
1428
|
self,
|
|
1429
1429
|
sym_name=name.value,
|
|
1430
1430
|
sym_name_node=name,
|
|
1431
|
-
sym_type=SymbolType.
|
|
1431
|
+
sym_type=SymbolType.HAS_VAR,
|
|
1432
1432
|
)
|
|
1433
1433
|
AstTypedVarNode.__init__(self, type_tag=type_tag)
|
|
1434
1434
|
AstSemStrNode.__init__(self, semstr=semstr)
|
|
@@ -3100,6 +3100,7 @@ class ArchRef(NameSpec):
|
|
|
3100
3100
|
sym_name_node=name_ref,
|
|
3101
3101
|
sym_type=SymbolType.TYPE,
|
|
3102
3102
|
)
|
|
3103
|
+
NameSpec.__init__(self)
|
|
3103
3104
|
|
|
3104
3105
|
def normalize(self, deep: bool = False) -> bool:
|
|
3105
3106
|
"""Normalize ast node."""
|
|
@@ -3137,6 +3138,7 @@ class SpecialVarRef(NameSpec):
|
|
|
3137
3138
|
sym_name_node=var,
|
|
3138
3139
|
sym_type=SymbolType.VAR,
|
|
3139
3140
|
)
|
|
3141
|
+
NameSpec.__init__(self)
|
|
3140
3142
|
|
|
3141
3143
|
def normalize(self, deep: bool = False) -> bool:
|
|
3142
3144
|
"""Normalize ast node."""
|
|
@@ -3820,6 +3822,7 @@ class Name(Token, NameSpec):
|
|
|
3820
3822
|
sym_name_node=self,
|
|
3821
3823
|
sym_type=SymbolType.VAR,
|
|
3822
3824
|
)
|
|
3825
|
+
NameSpec.__init__(self)
|
|
3823
3826
|
|
|
3824
3827
|
def unparse(self) -> str:
|
|
3825
3828
|
"""Unparse name."""
|
jaclang/compiler/compile.py
CHANGED
|
@@ -57,6 +57,27 @@ def jac_str_to_pass(
|
|
|
57
57
|
return ast_ret
|
|
58
58
|
|
|
59
59
|
|
|
60
|
+
def jac_ir_to_pass(
|
|
61
|
+
ir: ast.AstNode,
|
|
62
|
+
target: Optional[Type[Pass]] = None,
|
|
63
|
+
schedule: list[Type[Pass]] = pass_schedule,
|
|
64
|
+
) -> Pass:
|
|
65
|
+
"""Convert a Jac file to an AST."""
|
|
66
|
+
if not target:
|
|
67
|
+
target = schedule[-1] if schedule else None
|
|
68
|
+
ast_ret = (
|
|
69
|
+
Pass(input_ir=ir, prior=None)
|
|
70
|
+
if not len(schedule)
|
|
71
|
+
else schedule[0](input_ir=ir, prior=None)
|
|
72
|
+
)
|
|
73
|
+
for i in schedule[1:]:
|
|
74
|
+
if i == target:
|
|
75
|
+
break
|
|
76
|
+
ast_ret = i(input_ir=ast_ret.ir, prior=ast_ret)
|
|
77
|
+
ast_ret = target(input_ir=ast_ret.ir, prior=ast_ret) if target else ast_ret
|
|
78
|
+
return ast_ret
|
|
79
|
+
|
|
80
|
+
|
|
60
81
|
def jac_pass_to_pass(
|
|
61
82
|
in_pass: Pass,
|
|
62
83
|
target: Optional[Type[Pass]] = None,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from .sub_node_tab_pass import SubNodeTabPass
|
|
4
4
|
from .import_pass import JacImportPass, PyImportPass # noqa: I100
|
|
5
5
|
from .sym_tab_build_pass import SymTabBuildPass # noqa: I100
|
|
6
|
-
from .def_impl_match_pass import
|
|
6
|
+
from .def_impl_match_pass import DeclImplMatchPass # noqa: I100
|
|
7
7
|
from .def_use_pass import DefUsePass # noqa: I100
|
|
8
8
|
from .pyout_pass import PyOutPass # noqa: I100
|
|
9
9
|
from .pyast_load_pass import PyastBuildPass # type: ignore # noqa: I100
|
|
@@ -20,7 +20,7 @@ __all__ = [
|
|
|
20
20
|
"JacImportPass",
|
|
21
21
|
"PyImportPass",
|
|
22
22
|
"SymTabBuildPass",
|
|
23
|
-
"
|
|
23
|
+
"DeclImplMatchPass",
|
|
24
24
|
"DefUsePass",
|
|
25
25
|
"PyOutPass",
|
|
26
26
|
"PyastBuildPass",
|
|
@@ -9,10 +9,10 @@ body field.
|
|
|
9
9
|
import jaclang.compiler.absyntree as ast
|
|
10
10
|
from jaclang.compiler.passes import Pass
|
|
11
11
|
from jaclang.compiler.passes.main import SubNodeTabPass
|
|
12
|
-
from jaclang.compiler.symtable import Symbol, SymbolTable
|
|
12
|
+
from jaclang.compiler.symtable import Symbol, SymbolTable
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class
|
|
15
|
+
class DeclImplMatchPass(Pass):
|
|
16
16
|
"""Decls and Def matching pass."""
|
|
17
17
|
|
|
18
18
|
def enter_module(self, node: ast.Module) -> None:
|
|
@@ -39,11 +39,12 @@ class DeclDefMatchPass(Pass):
|
|
|
39
39
|
def connect_def_impl(self, sym_tab: SymbolTable) -> None:
|
|
40
40
|
"""Connect Decls and Defs."""
|
|
41
41
|
for sym in sym_tab.tab.values():
|
|
42
|
-
if sym.
|
|
42
|
+
if isinstance(sym.decl, ast.AstImplOnlyNode):
|
|
43
43
|
# currently strips the type info from impls
|
|
44
44
|
arch_refs = [x[3:] for x in sym.sym_name.split(".")]
|
|
45
|
+
name_of_links = [] # to link archref names to decls
|
|
45
46
|
lookup = sym_tab.lookup(arch_refs[0])
|
|
46
|
-
#
|
|
47
|
+
# If below may need to be a while instead of if to skip over local
|
|
47
48
|
# import name collisions (see test: test_impl_decl_resolution_fix)
|
|
48
49
|
if lookup and not isinstance(lookup.decl, ast.AstImplNeedingNode):
|
|
49
50
|
lookup = sym_tab.parent.lookup(arch_refs[0])
|
|
@@ -52,6 +53,7 @@ class DeclDefMatchPass(Pass):
|
|
|
52
53
|
if len(arch_refs) == 1 and lookup
|
|
53
54
|
else lookup.defn[-1] if lookup else None
|
|
54
55
|
)
|
|
56
|
+
name_of_links.append(decl_node) if decl_node else None
|
|
55
57
|
for name in arch_refs[1:]:
|
|
56
58
|
if decl_node:
|
|
57
59
|
lookup = (
|
|
@@ -64,6 +66,7 @@ class DeclDefMatchPass(Pass):
|
|
|
64
66
|
if len(arch_refs) == 1 and lookup
|
|
65
67
|
else lookup.defn[-1] if lookup else None
|
|
66
68
|
)
|
|
69
|
+
name_of_links.append(decl_node) if decl_node else None
|
|
67
70
|
else:
|
|
68
71
|
break
|
|
69
72
|
if not decl_node:
|
|
@@ -76,10 +79,9 @@ class DeclDefMatchPass(Pass):
|
|
|
76
79
|
continue
|
|
77
80
|
decl_node.body = sym.decl # type: ignore
|
|
78
81
|
sym.decl.decl_link = decl_node # type: ignore
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
source_node.kid.remove(sym.decl)
|
|
82
|
+
for idx, a in enumerate(sym.decl.target.archs):
|
|
83
|
+
if isinstance(a.name_ref.sym_name_node, ast.NameSpec):
|
|
84
|
+
a.name_ref.sym_name_node.name_of = name_of_links[idx]
|
|
83
85
|
decl_node.sym_tab.tab = sym.decl.sym_tab.tab # type: ignore
|
|
84
86
|
for i in sym_tab.kid:
|
|
85
87
|
self.connect_def_impl(i)
|
|
@@ -28,13 +28,20 @@ class DefUsePass(SymTabPass):
|
|
|
28
28
|
sym_tab: Optional[SymbolTable],
|
|
29
29
|
"""
|
|
30
30
|
if node.arch_type.name == Tok.KW_WALKER:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
self.inform_from_walker(node)
|
|
32
|
+
for i in self.get_all_sub_nodes(node, ast.Ability):
|
|
33
|
+
if isinstance(i.body, ast.AbilityDef):
|
|
34
|
+
self.inform_from_walker(i.body)
|
|
35
|
+
|
|
36
|
+
def inform_from_walker(self, node: ast.AstNode) -> None:
|
|
37
|
+
"""Inform all sub nodes that they are from a walker."""
|
|
38
|
+
for i in (
|
|
39
|
+
self.get_all_sub_nodes(node, ast.VisitStmt)
|
|
40
|
+
+ self.get_all_sub_nodes(node, ast.IgnoreStmt)
|
|
41
|
+
+ self.get_all_sub_nodes(node, ast.DisengageStmt)
|
|
42
|
+
+ self.get_all_sub_nodes(node, ast.EdgeOpRef)
|
|
43
|
+
):
|
|
44
|
+
i.from_walker = True
|
|
38
45
|
|
|
39
46
|
def enter_arch_ref(self, node: ast.ArchRef) -> None:
|
|
40
47
|
"""Sub objects.
|
|
@@ -129,8 +129,10 @@ class FuseTypeInfoPass(Pass):
|
|
|
129
129
|
if isinstance(mypy_node, MypyNodes.MemberExpr):
|
|
130
130
|
if mypy_node in self.node_type_hash:
|
|
131
131
|
t = str(self.node_type_hash[mypy_node])
|
|
132
|
-
if "->" in t:
|
|
132
|
+
if "def" in t and "->" in t:
|
|
133
133
|
t = t.split("->")[1].strip()
|
|
134
|
+
elif "def" in t:
|
|
135
|
+
t = "None"
|
|
134
136
|
node.sym_info.typ = t
|
|
135
137
|
else:
|
|
136
138
|
self.__debug_print(f"{node.loc} MemberExpr type is not found")
|
|
@@ -181,6 +183,18 @@ class FuseTypeInfoPass(Pass):
|
|
|
181
183
|
"""Pass handler for name nodes."""
|
|
182
184
|
self.__collect_type_from_symbol(node)
|
|
183
185
|
|
|
186
|
+
# Assign correct symbols to sym_link in case of
|
|
187
|
+
# AtomTrailer Object
|
|
188
|
+
if isinstance(node.parent, ast.AtomTrailer):
|
|
189
|
+
target_node = node.parent.target
|
|
190
|
+
if isinstance(target_node, ast.AstSymbolNode):
|
|
191
|
+
parent_symbol_table = target_node.sym_info.typ_sym_table
|
|
192
|
+
if isinstance(parent_symbol_table, ast.SymbolTable):
|
|
193
|
+
owner = parent_symbol_table.owner
|
|
194
|
+
if isinstance(owner, ast.AstSymbolNode):
|
|
195
|
+
target_node.sym_link = owner.sym_link
|
|
196
|
+
node.sym_link = parent_symbol_table.lookup(node.sym_name)
|
|
197
|
+
|
|
184
198
|
@__handle_node
|
|
185
199
|
def enter_module_path(self, node: ast.ModulePath) -> None:
|
|
186
200
|
"""Pass handler for ModulePath nodes."""
|
|
@@ -263,6 +277,11 @@ class FuseTypeInfoPass(Pass):
|
|
|
263
277
|
"Getting type of 'HasVar' is only supported with AssignmentStmt"
|
|
264
278
|
)
|
|
265
279
|
|
|
280
|
+
def exit_has_var(self, node: ast.HasVar) -> None:
|
|
281
|
+
"""Pass handler for HasVar nodes."""
|
|
282
|
+
node.sym_info.typ = node.name.sym_info.typ
|
|
283
|
+
node.sym_info.typ_sym_table = node.name.sym_info.typ_sym_table
|
|
284
|
+
|
|
266
285
|
@__handle_node
|
|
267
286
|
def enter_multi_string(self, node: ast.MultiString) -> None:
|
|
268
287
|
"""Pass handler for MultiString nodes."""
|
|
@@ -46,17 +46,25 @@ class JacImportPass(Pass):
|
|
|
46
46
|
"""Process an import."""
|
|
47
47
|
lang = i.parent_of_type(ast.Import).hint.tag.value
|
|
48
48
|
if lang == "jac" and not i.sub_module:
|
|
49
|
-
|
|
49
|
+
self.import_jac_module(
|
|
50
50
|
node=i,
|
|
51
51
|
mod_path=node.loc.mod_path,
|
|
52
52
|
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
|
|
54
|
+
def attach_mod_to_node(
|
|
55
|
+
self, node: ast.ModulePath | ast.ModuleItem, mod: ast.Module | None
|
|
56
|
+
) -> None:
|
|
57
|
+
"""Attach a module to a node."""
|
|
58
|
+
if mod:
|
|
59
|
+
self.run_again = True
|
|
60
|
+
node.sub_module = mod
|
|
61
|
+
self.__annex_impl(mod)
|
|
62
|
+
node.add_kids_right([mod], pos_update=False)
|
|
57
63
|
|
|
58
64
|
def __annex_impl(self, node: ast.Module) -> None:
|
|
59
65
|
"""Annex impl and test modules."""
|
|
66
|
+
if node.stub_only:
|
|
67
|
+
return
|
|
60
68
|
if not node.loc.mod_path:
|
|
61
69
|
self.error("Module has no path")
|
|
62
70
|
if not node.loc.mod_path.endswith(".jac"):
|
|
@@ -99,7 +107,7 @@ class JacImportPass(Pass):
|
|
|
99
107
|
) and cur_file.endswith(".test.jac"):
|
|
100
108
|
mod = self.import_jac_mod_from_file(cur_file)
|
|
101
109
|
if mod:
|
|
102
|
-
node.test_mod
|
|
110
|
+
node.test_mod.append(mod)
|
|
103
111
|
node.add_kids_right([mod], pos_update=False)
|
|
104
112
|
mod.parent = node
|
|
105
113
|
|
|
@@ -114,15 +122,56 @@ class JacImportPass(Pass):
|
|
|
114
122
|
node.sub_module.name = node.alias.value
|
|
115
123
|
# Items matched during def/decl pass
|
|
116
124
|
|
|
117
|
-
def import_jac_module(
|
|
118
|
-
self, node: ast.ModulePath, mod_path: str
|
|
119
|
-
) -> ast.Module | None:
|
|
125
|
+
def import_jac_module(self, node: ast.ModulePath, mod_path: str) -> None:
|
|
120
126
|
"""Import a module."""
|
|
121
127
|
self.cur_node = node # impacts error reporting
|
|
122
128
|
target = import_target_to_relative_path(
|
|
123
|
-
node.level,
|
|
129
|
+
level=node.level,
|
|
130
|
+
target=node.path_str,
|
|
131
|
+
base_path=os.path.dirname(node.loc.mod_path),
|
|
124
132
|
)
|
|
125
|
-
|
|
133
|
+
# If the module is a package (dir)
|
|
134
|
+
if os.path.isdir(target):
|
|
135
|
+
self.attach_mod_to_node(node, self.import_jac_mod_from_dir(target))
|
|
136
|
+
import_node = node.parent_of_type(ast.Import)
|
|
137
|
+
# And the import is a from import and I am the from module
|
|
138
|
+
if node == import_node.from_loc:
|
|
139
|
+
# Import all from items as modules or packages
|
|
140
|
+
for i in import_node.items.items:
|
|
141
|
+
if isinstance(i, ast.ModuleItem):
|
|
142
|
+
from_mod_target = import_target_to_relative_path(
|
|
143
|
+
level=node.level,
|
|
144
|
+
target=node.path_str + "." + i.name.value,
|
|
145
|
+
base_path=os.path.dirname(node.loc.mod_path),
|
|
146
|
+
)
|
|
147
|
+
# If package
|
|
148
|
+
if os.path.isdir(from_mod_target):
|
|
149
|
+
self.attach_mod_to_node(
|
|
150
|
+
i, self.import_jac_mod_from_dir(from_mod_target)
|
|
151
|
+
)
|
|
152
|
+
# Else module
|
|
153
|
+
else:
|
|
154
|
+
self.attach_mod_to_node(
|
|
155
|
+
i, self.import_jac_mod_from_file(from_mod_target)
|
|
156
|
+
)
|
|
157
|
+
else:
|
|
158
|
+
self.attach_mod_to_node(node, self.import_jac_mod_from_file(target))
|
|
159
|
+
|
|
160
|
+
def import_jac_mod_from_dir(self, target: str) -> ast.Module | None:
|
|
161
|
+
"""Import a module from a directory."""
|
|
162
|
+
with_init = os.path.join(target, "__init__.jac")
|
|
163
|
+
if os.path.exists(with_init):
|
|
164
|
+
return self.import_jac_mod_from_file(with_init)
|
|
165
|
+
else:
|
|
166
|
+
return ast.Module(
|
|
167
|
+
name=target.split(os.path.sep)[-1],
|
|
168
|
+
source=ast.JacSource("", mod_path=target),
|
|
169
|
+
doc=None,
|
|
170
|
+
body=[],
|
|
171
|
+
is_imported=False,
|
|
172
|
+
stub_only=True,
|
|
173
|
+
kid=[ast.EmptyToken()],
|
|
174
|
+
)
|
|
126
175
|
|
|
127
176
|
def import_jac_mod_from_file(self, target: str) -> ast.Module | None:
|
|
128
177
|
"""Import a module from a file."""
|
|
@@ -42,6 +42,7 @@ class PyastGenPass(Pass):
|
|
|
42
42
|
"""Initialize pass."""
|
|
43
43
|
self.debuginfo: dict[str, list[str]] = {"jac_mods": []}
|
|
44
44
|
self.already_added: list[str] = []
|
|
45
|
+
self.method_sigs: list[ast.FuncSignature | ast.EventSignature] = []
|
|
45
46
|
self.preamble: list[ast3.AST] = [
|
|
46
47
|
self.sync(
|
|
47
48
|
ast3.ImportFrom(
|
|
@@ -53,6 +54,13 @@ class PyastGenPass(Pass):
|
|
|
53
54
|
)
|
|
54
55
|
]
|
|
55
56
|
|
|
57
|
+
def enter_node(self, node: ast.AstNode) -> None:
|
|
58
|
+
"""Enter node."""
|
|
59
|
+
if node.gen.py_ast:
|
|
60
|
+
self.prune()
|
|
61
|
+
return
|
|
62
|
+
super().enter_node(node)
|
|
63
|
+
|
|
56
64
|
def exit_node(self, node: ast.AstNode) -> None:
|
|
57
65
|
"""Exit node."""
|
|
58
66
|
super().exit_node(node)
|
|
@@ -324,7 +332,8 @@ class PyastGenPass(Pass):
|
|
|
324
332
|
for pbody in node.impl_mod:
|
|
325
333
|
pre_body = [*pre_body, *pbody.body]
|
|
326
334
|
pre_body = [*pre_body, *clean_body]
|
|
327
|
-
|
|
335
|
+
for pbody in node.test_mod:
|
|
336
|
+
pre_body = [*pre_body, *pbody.body]
|
|
328
337
|
body = (
|
|
329
338
|
[
|
|
330
339
|
self.sync(ast3.Expr(value=node.doc.gen.py_ast[0]), jac_node=node.doc),
|
|
@@ -658,6 +667,28 @@ class PyastGenPass(Pass):
|
|
|
658
667
|
)
|
|
659
668
|
]
|
|
660
669
|
|
|
670
|
+
def enter_architype(self, node: ast.Architype) -> None:
|
|
671
|
+
"""Sub objects.
|
|
672
|
+
|
|
673
|
+
name: Name,
|
|
674
|
+
arch_type: Token,
|
|
675
|
+
access: Optional[SubTag[Token]],
|
|
676
|
+
base_classes: Optional[SubNodeList[AtomType]],
|
|
677
|
+
body: Optional[SubNodeList[ArchBlockStmt] | ArchDef],
|
|
678
|
+
doc: Optional[String],
|
|
679
|
+
decorators: Optional[SubNodeList[ExprType]],
|
|
680
|
+
"""
|
|
681
|
+
# Record all signatures that are part of methods
|
|
682
|
+
for i in (
|
|
683
|
+
node.body.body.items
|
|
684
|
+
if isinstance(node.body, ast.ArchDef)
|
|
685
|
+
else node.body.items if node.body else []
|
|
686
|
+
):
|
|
687
|
+
if isinstance(i, ast.Ability):
|
|
688
|
+
self.method_sigs.append(i.signature)
|
|
689
|
+
if isinstance(node.body, ast.AstImplOnlyNode):
|
|
690
|
+
self.traverse(node.body)
|
|
691
|
+
|
|
661
692
|
def exit_architype(self, node: ast.Architype) -> None:
|
|
662
693
|
"""Sub objects.
|
|
663
694
|
|
|
@@ -821,6 +852,19 @@ class PyastGenPass(Pass):
|
|
|
821
852
|
decorators: Optional[SubNodeList[ExprType]],
|
|
822
853
|
"""
|
|
823
854
|
|
|
855
|
+
def enter_enum(self, node: ast.Enum) -> None:
|
|
856
|
+
"""Sub objects.
|
|
857
|
+
|
|
858
|
+
name: Name,
|
|
859
|
+
access: Optional[SubTag[Token]],
|
|
860
|
+
base_classes: Optional[SubNodeList[AtomType]],
|
|
861
|
+
body: Optional[SubNodeList[EnumBlockStmt] | EnumDef],
|
|
862
|
+
doc: Optional[String],
|
|
863
|
+
decorators: Optional[SubNodeList[ExprType]],
|
|
864
|
+
"""
|
|
865
|
+
if isinstance(node.body, ast.AstImplOnlyNode):
|
|
866
|
+
self.traverse(node.body)
|
|
867
|
+
|
|
824
868
|
def exit_enum(self, node: ast.Enum) -> None:
|
|
825
869
|
"""Sub objects.
|
|
826
870
|
|
|
@@ -870,6 +914,23 @@ class PyastGenPass(Pass):
|
|
|
870
914
|
decorators: Optional[SubNodeList[ExprType]],
|
|
871
915
|
"""
|
|
872
916
|
|
|
917
|
+
def enter_ability(self, node: ast.Ability) -> None:
|
|
918
|
+
"""Sub objects.
|
|
919
|
+
|
|
920
|
+
name_ref: NameType,
|
|
921
|
+
is_func: bool,
|
|
922
|
+
is_async: bool,
|
|
923
|
+
is_static: bool,
|
|
924
|
+
is_abstract: bool,
|
|
925
|
+
access: Optional[SubTag[Token]],
|
|
926
|
+
signature: Optional[FuncSignature | ExprType | EventSignature],
|
|
927
|
+
body: Optional[SubNodeList[CodeBlockStmt] | AbilityDef | FuncCall],
|
|
928
|
+
doc: Optional[String],
|
|
929
|
+
decorators: Optional[SubNodeList[ExprType]],
|
|
930
|
+
"""
|
|
931
|
+
if isinstance(node.body, ast.AstImplOnlyNode):
|
|
932
|
+
self.traverse(node.body)
|
|
933
|
+
|
|
873
934
|
def exit_ability(self, node: ast.Ability) -> None:
|
|
874
935
|
"""Sub objects.
|
|
875
936
|
|
|
@@ -1043,7 +1104,7 @@ class PyastGenPass(Pass):
|
|
|
1043
1104
|
action = (
|
|
1044
1105
|
node.semstr.gen.py_ast[0]
|
|
1045
1106
|
if node.semstr
|
|
1046
|
-
else self.sync(ast3.Constant(value=
|
|
1107
|
+
else self.sync(ast3.Constant(value=node.name_ref.sym_name))
|
|
1047
1108
|
)
|
|
1048
1109
|
return [
|
|
1049
1110
|
self.sync(
|
|
@@ -1272,7 +1333,7 @@ class PyastGenPass(Pass):
|
|
|
1272
1333
|
"""
|
|
1273
1334
|
params = (
|
|
1274
1335
|
[self.sync(ast3.arg(arg="self", annotation=None))]
|
|
1275
|
-
if node.
|
|
1336
|
+
if node in self.method_sigs and not node.is_static
|
|
1276
1337
|
else []
|
|
1277
1338
|
)
|
|
1278
1339
|
vararg = None
|
|
@@ -1330,7 +1391,7 @@ class PyastGenPass(Pass):
|
|
|
1330
1391
|
posonlyargs=[],
|
|
1331
1392
|
args=(
|
|
1332
1393
|
[self.sync(ast3.arg(arg="self", annotation=None)), here]
|
|
1333
|
-
if node.
|
|
1394
|
+
if node in self.method_sigs
|
|
1334
1395
|
else [here]
|
|
1335
1396
|
),
|
|
1336
1397
|
kwonlyargs=[],
|