jaclang 0.4.7__py3-none-any.whl → 0.5.0__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.

Files changed (152) hide show
  1. jaclang/__init__.py +5 -2
  2. jaclang/cli/cli.py +56 -8
  3. jaclang/cli/cmdreg.py +16 -9
  4. jaclang/compiler/__jac_gen__/jac_parser.py +11 -15
  5. jaclang/compiler/absyntree.py +53 -19
  6. jaclang/compiler/codeloc.py +3 -1
  7. jaclang/compiler/{transpiler.py → compile.py} +3 -2
  8. jaclang/compiler/constant.py +4 -0
  9. jaclang/compiler/parser.py +156 -108
  10. jaclang/compiler/passes/ir_pass.py +1 -0
  11. jaclang/compiler/passes/main/__init__.py +2 -1
  12. jaclang/compiler/passes/main/def_impl_match_pass.py +1 -0
  13. jaclang/compiler/passes/main/def_use_pass.py +1 -0
  14. jaclang/compiler/passes/main/import_pass.py +18 -18
  15. jaclang/compiler/passes/main/pyast_gen_pass.py +1228 -853
  16. jaclang/compiler/passes/main/pyast_load_pass.py +3 -1
  17. jaclang/compiler/passes/main/pybc_gen_pass.py +46 -0
  18. jaclang/compiler/passes/main/pyout_pass.py +6 -7
  19. jaclang/compiler/passes/main/schedules.py +5 -9
  20. jaclang/compiler/passes/main/sub_node_tab_pass.py +1 -0
  21. jaclang/compiler/passes/main/sym_tab_build_pass.py +21 -9
  22. jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +2 -1
  23. jaclang/compiler/passes/main/tests/test_def_use_pass.py +2 -1
  24. jaclang/compiler/passes/main/tests/test_import_pass.py +2 -1
  25. jaclang/compiler/passes/main/tests/test_pyast_build_pass.py +1 -0
  26. jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +15 -38
  27. jaclang/compiler/passes/main/tests/test_pybc_gen_pass.py +25 -0
  28. jaclang/compiler/passes/main/tests/test_sub_node_pass.py +1 -1
  29. jaclang/compiler/passes/main/tests/test_sym_tab_build_pass.py +2 -1
  30. jaclang/compiler/passes/main/tests/test_type_check_pass.py +17 -1
  31. jaclang/compiler/passes/main/type_check_pass.py +9 -6
  32. jaclang/compiler/passes/tool/__init__.py +1 -0
  33. jaclang/compiler/passes/tool/ast_printer_pass.py +1 -0
  34. jaclang/compiler/passes/tool/fuse_comments_pass.py +1 -1
  35. jaclang/compiler/passes/tool/jac_formatter_pass.py +69 -32
  36. jaclang/compiler/passes/tool/schedules.py +1 -0
  37. jaclang/compiler/passes/tool/sym_tab_printer_pass.py +1 -0
  38. jaclang/compiler/passes/tool/tests/test_ast_print_pass.py +2 -1
  39. jaclang/compiler/passes/tool/tests/test_fuse_comments_pass.py +1 -0
  40. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +4 -3
  41. jaclang/compiler/passes/tool/tests/test_symtab_print_pass.py +2 -1
  42. jaclang/compiler/passes/transform.py +1 -0
  43. jaclang/compiler/passes/utils/mypy_ast_build.py +203 -17
  44. jaclang/compiler/symtable.py +1 -0
  45. jaclang/compiler/tests/test_importer.py +3 -2
  46. jaclang/compiler/tests/test_parser.py +1 -0
  47. jaclang/compiler/tests/test_workspace.py +1 -0
  48. jaclang/compiler/workspace.py +18 -5
  49. jaclang/core/construct.py +9 -32
  50. jaclang/{compiler → core}/importer.py +95 -85
  51. jaclang/core/utils.py +17 -12
  52. jaclang/plugin/__init__.py +1 -0
  53. jaclang/plugin/default.py +145 -43
  54. jaclang/plugin/feature.py +65 -19
  55. jaclang/plugin/spec.py +56 -34
  56. jaclang/plugin/tests/test_features.py +9 -0
  57. jaclang/utils/helpers.py +1 -0
  58. jaclang/utils/lang_tools.py +13 -19
  59. jaclang/utils/tests/test_lang_tools.py +2 -1
  60. jaclang/utils/treeprinter.py +2 -1
  61. jaclang/vendor/lark/common.py +3 -1
  62. jaclang/vendor/lark/lexer.py +6 -12
  63. jaclang/vendor/lark/parsers/lalr_parser.py +1 -0
  64. jaclang/vendor/mypy/applytype.py +2 -1
  65. jaclang/vendor/mypy/binder.py +1 -1
  66. jaclang/vendor/mypy/build.py +7 -9
  67. jaclang/vendor/mypy/checker.py +57 -33
  68. jaclang/vendor/mypy/checkexpr.py +42 -29
  69. jaclang/vendor/mypy/checkmember.py +13 -1
  70. jaclang/vendor/mypy/checkpattern.py +1 -1
  71. jaclang/vendor/mypy/checkstrformat.py +2 -4
  72. jaclang/vendor/mypy/constraints.py +10 -5
  73. jaclang/vendor/mypy/dmypy_server.py +3 -3
  74. jaclang/vendor/mypy/dmypy_util.py +62 -3
  75. jaclang/vendor/mypy/errors.py +1 -1
  76. jaclang/vendor/mypy/evalexpr.py +1 -0
  77. jaclang/vendor/mypy/expandtype.py +29 -29
  78. jaclang/vendor/mypy/fastparse.py +51 -31
  79. jaclang/vendor/mypy/inspections.py +5 -3
  80. jaclang/vendor/mypy/join.py +4 -4
  81. jaclang/vendor/mypy/main.py +6 -6
  82. jaclang/vendor/mypy/message_registry.py +1 -2
  83. jaclang/vendor/mypy/messages.py +31 -23
  84. jaclang/vendor/mypy/metastore.py +1 -2
  85. jaclang/vendor/mypy/modulefinder.py +2 -22
  86. jaclang/vendor/mypy/nodes.py +22 -20
  87. jaclang/vendor/mypy/options.py +4 -0
  88. jaclang/vendor/mypy/parse.py +6 -2
  89. jaclang/vendor/mypy/patterns.py +6 -6
  90. jaclang/vendor/mypy/plugin.py +3 -1
  91. jaclang/vendor/mypy/plugins/attrs.py +52 -10
  92. jaclang/vendor/mypy/plugins/common.py +2 -1
  93. jaclang/vendor/mypy/plugins/enums.py +3 -2
  94. jaclang/vendor/mypy/plugins/functools.py +1 -0
  95. jaclang/vendor/mypy/renaming.py +1 -1
  96. jaclang/vendor/mypy/report.py +15 -15
  97. jaclang/vendor/mypy/semanal.py +22 -13
  98. jaclang/vendor/mypy/semanal_enum.py +1 -1
  99. jaclang/vendor/mypy/semanal_namedtuple.py +1 -2
  100. jaclang/vendor/mypy/semanal_shared.py +3 -6
  101. jaclang/vendor/mypy/semanal_typeddict.py +16 -5
  102. jaclang/vendor/mypy/server/astdiff.py +15 -9
  103. jaclang/vendor/mypy/server/astmerge.py +5 -5
  104. jaclang/vendor/mypy/stats.py +0 -5
  105. jaclang/vendor/mypy/stubdoc.py +1 -1
  106. jaclang/vendor/mypy/stubgen.py +12 -21
  107. jaclang/vendor/mypy/stubgenc.py +16 -8
  108. jaclang/vendor/mypy/stubtest.py +57 -48
  109. jaclang/vendor/mypy/stubutil.py +28 -15
  110. jaclang/vendor/mypy/subtypes.py +4 -4
  111. jaclang/vendor/mypy/test/helpers.py +2 -2
  112. jaclang/vendor/mypy/test/meta/test_parse_data.py +1 -0
  113. jaclang/vendor/mypy/test/meta/test_update_data.py +1 -0
  114. jaclang/vendor/mypy/test/testargs.py +1 -0
  115. jaclang/vendor/mypy/test/testcheck.py +4 -1
  116. jaclang/vendor/mypy/test/testconstraints.py +25 -7
  117. jaclang/vendor/mypy/test/testerrorstream.py +1 -0
  118. jaclang/vendor/mypy/test/testformatter.py +2 -2
  119. jaclang/vendor/mypy/test/testparse.py +6 -4
  120. jaclang/vendor/mypy/test/testpythoneval.py +1 -0
  121. jaclang/vendor/mypy/test/testreports.py +1 -0
  122. jaclang/vendor/mypy/test/teststubgen.py +1 -2
  123. jaclang/vendor/mypy/test/teststubtest.py +98 -4
  124. jaclang/vendor/mypy/test/testtypes.py +1 -1
  125. jaclang/vendor/mypy/test/testutil.py +22 -0
  126. jaclang/vendor/mypy/typeanal.py +302 -158
  127. jaclang/vendor/mypy/typeops.py +22 -13
  128. jaclang/vendor/mypy/types.py +33 -34
  129. jaclang/vendor/mypy/typestate.py +2 -2
  130. jaclang/vendor/mypy/util.py +7 -6
  131. jaclang/vendor/mypy/version.py +1 -1
  132. jaclang/vendor/mypyc/analysis/ircheck.py +1 -0
  133. jaclang/vendor/mypyc/codegen/emitfunc.py +5 -3
  134. jaclang/vendor/mypyc/codegen/emitmodule.py +12 -12
  135. jaclang/vendor/mypyc/codegen/emitwrapper.py +2 -2
  136. jaclang/vendor/mypyc/ir/class_ir.py +10 -6
  137. jaclang/vendor/mypyc/irbuild/builder.py +3 -4
  138. jaclang/vendor/mypyc/irbuild/function.py +5 -3
  139. jaclang/vendor/mypyc/irbuild/nonlocalcontrol.py +1 -2
  140. jaclang/vendor/mypyc/irbuild/prepare.py +6 -6
  141. jaclang/vendor/mypyc/primitives/registry.py +15 -5
  142. jaclang/vendor/mypyc/test/test_run.py +1 -2
  143. jaclang/vendor/mypyc/transform/uninit.py +3 -3
  144. jaclang/vendor/pluggy/_callers.py +1 -0
  145. jaclang/vendor/pluggy/_hooks.py +6 -10
  146. jaclang/vendor/pluggy/_result.py +1 -0
  147. jaclang/vendor/pluggy/_tracing.py +1 -0
  148. {jaclang-0.4.7.dist-info → jaclang-0.5.0.dist-info}/METADATA +1 -1
  149. {jaclang-0.4.7.dist-info → jaclang-0.5.0.dist-info}/RECORD +152 -150
  150. {jaclang-0.4.7.dist-info → jaclang-0.5.0.dist-info}/WHEEL +0 -0
  151. {jaclang-0.4.7.dist-info → jaclang-0.5.0.dist-info}/entry_points.txt +0 -0
  152. {jaclang-0.4.7.dist-info → jaclang-0.5.0.dist-info}/top_level.txt +0 -0
