jaclang 0.5.7__py3-none-any.whl → 0.5.9__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 (49) hide show
  1. jaclang/cli/cli.py +113 -7
  2. jaclang/cli/cmdreg.py +12 -0
  3. jaclang/compiler/__init__.py +58 -2
  4. jaclang/compiler/absyntree.py +1775 -61
  5. jaclang/compiler/codeloc.py +7 -0
  6. jaclang/compiler/compile.py +1 -1
  7. jaclang/compiler/constant.py +17 -0
  8. jaclang/compiler/parser.py +134 -112
  9. jaclang/compiler/passes/ir_pass.py +18 -0
  10. jaclang/compiler/passes/main/__init__.py +2 -0
  11. jaclang/compiler/passes/main/def_impl_match_pass.py +19 -3
  12. jaclang/compiler/passes/main/def_use_pass.py +1 -1
  13. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +357 -0
  14. jaclang/compiler/passes/main/import_pass.py +7 -3
  15. jaclang/compiler/passes/main/pyast_gen_pass.py +350 -109
  16. jaclang/compiler/passes/main/pyast_load_pass.py +1779 -206
  17. jaclang/compiler/passes/main/registry_pass.py +126 -0
  18. jaclang/compiler/passes/main/schedules.py +4 -1
  19. jaclang/compiler/passes/main/sym_tab_build_pass.py +20 -28
  20. jaclang/compiler/passes/main/tests/test_pyast_build_pass.py +14 -5
  21. jaclang/compiler/passes/main/tests/test_registry_pass.py +39 -0
  22. jaclang/compiler/passes/main/tests/test_sym_tab_build_pass.py +8 -8
  23. jaclang/compiler/passes/main/tests/test_typeinfo_pass.py +7 -0
  24. jaclang/compiler/passes/main/type_check_pass.py +0 -1
  25. jaclang/compiler/passes/tool/jac_formatter_pass.py +8 -17
  26. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +65 -0
  27. jaclang/compiler/passes/utils/mypy_ast_build.py +28 -14
  28. jaclang/compiler/symtable.py +23 -2
  29. jaclang/compiler/tests/test_parser.py +53 -0
  30. jaclang/compiler/workspace.py +52 -26
  31. jaclang/core/aott.py +193 -28
  32. jaclang/core/construct.py +59 -2
  33. jaclang/core/registry.py +115 -0
  34. jaclang/core/utils.py +25 -0
  35. jaclang/plugin/default.py +108 -26
  36. jaclang/plugin/feature.py +22 -4
  37. jaclang/plugin/spec.py +13 -7
  38. jaclang/utils/helpers.py +66 -3
  39. jaclang/utils/lang_tools.py +6 -38
  40. jaclang/utils/test.py +1 -0
  41. jaclang/utils/tests/test_lang_tools.py +11 -14
  42. jaclang/utils/treeprinter.py +10 -2
  43. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/METADATA +1 -1
  44. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/RECORD +47 -43
  45. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/WHEEL +1 -1
  46. jaclang/compiler/__jac_gen__/__init__.py +0 -0
  47. jaclang/compiler/__jac_gen__/jac_parser.py +0 -4069
  48. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/entry_points.txt +0 -0
  49. {jaclang-0.5.7.dist-info → jaclang-0.5.9.dist-info}/top_level.txt +0 -0
@@ -9,7 +9,7 @@ body field.
9
9
  import jaclang.compiler.absyntree as ast
10
10
  from jaclang.compiler.passes import Pass
11
11
  from jaclang.compiler.passes.main import SubNodeTabPass
12
- from jaclang.compiler.symtable import SymbolTable, SymbolType
12
+ from jaclang.compiler.symtable import Symbol, SymbolTable, SymbolType
13
13
 
14
14
 
15
15
  class DeclDefMatchPass(Pass):
@@ -28,6 +28,14 @@ class DeclDefMatchPass(Pass):
28
28
  """Rebuild sub node table."""
29
29
  self.ir = SubNodeTabPass(input_ir=self.ir, prior=self).ir
