jaclang 0.7.14__py3-none-any.whl → 0.7.16__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 +15 -10
- jaclang/cli/cmdreg.py +9 -12
- jaclang/compiler/__init__.py +19 -53
- jaclang/compiler/absyntree.py +86 -13
- jaclang/compiler/jac.lark +4 -3
- jaclang/compiler/parser.py +31 -23
- jaclang/compiler/passes/ir_pass.py +4 -13
- jaclang/compiler/passes/main/access_modifier_pass.py +1 -1
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +4 -5
- jaclang/compiler/passes/main/import_pass.py +18 -23
- jaclang/compiler/passes/main/pyast_gen_pass.py +307 -559
- jaclang/compiler/passes/main/pyast_load_pass.py +32 -6
- jaclang/compiler/passes/main/registry_pass.py +37 -3
- jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -1
- jaclang/compiler/passes/main/tests/__init__.py +1 -1
- jaclang/compiler/passes/main/type_check_pass.py +7 -0
- jaclang/compiler/passes/tool/jac_formatter_pass.py +124 -86
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +0 -1
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/architype_test.jac +13 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comment_alignment.jac +11 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comments.jac +13 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/decorator_stack.jac +37 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/esc_keywords.jac +5 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/long_names.jac +19 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +6 -0
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -0
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +33 -39
- jaclang/compiler/passes/transform.py +4 -0
- jaclang/compiler/semtable.py +31 -7
- jaclang/compiler/tests/test_importer.py +12 -5
- jaclang/langserve/engine.py +65 -118
- jaclang/langserve/sem_manager.py +379 -0
- jaclang/langserve/server.py +8 -10
- jaclang/langserve/tests/fixtures/base_module_structure.jac +27 -6
- jaclang/langserve/tests/fixtures/circle.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
- jaclang/langserve/tests/fixtures/import_include_statements.jac +1 -1
- jaclang/langserve/tests/test_sem_tokens.py +277 -0
- jaclang/langserve/tests/test_server.py +72 -16
- jaclang/langserve/utils.py +163 -96
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +212 -24
- jaclang/plugin/feature.py +59 -11
- jaclang/plugin/spec.py +58 -6
- jaclang/{core → runtimelib}/architype.py +1 -1
- jaclang/{core → runtimelib}/context.py +8 -1
- jaclang/runtimelib/importer.py +361 -0
- jaclang/runtimelib/machine.py +94 -0
- jaclang/{core → runtimelib}/utils.py +13 -5
- jaclang/settings.py +4 -1
- jaclang/tests/fixtures/abc.jac +3 -3
- jaclang/tests/fixtures/byllmissue.jac +1 -5
- jaclang/tests/fixtures/chandra_bugs2.jac +11 -10
- jaclang/tests/fixtures/cls_method.jac +41 -0
- jaclang/tests/fixtures/dblhello.jac +6 -0
- jaclang/tests/fixtures/deep/one_lev.jac +3 -3
- jaclang/tests/fixtures/deep/one_lev_dup.jac +2 -3
- jaclang/tests/fixtures/deep_import_mods.jac +13 -0
- jaclang/tests/fixtures/err.impl.jac +3 -0
- jaclang/tests/fixtures/err.jac +4 -2
- jaclang/tests/fixtures/err.test.jac +3 -0
- jaclang/tests/fixtures/err_runtime.jac +15 -0
- jaclang/tests/fixtures/game1.jac +1 -1
- jaclang/tests/fixtures/hello.jac +4 -0
- jaclang/tests/fixtures/impl_grab.impl.jac +2 -1
- jaclang/tests/fixtures/impl_grab.jac +4 -1
- jaclang/tests/fixtures/jp_importer_auto.jac +14 -0
- jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
- jaclang/tests/fixtures/needs_import.jac +2 -2
- jaclang/tests/fixtures/pyfunc_2.py +3 -0
- jaclang/tests/fixtures/registry.jac +9 -0
- jaclang/tests/fixtures/run_test.jac +4 -4
- jaclang/tests/fixtures/semstr.jac +1 -4
- jaclang/tests/fixtures/simple_archs.jac +1 -1
- jaclang/tests/test_cli.py +65 -2
- jaclang/tests/test_language.py +74 -7
- jaclang/tests/test_reference.py +6 -0
- jaclang/utils/helpers.py +45 -21
- jaclang/utils/test.py +9 -0
- jaclang/utils/treeprinter.py +0 -4
- {jaclang-0.7.14.dist-info → jaclang-0.7.16.dist-info}/METADATA +3 -2
- {jaclang-0.7.14.dist-info → jaclang-0.7.16.dist-info}/RECORD +89 -74
- jaclang/core/importer.py +0 -344
- jaclang/tests/fixtures/aott_raise.jac +0 -25
- jaclang/tests/fixtures/package_import.jac +0 -6
- /jaclang/{core → runtimelib}/__init__.py +0 -0
- /jaclang/{core → runtimelib}/constructs.py +0 -0
- /jaclang/{core → runtimelib}/memory.py +0 -0
- /jaclang/{core → runtimelib}/test.py +0 -0
- {jaclang-0.7.14.dist-info → jaclang-0.7.16.dist-info}/WHEEL +0 -0
- {jaclang-0.7.14.dist-info → jaclang-0.7.16.dist-info}/entry_points.txt +0 -0
jaclang/cli/cli.py
CHANGED
|
@@ -19,10 +19,11 @@ from jaclang.compiler.constant import Constants
|
|
|
19
19
|
from jaclang.compiler.passes.main.pyast_load_pass import PyastBuildPass
|
|
20
20
|
from jaclang.compiler.passes.main.schedules import py_code_gen_typed
|
|
21
21
|
from jaclang.compiler.passes.tool.schedules import format_pass
|
|
22
|
-
from jaclang.core.constructs import Architype
|
|
23
22
|
from jaclang.plugin.builtin import dotgen
|
|
24
23
|
from jaclang.plugin.feature import JacCmd as Cmd
|
|
25
24
|
from jaclang.plugin.feature import JacFeature as Jac
|
|
25
|
+
from jaclang.runtimelib.constructs import Architype
|
|
26
|
+
from jaclang.runtimelib.machine import JacProgram
|
|
26
27
|
from jaclang.utils.helpers import debugger as db
|
|
27
28
|
from jaclang.utils.lang_tools import AstTool
|
|
28
29
|
|
|
@@ -86,11 +87,10 @@ def run(
|
|
|
86
87
|
else ""
|
|
87
88
|
)
|
|
88
89
|
|
|
89
|
-
Jac.context().init_memory(session)
|
|
90
|
-
|
|
91
90
|
base, mod = os.path.split(filename)
|
|
92
91
|
base = base if base else "./"
|
|
93
92
|
mod = mod[:-4]
|
|
93
|
+
Jac.context().init_memory(base_path=base, session=session)
|
|
94
94
|
if filename.endswith(".jac"):
|
|
95
95
|
ret_module = jac_import(
|
|
96
96
|
target=mod,
|
|
@@ -105,12 +105,13 @@ def run(
|
|
|
105
105
|
elif filename.endswith(".jir"):
|
|
106
106
|
with open(filename, "rb") as f:
|
|
107
107
|
ir = pickle.load(f)
|
|
108
|
+
jac_program = JacProgram(mod_bundle=ir, bytecode=None)
|
|
109
|
+
Jac.context().jac_machine.attach_program(jac_program)
|
|
108
110
|
ret_module = jac_import(
|
|
109
111
|
target=mod,
|
|
110
112
|
base_path=base,
|
|
111
113
|
cachable=cache,
|
|
112
114
|
override_name="__main__" if main else None,
|
|
113
|
-
mod_bundle=ir,
|
|
114
115
|
)
|
|
115
116
|
if ret_module is None:
|
|
116
117
|
loaded_mod = None
|
|
@@ -146,7 +147,7 @@ def get_object(id: str, session: str = "") -> dict:
|
|
|
146
147
|
if session == "":
|
|
147
148
|
session = cmd_registry.args.session if "session" in cmd_registry.args else ""
|
|
148
149
|
|
|
149
|
-
Jac.context().init_memory(session)
|
|
150
|
+
Jac.context().init_memory(session=session)
|
|
150
151
|
|
|
151
152
|
if id == "root":
|
|
152
153
|
id_uuid = UUID(int=0)
|
|
@@ -221,7 +222,7 @@ def enter(filename: str, entrypoint: str, args: list) -> None:
|
|
|
221
222
|
base, mod_name = os.path.split(filename)
|
|
222
223
|
base = base if base else "./"
|
|
223
224
|
mod_name = mod_name[:-4]
|
|
224
|
-
mod = jac_import(target=mod_name, base_path=base)
|
|
225
|
+
(mod,) = jac_import(target=mod_name, base_path=base)
|
|
225
226
|
if not mod:
|
|
226
227
|
print("Errors occurred while importing the module.")
|
|
227
228
|
return
|
|
@@ -357,11 +358,10 @@ def dot(
|
|
|
357
358
|
else ""
|
|
358
359
|
)
|
|
359
360
|
|
|
360
|
-
Jac.context().init_memory(session)
|
|
361
|
-
|
|
362
361
|
base, mod = os.path.split(filename)
|
|
363
362
|
base = base if base else "./"
|
|
364
363
|
mod = mod[:-4]
|
|
364
|
+
Jac.context().init_memory(base_path=base, session=session)
|
|
365
365
|
if filename.endswith(".jac"):
|
|
366
366
|
jac_import(
|
|
367
367
|
target=mod,
|
|
@@ -437,12 +437,17 @@ def start_cli() -> None:
|
|
|
437
437
|
parser = cmd_registry.parser
|
|
438
438
|
args = parser.parse_args()
|
|
439
439
|
cmd_registry.args = args
|
|
440
|
+
|
|
441
|
+
if args.version:
|
|
442
|
+
version = importlib.metadata.version("jaclang")
|
|
443
|
+
print(f"Jac version {version}")
|
|
444
|
+
return
|
|
445
|
+
|
|
440
446
|
command = cmd_registry.get(args.command)
|
|
441
447
|
if command:
|
|
442
448
|
args_dict = vars(args)
|
|
443
449
|
args_dict.pop("command")
|
|
444
|
-
|
|
445
|
-
args_dict.pop("session")
|
|
450
|
+
args_dict.pop("version", None)
|
|
446
451
|
ret = command.call(**args_dict)
|
|
447
452
|
if ret:
|
|
448
453
|
print(ret)
|
jaclang/cli/cmdreg.py
CHANGED
|
@@ -38,7 +38,7 @@ class CommandRegistry:
|
|
|
38
38
|
self.registry = {}
|
|
39
39
|
self.parser = argparse.ArgumentParser(prog="jac")
|
|
40
40
|
self.parser.add_argument(
|
|
41
|
-
"
|
|
41
|
+
"-V", "--version", action="store_true", help="Show the Jac version"
|
|
42
42
|
)
|
|
43
43
|
self.sub_parsers = self.parser.add_subparsers(title="commands", dest="command")
|
|
44
44
|
self.args = argparse.Namespace()
|
|
@@ -172,17 +172,14 @@ class CommandShell(cmd.Cmd):
|
|
|
172
172
|
|
|
173
173
|
def default(self, line: str) -> None:
|
|
174
174
|
"""Process the command line input."""
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
self.stdout.write(f"{ret_str}\n")
|
|
184
|
-
except Exception as e:
|
|
185
|
-
print(e)
|
|
175
|
+
args = vars(self.cmd_reg.parser.parse_args(line.split()))
|
|
176
|
+
command = self.cmd_reg.get(args["command"])
|
|
177
|
+
if command:
|
|
178
|
+
args.pop("command")
|
|
179
|
+
ret = command.call(**args)
|
|
180
|
+
if ret:
|
|
181
|
+
ret_str = pprint.pformat(ret, indent=2)
|
|
182
|
+
self.stdout.write(f"{ret_str}\n")
|
|
186
183
|
|
|
187
184
|
def do_help(self, arg: str) -> None:
|
|
188
185
|
"""Jac CLI 'help' implementaion."""
|
jaclang/compiler/__init__.py
CHANGED
|
@@ -35,7 +35,6 @@ def generate_static_parser(force: bool = False) -> None:
|
|
|
35
35
|
logging.error(f"Error generating reference files: {e}")
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
generate_static_parser()
|
|
39
38
|
try:
|
|
40
39
|
from jaclang.compiler.generated import jac_parser as jac_lark
|
|
41
40
|
except ModuleNotFoundError:
|
|
@@ -50,62 +49,29 @@ TOKEN_MAP = {
|
|
|
50
49
|
for x in jac_lark.Lark_StandAlone().parser.lexer_conf.terminals
|
|
51
50
|
}
|
|
52
51
|
|
|
52
|
+
# fmt: off
|
|
53
53
|
TOKEN_MAP.update(
|
|
54
54
|
{
|
|
55
|
-
"CARROW_L": "<++",
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"ARROW_L_P1": "<-:",
|
|
73
|
-
"ARROW_R_P2": ":->",
|
|
74
|
-
"ARROW_L_P2": ":-",
|
|
75
|
-
"ARROW_R_P1": "-:",
|
|
76
|
-
"CARROW_BI": "<++>",
|
|
77
|
-
"CARROW_L": "<++",
|
|
78
|
-
"CARROW_R": "++>",
|
|
79
|
-
"CARROW_L_P1": "<+:",
|
|
80
|
-
"CARROW_R_P2": ":+>",
|
|
81
|
-
"CARROW_L_P2": ":+",
|
|
82
|
-
"CARROW_R_P1": "+:",
|
|
83
|
-
"PIPE_FWD": "|>",
|
|
84
|
-
"PIPE_BKWD": "<|",
|
|
85
|
-
"A_PIPE_FWD": ":>",
|
|
86
|
-
"A_PIPE_BKWD": "<:",
|
|
87
|
-
"DOT_FWD": ".>",
|
|
88
|
-
"STAR_POW": "**",
|
|
89
|
-
"STAR_MUL": "*",
|
|
90
|
-
"FLOOR_DIV": "//",
|
|
91
|
-
"DIV": "/",
|
|
92
|
-
"PYNLINE": "::py::",
|
|
93
|
-
"ADD_EQ": "+=",
|
|
94
|
-
"SUB_EQ": "-=",
|
|
95
|
-
"STAR_POW_EQ": "**=",
|
|
96
|
-
"MUL_EQ": "*=",
|
|
97
|
-
"FLOOR_DIV_EQ": "//=",
|
|
98
|
-
"DIV_EQ": "/=",
|
|
99
|
-
"MOD_EQ": "%=",
|
|
100
|
-
"BW_AND_EQ": "&=",
|
|
101
|
-
"BW_OR_EQ": "|=",
|
|
102
|
-
"BW_XOR_EQ": "^=",
|
|
103
|
-
"BW_NOT_EQ": "~=",
|
|
104
|
-
"LSHIFT_EQ": "<<=",
|
|
105
|
-
"RSHIFT_EQ": ">>=",
|
|
106
|
-
"ELLIPSIS": "...",
|
|
55
|
+
"CARROW_L": "<++", "CARROW_R": "++>", "GLOBAL_OP": ":global:",
|
|
56
|
+
"NONLOCAL_OP": ":nonlocal:", "WALKER_OP": ":walker:", "NODE_OP": ":node:",
|
|
57
|
+
"EDGE_OP": ":edge:", "CLASS_OP": ":class:", "OBJECT_OP": ":obj:",
|
|
58
|
+
"TYPE_OP": "`", "ABILITY_OP": ":can:", "ELVIS_OP": "?:", "NULL_OK": "?",
|
|
59
|
+
"KW_OR": "|", "ARROW_BI": "<-->", "ARROW_L": "<--",
|
|
60
|
+
"ARROW_R": "-->", "ARROW_L_P1": "<-:", "ARROW_R_P2": ":->",
|
|
61
|
+
"ARROW_L_P2": ":-", "ARROW_R_P1": "-:", "CARROW_BI": "<++>",
|
|
62
|
+
"CARROW_L": "<++", "CARROW_R": "++>", "CARROW_L_P1": "<+:",
|
|
63
|
+
"CARROW_R_P2": ":+>", "CARROW_L_P2": ":+", "CARROW_R_P1": "+:",
|
|
64
|
+
"PIPE_FWD": "|>", "PIPE_BKWD": "<|", "A_PIPE_FWD": ":>",
|
|
65
|
+
"A_PIPE_BKWD": "<:", "DOT_FWD": ".>", "STAR_POW": "**",
|
|
66
|
+
"STAR_MUL": "*", "FLOOR_DIV": "//", "DIV": "/",
|
|
67
|
+
"PYNLINE": "::py::", "ADD_EQ": "+=", "SUB_EQ": "-=",
|
|
68
|
+
"STAR_POW_EQ": "**=", "MUL_EQ": "*=", "FLOOR_DIV_EQ": "//=",
|
|
69
|
+
"DIV_EQ": "/=", "MOD_EQ": "%=", "BW_AND_EQ": "&=",
|
|
70
|
+
"BW_OR_EQ": "|=", "BW_XOR_EQ": "^=", "BW_NOT_EQ": "~=",
|
|
71
|
+
"LSHIFT_EQ": "<<=", "RSHIFT_EQ": ">>=", "ELLIPSIS": "...",
|
|
107
72
|
}
|
|
108
73
|
)
|
|
74
|
+
# fmt: on
|
|
109
75
|
|
|
110
76
|
|
|
111
77
|
__all__ = ["jac_lark", "TOKEN_MAP"]
|
jaclang/compiler/absyntree.py
CHANGED
|
@@ -55,15 +55,10 @@ class AstNode:
|
|
|
55
55
|
"""Get symbol table."""
|
|
56
56
|
# sym_tab should never be accessed without being set in codebase
|
|
57
57
|
if not self._sym_tab:
|
|
58
|
-
import traceback
|
|
59
|
-
|
|
60
|
-
if self.parent:
|
|
61
|
-
print(f"Parent: {self.parent.pp()}")
|
|
62
|
-
print("Node: ", self.pp())
|
|
63
|
-
stack_trace = traceback.format_stack()
|
|
64
|
-
print("".join(stack_trace))
|
|
65
58
|
raise ValueError(
|
|
66
|
-
f"Symbol table not set for {type(self).__name__}. Impossible
|
|
59
|
+
f"Symbol table not set for {type(self).__name__}. Impossible.\n"
|
|
60
|
+
f"Node: {self.pp()}\n"
|
|
61
|
+
f"Parent: {self.parent.pp() if self.parent else None}\n"
|
|
67
62
|
)
|
|
68
63
|
return self._sym_tab
|
|
69
64
|
|
|
@@ -163,7 +158,7 @@ class AstNode:
|
|
|
163
158
|
"""Get parent of type."""
|
|
164
159
|
from jaclang.compiler.passes import Pass
|
|
165
160
|
|
|
166
|
-
return Pass.
|
|
161
|
+
return Pass.find_parent_of_type(node=self, typ=typ)
|
|
167
162
|
|
|
168
163
|
def parent_of_type(self, typ: Type[T]) -> T:
|
|
169
164
|
"""Get parent of type."""
|
|
@@ -863,7 +858,7 @@ class Import(ElementStmt, CodeBlockStmt):
|
|
|
863
858
|
|
|
864
859
|
def __init__(
|
|
865
860
|
self,
|
|
866
|
-
hint: SubTag[Name],
|
|
861
|
+
hint: Optional[SubTag[Name]],
|
|
867
862
|
from_loc: Optional[ModulePath],
|
|
868
863
|
items: SubNodeList[ModuleItem] | SubNodeList[ModulePath],
|
|
869
864
|
is_absorb: bool, # For includes
|
|
@@ -878,11 +873,52 @@ class Import(ElementStmt, CodeBlockStmt):
|
|
|
878
873
|
AstNode.__init__(self, kid=kid)
|
|
879
874
|
AstDocNode.__init__(self, doc=doc)
|
|
880
875
|
|
|
876
|
+
@property
|
|
877
|
+
def is_py(self) -> bool:
|
|
878
|
+
"""Check if import is python."""
|
|
879
|
+
if self.hint and self.hint.tag.value == "py":
|
|
880
|
+
return True
|
|
881
|
+
if not self.hint:
|
|
882
|
+
return not self.__jac_detected
|
|
883
|
+
return False
|
|
884
|
+
|
|
885
|
+
@property
|
|
886
|
+
def is_jac(self) -> bool:
|
|
887
|
+
"""Check if import is jac."""
|
|
888
|
+
if self.hint and self.hint.tag.value == "jac":
|
|
889
|
+
return True
|
|
890
|
+
if not self.hint:
|
|
891
|
+
return self.__jac_detected
|
|
892
|
+
return False
|
|
893
|
+
|
|
894
|
+
@property
|
|
895
|
+
def __jac_detected(self) -> bool:
|
|
896
|
+
"""Check if import is jac."""
|
|
897
|
+
if self.from_loc:
|
|
898
|
+
if self.from_loc.resolve_relative_path().endswith(".jac"):
|
|
899
|
+
return True
|
|
900
|
+
if os.path.isdir(self.from_loc.resolve_relative_path()):
|
|
901
|
+
if os.path.exists(
|
|
902
|
+
os.path.join(self.from_loc.resolve_relative_path(), "__init__.jac")
|
|
903
|
+
):
|
|
904
|
+
return True
|
|
905
|
+
for i in self.items.items:
|
|
906
|
+
if isinstance(
|
|
907
|
+
i, ModuleItem
|
|
908
|
+
) and self.from_loc.resolve_relative_path(i.name.value).endswith(
|
|
909
|
+
".jac"
|
|
910
|
+
):
|
|
911
|
+
return True
|
|
912
|
+
return any(
|
|
913
|
+
isinstance(i, ModulePath) and i.resolve_relative_path().endswith(".jac")
|
|
914
|
+
for i in self.items.items
|
|
915
|
+
)
|
|
916
|
+
|
|
881
917
|
def normalize(self, deep: bool = False) -> bool:
|
|
882
918
|
"""Normalize import node."""
|
|
883
919
|
res = True
|
|
884
920
|
if deep:
|
|
885
|
-
res = self.hint.normalize(deep)
|
|
921
|
+
res = self.hint.normalize(deep) if self.hint else res
|
|
886
922
|
res = res and self.from_loc.normalize(deep) if self.from_loc else res
|
|
887
923
|
res = res and self.items.normalize(deep)
|
|
888
924
|
res = res and self.doc.normalize(deep) if self.doc else res
|
|
@@ -893,7 +929,8 @@ class Import(ElementStmt, CodeBlockStmt):
|
|
|
893
929
|
new_kid.append(self.gen_token(Tok.KW_INCLUDE))
|
|
894
930
|
else:
|
|
895
931
|
new_kid.append(self.gen_token(Tok.KW_IMPORT))
|
|
896
|
-
|
|
932
|
+
if self.hint:
|
|
933
|
+
new_kid.append(self.hint)
|
|
897
934
|
if self.from_loc:
|
|
898
935
|
new_kid.append(self.gen_token(Tok.KW_FROM))
|
|
899
936
|
new_kid.append(self.from_loc)
|
|
@@ -946,6 +983,26 @@ class ModulePath(AstSymbolNode):
|
|
|
946
983
|
[p.value for p in self.path] if self.path else [self.name_spec.sym_name]
|
|
947
984
|
)
|
|
948
985
|
|
|
986
|
+
def resolve_relative_path(self, target_item: Optional[str] = None) -> str:
|
|
987
|
+
"""Convert an import target string into a relative file path."""
|
|
988
|
+
target = self.path_str
|
|
989
|
+
if target_item:
|
|
990
|
+
target += f".{target_item}"
|
|
991
|
+
base_path = os.path.dirname(self.loc.mod_path)
|
|
992
|
+
base_path = base_path if base_path else os.getcwd()
|
|
993
|
+
parts = target.split(".")
|
|
994
|
+
traversal_levels = self.level - 1 if self.level > 0 else 0
|
|
995
|
+
actual_parts = parts[traversal_levels:]
|
|
996
|
+
for _ in range(traversal_levels):
|
|
997
|
+
base_path = os.path.dirname(base_path)
|
|
998
|
+
relative_path = os.path.join(base_path, *actual_parts)
|
|
999
|
+
relative_path = (
|
|
1000
|
+
relative_path + ".jac"
|
|
1001
|
+
if os.path.exists(relative_path + ".jac")
|
|
1002
|
+
else relative_path
|
|
1003
|
+
)
|
|
1004
|
+
return relative_path
|
|
1005
|
+
|
|
949
1006
|
def normalize(self, deep: bool = False) -> bool:
|
|
950
1007
|
"""Normalize module path node."""
|
|
951
1008
|
res = True
|
|
@@ -1132,7 +1189,6 @@ class ArchDef(AstImplOnlyNode):
|
|
|
1132
1189
|
body: SubNodeList[ArchBlockStmt],
|
|
1133
1190
|
kid: Sequence[AstNode],
|
|
1134
1191
|
doc: Optional[String] = None,
|
|
1135
|
-
decorators: Optional[SubNodeList[Expr]] = None,
|
|
1136
1192
|
decl_link: Optional[Architype] = None,
|
|
1137
1193
|
) -> None:
|
|
1138
1194
|
"""Initialize arch def node."""
|
|
@@ -1473,6 +1529,23 @@ class FuncSignature(AstSemStrNode):
|
|
|
1473
1529
|
and self.parent.decl_link.is_static
|
|
1474
1530
|
)
|
|
1475
1531
|
|
|
1532
|
+
@property
|
|
1533
|
+
def is_in_py_class(self) -> bool:
|
|
1534
|
+
"""Check if the ability belongs to a class."""
|
|
1535
|
+
is_archi = self.find_parent_of_type(Architype)
|
|
1536
|
+
is_class = is_archi is not None and is_archi.arch_type.name == Tok.KW_CLASS
|
|
1537
|
+
|
|
1538
|
+
return (
|
|
1539
|
+
isinstance(self.parent, Ability)
|
|
1540
|
+
and self.parent.is_method is not None
|
|
1541
|
+
and is_class
|
|
1542
|
+
) or (
|
|
1543
|
+
isinstance(self.parent, AbilityDef)
|
|
1544
|
+
and isinstance(self.parent.decl_link, Ability)
|
|
1545
|
+
and self.parent.decl_link.is_method
|
|
1546
|
+
and is_class
|
|
1547
|
+
)
|
|
1548
|
+
|
|
1476
1549
|
|
|
1477
1550
|
class EventSignature(AstSemStrNode):
|
|
1478
1551
|
"""EventSignature node type for Jac Ast."""
|
jaclang/compiler/jac.lark
CHANGED
|
@@ -16,8 +16,9 @@ element: import_stmt
|
|
|
16
16
|
| test
|
|
17
17
|
|
|
18
18
|
// Import/Include Statements
|
|
19
|
-
import_stmt: KW_IMPORT sub_name KW_FROM from_path
|
|
20
|
-
| KW_IMPORT sub_name
|
|
19
|
+
import_stmt: KW_IMPORT sub_name? KW_FROM from_path LBRACE import_items RBRACE
|
|
20
|
+
| KW_IMPORT sub_name? KW_FROM from_path COMMA import_items SEMI //Deprecated
|
|
21
|
+
| KW_IMPORT sub_name? import_path (COMMA import_path)* SEMI
|
|
21
22
|
| include_stmt
|
|
22
23
|
|
|
23
24
|
from_path: (DOT | ELLIPSIS)* import_path
|
|
@@ -27,7 +28,7 @@ import_path: named_ref (DOT named_ref)* (KW_AS NAME)?
|
|
|
27
28
|
import_items: (import_item COMMA)* import_item
|
|
28
29
|
import_item: named_ref (KW_AS NAME)?
|
|
29
30
|
sub_name: COLON NAME
|
|
30
|
-
include_stmt: KW_INCLUDE sub_name import_path SEMI
|
|
31
|
+
include_stmt: KW_INCLUDE sub_name? import_path SEMI
|
|
31
32
|
|
|
32
33
|
// Architypes
|
|
33
34
|
architype: decorators? architype_decl
|
jaclang/compiler/parser.py
CHANGED
|
@@ -298,26 +298,29 @@ class JacParser(Pass):
|
|
|
298
298
|
def import_stmt(self, kid: list[ast.AstNode]) -> ast.Import:
|
|
299
299
|
"""Grammar rule.
|
|
300
300
|
|
|
301
|
-
import_stmt: KW_IMPORT sub_name KW_FROM from_path
|
|
302
|
-
| KW_IMPORT sub_name
|
|
301
|
+
import_stmt: KW_IMPORT sub_name? KW_FROM from_path LBRACE import_items RBRACE
|
|
302
|
+
| KW_IMPORT sub_name? KW_FROM from_path COMMA import_items SEMI //Deprecated
|
|
303
|
+
| KW_IMPORT sub_name? import_path (COMMA import_path)* SEMI
|
|
303
304
|
| include_stmt
|
|
304
305
|
"""
|
|
305
306
|
if len(kid) == 1 and isinstance(kid[0], ast.Import):
|
|
306
307
|
return self.nu(kid[0])
|
|
307
|
-
|
|
308
|
-
|
|
308
|
+
chomp = [*kid]
|
|
309
|
+
lang = kid[1] if isinstance(kid[1], ast.SubTag) else None
|
|
310
|
+
chomp = chomp[2:] if lang else chomp[1:]
|
|
311
|
+
from_path = chomp[1] if isinstance(chomp[1], ast.ModulePath) else None
|
|
309
312
|
if from_path:
|
|
310
313
|
items = kid[-2] if isinstance(kid[-2], ast.SubNodeList) else None
|
|
311
314
|
else:
|
|
312
315
|
paths = [i for i in kid if isinstance(i, ast.ModulePath)]
|
|
313
316
|
items = ast.SubNodeList[ast.ModulePath](
|
|
314
|
-
items=paths, delim=Tok.COMMA, kid=kid[2
|
|
317
|
+
items=paths, delim=Tok.COMMA, kid=kid[2 if lang else 1 : -1]
|
|
315
318
|
)
|
|
316
|
-
kid = kid[:2] + [items] + kid[-1:]
|
|
319
|
+
kid = (kid[:2] if lang else kid[:1]) + [items] + kid[-1:]
|
|
317
320
|
|
|
318
321
|
is_absorb = False
|
|
319
|
-
if isinstance(
|
|
320
|
-
|
|
322
|
+
if isinstance(items, ast.SubNodeList):
|
|
323
|
+
ret = self.nu(
|
|
321
324
|
ast.Import(
|
|
322
325
|
hint=lang,
|
|
323
326
|
from_loc=from_path,
|
|
@@ -326,7 +329,15 @@ class JacParser(Pass):
|
|
|
326
329
|
kid=kid,
|
|
327
330
|
)
|
|
328
331
|
)
|
|
329
|
-
|
|
332
|
+
if (
|
|
333
|
+
from_path
|
|
334
|
+
and isinstance(kid[-1], ast.Token)
|
|
335
|
+
and kid[-1].name == Tok.SEMI
|
|
336
|
+
):
|
|
337
|
+
self.parse_ref.warning(
|
|
338
|
+
"Deprecated syntax, use braces for multiple imports (e.g, import from mymod {a, b, c})",
|
|
339
|
+
)
|
|
340
|
+
return ret
|
|
330
341
|
else:
|
|
331
342
|
raise self.ice()
|
|
332
343
|
|
|
@@ -364,27 +375,24 @@ class JacParser(Pass):
|
|
|
364
375
|
|
|
365
376
|
include_stmt: KW_INCLUDE sub_name import_path SEMI
|
|
366
377
|
"""
|
|
367
|
-
lang = kid[1]
|
|
368
|
-
from_path = kid[2]
|
|
378
|
+
lang = kid[1] if isinstance(kid[1], ast.SubTag) else None
|
|
379
|
+
from_path = kid[2] if lang else kid[1]
|
|
369
380
|
if not isinstance(from_path, ast.ModulePath):
|
|
370
381
|
raise self.ice()
|
|
371
382
|
items = ast.SubNodeList[ast.ModulePath](
|
|
372
383
|
items=[from_path], delim=Tok.COMMA, kid=[from_path]
|
|
373
384
|
)
|
|
374
|
-
kid = kid[:2] + [items] + kid[
|
|
385
|
+
kid = (kid[:2] if lang else kid[:1]) + [items] + kid[-1:]
|
|
375
386
|
is_absorb = True
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
kid=kid,
|
|
384
|
-
)
|
|
387
|
+
return self.nu(
|
|
388
|
+
ast.Import(
|
|
389
|
+
hint=lang,
|
|
390
|
+
from_loc=None,
|
|
391
|
+
items=items,
|
|
392
|
+
is_absorb=is_absorb,
|
|
393
|
+
kid=kid,
|
|
385
394
|
)
|
|
386
|
-
|
|
387
|
-
raise self.ice()
|
|
395
|
+
)
|
|
388
396
|
|
|
389
397
|
def import_path(self, kid: list[ast.AstNode]) -> ast.ModulePath:
|
|
390
398
|
"""Grammar rule.
|
|
@@ -74,7 +74,7 @@ class Pass(Transform[T]):
|
|
|
74
74
|
return result
|
|
75
75
|
|
|
76
76
|
@staticmethod
|
|
77
|
-
def
|
|
77
|
+
def find_parent_of_type(node: ast.AstNode, typ: Type[T]) -> Optional[T]:
|
|
78
78
|
"""Check if node has parent of type."""
|
|
79
79
|
while node.parent:
|
|
80
80
|
if isinstance(node.parent, typ):
|
|
@@ -115,7 +115,7 @@ class Pass(Transform[T]):
|
|
|
115
115
|
self.after_pass()
|
|
116
116
|
self.time_taken = time.time() - start_time
|
|
117
117
|
if settings.pass_timer:
|
|
118
|
-
|
|
118
|
+
self.log_info(
|
|
119
119
|
f"Time taken in {self.__class__.__name__}: {self.time_taken:.4f} seconds"
|
|
120
120
|
)
|
|
121
121
|
return self.ir
|
|
@@ -136,21 +136,12 @@ class Pass(Transform[T]):
|
|
|
136
136
|
self.exit_node(node)
|
|
137
137
|
return node
|
|
138
138
|
|
|
139
|
-
def update_code_loc(self, node: Optional[ast.AstNode] = None) -> None:
|
|
140
|
-
"""Update code location."""
|
|
141
|
-
if node is None:
|
|
142
|
-
node = self.cur_node
|
|
143
|
-
if not isinstance(node, ast.AstNode):
|
|
144
|
-
self.ice("Current node is not an AstNode.")
|
|
145
|
-
|
|
146
139
|
def error(self, msg: str, node_override: Optional[ast.AstNode] = None) -> None:
|
|
147
140
|
"""Pass Error."""
|
|
148
|
-
self.update_code_loc(node_override)
|
|
149
141
|
self.log_error(f"{msg}", node_override=node_override)
|
|
150
142
|
|
|
151
143
|
def warning(self, msg: str, node_override: Optional[ast.AstNode] = None) -> None:
|
|
152
144
|
"""Pass Error."""
|
|
153
|
-
self.update_code_loc(node_override)
|
|
154
145
|
self.log_warning(f"{msg}", node_override=node_override)
|
|
155
146
|
|
|
156
147
|
def ice(self, msg: str = "Something went horribly wrong!") -> RuntimeError:
|
|
@@ -166,10 +157,10 @@ class PrinterPass(Pass):
|
|
|
166
157
|
|
|
167
158
|
def enter_node(self, node: ast.AstNode) -> None:
|
|
168
159
|
"""Run on entering node."""
|
|
169
|
-
|
|
160
|
+
self.log_info(f"Entering: {node.__class__.__name__}: {node.loc}")
|
|
170
161
|
super().enter_node(node)
|
|
171
162
|
|
|
172
163
|
def exit_node(self, node: ast.AstNode) -> None:
|
|
173
164
|
"""Run on exiting node."""
|
|
174
165
|
super().exit_node(node)
|
|
175
|
-
|
|
166
|
+
self.log_info(f"Exiting: {node.__class__.__name__}: {node.loc}")
|
|
@@ -175,7 +175,7 @@ class AccessCheckPass(Pass):
|
|
|
175
175
|
if isinstance(node.parent, ast.FuncCall):
|
|
176
176
|
self.access_check(node)
|
|
177
177
|
|
|
178
|
-
if node.sym and Pass.
|
|
178
|
+
if node.sym and Pass.find_parent_of_type(
|
|
179
179
|
node=node.sym.defn[-1], typ=ast.GlobalVars
|
|
180
180
|
):
|
|
181
181
|
self.access_check(node)
|
|
@@ -6,7 +6,6 @@ mypy apis into Jac and use jac py ast in it.
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
-
import traceback
|
|
10
9
|
from typing import Callable, TypeVar
|
|
11
10
|
|
|
12
11
|
import jaclang.compiler.absyntree as ast
|
|
@@ -32,7 +31,7 @@ class FuseTypeInfoPass(Pass):
|
|
|
32
31
|
|
|
33
32
|
def __debug_print(self, *argv: object) -> None:
|
|
34
33
|
if settings.fuse_type_info_debug:
|
|
35
|
-
|
|
34
|
+
self.log_info("FuseTypeInfo::", *argv)
|
|
36
35
|
|
|
37
36
|
def __call_type_handler(
|
|
38
37
|
self, node: ast.AstSymbolNode, mypy_type: MypyTypes.ProperType
|
|
@@ -72,7 +71,9 @@ class FuseTypeInfoPass(Pass):
|
|
|
72
71
|
) -> Callable[[FuseTypeInfoPass, T], None]:
|
|
73
72
|
def node_handler(self: FuseTypeInfoPass, node: T) -> None:
|
|
74
73
|
if not isinstance(node, ast.AstSymbolNode):
|
|
75
|
-
|
|
74
|
+
self.__debug_print(
|
|
75
|
+
f"Warning {node.__class__.__name__} is not an AstSymbolNode"
|
|
76
|
+
)
|
|
76
77
|
|
|
77
78
|
try:
|
|
78
79
|
jac_node_str = f'jac node "{node.loc}::{node.__class__.__name__}'
|
|
@@ -119,8 +120,6 @@ class FuseTypeInfoPass(Pass):
|
|
|
119
120
|
self.__debug_print(
|
|
120
121
|
f'Internal error happened while parsing "{e.obj.__class__.__name__}"'
|
|
121
122
|
)
|
|
122
|
-
traceback.print_exc()
|
|
123
|
-
print(e)
|
|
124
123
|
|
|
125
124
|
return node_handler
|
|
126
125
|
|