jaclang 0.7.13__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 +95 -17
- jaclang/compiler/jac.lark +4 -3
- jaclang/compiler/parser.py +35 -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 +19 -23
- jaclang/compiler/passes/main/pyast_gen_pass.py +308 -567
- jaclang/compiler/passes/main/pyast_load_pass.py +33 -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/tests/test_import_pass.py +5 -1
- jaclang/compiler/passes/main/type_check_pass.py +7 -0
- jaclang/compiler/passes/tool/fuse_comments_pass.py +14 -2
- jaclang/compiler/passes/tool/jac_formatter_pass.py +144 -94
- 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 +82 -143
- 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 +96 -16
- jaclang/langserve/utils.py +163 -96
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +214 -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/blankwithentry.jac +3 -0
- 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 +83 -7
- jaclang/tests/test_man_code.py +17 -0
- 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.13.dist-info → jaclang-0.7.16.dist-info}/METADATA +3 -2
- {jaclang-0.7.13.dist-info → jaclang-0.7.16.dist-info}/RECORD +93 -77
- 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.13.dist-info → jaclang-0.7.16.dist-info}/WHEEL +0 -0
- {jaclang-0.7.13.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."""
|
|
@@ -621,6 +616,7 @@ class Module(AstDocNode):
|
|
|
621
616
|
doc: Optional[String],
|
|
622
617
|
body: Sequence[ElementStmt | String | EmptyToken],
|
|
623
618
|
is_imported: bool,
|
|
619
|
+
terminals: list[Token],
|
|
624
620
|
kid: Sequence[AstNode],
|
|
625
621
|
stub_only: bool = False,
|
|
626
622
|
registry: Optional[SemRegistry] = None,
|
|
@@ -635,6 +631,7 @@ class Module(AstDocNode):
|
|
|
635
631
|
self.test_mod: list[Module] = []
|
|
636
632
|
self.mod_deps: dict[str, Module] = {}
|
|
637
633
|
self.registry = registry
|
|
634
|
+
self.terminals: list[Token] = terminals
|
|
638
635
|
AstNode.__init__(self, kid=kid)
|
|
639
636
|
AstDocNode.__init__(self, doc=doc)
|
|
640
637
|
|
|
@@ -642,15 +639,15 @@ class Module(AstDocNode):
|
|
|
642
639
|
def annexable_by(self) -> Optional[str]:
|
|
643
640
|
"""Get annexable by."""
|
|
644
641
|
if not self.stub_only and (
|
|
645
|
-
self.loc.mod_path.endswith("impl.jac")
|
|
646
|
-
or self.loc.mod_path.endswith("test.jac")
|
|
642
|
+
self.loc.mod_path.endswith(".impl.jac")
|
|
643
|
+
or self.loc.mod_path.endswith(".test.jac")
|
|
647
644
|
):
|
|
648
645
|
head_mod_name = self.name.split(".")[0]
|
|
649
646
|
potential_path = os.path.join(
|
|
650
647
|
os.path.dirname(self.loc.mod_path),
|
|
651
648
|
f"{head_mod_name}.jac",
|
|
652
649
|
)
|
|
653
|
-
if os.path.exists(potential_path):
|
|
650
|
+
if os.path.exists(potential_path) and potential_path != self.loc.mod_path:
|
|
654
651
|
return potential_path
|
|
655
652
|
annex_dir = os.path.split(os.path.dirname(self.loc.mod_path))[-1]
|
|
656
653
|
if annex_dir.endswith(".impl") or annex_dir.endswith(".test"):
|
|
@@ -661,7 +658,10 @@ class Module(AstDocNode):
|
|
|
661
658
|
os.path.dirname(os.path.dirname(self.loc.mod_path)),
|
|
662
659
|
f"{head_mod_name}.jac",
|
|
663
660
|
)
|
|
664
|
-
if
|
|
661
|
+
if (
|
|
662
|
+
os.path.exists(potential_path)
|
|
663
|
+
and potential_path != self.loc.mod_path
|
|
664
|
+
):
|
|
665
665
|
return potential_path
|
|
666
666
|
return None
|
|
667
667
|
|
|
@@ -858,7 +858,7 @@ class Import(ElementStmt, CodeBlockStmt):
|
|
|
858
858
|
|
|
859
859
|
def __init__(
|
|
860
860
|
self,
|
|
861
|
-
hint: SubTag[Name],
|
|
861
|
+
hint: Optional[SubTag[Name]],
|
|
862
862
|
from_loc: Optional[ModulePath],
|
|
863
863
|
items: SubNodeList[ModuleItem] | SubNodeList[ModulePath],
|
|
864
864
|
is_absorb: bool, # For includes
|
|
@@ -873,11 +873,52 @@ class Import(ElementStmt, CodeBlockStmt):
|
|
|
873
873
|
AstNode.__init__(self, kid=kid)
|
|
874
874
|
AstDocNode.__init__(self, doc=doc)
|
|
875
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
|
+
|
|
876
917
|
def normalize(self, deep: bool = False) -> bool:
|
|
877
918
|
"""Normalize import node."""
|
|
878
919
|
res = True
|
|
879
920
|
if deep:
|
|
880
|
-
res = self.hint.normalize(deep)
|
|
921
|
+
res = self.hint.normalize(deep) if self.hint else res
|
|
881
922
|
res = res and self.from_loc.normalize(deep) if self.from_loc else res
|
|
882
923
|
res = res and self.items.normalize(deep)
|
|
883
924
|
res = res and self.doc.normalize(deep) if self.doc else res
|
|
@@ -888,7 +929,8 @@ class Import(ElementStmt, CodeBlockStmt):
|
|
|
888
929
|
new_kid.append(self.gen_token(Tok.KW_INCLUDE))
|
|
889
930
|
else:
|
|
890
931
|
new_kid.append(self.gen_token(Tok.KW_IMPORT))
|
|
891
|
-
|
|
932
|
+
if self.hint:
|
|
933
|
+
new_kid.append(self.hint)
|
|
892
934
|
if self.from_loc:
|
|
893
935
|
new_kid.append(self.gen_token(Tok.KW_FROM))
|
|
894
936
|
new_kid.append(self.from_loc)
|
|
@@ -941,6 +983,26 @@ class ModulePath(AstSymbolNode):
|
|
|
941
983
|
[p.value for p in self.path] if self.path else [self.name_spec.sym_name]
|
|
942
984
|
)
|
|
943
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
|
+
|
|
944
1006
|
def normalize(self, deep: bool = False) -> bool:
|
|
945
1007
|
"""Normalize module path node."""
|
|
946
1008
|
res = True
|
|
@@ -1127,7 +1189,6 @@ class ArchDef(AstImplOnlyNode):
|
|
|
1127
1189
|
body: SubNodeList[ArchBlockStmt],
|
|
1128
1190
|
kid: Sequence[AstNode],
|
|
1129
1191
|
doc: Optional[String] = None,
|
|
1130
|
-
decorators: Optional[SubNodeList[Expr]] = None,
|
|
1131
1192
|
decl_link: Optional[Architype] = None,
|
|
1132
1193
|
) -> None:
|
|
1133
1194
|
"""Initialize arch def node."""
|
|
@@ -1468,6 +1529,23 @@ class FuncSignature(AstSemStrNode):
|
|
|
1468
1529
|
and self.parent.decl_link.is_static
|
|
1469
1530
|
)
|
|
1470
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
|
+
|
|
1471
1549
|
|
|
1472
1550
|
class EventSignature(AstSemStrNode):
|
|
1473
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
|
@@ -56,6 +56,7 @@ class JacParser(Pass):
|
|
|
56
56
|
source=self.source,
|
|
57
57
|
doc=None,
|
|
58
58
|
body=[],
|
|
59
|
+
terminals=[],
|
|
59
60
|
is_imported=False,
|
|
60
61
|
kid=[ast.EmptyToken()],
|
|
61
62
|
)
|
|
@@ -120,6 +121,7 @@ class JacParser(Pass):
|
|
|
120
121
|
"""Initialize transformer."""
|
|
121
122
|
super().__init__(*args, **kwargs)
|
|
122
123
|
self.parse_ref = parser
|
|
124
|
+
self.terminals: list[ast.Token] = []
|
|
123
125
|
|
|
124
126
|
def ice(self) -> Exception:
|
|
125
127
|
"""Raise internal compiler error."""
|
|
@@ -160,6 +162,7 @@ class JacParser(Pass):
|
|
|
160
162
|
doc=doc,
|
|
161
163
|
body=body,
|
|
162
164
|
is_imported=False,
|
|
165
|
+
terminals=self.terminals,
|
|
163
166
|
kid=kid if len(kid) else [ast.EmptyToken()],
|
|
164
167
|
)
|
|
165
168
|
return self.nu(mod)
|
|
@@ -295,26 +298,29 @@ class JacParser(Pass):
|
|
|
295
298
|
def import_stmt(self, kid: list[ast.AstNode]) -> ast.Import:
|
|
296
299
|
"""Grammar rule.
|
|
297
300
|
|
|
298
|
-
import_stmt: KW_IMPORT sub_name KW_FROM from_path
|
|
299
|
-
| 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
|
|
300
304
|
| include_stmt
|
|
301
305
|
"""
|
|
302
306
|
if len(kid) == 1 and isinstance(kid[0], ast.Import):
|
|
303
307
|
return self.nu(kid[0])
|
|
304
|
-
|
|
305
|
-
|
|
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
|
|
306
312
|
if from_path:
|
|
307
313
|
items = kid[-2] if isinstance(kid[-2], ast.SubNodeList) else None
|
|
308
314
|
else:
|
|
309
315
|
paths = [i for i in kid if isinstance(i, ast.ModulePath)]
|
|
310
316
|
items = ast.SubNodeList[ast.ModulePath](
|
|
311
|
-
items=paths, delim=Tok.COMMA, kid=kid[2
|
|
317
|
+
items=paths, delim=Tok.COMMA, kid=kid[2 if lang else 1 : -1]
|
|
312
318
|
)
|
|
313
|
-
kid = kid[:2] + [items] + kid[-1:]
|
|
319
|
+
kid = (kid[:2] if lang else kid[:1]) + [items] + kid[-1:]
|
|
314
320
|
|
|
315
321
|
is_absorb = False
|
|
316
|
-
if isinstance(
|
|
317
|
-
|
|
322
|
+
if isinstance(items, ast.SubNodeList):
|
|
323
|
+
ret = self.nu(
|
|
318
324
|
ast.Import(
|
|
319
325
|
hint=lang,
|
|
320
326
|
from_loc=from_path,
|
|
@@ -323,7 +329,15 @@ class JacParser(Pass):
|
|
|
323
329
|
kid=kid,
|
|
324
330
|
)
|
|
325
331
|
)
|
|
326
|
-
|
|
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
|
|
327
341
|
else:
|
|
328
342
|
raise self.ice()
|
|
329
343
|
|
|
@@ -361,27 +375,24 @@ class JacParser(Pass):
|
|
|
361
375
|
|
|
362
376
|
include_stmt: KW_INCLUDE sub_name import_path SEMI
|
|
363
377
|
"""
|
|
364
|
-
lang = kid[1]
|
|
365
|
-
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]
|
|
366
380
|
if not isinstance(from_path, ast.ModulePath):
|
|
367
381
|
raise self.ice()
|
|
368
382
|
items = ast.SubNodeList[ast.ModulePath](
|
|
369
383
|
items=[from_path], delim=Tok.COMMA, kid=[from_path]
|
|
370
384
|
)
|
|
371
|
-
kid = kid[:2] + [items] + kid[
|
|
385
|
+
kid = (kid[:2] if lang else kid[:1]) + [items] + kid[-1:]
|
|
372
386
|
is_absorb = True
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
kid=kid,
|
|
381
|
-
)
|
|
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,
|
|
382
394
|
)
|
|
383
|
-
|
|
384
|
-
raise self.ice()
|
|
395
|
+
)
|
|
385
396
|
|
|
386
397
|
def import_path(self, kid: list[ast.AstNode]) -> ast.ModulePath:
|
|
387
398
|
"""Grammar rule.
|
|
@@ -3983,4 +3994,5 @@ class JacParser(Pass):
|
|
|
3983
3994
|
err.line = ret.loc.first_line
|
|
3984
3995
|
err.column = ret.loc.col_start
|
|
3985
3996
|
raise err
|
|
3997
|
+
self.terminals.append(ret)
|
|
3986
3998
|
return self.nu(ret)
|
|
@@ -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
|
|