30
30
 
31
+ def defn_lookup(self, lookup: Symbol) -> ast.AstImplNeedingNode | None:
32
+ """Lookup a definition in a symbol table."""
33
+ for defn in range(len(lookup.defn)):
34
+ candidate = lookup.defn[len(lookup.defn) - (defn + 1)]
35
+ if isinstance(candidate, ast.AstImplNeedingNode) and candidate.needs_impl:
36
+ return candidate
37
+ return None
38
+
31
39
  def connect_def_impl(self, sym_tab: SymbolTable) -> None:
32
40
  """Connect Decls and Defs."""
33
41
  for sym in sym_tab.tab.values():
@@ -35,7 +43,11 @@ class DeclDefMatchPass(Pass):
35
43
  # currently strips the type info from impls
36
44
  arch_refs = [x[3:] for x in sym.sym_name.split(".")]
37
45
  lookup = sym_tab.lookup(arch_refs[0])
38
- decl_node = lookup.decl if lookup else None
46
+ decl_node = (
47
+ self.defn_lookup(lookup)
48
+ if len(arch_refs) == 1 and lookup
49
+ else lookup.defn[-1] if lookup else None
50
+ )
39
51
  for name in arch_refs[1:]:
40
52
  if decl_node:
41
53
  lookup = (
@@ -43,7 +55,11 @@ class DeclDefMatchPass(Pass):
43
55
  if decl_node.sym_tab
44
56
  else None
45
57
  )
46
- decl_node = lookup.decl if lookup else None
58
+ decl_node = (
59
+ self.defn_lookup(lookup)
60
+ if len(arch_refs) == 1 and lookup
61
+ else lookup.defn[-1] if lookup else None
62
+ )
47
63
  else:
48
64
  break
49
65
  if not decl_node:
@@ -73,7 +73,7 @@ class DefUsePass(SymTabPass):
73
73
  ):
74
74
  self.def_insert(
75
75
  node,
76
- single_use="has var",
76
+ single_decl="has var",
77
77
  access_spec=node.parent.parent,
78
78
  )
79
79
  else:
