jaclang 0.7.13__py3-none-any.whl → 0.7.15__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 +11 -8
- jaclang/cli/cmdreg.py +9 -12
- jaclang/compiler/__init__.py +0 -2
- jaclang/compiler/absyntree.py +12 -12
- jaclang/compiler/parser.py +4 -0
- jaclang/compiler/passes/ir_pass.py +3 -12
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +4 -5
- jaclang/compiler/passes/main/import_pass.py +5 -2
- jaclang/compiler/passes/main/pyast_gen_pass.py +33 -39
- jaclang/compiler/passes/main/pyast_load_pass.py +1 -0
- jaclang/compiler/passes/main/registry_pass.py +1 -1
- jaclang/compiler/passes/main/tests/test_import_pass.py +5 -1
- jaclang/compiler/passes/tool/fuse_comments_pass.py +14 -2
- jaclang/compiler/passes/tool/jac_formatter_pass.py +23 -28
- jaclang/compiler/passes/transform.py +4 -0
- jaclang/compiler/semtable.py +5 -3
- jaclang/compiler/tests/test_importer.py +3 -0
- jaclang/langserve/engine.py +227 -94
- jaclang/langserve/server.py +6 -10
- jaclang/langserve/tests/fixtures/base_module_structure.jac +1 -1
- 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 +28 -4
- jaclang/langserve/utils.py +128 -95
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +25 -16
- jaclang/plugin/feature.py +4 -5
- jaclang/plugin/spec.py +2 -2
- jaclang/{core → runtimelib}/architype.py +1 -1
- jaclang/{core → runtimelib}/context.py +4 -1
- jaclang/runtimelib/importer.py +414 -0
- jaclang/runtimelib/machine.py +19 -0
- jaclang/{core → runtimelib}/utils.py +1 -1
- jaclang/tests/fixtures/blankwithentry.jac +3 -0
- jaclang/tests/fixtures/deep/one_lev.jac +3 -3
- jaclang/tests/fixtures/deep/one_lev_dup.jac +2 -3
- jaclang/tests/test_cli.py +1 -1
- jaclang/tests/test_language.py +16 -0
- jaclang/tests/test_man_code.py +17 -0
- jaclang/utils/treeprinter.py +0 -4
- {jaclang-0.7.13.dist-info → jaclang-0.7.15.dist-info}/METADATA +1 -1
- {jaclang-0.7.13.dist-info → jaclang-0.7.15.dist-info}/RECORD +48 -45
- jaclang/core/importer.py +0 -344
- /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.15.dist-info}/WHEEL +0 -0
- {jaclang-0.7.13.dist-info → jaclang-0.7.15.dist-info}/entry_points.txt +0 -0
jaclang/cli/cli.py
CHANGED
|
@@ -19,10 +19,10 @@ 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
26
|
from jaclang.utils.helpers import debugger as db
|
|
27
27
|
from jaclang.utils.lang_tools import AstTool
|
|
28
28
|
|
|
@@ -86,11 +86,10 @@ def run(
|
|
|
86
86
|
else ""
|
|
87
87
|
)
|
|
88
88
|
|
|
89
|
-
Jac.context().init_memory(session)
|
|
90
|
-
|
|
91
89
|
base, mod = os.path.split(filename)
|
|
92
90
|
base = base if base else "./"
|
|
93
91
|
mod = mod[:-4]
|
|
92
|
+
Jac.context().init_memory(base_path=base, session=session)
|
|
94
93
|
if filename.endswith(".jac"):
|
|
95
94
|
ret_module = jac_import(
|
|
96
95
|
target=mod,
|
|
@@ -146,7 +145,7 @@ def get_object(id: str, session: str = "") -> dict:
|
|
|
146
145
|
if session == "":
|
|
147
146
|
session = cmd_registry.args.session if "session" in cmd_registry.args else ""
|
|
148
147
|
|
|
149
|
-
Jac.context().init_memory(session)
|
|
148
|
+
Jac.context().init_memory(session=session)
|
|
150
149
|
|
|
151
150
|
if id == "root":
|
|
152
151
|
id_uuid = UUID(int=0)
|
|
@@ -357,11 +356,10 @@ def dot(
|
|
|
357
356
|
else ""
|
|
358
357
|
)
|
|
359
358
|
|
|
360
|
-
Jac.context().init_memory(session)
|
|
361
|
-
|
|
362
359
|
base, mod = os.path.split(filename)
|
|
363
360
|
base = base if base else "./"
|
|
364
361
|
mod = mod[:-4]
|
|
362
|
+
Jac.context().init_memory(base_path=base, session=session)
|
|
365
363
|
if filename.endswith(".jac"):
|
|
366
364
|
jac_import(
|
|
367
365
|
target=mod,
|
|
@@ -437,12 +435,17 @@ def start_cli() -> None:
|
|
|
437
435
|
parser = cmd_registry.parser
|
|
438
436
|
args = parser.parse_args()
|
|
439
437
|
cmd_registry.args = args
|
|
438
|
+
|
|
439
|
+
if args.version:
|
|
440
|
+
version = importlib.metadata.version("jaclang")
|
|
441
|
+
print(f"Jac version {version}")
|
|
442
|
+
return
|
|
443
|
+
|
|
440
444
|
command = cmd_registry.get(args.command)
|
|
441
445
|
if command:
|
|
442
446
|
args_dict = vars(args)
|
|
443
447
|
args_dict.pop("command")
|
|
444
|
-
|
|
445
|
-
args_dict.pop("session")
|
|
448
|
+
args_dict.pop("version", None)
|
|
446
449
|
ret = command.call(**args_dict)
|
|
447
450
|
if ret:
|
|
448
451
|
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
|
@@ -34,8 +34,6 @@ def generate_static_parser(force: bool = False) -> None:
|
|
|
34
34
|
except Exception as e:
|
|
35
35
|
logging.error(f"Error generating reference files: {e}")
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
generate_static_parser()
|
|
39
37
|
try:
|
|
40
38
|
from jaclang.compiler.generated import jac_parser as jac_lark
|
|
41
39
|
except ModuleNotFoundError:
|
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
|
|
|
@@ -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
|
|
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)
|
|
@@ -3983,4 +3986,5 @@ class JacParser(Pass):
|
|
|
3983
3986
|
err.line = ret.loc.first_line
|
|
3984
3987
|
err.column = ret.loc.col_start
|
|
3985
3988
|
raise err
|
|
3989
|
+
self.terminals.append(ret)
|
|
3986
3990
|
return self.nu(ret)
|
|
@@ -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}")
|
|
@@ -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
|
|
|
@@ -17,6 +17,9 @@ from jaclang.compiler.passes import Pass
|
|
|
17
17
|
from jaclang.compiler.passes.main import SubNodeTabPass
|
|
18
18
|
from jaclang.settings import settings
|
|
19
19
|
from jaclang.utils.helpers import import_target_to_relative_path, is_standard_lib_module
|
|
20
|
+
from jaclang.utils.log import logging
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
20
23
|
|
|
21
24
|
|
|
22
25
|
class JacImportPass(Pass):
|
|
@@ -182,6 +185,7 @@ class JacImportPass(Pass):
|
|
|
182
185
|
source=ast.JacSource("", mod_path=target),
|
|
183
186
|
doc=None,
|
|
184
187
|
body=[],
|
|
188
|
+
terminals=[],
|
|
185
189
|
is_imported=False,
|
|
186
190
|
stub_only=True,
|
|
187
191
|
kid=[ast.EmptyToken()],
|
|
@@ -203,7 +207,7 @@ class JacImportPass(Pass):
|
|
|
203
207
|
self.warnings_had += mod_pass.warnings_had
|
|
204
208
|
mod = mod_pass.ir
|
|
205
209
|
except Exception as e:
|
|
206
|
-
|
|
210
|
+
logger.info(e)
|
|
207
211
|
mod = None
|
|
208
212
|
if isinstance(mod, ast.Module):
|
|
209
213
|
self.import_table[target] = mod
|
|
@@ -251,7 +255,6 @@ class PyImportPass(JacImportPass):
|
|
|
251
255
|
if spec.origin in self.import_table:
|
|
252
256
|
return self.import_table[spec.origin]
|
|
253
257
|
with open(spec.origin, "r", encoding="utf-8") as f:
|
|
254
|
-
# print(f"\nImporting python module {node.path_str}")
|
|
255
258
|
mod = PyastBuildPass(
|
|
256
259
|
input_ir=ast.PythonModuleAst(
|
|
257
260
|
py_ast.parse(f.read()), mod_path=spec.origin
|
|
@@ -11,7 +11,7 @@ from typing import Optional, Sequence, TypeVar
|
|
|
11
11
|
import jaclang.compiler.absyntree as ast
|
|
12
12
|
from jaclang.compiler.constant import Constants as Con, EdgeDir, Tokens as Tok
|
|
13
13
|
from jaclang.compiler.passes import Pass
|
|
14
|
-
from jaclang.
|
|
14
|
+
from jaclang.runtimelib.utils import extract_params, extract_type, get_sem_scope
|
|
15
15
|
|
|
16
16
|
T = TypeVar("T", bound=ast3.AST)
|
|
17
17
|
|
|
@@ -19,24 +19,25 @@ T = TypeVar("T", bound=ast3.AST)
|
|
|
19
19
|
class PyastGenPass(Pass):
|
|
20
20
|
"""Jac blue transpilation to python pass."""
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
22
|
+
# TODO: This should live in utils and perhaps a test added using it
|
|
23
|
+
# @staticmethod
|
|
24
|
+
# def node_compilable_test(node: ast3.AST) -> None:
|
|
25
|
+
# """Convert any AST node to a compilable module node."""
|
|
26
|
+
# if isinstance(node, ast3.Module):
|
|
27
|
+
# pass
|
|
28
|
+
# elif isinstance(node, (ast3.Expr, ast3.stmt)):
|
|
29
|
+
# node = ast3.Module(body=[node], type_ignores=[])
|
|
30
|
+
# elif isinstance(node, list) and all(isinstance(n, ast3.stmt) for n in node):
|
|
31
|
+
# node = ast3.Module(body=node, type_ignores=[])
|
|
32
|
+
# else:
|
|
33
|
+
# node = ast3.Module(body=[], type_ignores=[])
|
|
34
|
+
# try:
|
|
35
|
+
# compile(node, "<ast>", "exec")
|
|
36
|
+
# except TypeError as e:
|
|
37
|
+
# print(ast3.dump(node, indent=2))
|
|
38
|
+
# raise e
|
|
39
|
+
# except Exception:
|
|
40
|
+
# pass
|
|
40
41
|
|
|
41
42
|
def before_pass(self) -> None:
|
|
42
43
|
"""Initialize pass."""
|
|
@@ -80,7 +81,7 @@ class PyastGenPass(Pass):
|
|
|
80
81
|
|
|
81
82
|
def needs_jac_import(self) -> None:
|
|
82
83
|
"""Check if import is needed."""
|
|
83
|
-
if
|
|
84
|
+
if self.needs_jac_import.__name__ in self.already_added:
|
|
84
85
|
return
|
|
85
86
|
self.preamble.append(
|
|
86
87
|
self.sync(
|
|
@@ -96,11 +97,11 @@ class PyastGenPass(Pass):
|
|
|
96
97
|
jac_node=self.ir,
|
|
97
98
|
)
|
|
98
99
|
)
|
|
99
|
-
self.already_added.append(
|
|
100
|
+
self.already_added.append(self.needs_jac_import.__name__)
|
|
100
101
|
|
|
101
102
|
def needs_typing(self) -> None:
|
|
102
103
|
"""Check if enum is needed."""
|
|
103
|
-
if
|
|
104
|
+
if self.needs_typing.__name__ in self.already_added:
|
|
104
105
|
return
|
|
105
106
|
self.preamble.append(
|
|
106
107
|
self.sync(
|
|
@@ -115,11 +116,11 @@ class PyastGenPass(Pass):
|
|
|
115
116
|
jac_node=self.ir,
|
|
116
117
|
)
|
|
117
118
|
)
|
|
118
|
-
self.already_added.append(
|
|
119
|
+
self.already_added.append(self.needs_typing.__name__)
|
|
119
120
|
|
|
120
121
|
def needs_enum(self) -> None:
|
|
121
122
|
"""Check if enum is needed."""
|
|
122
|
-
if
|
|
123
|
+
if self.needs_enum.__name__ in self.already_added:
|
|
123
124
|
return
|
|
124
125
|
self.preamble.append(
|
|
125
126
|
self.sync(
|
|
@@ -134,11 +135,11 @@ class PyastGenPass(Pass):
|
|
|
134
135
|
jac_node=self.ir,
|
|
135
136
|
)
|
|
136
137
|
)
|
|
137
|
-
self.already_added.append(
|
|
138
|
+
self.already_added.append(self.needs_enum.__name__)
|
|
138
139
|
|
|
139
140
|
def needs_jac_feature(self) -> None:
|
|
140
141
|
"""Check if enum is needed."""
|
|
141
|
-
if
|
|
142
|
+
if self.needs_jac_feature.__name__ in self.already_added:
|
|
142
143
|
return
|
|
143
144
|
self.preamble.append(
|
|
144
145
|
self.sync(
|
|
@@ -164,11 +165,11 @@ class PyastGenPass(Pass):
|
|
|
164
165
|
jac_node=self.ir,
|
|
165
166
|
)
|
|
166
167
|
)
|
|
167
|
-
self.already_added.append(
|
|
168
|
+
self.already_added.append(self.needs_jac_feature.__name__)
|
|
168
169
|
|
|
169
170
|
def needs_dataclass(self) -> None:
|
|
170
171
|
"""Check if enum is needed."""
|
|
171
|
-
if
|
|
172
|
+
if self.needs_dataclass.__name__ in self.already_added:
|
|
172
173
|
return
|
|
173
174
|
self.preamble.append(
|
|
174
175
|
self.sync(
|
|
@@ -184,11 +185,11 @@ class PyastGenPass(Pass):
|
|
|
184
185
|
jac_node=self.ir,
|
|
185
186
|
)
|
|
186
187
|
)
|
|
187
|
-
self.already_added.append(
|
|
188
|
+
self.already_added.append(self.needs_dataclass.__name__)
|
|
188
189
|
|
|
189
190
|
def needs_dataclass_field(self) -> None:
|
|
190
191
|
"""Check if enum is needed."""
|
|
191
|
-
if
|
|
192
|
+
if self.needs_dataclass_field.__name__ in self.already_added:
|
|
192
193
|
return
|
|
193
194
|
self.preamble.append(
|
|
194
195
|
self.sync(
|
|
@@ -202,7 +203,7 @@ class PyastGenPass(Pass):
|
|
|
202
203
|
jac_node=self.ir,
|
|
203
204
|
)
|
|
204
205
|
)
|
|
205
|
-
self.already_added.append(
|
|
206
|
+
self.already_added.append(self.needs_dataclass_field.__name__)
|
|
206
207
|
|
|
207
208
|
def flatten(self, body: list[T | list[T] | None]) -> list[T]:
|
|
208
209
|
"""Flatten ast list."""
|
|
@@ -434,14 +435,7 @@ class PyastGenPass(Pass):
|
|
|
434
435
|
body: SubNodeList[CodeBlockStmt],
|
|
435
436
|
doc: Optional[String],
|
|
436
437
|
"""
|
|
437
|
-
|
|
438
|
-
doc = self.sync(ast3.Expr(value=node.doc.gen.py_ast[0]), jac_node=node.doc)
|
|
439
|
-
if isinstance(node.body.gen.py_ast, list):
|
|
440
|
-
node.gen.py_ast = [doc] + node.body.gen.py_ast
|
|
441
|
-
else:
|
|
442
|
-
raise self.ice()
|
|
443
|
-
else:
|
|
444
|
-
node.gen.py_ast = node.body.gen.py_ast
|
|
438
|
+
node.gen.py_ast = self.resolve_stmt_block(node.body, doc=node.doc)
|
|
445
439
|
if node.name:
|
|
446
440
|
node.gen.py_ast = [
|
|
447
441
|
self.sync(
|
|
@@ -124,6 +124,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
124
124
|
source=ast.JacSource("", mod_path=self.mod_path),
|
|
125
125
|
doc=doc_str,
|
|
126
126
|
body=valid[1:] if valid and isinstance(valid[0], ast.String) else valid,
|
|
127
|
+
terminals=[],
|
|
127
128
|
is_imported=False,
|
|
128
129
|
kid=valid,
|
|
129
130
|
)
|
|
@@ -13,7 +13,7 @@ import jaclang.compiler.absyntree as ast
|
|
|
13
13
|
from jaclang.compiler.constant import Constants as Con
|
|
14
14
|
from jaclang.compiler.passes import Pass
|
|
15
15
|
from jaclang.compiler.semtable import SemInfo, SemRegistry
|
|
16
|
-
from jaclang.
|
|
16
|
+
from jaclang.runtimelib.utils import get_sem_scope
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class RegistryPass(Pass):
|
|
@@ -47,8 +47,12 @@ class ImportPassPassTests(TestCase):
|
|
|
47
47
|
state = jac_file_to_pass(
|
|
48
48
|
self.fixture_abs_path("incautoimpl.jac"), JacImportPass
|
|
49
49
|
)
|
|
50
|
+
count = 0
|
|
50
51
|
for i in state.ir.get_all_sub_nodes(ast.Module):
|
|
51
|
-
|
|
52
|
+
if i.name != "autoimpl":
|
|
53
|
+
count += 1
|
|
54
|
+
self.assertEqual(i.annexable_by, self.fixture_abs_path("autoimpl.jac"))
|
|
55
|
+
self.assertEqual(count, 3)
|
|
52
56
|
|
|
53
57
|
def test_py_resolve_list(self) -> None:
|
|
54
58
|
"""Basic test for pass."""
|
|
@@ -27,7 +27,12 @@ class FuseCommentsPass(Pass):
|
|
|
27
27
|
"""Insert comment tokens into all_tokens."""
|
|
28
28
|
comment_stream = iter(self.comments) # Iterator for comments
|
|
29
29
|
code_stream = iter(self.all_tokens) # Iterator for code tokens
|
|
30
|
-
new_stream: list[ast.
|
|
30
|
+
new_stream: list[ast.Token] = [] # New stream to hold ordered tokens
|
|
31
|
+
|
|
32
|
+
if not isinstance(self.ir, ast.Module):
|
|
33
|
+
raise self.ice(
|
|
34
|
+
f"FuseCommentsPass can only be run on a Module, not a {type(self.ir)}"
|
|
35
|
+
)
|
|
31
36
|
|
|
32
37
|
try:
|
|
33
38
|
next_comment = next(comment_stream) # Get the first comment
|
|
@@ -39,12 +44,20 @@ class FuseCommentsPass(Pass):
|
|
|
39
44
|
except StopIteration:
|
|
40
45
|
next_code = None
|
|
41
46
|
|
|
47
|
+
if next_comment and (not next_code or is_comment_next(next_comment, next_code)):
|
|
48
|
+
self.ir.terminals.insert(0, next_comment)
|
|
49
|
+
|
|
42
50
|
while next_comment or next_code:
|
|
43
51
|
if next_comment and (
|
|
44
52
|
not next_code or is_comment_next(next_comment, next_code)
|
|
45
53
|
):
|
|
46
54
|
# Add the comment to the new stream
|
|
55
|
+
last_tok = new_stream[-1] if len(new_stream) else None
|
|
47
56
|
new_stream.append(next_comment)
|
|
57
|
+
if last_tok:
|
|
58
|
+
self.ir.terminals.insert(
|
|
59
|
+
self.ir.terminals.index(last_tok) + 1, next_comment
|
|
60
|
+
)
|
|
48
61
|
try:
|
|
49
62
|
next_comment = next(comment_stream)
|
|
50
63
|
except StopIteration:
|
|
@@ -70,7 +83,6 @@ class FuseCommentsPass(Pass):
|
|
|
70
83
|
parent_kids.insert(insert_index, token)
|
|
71
84
|
prev_token.parent.set_kids(parent_kids)
|
|
72
85
|
else:
|
|
73
|
-
prev_token.pp()
|
|
74
86
|
raise self.ice(
|
|
75
87
|
"Token without parent in AST should be impossible"
|
|
76
88
|
)
|
|
@@ -27,6 +27,22 @@ class JacFormatPass(Pass):
|
|
|
27
27
|
node.gen.jac = ""
|
|
28
28
|
super().enter_node(node)
|
|
29
29
|
|
|
30
|
+
def token_before(self, node: ast.Token) -> Optional[ast.Token]:
|
|
31
|
+
"""Token before."""
|
|
32
|
+
if not isinstance(self.ir, ast.Module):
|
|
33
|
+
raise self.ice("IR must be module. Impossible")
|
|
34
|
+
if self.ir.terminals.index(node) == 0:
|
|
35
|
+
return None
|
|
36
|
+
return self.ir.terminals[self.ir.terminals.index(node) - 1]
|
|
37
|
+
|
|
38
|
+
def token_after(self, node: ast.Token) -> Optional[ast.Token]:
|
|
39
|
+
"""Token after."""
|
|
40
|
+
if not isinstance(self.ir, ast.Module):
|
|
41
|
+
raise self.ice("IR must be module. Impossible")
|
|
42
|
+
if self.ir.terminals.index(node) == len(self.ir.terminals) - 1:
|
|
43
|
+
return None
|
|
44
|
+
return self.ir.terminals[self.ir.terminals.index(node) + 1]
|
|
45
|
+
|
|
30
46
|
def indent_str(self) -> str:
|
|
31
47
|
"""Return string for indent."""
|
|
32
48
|
return " " * self.indent_size * self.indent_level
|
|
@@ -196,7 +212,7 @@ class JacFormatPass(Pass):
|
|
|
196
212
|
items: list[T],
|
|
197
213
|
"""
|
|
198
214
|
prev_token = None
|
|
199
|
-
for
|
|
215
|
+
for stmt in node.kid:
|
|
200
216
|
if isinstance(node.parent, (ast.EnumDef, ast.Enum)) and stmt.gen.jac == ",":
|
|
201
217
|
self.indent_level -= 1
|
|
202
218
|
self.emit_ln(node, f"{stmt.gen.jac}")
|
|
@@ -220,40 +236,15 @@ class JacFormatPass(Pass):
|
|
|
220
236
|
self.emit_ln(node, "")
|
|
221
237
|
self.indent_level += 1
|
|
222
238
|
if stmt.name == Tok.LBRACE:
|
|
223
|
-
|
|
224
|
-
if isinstance(next_kid, ast.CommentToken) and next_kid.is_inline:
|
|
225
|
-
self.emit(node, f" {stmt.value}")
|
|
226
|
-
else:
|
|
227
|
-
self.emit(node, f" {stmt.value}")
|
|
239
|
+
self.emit(node, f" {stmt.value}")
|
|
228
240
|
elif stmt.name == Tok.RBRACE:
|
|
229
241
|
if self.indent_level > 0:
|
|
230
242
|
self.indent_level -= 1
|
|
231
243
|
if stmt.parent and stmt.parent.gen.jac.strip() == "{":
|
|
232
|
-
self.emit_ln(node, stmt.gen.jac.strip())
|
|
233
|
-
elif (
|
|
234
|
-
stmt.parent
|
|
235
|
-
and stmt.parent.parent
|
|
236
|
-
and isinstance(
|
|
237
|
-
stmt.parent.parent,
|
|
238
|
-
(ast.ElseIf, ast.IfStmt, ast.IterForStmt, ast.TryStmt),
|
|
239
|
-
)
|
|
240
|
-
):
|
|
241
244
|
self.emit(node, f"{stmt.value}")
|
|
242
245
|
else:
|
|
243
|
-
|
|
244
|
-
node.kid[i + 1]
|
|
245
|
-
if i < (len(node.kid) - 1)
|
|
246
|
-
else ast.EmptyToken()
|
|
247
|
-
)
|
|
248
|
-
if (
|
|
249
|
-
isinstance(next_kid, ast.CommentToken)
|
|
250
|
-
and next_kid.is_inline
|
|
251
|
-
):
|
|
252
|
-
self.emit(node, f" {stmt.value}")
|
|
253
|
-
elif not (node.gen.jac).endswith("\n"):
|
|
254
|
-
self.indent_level -= 1
|
|
246
|
+
if not (node.gen.jac).endswith("\n"):
|
|
255
247
|
self.emit_ln(node, "")
|
|
256
|
-
self.indent_level += 1
|
|
257
248
|
self.emit(node, f"{stmt.value}")
|
|
258
249
|
else:
|
|
259
250
|
self.emit(node, f"{stmt.value}")
|
|
@@ -1392,8 +1383,12 @@ class JacFormatPass(Pass):
|
|
|
1392
1383
|
self.emit(node, i.gen.jac)
|
|
1393
1384
|
if isinstance(prev_token, ast.Semi):
|
|
1394
1385
|
self.emit_ln(node, "")
|
|
1386
|
+
elif (tok := self.token_before(i)) and (i.line_no - tok.line_no > 1):
|
|
1387
|
+
self.emit_ln(node, "")
|
|
1388
|
+
self.emit_ln(node, i.gen.jac)
|
|
1395
1389
|
else:
|
|
1396
1390
|
self.emit_ln(node, i.gen.jac)
|
|
1391
|
+
self.emit_ln(node, "")
|
|
1397
1392
|
elif isinstance(i, ast.Semi):
|
|
1398
1393
|
self.emit(node, f"{i.gen.jac} ")
|
|
1399
1394
|
elif isinstance(i, ast.SubNodeList) and i.gen.jac.startswith("@"):
|
jaclang/compiler/semtable.py
CHANGED
|
@@ -127,9 +127,11 @@ class SemRegistry:
|
|
|
127
127
|
break
|
|
128
128
|
return i
|
|
129
129
|
|
|
130
|
-
def pp(self) ->
|
|
130
|
+
def pp(self) -> str:
|
|
131
131
|
"""Pretty print the registry."""
|
|
132
|
+
ret_str = ""
|
|
132
133
|
for k, v in self.registry.items():
|
|
133
|
-
|
|
134
|
+
ret_str += f"{k}\n"
|
|
134
135
|
for i in v:
|
|
135
|
-
|
|
136
|
+
ret_str += f" {i.name} {i.type} {i.semstr}\n"
|
|
137
|
+
return ret_str
|