jaclang/core/construct.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Core constructs for Jac Language."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import types
@@ -15,7 +16,7 @@ from jaclang.core.utils import collect_node_connections
15
16
  class ElementAnchor:
16
17
  """Element Anchor."""
17
18
 
18
- obj: Optional[Architype]
19
+ obj: Architype
19
20
 
20
21
 
21
22
  @dataclass(eq=False)
@@ -41,30 +42,6 @@ class NodeAnchor(ObjectAnchor):
41
42
  edg._jac_.attach(self.obj, nd)
42
43
  return self.obj
43
44
 
44
- # def edges_to_nodes(
45
- # self, dir: EdgeDir, filter_type: Optional[type], filter_func: Optional[Callable]
46
- # ) -> list[NodeArchitype]:
47
- # """Get set of nodes connected to this node."""
48
- # filter_func = filter_func if filter_func else lambda x: x
49
- # ret_nodes: list[NodeArchitype] = []
50
- # if dir in [EdgeDir.OUT]:
51
- # edge_list = []
52
- # for x in self.edges[EdgeDir.OUT]:
53
- # if x._jac_.target and (not filter_type or isinstance(x, filter_type)):
54
- # edge_list.append(x)
55
- # new_edge = filter_func(edge_list)
56
- # for i in new_edge:
57
- # ret_nodes.append(i._jac_.target)
58
- # elif dir in [EdgeDir.IN]:
59
- # edge_list = []
60
- # for i in self.edges[EdgeDir.IN]:
61
- # if i._jac_.source and (not filter_type or isinstance(i, filter_type)):
62
- # edge_list.append(i)
63
- # new_edge = filter_func(edge_list)
64
- # for i in new_edge:
65
- # ret_nodes.append(i._jac_.source)
66
- # return ret_nodes
67
-
68
45
  def edges_to_nodes(
69
46
  self, dir: EdgeDir, filter_type: Optional[type], filter_func: Optional[Callable]
70
47
  ) -> list[NodeArchitype]:
@@ -83,8 +60,8 @@ class NodeAnchor(ObjectAnchor):
83
60
 
84
61
  def gen_dot(self, dot_file: Optional[str] = None) -> str:
85
62
  """Generate Dot file for visualizing nodes and edges."""
86
- visited_nodes = set()
87
- connections = set()
63
+ visited_nodes: set[NodeAnchor] = set()
64
+ connections: set[tuple[NodeArchitype, NodeArchitype, str]] = set()
88
65
  unique_node_id_dict = {}
89
66
 
90
67
  collect_node_connections(self, visited_nodes, connections)
@@ -96,7 +73,7 @@ class NodeAnchor(ObjectAnchor):
96
73
 
97
74
  for pair in list(set(connections)):
98
75
  dot_content += (
99
- f"{unique_node_id_dict.get(pair[0])[1]} -> {unique_node_id_dict.get(pair[1])[1]}"
76
+ f"{unique_node_id_dict[pair[0]][1]} -> {unique_node_id_dict[pair[1]][1]}"
100
77
  f' [label="{pair[2]}"];\n'
101
78
  )
102
79
  if dot_file:
@@ -246,7 +223,7 @@ class Architype:
246
223
 
247
224
  def __init__(self) -> None:
248
225
  """Create default architype."""
249
- self._jac_ = ObjectAnchor(obj=self)
226
+ self._jac_: ObjectAnchor = ObjectAnchor(obj=self)
250
227
 