@@ -0,0 +1,357 @@
1
+ """Integrate mypy infrastructure into Jac.
2
+
3
+ This is used to call mypy type checking into Jac files by integrating
4
+ mypy apis into Jac and use jac py ast in it.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import os
10
+ import traceback
11
+ from typing import Callable, TypeVar
12
+
13
+ import jaclang.compiler.absyntree as ast
14
+ from jaclang.compiler.passes import Pass
15
+ from jaclang.utils.helpers import pascal_to_snake
16
+
17
+ import mypy.nodes as MypyNode # noqa N812
18
+ import mypy.types as MypyTypes # noqa N812
19
+
20
+
21
+ T = TypeVar("T", bound=ast.AstSymbolNode)
22
+
23
+
24
+ class FuseTypeInfoPass(Pass):
25
+ """Python and bytecode file self.__debug_printing pass."""
26
+
27
+ def __debug_print(self, *argv: object) -> None:
28
+ if "FuseTypeInfoDebug" in os.environ:
29
+ print("FuseTypeInfo::", *argv)
30
+
31
+ def __call_type_handler(
32
+ self, node: ast.AstSymbolNode, mypy_type: MypyTypes.ProperType
33
+ ) -> None:
34
+ mypy_type_name = pascal_to_snake(mypy_type.__class__.__name__)
35
+ type_handler_name = f"get_type_from_{mypy_type_name}"
36
+ if hasattr(self, type_handler_name):
37
+ getattr(self, type_handler_name)(node, mypy_type)
38
+ else:
39
+ self.__debug_print(
40
+ f'{node.loc}"MypyTypes::{mypy_type.__class__.__name__}" isn\'t supported yet'
41
+ )
42
+
43
+ def __set_sym_table_link(self, node: ast.AstSymbolNode) -> None:
44
+ typ = node.sym_info.typ.split(".")
45
+ typ_sym_table = self.ir.sym_tab
46
+ if typ_sym_table and typ[0] == typ_sym_table.name:
47
+ for i in typ[1:]:
48
+ f = typ_sym_table.find_scope(i)
49
+ if f:
50
+ typ_sym_table = f
51
+
52
+ if typ_sym_table != self.ir.sym_tab:
53
+ node.sym_info.typ_sym_table = typ_sym_table
54
+
55
+ @staticmethod
56
+ def __handle_node(
57
+ func: Callable[[FuseTypeInfoPass, T], None]
58
+ ) -> Callable[[FuseTypeInfoPass, T], None]:
59
+ def node_handler(self: FuseTypeInfoPass, node: T) -> None:
60
+ if not isinstance(node, ast.AstSymbolNode):
61
+ print(f"Warning {node.__class__.__name__} is not an AstSymbolNode")
62
+
63
+ try:
64
+ jac_node_str = f'jac node "{node.loc}::{node.__class__.__name__}'
65
+ if hasattr(node, "value"):
66
+ jac_node_str += f'::{node.value}"'
67
+ else:
68
+ jac_node_str += '"'
69
+
70
+ # Jac node has only one mypy node linked to it
71
+ if len(node.gen.mypy_ast) == 1:
72
+ func(self, node)
73
+ self.__set_sym_table_link(node)
74
+
75
+ # Jac node has multiple mypy nodes linked to it
76
+ elif len(node.gen.mypy_ast) > 1:
77
+ # Checking that these nodes are duplicate or not
78
+ temp = []
79
+ for n in node.gen.mypy_ast:
80
+ n_id = f"{type(node)}"
81
+ n_id += f"::{n.line}::{n.column}"
82
+ n_id += f" - {n.end_line}::{n.end_column}"
83
+ if n_id not in temp:
84
+ temp.append(n_id)
85
+
86
+ # Check the number of unique mypy nodes linked
87
+ if len(temp) > 1:
88
+ self.__debug_print(
89
+ jac_node_str, "has multiple mypy nodes associated to it"
90
+ )
91
+ else:
92
+ # self.__debug_print(jac_node_str, "has duplicate mypy nodes associated to it")
93
+ func(self, node)
94
+ self.__set_sym_table_link(node)
95
+
96
+ # Jac node doesn't have mypy nodes linked to it
97
+ else:
98
+ self.__debug_print(
99
+ jac_node_str, "doesn't have mypy node associated to it"
100
+ )
101
+
102
+ except AttributeError as e:
103
+ self.__debug_print(
104
+ f'Internal error happened while parsing "{e.obj.__class__.__name__}"'
105
+ )
106
+ traceback.print_exc()
107
+ print(e)
108
+
109
+ return node_handler
110
+
111
+ def enter_import(self, node: ast.Import) -> None:
112
+ """Pass handler for import nodes."""
113
+ # Pruning the import nodes
114
+ self.prune()
115
+
116
+ @__handle_node
117
+ def enter_name(self, node: ast.NameSpec) -> None:
118
+ """Pass handler for name nodes."""
119
+ mypy_node = node.gen.mypy_ast[0]
120
+
121
+ if hasattr(mypy_node, "node"):
122
+ # orig_node = mypy_node
123
+ mypy_node = mypy_node.node
124
+
125
+ if isinstance(mypy_node, (MypyNode.Var, MypyNode.FuncDef)):
126
+ self.__call_type_handler(node, mypy_node.type)
127
+
128
+ elif isinstance(mypy_node, MypyNode.MypyFile):
129
+ node.sym_info = ast.SymbolInfo("types.ModuleType")
130
+
131
+ elif isinstance(mypy_node, MypyNode.TypeInfo):
132
+ node.sym_info = ast.SymbolInfo(mypy_node.fullname)
133
+
134
+ elif isinstance(mypy_node, MypyNode.OverloadedFuncDef):
135
+ self.__call_type_handler(node, mypy_node.items[0].func.type)
136
+
137
+ else:
138
+ self.__debug_print(
139
+ f'"{node.loc}::{node.__class__.__name__}" mypy (with node attr) node isn\'t supported',
140
+ type(mypy_node),
141
+ )
142
+
143
+ else:
144
+ if isinstance(mypy_node, MypyNode.ClassDef):
145
+ node.sym_info.typ = mypy_node.fullname
146
+ self.__set_sym_table_link(node)
147
+ elif isinstance(mypy_node, MypyNode.FuncDef):
148
+ self.__call_type_handler(node, mypy_node.type)
149
+ elif isinstance(mypy_node, MypyNode.Argument):
150
+ self.__call_type_handler(node, mypy_node.variable.type)
151
+ else:
152
+ self.__debug_print(
153
+ f'"{node.loc}::{node.__class__.__name__}" mypy node isn\'t supported',
154
+ type(mypy_node),
155
+ )
156
+
157
+ @__handle_node
158
+ def enter_module_path(self, node: ast.ModulePath) -> None:
159
+ """Pass handler for ModulePath nodes."""
160
+ self.__debug_print("Getting type not supported in", type(node))
161
+
162
+ @__handle_node
163
+ def enter_module_item(self, node: ast.ModuleItem) -> None:
164
+ """Pass handler for ModuleItem nodes."""
165
+ self.__debug_print("Getting type not supported in", type(node))
166
+
167
+ @__handle_node
168
+ def enter_architype(self, node: ast.Architype) -> None:
169
+ """Pass handler for Architype nodes."""
170
+ self.__debug_print("Getting type not supported in", type(node))
171
+
172
+ @__handle_node
173
+ def enter_arch_def(self, node: ast.ArchDef) -> None:
174
+ """Pass handler for ArchDef nodes."""
175
+ self.__debug_print("Getting type not supported in", type(node))
176
+
177
+ @__handle_node
178
+ def enter_enum(self, node: ast.Enum) -> None:
179
+ """Pass handler for Enum nodes."""
180
+ self.__debug_print("Getting type not supported in", type(node))
181
+
182
+ @__handle_node
183
+ def enter_enum_def(self, node: ast.EnumDef) -> None:
184
+ """Pass handler for EnumDef nodes."""
185
+ self.__debug_print("Getting type not supported in", type(node))
186
+
187
+ @__handle_node
188
+ def enter_ability(self, node: ast.Ability) -> None:
189
+ """Pass handler for Ability nodes."""
190
+ if isinstance(node.gen.mypy_ast[0], MypyNode.FuncDef):
191
+ self.__call_type_handler(node, node.gen.mypy_ast[0].type.ret_type)
192
+ else:
193
+ self.__debug_print(
194
+ f"{node.loc}: Can't get type of an ability from mypy node other than Ability."
195
+ )
196
+
197
+ @__handle_node
198
+ def enter_ability_def(self, node: ast.AbilityDef) -> None:
199
+ """Pass handler for AbilityDef nodes."""
200
+ self.__debug_print("Getting type not supported in", type(node))
201
+
202
+ @__handle_node
203
+ def enter_param_var(self, node: ast.ParamVar) -> None:
204
+ """Pass handler for ParamVar nodes."""
205
+ if isinstance(node.gen.mypy_ast[0], MypyNode.Argument):
206
+ mypy_node: MypyNode.Argument = node.gen.mypy_ast[0]
207
+ if mypy_node.variable.type:
208
+ self.__call_type_handler(node, mypy_node.variable.type)
209
+ else:
210
+ self.__debug_print(
211
+ f"{node.loc}: Can't get parameter value from mypyNode other than Argument"
212
+ )
213
+
214
+ # TODO: support all lhs if needed
215
+ @__handle_node
216
+ def enter_has_var(self, node: ast.HasVar) -> None:
217
+ """Pass handler for HasVar nodes."""
218
+ mypy_node = node.gen.mypy_ast[0]
219
+ if isinstance(mypy_node, MypyNode.AssignmentStmt):
220
+ n = mypy_node.lvalues[0].node
221
+ if isinstance(n, (MypyNode.Var, MypyNode.FuncDef)):
222
+ self.__call_type_handler(node, n.type)
223
+ else:
224
+ self.__debug_print(
225
+ "Getting type of 'AssignmentStmt' is only supported with Var and FuncDef"
226
+ )
227
+ else:
228
+ self.__debug_print(
229
+ "Getting type of 'HasVar' is only supported with AssignmentStmt"
230
+ )
231
+
232
+ @__handle_node
233
+ def enter_multi_string(self, node: ast.MultiString) -> None:
234
+ """Pass handler for MultiString nodes."""
235
+ node.sym_info = ast.SymbolInfo("builtins.str")
236
+
237
+ @__handle_node
238
+ def enter_f_string(self, node: ast.FString) -> None:
239
+ """Pass handler for FString nodes."""
240
+ self.__debug_print("Getting type not supported in", type(node))
241
+
242
+ @__handle_node
243
+ def enter_list_val(self, node: ast.ListVal) -> None:
244
+ """Pass handler for ListVal nodes."""
245
+ self.__debug_print("Getting type not supported in", type(node))
246
+
247
+ @__handle_node
248
+ def enter_set_val(self, node: ast.SetVal) -> None:
249
+ """Pass handler for SetVal nodes."""
250
+ self.__debug_print("Getting type not supported in", type(node))
251
+
252
+ @__handle_node
253
+ def enter_tuple_val(self, node: ast.TupleVal) -> None:
254
+ """Pass handler for TupleVal nodes."""
255
+ self.__debug_print("Getting type not supported in", type(node))
256
+
257
+ @__handle_node
258
+ def enter_dict_val(self, node: ast.DictVal) -> None:
259
+ """Pass handler for DictVal nodes."""
260
+ self.__debug_print("Getting type not supported in", type(node))
261
+
262
+ @__handle_node
263
+ def enter_list_compr(self, node: ast.ListCompr) -> None:
264
+ """Pass handler for ListCompr nodes."""
265
+ self.__debug_print("Getting type not supported in", type(node))
266
+
267
+ @__handle_node
268
+ def enter_dict_compr(self, node: ast.DictCompr) -> None:
269
+ """Pass handler for DictCompr nodes."""
270
+ self.__debug_print("Getting type not supported in", type(node))
271
+
272
+ @__handle_node
273
+ def enter_index_slice(self, node: ast.IndexSlice) -> None:
274
+ """Pass handler for IndexSlice nodes."""
275
+ self.__debug_print("Getting type not supported in", type(node))
276
+
277
+ @__handle_node
278
+ def enter_arch_ref(self, node: ast.ArchRef) -> None:
279
+ """Pass handler for ArchRef nodes."""
280
+ if isinstance(node.gen.mypy_ast[0], MypyNode.ClassDef):
281
+ mypy_node: MypyNode.ClassDef = node.gen.mypy_ast[0]
282
+ node.sym_info.typ = mypy_node.fullname
283
+ self.__set_sym_table_link(node)
284
+ else:
285
+ self.__debug_print(
286
+ f"{node.loc}: Can't get ArchRef value from mypyNode other than ClassDef"
287
+ )
288
+
289
+ @__handle_node
290
+ def enter_special_var_ref(self, node: ast.SpecialVarRef) -> None:
291
+ """Pass handler for SpecialVarRef nodes."""
292
+ return self.enter_name(node)
293
+
294
+ @__handle_node
295
+ def enter_edge_op_ref(self, node: ast.EdgeOpRef) -> None:
296
+ """Pass handler for EdgeOpRef nodes."""
297
+ self.__debug_print("Getting type not supported in", type(node))
298
+
299
+ @__handle_node
300
+ def enter_filter_compr(self, node: ast.FilterCompr) -> None:
301
+ """Pass handler for FilterCompr nodes."""
302
+ self.__debug_print("Getting type not supported in", type(node))
303
+
304
+ @__handle_node
305
+ def enter_assign_compr(self, node: ast.AssignCompr) -> None:
306
+ """Pass handler for AssignCompr nodes."""
307
+ self.__debug_print("Getting type not supported in", type(node))
308
+
309
+ @__handle_node
310
+ def enter_int(self, node: ast.Int) -> None:
311
+ """Pass handler for Int nodes."""
312
+ node.sym_info.typ = "builtins.int"
313
+
314
+ @__handle_node
315
+ def enter_float(self, node: ast.Float) -> None:
316
+ """Pass handler for Float nodes."""
317
+ node.sym_info.typ = "builtins.float"
318
+
319
+ @__handle_node
320
+ def enter_string(self, node: ast.String) -> None:
321
+ """Pass handler for String nodes."""
322
+ node.sym_info.typ = "builtins.str"
323
+
324
+ @__handle_node
325
+ def enter_bool(self, node: ast.Bool) -> None:
326
+ """Pass handler for Bool nodes."""
327
+ node.sym_info.typ = "builtins.bool"
328
+
329
+ @__handle_node
330
+ def enter_builtin_type(self, node: ast.BuiltinType) -> None:
331
+ """Pass handler for BuiltinType nodes."""
332
+ self.__debug_print("Getting type not supported in", type(node))
333
+
334
+ def get_type_from_instance(
335
+ self, node: ast.AstSymbolNode, mypy_type: MypyTypes.Instance
336
+ ) -> None:
337
+ """Get type info from mypy type Instance."""
338
+ node.sym_info = ast.SymbolInfo(str(mypy_type))
339
+
340
+ def get_type_from_callable_type(
341
+ self, node: ast.AstSymbolNode, mypy_type: MypyTypes.CallableType
342
+ ) -> None:
343
+ """Get type info from mypy type CallableType."""
344
+ node.sym_info = ast.SymbolInfo(str(mypy_type.ret_type))
345
+
346
+ # TODO: Which overloaded function to get the return value from?
347
+ def get_type_from_overloaded(
348
+ self, node: ast.AstSymbolNode, mypy_type: MypyTypes.Overloaded
349
+ ) -> None:
350
+ """Get type info from mypy type Overloaded."""
351
+ self.__call_type_handler(node, mypy_type.items[0])
352
+
353
+ def get_type_from_none_type(
354
+ self, node: ast.AstSymbolNode, mypy_type: MypyTypes.NoneType
355
+ ) -> None:
356
+ """Get type info from mypy type NoneType."""
357
+ node.sym_info = ast.SymbolInfo("None")
@@ -47,8 +47,10 @@ class ImportPass(Pass):
47
47
  self.annex_impl(mod)
48
48
  i.sub_module = mod
49
49
  i.add_kids_right([mod], pos_update=False)
50
- # elif i.lang.tag.value == "py":
51
- # self.import_py_module(node=i, mod_path=node.loc.mod_path)
50
+ # elif i.parent.lang.tag.value == "py":
51
+ # mod = self.import_py_module(node=i, mod_path=node.loc.mod_path)
52
+ # i.sub_module = mod
53
+ # i.add_kids_right([mod], pos_update=False)
52
54
  self.enter_module_path(i)
53
55
  SubNodeTabPass(prior=self, input_ir=node)
54
56
  self.annex_impl(node)
@@ -140,9 +142,10 @@ class ImportPass(Pass):
140
142
  if spec.origin in self.import_table:
141
143
  return self.import_table[spec.origin]
142
144
  with open(spec.origin, "r", encoding="utf-8") as f:
145
+ # print(f"\nImporting python module {node.path_str}")
143
146
  mod = PyastBuildPass(
144
147
  input_ir=ast.PythonModuleAst(
145
- py_ast.parse(f.read()), mod_path=mod_path
148
+ py_ast.parse(f.read()), mod_path=spec.origin
146
149
  ),
147
150
  ).ir
148
151
  if mod:
@@ -157,4 +160,5 @@ class ImportPass(Pass):
157
160
  f"Failed to import python module {node.path_str}: {e}",
158
161
  node_override=node,
159
162
  )
163
+ raise e
160
164
  return None