jaclang 0.7.27__py3-none-any.whl → 0.7.30__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 +3 -0
- jaclang/compiler/__init__.py +1 -1
- jaclang/compiler/absyntree.py +30 -5
- jaclang/compiler/compile.py +1 -1
- jaclang/compiler/constant.py +0 -1
- jaclang/compiler/jac.lark +1 -5
- jaclang/compiler/parser.py +2 -10
- jaclang/compiler/passes/main/__init__.py +1 -1
- jaclang/compiler/passes/main/access_modifier_pass.py +1 -1
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +62 -33
- jaclang/compiler/passes/main/import_pass.py +285 -64
- jaclang/compiler/passes/main/inheritance_pass.py +103 -0
- jaclang/compiler/passes/main/py_collect_dep_pass.py +5 -5
- jaclang/compiler/passes/main/pyast_gen_pass.py +0 -19
- jaclang/compiler/passes/main/pyast_load_pass.py +1 -1
- jaclang/compiler/passes/main/schedules.py +2 -0
- jaclang/compiler/passes/main/sym_tab_build_pass.py +17 -0
- jaclang/compiler/passes/main/tests/fixtures/data_spatial_types.jac +130 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.py +3 -3
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.pyi +3 -3
- jaclang/compiler/passes/main/tests/test_import_pass.py +16 -17
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +24 -0
- jaclang/compiler/passes/main/type_check_pass.py +3 -2
- jaclang/compiler/passes/tool/jac_formatter_pass.py +0 -1
- jaclang/compiler/py_info.py +22 -0
- jaclang/compiler/symtable.py +9 -2
- jaclang/compiler/tests/test_importer.py +45 -1
- jaclang/langserve/tests/test_server.py +2 -2
- jaclang/plugin/default.py +86 -62
- jaclang/plugin/feature.py +2 -5
- jaclang/plugin/spec.py +1 -6
- jaclang/runtimelib/architype.py +20 -16
- jaclang/runtimelib/importer.py +26 -3
- jaclang/runtimelib/machine.py +2 -2
- jaclang/runtimelib/test.py +59 -4
- jaclang/runtimelib/utils.py +15 -0
- jaclang/settings.py +3 -0
- jaclang/tests/fixtures/base_class1.jac +11 -0
- jaclang/tests/fixtures/base_class2.jac +11 -0
- jaclang/tests/fixtures/import_all.jac +7 -0
- jaclang/tests/fixtures/import_all_py.py +8 -0
- jaclang/tests/fixtures/jactest_imported.jac +6 -0
- jaclang/tests/fixtures/jactest_main.jac +22 -0
- jaclang/tests/fixtures/multi_dim_array_split.jac +2 -6
- jaclang/tests/fixtures/test_py.py +12 -0
- jaclang/tests/fixtures/visit_sequence.jac +50 -0
- jaclang/tests/test_cli.py +83 -1
- jaclang/tests/test_language.py +24 -9
- jaclang/utils/helpers.py +9 -1
- jaclang/utils/test.py +2 -2
- jaclang/utils/tests/test_lang_tools.py +4 -2
- jaclang/utils/treeprinter.py +6 -3
- {jaclang-0.7.27.dist-info → jaclang-0.7.30.dist-info}/METADATA +3 -3
- {jaclang-0.7.27.dist-info → jaclang-0.7.30.dist-info}/RECORD +56 -45
- {jaclang-0.7.27.dist-info → jaclang-0.7.30.dist-info}/WHEEL +1 -1
- {jaclang-0.7.27.dist-info → jaclang-0.7.30.dist-info}/entry_points.txt +0 -0
jaclang/cli/cli.py
CHANGED
|
@@ -307,6 +307,7 @@ def enter(
|
|
|
307
307
|
@cmd_registry.register
|
|
308
308
|
def test(
|
|
309
309
|
filepath: str,
|
|
310
|
+
test_name: str = "",
|
|
310
311
|
filter: str = "",
|
|
311
312
|
xit: bool = False,
|
|
312
313
|
maxfail: int = None, # type:ignore
|
|
@@ -316,6 +317,7 @@ def test(
|
|
|
316
317
|
"""Run the test suite in the specified .jac file.
|
|
317
318
|
|
|
318
319
|
:param filepath: Path/to/file.jac
|
|
320
|
+
:param test_name: Run a specific test.
|
|
319
321
|
:param filter: Filter the files using Unix shell style conventions.
|
|
320
322
|
:param xit(exit): Stop(exit) running tests as soon as finds an error.
|
|
321
323
|
:param maxfail: Stop running tests after n failures.
|
|
@@ -328,6 +330,7 @@ def test(
|
|
|
328
330
|
|
|
329
331
|
failcount = Jac.run_test(
|
|
330
332
|
filepath=filepath,
|
|
333
|
+
func_name=("test_" + test_name) if test_name else None,
|
|
331
334
|
filter=filter,
|
|
332
335
|
xit=xit,
|
|
333
336
|
maxfail=maxfail,
|
jaclang/compiler/__init__.py
CHANGED
|
@@ -55,7 +55,7 @@ TOKEN_MAP.update(
|
|
|
55
55
|
"CARROW_L": "<++", "CARROW_R": "++>", "GLOBAL_OP": ":global:",
|
|
56
56
|
"NONLOCAL_OP": ":nonlocal:", "WALKER_OP": ":walker:", "NODE_OP": ":node:",
|
|
57
57
|
"EDGE_OP": ":edge:", "CLASS_OP": ":class:", "OBJECT_OP": ":obj:",
|
|
58
|
-
"TYPE_OP": "`", "ABILITY_OP": ":can:", "
|
|
58
|
+
"TYPE_OP": "`", "ABILITY_OP": ":can:", "NULL_OK": "?",
|
|
59
59
|
"KW_OR": "|", "ARROW_BI": "<-->", "ARROW_L": "<--",
|
|
60
60
|
"ARROW_R": "-->", "ARROW_L_P1": "<-:", "ARROW_R_P2": ":->",
|
|
61
61
|
"ARROW_L_P2": ":-", "ARROW_R_P1": "-:", "CARROW_BI": "<++>",
|
jaclang/compiler/absyntree.py
CHANGED
|
@@ -30,6 +30,7 @@ from jaclang.compiler.constant import (
|
|
|
30
30
|
SymbolType,
|
|
31
31
|
)
|
|
32
32
|
from jaclang.compiler.constant import DELIM_MAP, SymbolAccess, Tokens as Tok
|
|
33
|
+
from jaclang.compiler.py_info import PyInfo
|
|
33
34
|
from jaclang.compiler.semtable import SemRegistry
|
|
34
35
|
from jaclang.utils.treeprinter import dotgen_ast_tree, print_ast_tree
|
|
35
36
|
|
|
@@ -636,11 +637,10 @@ class Module(AstDocNode):
|
|
|
636
637
|
self.impl_mod: list[Module] = []
|
|
637
638
|
self.test_mod: list[Module] = []
|
|
638
639
|
self.mod_deps: dict[str, Module] = {}
|
|
639
|
-
self.py_mod_dep_map: dict[str, str] = {}
|
|
640
|
-
self.py_raise_map: dict[str, str] = {}
|
|
641
640
|
self.registry = registry
|
|
642
641
|
self.terminals: list[Token] = terminals
|
|
643
|
-
self.
|
|
642
|
+
self.py_info: PyInfo = PyInfo()
|
|
643
|
+
|
|
644
644
|
AstNode.__init__(self, kid=kid)
|
|
645
645
|
AstDocNode.__init__(self, doc=doc)
|
|
646
646
|
|
|
@@ -693,6 +693,21 @@ class Module(AstDocNode):
|
|
|
693
693
|
super().unparse()
|
|
694
694
|
return self.format()
|
|
695
695
|
|
|
696
|
+
@staticmethod
|
|
697
|
+
def get_href_path(node: AstNode) -> str:
|
|
698
|
+
"""Return the full path of the module that contains this node."""
|
|
699
|
+
parent = node.find_parent_of_type(Module)
|
|
700
|
+
mod_list: list[Module | Architype] = []
|
|
701
|
+
if isinstance(node, (Module, Architype)):
|
|
702
|
+
mod_list.append(node)
|
|
703
|
+
while parent is not None:
|
|
704
|
+
mod_list.append(parent)
|
|
705
|
+
parent = parent.find_parent_of_type(Module)
|
|
706
|
+
mod_list.reverse()
|
|
707
|
+
return ".".join(
|
|
708
|
+
p.name if isinstance(p, Module) else p.name.sym_name for p in mod_list
|
|
709
|
+
)
|
|
710
|
+
|
|
696
711
|
|
|
697
712
|
class GlobalVars(ElementStmt, AstAccessNode):
|
|
698
713
|
"""GlobalVars node type for Jac Ast."""
|
|
@@ -998,8 +1013,9 @@ class ModulePath(AstSymbolNode):
|
|
|
998
1013
|
target = self.dot_path_str
|
|
999
1014
|
if target_item:
|
|
1000
1015
|
target += f".{target_item}"
|
|
1001
|
-
base_path =
|
|
1002
|
-
|
|
1016
|
+
base_path = (
|
|
1017
|
+
os.getenv("JACPATH") or os.path.dirname(self.loc.mod_path) or os.getcwd()
|
|
1018
|
+
)
|
|
1003
1019
|
parts = target.split(".")
|
|
1004
1020
|
traversal_levels = self.level - 1 if self.level > 0 else 0
|
|
1005
1021
|
actual_parts = parts[traversal_levels:]
|
|
@@ -1011,6 +1027,15 @@ class ModulePath(AstSymbolNode):
|
|
|
1011
1027
|
if os.path.exists(relative_path + ".jac")
|
|
1012
1028
|
else relative_path
|
|
1013
1029
|
)
|
|
1030
|
+
jacpath = os.getenv("JACPATH")
|
|
1031
|
+
if not os.path.exists(relative_path) and jacpath:
|
|
1032
|
+
name_to_find = actual_parts[-1] + ".jac"
|
|
1033
|
+
|
|
1034
|
+
# Walk through the single path in JACPATH
|
|
1035
|
+
for root, _, files in os.walk(jacpath):
|
|
1036
|
+
if name_to_find in files:
|
|
1037
|
+
relative_path = os.path.join(root, name_to_find)
|
|
1038
|
+
break
|
|
1014
1039
|
return relative_path
|
|
1015
1040
|
|
|
1016
1041
|
def normalize(self, deep: bool = False) -> bool:
|
jaclang/compiler/compile.py
CHANGED
|
@@ -31,7 +31,7 @@ def jac_file_to_pass(
|
|
|
31
31
|
schedule: list[Type[Pass]] = pass_schedule,
|
|
32
32
|
) -> Pass:
|
|
33
33
|
"""Convert a Jac file to an AST."""
|
|
34
|
-
with open(file_path) as file:
|
|
34
|
+
with open(file_path, "r", encoding="utf-8") as file:
|
|
35
35
|
return jac_str_to_pass(
|
|
36
36
|
jac_str=file.read(),
|
|
37
37
|
file_path=file_path,
|
jaclang/compiler/constant.py
CHANGED
jaclang/compiler/jac.lark
CHANGED
|
@@ -298,10 +298,7 @@ lambda_expr: KW_WITH func_decl_params? (RETURN_HINT expression)? KW_CAN expressi
|
|
|
298
298
|
pipe: (pipe PIPE_FWD)? pipe_back
|
|
299
299
|
|
|
300
300
|
// Pipe back expressions
|
|
301
|
-
pipe_back: (pipe_back PIPE_BKWD)?
|
|
302
|
-
|
|
303
|
-
// Elvis expressions
|
|
304
|
-
elvis_check: (elvis_check ELVIS_OP)? bitwise_or
|
|
301
|
+
pipe_back: (pipe_back PIPE_BKWD)? bitwise_or
|
|
305
302
|
|
|
306
303
|
// Bitwise expressions
|
|
307
304
|
bitwise_or: (bitwise_or BW_OR)? bitwise_xor
|
|
@@ -599,7 +596,6 @@ PIPE_BKWD: /<\|/
|
|
|
599
596
|
DOT_FWD: /\.>/
|
|
600
597
|
DOT_BKWD: /<\./
|
|
601
598
|
RETURN_HINT: /->/
|
|
602
|
-
ELVIS_OP: /\?:/
|
|
603
599
|
NULL_OK: /\?/
|
|
604
600
|
MATMUL_EQ: /@=/
|
|
605
601
|
DECOR_OP: /@/
|
jaclang/compiler/parser.py
CHANGED
|
@@ -2037,16 +2037,8 @@ class JacParser(Pass):
|
|
|
2037
2037
|
def pipe_back(self, kid: list[ast.AstNode]) -> ast.Expr:
|
|
2038
2038
|
"""Grammar rule.
|
|
2039
2039
|
|
|
2040
|
-
pipe_back:
|
|
2041
|
-
|
|
|
2042
|
-
"""
|
|
2043
|
-
return self.binary_expr_unwind(kid)
|
|
2044
|
-
|
|
2045
|
-
def elvis_check(self, kid: list[ast.AstNode]) -> ast.Expr:
|
|
2046
|
-
"""Grammar rule.
|
|
2047
|
-
|
|
2048
|
-
elvis_check: bitwise_or ELVIS_OP elvis_check
|
|
2049
|
-
| bitwise_or
|
|
2040
|
+
pipe_back: bitwise_or PIPE_BKWD pipe_back
|
|
2041
|
+
| bitwise_or
|
|
2050
2042
|
"""
|
|
2051
2043
|
return self.binary_expr_unwind(kid)
|
|
2052
2044
|
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
from .sub_node_tab_pass import SubNodeTabPass
|
|
4
4
|
from .sym_tab_build_pass import SymTabBuildPass # noqa: I100
|
|
5
|
+
from .def_use_pass import DefUsePass # noqa: I100
|
|
5
6
|
from .import_pass import JacImportPass, PyImportPass # noqa: I100
|
|
6
7
|
from .def_impl_match_pass import DeclImplMatchPass # noqa: I100
|
|
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
|
|
10
10
|
from .pyast_gen_pass import PyastGenPass # noqa: I100
|
|
@@ -45,7 +45,7 @@ class AccessCheckPass(Pass):
|
|
|
45
45
|
settings.lsp_debug
|
|
46
46
|
and isinstance(node, ast.NameAtom)
|
|
47
47
|
and not node.sym
|
|
48
|
-
and not node.parent_of_type(ast.Module).is_raised_from_py
|
|
48
|
+
and not node.parent_of_type(ast.Module).py_info.is_raised_from_py
|
|
49
49
|
and not (
|
|
50
50
|
node.sym_name == "py"
|
|
51
51
|
and node.parent
|
|
@@ -10,6 +10,7 @@ import re
|
|
|
10
10
|
from typing import Callable, Optional, TypeVar
|
|
11
11
|
|
|
12
12
|
import jaclang.compiler.absyntree as ast
|
|
13
|
+
from jaclang.compiler.constant import Constants, Tokens
|
|
13
14
|
from jaclang.compiler.passes import Pass
|
|
14
15
|
from jaclang.compiler.symtable import SymbolTable
|
|
15
16
|
from jaclang.settings import settings
|
|
@@ -76,35 +77,6 @@ class FuseTypeInfoPass(Pass):
|
|
|
76
77
|
if typ_sym_table != self.ir.sym_tab:
|
|
77
78
|
node.name_spec.type_sym_tab = typ_sym_table
|
|
78
79
|
|
|
79
|
-
def __collect_python_dependencies(self, node: ast.AstNode) -> None:
|
|
80
|
-
assert isinstance(node, ast.AstSymbolNode)
|
|
81
|
-
assert isinstance(self.ir, ast.Module)
|
|
82
|
-
|
|
83
|
-
mypy_node = node.gen.mypy_ast[0]
|
|
84
|
-
|
|
85
|
-
if isinstance(mypy_node, MypyNodes.RefExpr) and mypy_node.node:
|
|
86
|
-
node_full_name = mypy_node.node.fullname
|
|
87
|
-
if "." in node_full_name:
|
|
88
|
-
mod_name = node_full_name[: node_full_name.rindex(".")]
|
|
89
|
-
else:
|
|
90
|
-
mod_name = node_full_name
|
|
91
|
-
|
|
92
|
-
if mod_name not in self.ir.py_mod_dep_map:
|
|
93
|
-
self.__debug_print(
|
|
94
|
-
f"Can't find a python file associated with {type(node)}::{node.loc}"
|
|
95
|
-
)
|
|
96
|
-
return
|
|
97
|
-
|
|
98
|
-
mode_path = self.ir.py_mod_dep_map[mod_name]
|
|
99
|
-
if mode_path.endswith(".jac"):
|
|
100
|
-
return
|
|
101
|
-
|
|
102
|
-
self.ir.py_raise_map[mod_name] = mode_path
|
|
103
|
-
else:
|
|
104
|
-
self.__debug_print(
|
|
105
|
-
f"Collect python dependencies is not supported in {type(node)}::{node.loc}"
|
|
106
|
-
)
|
|
107
|
-
|
|
108
80
|
@staticmethod
|
|
109
81
|
def __handle_node(
|
|
110
82
|
func: Callable[[FuseTypeInfoPass, T], None]
|
|
@@ -126,7 +98,6 @@ class FuseTypeInfoPass(Pass):
|
|
|
126
98
|
if len(node.gen.mypy_ast) == 1:
|
|
127
99
|
func(self, node)
|
|
128
100
|
self.__set_type_sym_table_link(node)
|
|
129
|
-
self.__collect_python_dependencies(node)
|
|
130
101
|
|
|
131
102
|
# Jac node has multiple mypy nodes linked to it
|
|
132
103
|
elif len(node.gen.mypy_ast) > 1:
|
|
@@ -150,7 +121,6 @@ class FuseTypeInfoPass(Pass):
|
|
|
150
121
|
)
|
|
151
122
|
func(self, node)
|
|
152
123
|
self.__set_type_sym_table_link(node)
|
|
153
|
-
self.__collect_python_dependencies(node)
|
|
154
124
|
|
|
155
125
|
# Special handing for BuiltinType
|
|
156
126
|
elif isinstance(node, ast.BuiltinType):
|
|
@@ -266,6 +236,43 @@ class FuseTypeInfoPass(Pass):
|
|
|
266
236
|
if len(node.gen.mypy_ast) == 0:
|
|
267
237
|
return
|
|
268
238
|
|
|
239
|
+
# No need to run this handling in case of a previous type
|
|
240
|
+
# was set during the pass, if not then we hope that the
|
|
241
|
+
# mypy node has a type associated to it
|
|
242
|
+
if node.expr_type != "NoType":
|
|
243
|
+
return
|
|
244
|
+
|
|
245
|
+
# Check if the expression is a data spatial expression
|
|
246
|
+
# Support disconnectOp
|
|
247
|
+
if isinstance(node, ast.BinaryExpr):
|
|
248
|
+
if isinstance(node.op, ast.DisconnectOp):
|
|
249
|
+
node.expr_type = "builtins.bool"
|
|
250
|
+
return
|
|
251
|
+
|
|
252
|
+
# Support spwan and connectOp
|
|
253
|
+
elif (
|
|
254
|
+
isinstance(node.op, ast.ConnectOp)
|
|
255
|
+
or node.op.name == Tokens.KW_SPAWN.value
|
|
256
|
+
):
|
|
257
|
+
if node.gen.mypy_ast[-1] in self.node_type_hash:
|
|
258
|
+
node.expr_type = (
|
|
259
|
+
self.__call_type_handler(
|
|
260
|
+
self.node_type_hash[node.gen.mypy_ast[-1]]
|
|
261
|
+
)
|
|
262
|
+
or node.expr_type
|
|
263
|
+
)
|
|
264
|
+
return
|
|
265
|
+
|
|
266
|
+
if isinstance(node, ast.EdgeRefTrailer) and any(
|
|
267
|
+
isinstance(k, ast.FilterCompr) for k in node.kid
|
|
268
|
+
):
|
|
269
|
+
if node.gen.mypy_ast[-1] in self.node_type_hash:
|
|
270
|
+
node.expr_type = (
|
|
271
|
+
self.__call_type_handler(self.node_type_hash[node.gen.mypy_ast[-1]])
|
|
272
|
+
or node.expr_type
|
|
273
|
+
)
|
|
274
|
+
return
|
|
275
|
+
|
|
269
276
|
# If the corrosponding mypy ast node type has stored here, get the values.
|
|
270
277
|
mypy_node = node.gen.mypy_ast[0]
|
|
271
278
|
if mypy_node in self.node_type_hash:
|
|
@@ -427,7 +434,14 @@ class FuseTypeInfoPass(Pass):
|
|
|
427
434
|
@__handle_node
|
|
428
435
|
def enter_special_var_ref(self, node: ast.SpecialVarRef) -> None:
|
|
429
436
|
"""Pass handler for SpecialVarRef nodes."""
|
|
430
|
-
|
|
437
|
+
if node.py_resolve_name() == Constants.ROOT:
|
|
438
|
+
if node.gen.mypy_ast[-1] in self.node_type_hash:
|
|
439
|
+
node.name_spec.expr_type = (
|
|
440
|
+
self.__call_type_handler(self.node_type_hash[node.gen.mypy_ast[-1]])
|
|
441
|
+
or node.name_spec.expr_type
|
|
442
|
+
)
|
|
443
|
+
else:
|
|
444
|
+
self.enter_name(node)
|
|
431
445
|
|
|
432
446
|
@__handle_node
|
|
433
447
|
def enter_edge_op_ref(self, node: ast.EdgeOpRef) -> None:
|
|
@@ -491,7 +505,7 @@ class FuseTypeInfoPass(Pass):
|
|
|
491
505
|
self, mypy_type: MypyTypes.Overloaded
|
|
492
506
|
) -> Optional[str]:
|
|
493
507
|
"""Get type info from mypy type Overloaded."""
|
|
494
|
-
return self.__call_type_handler(mypy_type.items[
|
|
508
|
+
return self.__call_type_handler(mypy_type.items[-1])
|
|
495
509
|
|
|
496
510
|
def get_type_from_none_type(self, mypy_type: MypyTypes.NoneType) -> Optional[str]:
|
|
497
511
|
"""Get type info from mypy type NoneType."""
|
|
@@ -509,6 +523,12 @@ class FuseTypeInfoPass(Pass):
|
|
|
509
523
|
"""Get type info from mypy type TypeType."""
|
|
510
524
|
return str(mypy_type.item)
|
|
511
525
|
|
|
526
|
+
def get_type_from_type_var_type(
|
|
527
|
+
self, mypy_type: MypyTypes.TypeVarType
|
|
528
|
+
) -> Optional[str]:
|
|
529
|
+
"""Get type info from mypy type TypeType."""
|
|
530
|
+
return str(mypy_type.name)
|
|
531
|
+
|
|
512
532
|
def exit_assignment(self, node: ast.Assignment) -> None:
|
|
513
533
|
"""Add new symbols in the symbol table in case of self."""
|
|
514
534
|
# This will fix adding new items to the class through self
|
|
@@ -590,6 +610,7 @@ class FuseTypeInfoPass(Pass):
|
|
|
590
610
|
# right index slice is a range then it's type is the same as left
|
|
591
611
|
if right.is_range:
|
|
592
612
|
right.expr_type = left.expr_type
|
|
613
|
+
right.parent_of_type(ast.AtomTrailer).expr_type = node_type
|
|
593
614
|
continue
|
|
594
615
|
|
|
595
616
|
# left type is a dictionary
|
|
@@ -603,6 +624,7 @@ class FuseTypeInfoPass(Pass):
|
|
|
603
624
|
continue
|
|
604
625
|
|
|
605
626
|
right.expr_type = node_type
|
|
627
|
+
right.parent_of_type(ast.AtomTrailer).expr_type = node_type
|
|
606
628
|
|
|
607
629
|
# Getting the correct symbol table and link it
|
|
608
630
|
type_symtab: Optional[SymbolTable] = self.ir.sym_tab
|
|
@@ -621,6 +643,13 @@ class FuseTypeInfoPass(Pass):
|
|
|
621
643
|
right.type_sym_tab = type_symtab
|
|
622
644
|
|
|
623
645
|
else:
|
|
646
|
+
# Fix the symbolTable linking in case of type annotations
|
|
647
|
+
if left.type_sym_tab is None and isinstance(node.parent, ast.SubTag):
|
|
648
|
+
assert isinstance(left, ast.AstSymbolNode)
|
|
649
|
+
left.name_spec.type_sym_tab = self.ir.sym_tab.find_scope(
|
|
650
|
+
left.sym_name
|
|
651
|
+
)
|
|
652
|
+
|
|
624
653
|
if left.type_sym_tab:
|
|
625
654
|
right.name_spec.sym = left.type_sym_tab.lookup(right.sym_name)
|
|
626
655
|
if right.name_spec.sym:
|