251
228
 
252
229
  class NodeArchitype(Architype):
@@ -254,7 +231,7 @@ class NodeArchitype(Architype):
254
231
 
255
232
  def __init__(self) -> None:
256
233
  """Create node architype."""
257
- self._jac_ = NodeAnchor(obj=self)
234
+ self._jac_: NodeAnchor = NodeAnchor(obj=self)
258
235
 
259
236
 
260
237
  class EdgeArchitype(Architype):
@@ -262,7 +239,7 @@ class EdgeArchitype(Architype):
262
239
 
263
240
  def __init__(self) -> None:
264
241
  """Create edge architype."""
265
- self._jac_ = EdgeAnchor(obj=self)
242
+ self._jac_: EdgeAnchor = EdgeAnchor(obj=self)
266
243
 
267
244
 
268
245
  class WalkerArchitype(Architype):
@@ -270,7 +247,7 @@ class WalkerArchitype(Architype):
270
247
 
271
248
  def __init__(self) -> None:
272
249
  """Create walker architype."""
273
- self._jac_ = WalkerAnchor(obj=self)
250
+ self._jac_: WalkerAnchor = WalkerAnchor(obj=self)
274
251
 
275
252
 
276
253
  class Root(NodeArchitype):
@@ -1,85 +1,95 @@
1
- """Special Imports for Jac Code."""
2
- import inspect
3
- import marshal
4
- import sys
5
- import types
6
- from os import path
7
- from typing import Optional
8
-
9
- from jaclang.compiler.constant import Constants as Con
10
- from jaclang.compiler.transpiler import transpile_jac
11
- from jaclang.utils.log import logging
12
-
13
-
14
- def jac_import(
15
- target: str,
16
- base_path: Optional[str] = None,
17
- cachable: bool = True,
18
- override_name: Optional[str] = None,
19
- ) -> Optional[types.ModuleType]:
20
- """Core Import Process."""
21
- dir_path, file_name = path.split(path.join(*(target.split("."))) + ".jac")
22
-
23
- module_name = path.splitext(file_name)[0]
24
- package_path = dir_path.replace(path.sep, ".")
25
-
26
- if package_path and f"{package_path}.{module_name}" in sys.modules:
27
- return sys.modules[f"{package_path}.{module_name}"]
28
- elif not package_path and module_name in sys.modules:
29
- return sys.modules[module_name]
30
-
31
- if base_path:
32
- caller_dir = path.dirname(base_path) if not path.isdir(base_path) else base_path
33
- else:
34
- frame = inspect.stack()[1]
35
- caller_dir = path.dirname(path.abspath(frame[0].f_code.co_filename))
36
- caller_dir = path.dirname(caller_dir) if target.startswith("..") else caller_dir
37
- caller_dir = path.join(caller_dir, dir_path)
38
-
39
- gen_dir = path.join(caller_dir, Con.JAC_GEN_DIR)
40
- full_target = path.normpath(path.join(caller_dir, file_name))
41
-
42
- py_file_path = path.join(gen_dir, module_name + ".py")
43
- pyc_file_path = path.join(gen_dir, module_name + ".jbc")
44
- if (
45
- cachable
46
- and path.exists(py_file_path)
47
- and path.getmtime(py_file_path) > path.getmtime(full_target)
48
- ):
49
- with open(pyc_file_path, "rb") as f:
50
- codeobj = marshal.load(f)
51
- else:
52
- if error := transpile_jac(full_target):
53
- if error:
54
- for e in error:
55
- print(e)
56
- logging.error(e)
57
- return None
58
- with open(pyc_file_path, "rb") as f:
59
- codeobj = marshal.load(f)
60
-
61
- module_name = override_name if override_name else module_name
62
- module = types.ModuleType(module_name)
63
- module.__file__ = full_target
64
- module.__name__ = module_name
65
-
66
- if package_path:
67
- parts = package_path.split(".")
68
- for i in range(len(parts)):
69
- package_name = ".".join(parts[: i + 1])
70
- if package_name not in sys.modules:
71
- sys.modules[package_name] = types.ModuleType(package_name)
72
-
73
- setattr(sys.modules[package_path], module_name, module)
74
- sys.modules[f"{package_path}.{module_name}"] = module
75
- sys.modules[module_name] = module
76
-
77
- path_added = False
78
- if caller_dir not in sys.path:
79
- sys.path.append(caller_dir)
80
- path_added = True
81
- exec(codeobj, module.__dict__)
82
- if path_added:
83
- sys.path.remove(caller_dir)
84
-
85
- return module
1
+ """Special Imports for Jac Code."""
2
+
3
+ import marshal
4
+ import sys
5
+ import types
6
+ from os import path
7
+ from typing import Optional
8
+
9
+ from jaclang.compiler.absyntree import Module
10
+ from jaclang.compiler.compile import compile_jac
11
+ from jaclang.compiler.constant import Constants as Con
12
+ from jaclang.utils.log import logging
13
+
14
+
15
+ def jac_importer(
16
+ target: str,
17
+ base_path: str,
18
+ cachable: bool = True,
19
+ override_name: Optional[str] = None,
20
+ mod_bundle: Optional[Module] = None,
21
+ ) -> Optional[types.ModuleType]:
22
+ """Core Import Process."""
23
+ dir_path, file_name = path.split(path.join(*(target.split("."))) + ".jac")
24
+
25
+ module_name = path.splitext(file_name)[0]
26
+ package_path = dir_path.replace(path.sep, ".")
27
+
28
+ if package_path and f"{package_path}.{module_name}" in sys.modules:
29
+ return sys.modules[f"{package_path}.{module_name}"]
30
+ elif not package_path and module_name in sys.modules:
31
+ return sys.modules[module_name]
32
+
33
+ caller_dir = path.dirname(base_path) if not path.isdir(base_path) else base_path
34
+ caller_dir = path.dirname(caller_dir) if target.startswith("..") else caller_dir
35
+ caller_dir = path.join(caller_dir, dir_path)
36
+
37
+ full_target = path.normpath(path.join(caller_dir, file_name))
38
+
39
+ if mod_bundle:
40
+ codeobj = (
41
+ mod_bundle.gen.py_bytecode
42
+ if full_target == mod_bundle.loc.mod_path
43
+ else mod_bundle.mod_deps[full_target].gen.py_bytecode
44
+ )
45
+ if isinstance(codeobj, bytes):
46
+ codeobj = marshal.loads(codeobj)
47
+ else:
48
+ gen_dir = path.join(caller_dir, Con.JAC_GEN_DIR)
49
+ py_file_path = path.join(gen_dir, module_name + ".py")
50
+ pyc_file_path = path.join(gen_dir, module_name + ".jbc")
51
+ if (
52
+ cachable
53
+ and path.exists(py_file_path)
54
+ and path.getmtime(py_file_path) > path.getmtime(full_target)
55
+ ):
56
+ with open(pyc_file_path, "rb") as f:
57
+ codeobj = marshal.load(f)
58
+ else:
59
+ if error := compile_jac(full_target):
60
+ if error:
61
+ for e in error:
62
+ print(e)
63
+ logging.error(e)
64
+ return None
65
+ with open(pyc_file_path, "rb") as f:
66
+ codeobj = marshal.load(f)
67
+
68
+ module_name = override_name if override_name else module_name
69
+ module = types.ModuleType(module_name)
70
+ module.__file__ = full_target
71
+ module.__name__ = module_name
72
+ module.__dict__["__jac_mod_bundle__"] = mod_bundle
73
+
74
+ if package_path:
75
+ parts = package_path.split(".")
76
+ for i in range(len(parts)):
77
+ package_name = ".".join(parts[: i + 1])
78
+ if package_name not in sys.modules:
79
+ sys.modules[package_name] = types.ModuleType(package_name)
80
+
81
+ setattr(sys.modules[package_path], module_name, module)
82
+ sys.modules[f"{package_path}.{module_name}"] = module
83
+ sys.modules[module_name] = module
84
+
85
+ path_added = False
86
+ if caller_dir not in sys.path:
87
+ sys.path.append(caller_dir)
88
+ path_added = True
89
+ if not codeobj:
90
+ raise ImportError(f"No bytecode found for {full_target}")
91
+ exec(codeobj, module.__dict__)
92
+ if path_added:
93
+ sys.path.remove(caller_dir)
94
+
95
+ return module
jaclang/core/utils.py CHANGED
@@ -1,15 +1,18 @@
1
1
  """Helper for construct."""
2
+
3
+ from __future__ import annotations
4
+
2
5
  from typing import TYPE_CHECKING
3
6
 
4
7
  from jaclang.compiler.constant import EdgeDir
5
8
 
6
9
 
7
10
  if TYPE_CHECKING:
8
- from jaclang.core.construct import NodeArchitype
11
+ from jaclang.core.construct import NodeAnchor
9
12
 
10
13
 
11
14
  def collect_node_connections(
12
- current_node: "NodeArchitype",
15
+ current_node: NodeAnchor,
13
16
  visited_nodes: set,
14
17
  connections: set,
15
18
  ) -> None:
@@ -20,15 +23,17 @@ def collect_node_connections(
20
23
  in_edges = current_node.edges.get(EdgeDir.IN, [])
21
24
 
22
25
  for edge_ in out_edges:
23
- target__ = edge_._jac_.target
24
- connections.add(
25
- (current_node.obj, target__._jac_.obj, edge_.__class__.__name__)
26
- )
27
- collect_node_connections(target__._jac_, visited_nodes, connections)
26
+ target = edge_._jac_.target
27
+ if target:
28
+ connections.add(
29
+ (current_node.obj, target._jac_.obj, edge_.__class__.__name__)
30
+ )
31
+ collect_node_connections(target._jac_, visited_nodes, connections)
28
32
 
29
33
  for edge_ in in_edges:
30
- source__ = edge_._jac_.source
31
- connections.add(
32
- (source__._jac_.obj, current_node.obj, edge_.__class__.__name__)
33
- )
34
- collect_node_connections(source__._jac_, visited_nodes, connections)
34
+ source = edge_._jac_.source
35
+ if source:
36
+ connections.add(
37
+ (source._jac_.obj, current_node.obj, edge_.__class__.__name__)
38
+ )
39
+ collect_node_connections(source._jac_, visited_nodes, connections)
@@ -1,4 +1,5 @@
1
1
  """Plugin interface for Jac."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from .default import hookimpl
jaclang/plugin/default.py CHANGED
@@ -1,76 +1,174 @@
1
1
  """Jac Language Features."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import os
6
+ import types
5
7
  from dataclasses import dataclass, field
6
8
  from functools import wraps
7
9
  from typing import Any, Callable, Optional, Type
8
10
 
9
- from jaclang import jac_import
10
- from jaclang.plugin.spec import (
11
- ArchBound,
11
+ from jaclang.compiler.absyntree import Module
12
+ from jaclang.compiler.constant import EdgeDir
13
+ from jaclang.core.construct import (
12
14
  Architype,
13
15
  DSFunc,
14
16
  EdgeAnchor,
15
17
  EdgeArchitype,
16
- EdgeDir,
17
18
  GenericEdge,
18
19
  JacTestCheck,
20
+ NodeAnchor,
19
21
  NodeArchitype,
20
- T,
22
+ ObjectAnchor,
23
+ Root,
24
+ WalkerAnchor,
21
25
  WalkerArchitype,
22
26
  root,
23
27
  )
28
+ from jaclang.core.importer import jac_importer
29
+ from jaclang.plugin.feature import JacFeature as Jac
30
+ from jaclang.plugin.spec import T
24
31
 
25
32
 
26
33
  import pluggy
27
34
 
35
+
36
+ __all__ = [
37
+ "EdgeAnchor",
38
+ "GenericEdge",
39
+ "JacTestCheck",
40
+ "NodeAnchor",
41
+ "ObjectAnchor",
42
+ "WalkerAnchor",
43
+ "NodeArchitype",
44
+ "EdgeArchitype",
45
+ "WalkerArchitype",
46
+ "Architype",
47
+ "DSFunc",
48
+ "root",
49
+ "Root",
50
+ "jac_importer",
51
+ "T",
52
+ ]
53
+
54
+
28
55
  hookimpl = pluggy.HookimplMarker("jac")
29
56
 
30
57
 
31
58
  class JacFeatureDefaults:
32
59
  """Jac Feature."""
33
60
 
61
+ pm = pluggy.PluginManager("jac")
62
+
34
63
  @staticmethod
35
64
  @hookimpl
36
65
  def make_architype(
37
- arch_type: str, on_entry: list[DSFunc], on_exit: list[DSFunc]
66
+ cls: type,
67
+ arch_base: Type[Architype],
68
+ on_entry: list[DSFunc],
69
+ on_exit: list[DSFunc],
70
+ ) -> Type[Architype]:
71
+ """Create a new architype."""
72
+ cls = dataclass(eq=False)(cls)
73
+ for i in on_entry + on_exit:
74
+ i.resolve(cls)
75
+ if not issubclass(cls, arch_base):
76
+ cls = type(cls.__name__, (cls, arch_base), {})
77
+ cls._jac_entry_funcs_ = on_entry
78
+ cls._jac_exit_funcs_ = on_exit
79
+ inner_init = cls.__init__
80
+
81
+ @wraps(inner_init)
82
+ def new_init(self: Architype, *args: object, **kwargs: object) -> None:
83
+ inner_init(self, *args, **kwargs)
84
+ arch_base.__init__(self)
85
+
86
+ cls.__init__ = new_init # type: ignore
87
+ return cls
88
+
89
+ @staticmethod
90
+ @hookimpl
91
+ def make_obj(
92
+ on_entry: list[DSFunc], on_exit: list[DSFunc]
38
93
  ) -> Callable[[type], type]:
39
94
  """Create a new architype."""
40
95
 
41
- def decorator(cls: Type[ArchBound]) -> Type[ArchBound]:
96
+ def decorator(cls: Type[Architype]) -> Type[Architype]:
97
+ """Decorate class."""
98
+ cls = Jac.make_architype(
99
+ cls=cls, arch_base=Architype, on_entry=on_entry, on_exit=on_exit
100
+ )
101
+ return cls
102
+
103
+ return decorator
104
+
105
+ @staticmethod
106
+ @hookimpl
107
+ def make_node(
108
+ on_entry: list[DSFunc], on_exit: list[DSFunc]
109
+ ) -> Callable[[type], type]:
110
+ """Create a obj architype."""
111
+
112
+ def decorator(cls: Type[Architype]) -> Type[Architype]:
113
+ """Decorate class."""
114
+ cls = Jac.make_architype(
115
+ cls=cls, arch_base=NodeArchitype, on_entry=on_entry, on_exit=on_exit
116
+ )
117
+ return cls
118
+
119
+ return decorator
120
+
121
+ @staticmethod
122
+ @hookimpl
123
+ def make_edge(
124
+ on_entry: list[DSFunc], on_exit: list[DSFunc]
125
+ ) -> Callable[[type], type]:
126
+ """Create a edge architype."""
127
+
128
+ def decorator(cls: Type[Architype]) -> Type[Architype]:
42
129
  """Decorate class."""
43
- cls = dataclass(eq=False)(cls)
44
- for i in on_entry + on_exit:
45
- i.resolve(cls)
46
-
47
- match arch_type:
48
- case "obj":
49
- arch_cls = Architype
50
- case "node":
51
- arch_cls = NodeArchitype
52
- case "edge":
53
- arch_cls = EdgeArchitype
54
- case "walker":
55
- arch_cls = WalkerArchitype
56
- case _:
57
- raise TypeError("Invalid archetype type")
58
- if not issubclass(cls, arch_cls):
59
- cls = type(cls.__name__, (cls, arch_cls), {})
60
- cls._jac_entry_funcs_ = on_entry
61
- cls._jac_exit_funcs_ = on_exit
62
- inner_init = cls.__init__
63
-
64
- @wraps(inner_init)
65
- def new_init(self: ArchBound, *args: object, **kwargs: object) -> None:
66
- inner_init(self, *args, **kwargs)
67
- arch_cls.__init__(self)
68
-
69
- cls.__init__ = new_init
130
+ cls = Jac.make_architype(
131
+ cls=cls, arch_base=EdgeArchitype, on_entry=on_entry, on_exit=on_exit
132
+ )
70
133
  return cls
71
134
 
72
135
  return decorator
73
136
 
137
+ @staticmethod
138
+ @hookimpl
139
+ def make_walker(
140
+ on_entry: list[DSFunc], on_exit: list[DSFunc]
141
+ ) -> Callable[[type], type]:
142
+ """Create a walker architype."""
143
+
144
+ def decorator(cls: Type[Architype]) -> Type[Architype]:
145
+ """Decorate class."""
146
+ cls = Jac.make_architype(
147
+ cls=cls, arch_base=WalkerArchitype, on_entry=on_entry, on_exit=on_exit
148
+ )
149
+ return cls
150
+
151
+ return decorator
152
+
153
+ @staticmethod
154
+ @hookimpl
155
+ def jac_import(
156
+ target: str,
157
+ base_path: str,
158
+ cachable: bool,
159
+ override_name: Optional[str],
160
+ mod_bundle: Optional[Module],
161
+ ) -> Optional[types.ModuleType]:
162
+ """Core Import Process."""
163
+ result = jac_importer(
164
+ target=target,
165
+ base_path=base_path,
166
+ cachable=cachable,
167
+ override_name=override_name,
168
+ mod_bundle=mod_bundle,
169
+ )
170
+ return result
171
+
74
172
  @staticmethod
75
173
  @hookimpl
76
174
  def create_test(test_fun: Callable) -> Callable:
@@ -86,7 +184,7 @@ class JacFeatureDefaults:
86
184
 
87
185
  @staticmethod
88
186
  @hookimpl
89
- def run_test(filename: str) -> None:
187
+ def run_test(filename: str) -> bool:
90
188
  """Run the test suite in the specified .jac file.
91
189
 
92
190
  :param filename: The path to the .jac file.
@@ -96,10 +194,11 @@ class JacFeatureDefaults:
96
194
  base = base if base else "./"
97
195
  mod_name = mod_name[:-4]
98
196
  JacTestCheck.reset()
99
- jac_import(target=mod_name, base_path=base)
197
+ Jac.jac_import(target=mod_name, base_path=base)
100
198
  JacTestCheck.run_test()
101
199
  else:
102
200
  print("Not a .jac file.")
201
+ return True
103
202
 
104
203
  @staticmethod
105
204
  @hookimpl
@@ -109,15 +208,21 @@ class JacFeatureDefaults:
109
208
 
110
209
  @staticmethod
111
210
  @hookimpl
112
- def has_instance_default(gen_func: Callable) -> list[Any] | dict[Any, Any]:
211
+ def has_instance_default(gen_func: Callable[[], T]) -> T:
113
212
  """Jac's has container default feature."""
114
213
  return field(default_factory=lambda: gen_func())
115
214
 
116
215
  @staticmethod
117
216
  @hookimpl
118
- def spawn_call(op1: Architype, op2: Architype) -> Architype:
217
+ def spawn_call(op1: Architype, op2: Architype) -> bool:
119
218
  """Jac's spawn operator feature."""
120
- return op1._jac_.spawn_call(op2)
219
+ if isinstance(op1, WalkerArchitype):
220
+ op1._jac_.spawn_call(op2)
221
+ elif isinstance(op2, WalkerArchitype):
222
+ op2._jac_.spawn_call(op1)
223
+ else:
224
+ raise TypeError("Invalid walker object")
225
+ return True
121
226
 
122
227
  @staticmethod
123
228
  @hookimpl
@@ -131,10 +236,7 @@ class JacFeatureDefaults:
131
236
  expr: list[NodeArchitype | EdgeArchitype] | NodeArchitype | EdgeArchitype,
132
237
  ) -> bool:
133
238
  """Jac's ignore stmt feature."""
134
- if isinstance(walker, WalkerArchitype):
135
- return walker._jac_.ignore_node(expr)
136
- else:
137
- raise TypeError("Invalid walker object")
239
+ return walker._jac_.ignore_node(expr)
138
240
 
139
241
  @staticmethod
140
242
  @hookimpl