jaclang 0.7.23__py3-none-any.whl → 0.7.25__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 (50) hide show
  1. jaclang/cli/cli.py +46 -29
  2. jaclang/compiler/__init__.py +2 -2
  3. jaclang/compiler/absyntree.py +87 -48
  4. jaclang/compiler/codeloc.py +7 -2
  5. jaclang/compiler/compile.py +10 -3
  6. jaclang/compiler/parser.py +26 -23
  7. jaclang/compiler/passes/ir_pass.py +2 -2
  8. jaclang/compiler/passes/main/def_impl_match_pass.py +46 -0
  9. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +146 -123
  10. jaclang/compiler/passes/main/import_pass.py +6 -2
  11. jaclang/compiler/passes/main/pyast_load_pass.py +36 -35
  12. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -7
  13. jaclang/compiler/passes/main/registry_pass.py +3 -12
  14. jaclang/compiler/passes/main/tests/fixtures/defn_decl_mismatch.jac +19 -0
  15. jaclang/compiler/passes/main/tests/fixtures/fstrings.jac +2 -0
  16. jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +59 -0
  17. jaclang/compiler/passes/main/tests/test_registry_pass.py +2 -10
  18. jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
  19. jaclang/compiler/passes/transform.py +27 -3
  20. jaclang/compiler/passes/utils/mypy_ast_build.py +246 -26
  21. jaclang/compiler/symtable.py +6 -0
  22. jaclang/compiler/tests/test_importer.py +2 -2
  23. jaclang/langserve/engine.py +14 -12
  24. jaclang/langserve/server.py +7 -2
  25. jaclang/langserve/tests/test_server.py +1 -1
  26. jaclang/langserve/utils.py +17 -3
  27. jaclang/plugin/default.py +32 -32
  28. jaclang/plugin/feature.py +2 -2
  29. jaclang/plugin/plugin.md +471 -0
  30. jaclang/plugin/spec.py +2 -1
  31. jaclang/runtimelib/context.py +2 -0
  32. jaclang/runtimelib/importer.py +7 -2
  33. jaclang/runtimelib/machine.py +21 -6
  34. jaclang/settings.py +3 -0
  35. jaclang/tests/fixtures/builtin_dotgen.jac +6 -6
  36. jaclang/tests/fixtures/enum_inside_archtype.jac +16 -11
  37. jaclang/tests/fixtures/expr_type.jac +54 -0
  38. jaclang/tests/fixtures/glob_multivar_statement.jac +15 -0
  39. jaclang/tests/fixtures/registry.jac +20 -8
  40. jaclang/tests/foo/__init__.jac +0 -0
  41. jaclang/tests/main.jac +2 -0
  42. jaclang/tests/test_cli.py +68 -4
  43. jaclang/tests/test_language.py +60 -27
  44. jaclang/utils/helpers.py +92 -14
  45. jaclang/utils/lang_tools.py +6 -2
  46. jaclang/utils/treeprinter.py +4 -2
  47. {jaclang-0.7.23.dist-info → jaclang-0.7.25.dist-info}/METADATA +2 -1
  48. {jaclang-0.7.23.dist-info → jaclang-0.7.25.dist-info}/RECORD +50 -44
  49. {jaclang-0.7.23.dist-info → jaclang-0.7.25.dist-info}/WHEEL +1 -1
  50. {jaclang-0.7.23.dist-info → jaclang-0.7.25.dist-info}/entry_points.txt +0 -0
jaclang/cli/cli.py CHANGED
@@ -6,6 +6,7 @@ import marshal
6
6
  import os
7
7
  import pickle
8
8
  import shutil
9
+ import sys
9
10
  import types
10
11
  from typing import Optional
11
12
 
@@ -38,7 +39,10 @@ def format(path: str, outfile: str = "", debug: bool = False) -> None:
38
39
  def format_file(filename: str) -> None:
39
40
  code_gen_format = jac_file_to_pass(filename, schedule=format_pass)
40
41
  if code_gen_format.errors_had:
41
- print(f"Errors occurred while formatting the file {filename}.")
42
+ print(
43
+ f"Errors occurred while formatting the file {filename}.",
44
+ file=sys.stderr,
45
+ )
42
46
  elif debug:
43
47
  print(code_gen_format.ir.gen.jac)
44
48
  elif outfile:
@@ -52,7 +56,7 @@ def format(path: str, outfile: str = "", debug: bool = False) -> None:
52
56
  if os.path.exists(path):
53
57
  format_file(path)
54
58
  else:
55
- print("File does not exist.")
59
+ print("File does not exist.", file=sys.stderr)
56
60
  elif os.path.isdir(path):
57
61
  count = 0
58
62
  for root, _, files in os.walk(path):
@@ -61,9 +65,9 @@ def format(path: str, outfile: str = "", debug: bool = False) -> None:
61
65
  file_path = os.path.join(root, file)
62
66
  format_file(file_path)
63
67
  count += 1
64
- print(f"Formatted {count} '.jac' files.")
68
+ print(f"Formatted {count} '.jac' files.", file=sys.stderr)
65
69
  else:
66
- print("Not a .jac file or directory.")
70
+ print("Not a .jac file or directory.", file=sys.stderr)
67
71
 
68
72
 
69
73
  @cmd_registry.register
@@ -89,23 +93,30 @@ def run(
89
93
  jctx = ExecutionContext.create(session=session)
90
94
 
91
95
  if filename.endswith(".jac"):
92
- jac_import(
93
- target=mod,
94
- base_path=base,
95
- cachable=cache,
96
- override_name="__main__" if main else None,
97
- )
98
- elif filename.endswith(".jir"):
99
- with open(filename, "rb") as f:
100
- JacMachine(base).attach_program(
101
- JacProgram(mod_bundle=pickle.load(f), bytecode=None)
102
- )
96
+ try:
103
97
  jac_import(
104
98
  target=mod,
105
99
  base_path=base,
106
100
  cachable=cache,
107
101
  override_name="__main__" if main else None,
108
102
  )
103
+ except Exception as e:
104
+ print(e, file=sys.stderr)
105
+ elif filename.endswith(".jir"):
106
+ try:
107
+ with open(filename, "rb") as f:
108
+ JacMachine(base).attach_program(
109
+ JacProgram(mod_bundle=pickle.load(f), bytecode=None, sem_ir=None)
110
+ )
111
+ jac_import(
112
+ target=mod,
113
+ base_path=base,
114
+ cachable=cache,
115
+ override_name="__main__" if main else None,
116
+ )
117
+ except Exception as e:
118
+ print(e, file=sys.stderr)
119
+
109
120
  else:
110
121
  jctx.close()
111
122
  JacMachine.detach()
@@ -145,7 +156,7 @@ def get_object(
145
156
  elif filename.endswith(".jir"):
146
157
  with open(filename, "rb") as f:
147
158
  JacMachine(base).attach_program(
148
- JacProgram(mod_bundle=pickle.load(f), bytecode=None)
159
+ JacProgram(mod_bundle=pickle.load(f), bytecode=None, sem_ir=None)
149
160
  )
150
161
  jac_import(
151
162
  target=mod,
@@ -163,7 +174,7 @@ def get_object(
163
174
  if obj:
164
175
  data = obj.__jac__.__getstate__()
165
176
  else:
166
- print(f"Object with id {id} not found.")
177
+ print(f"Object with id {id} not found.", file=sys.stderr)
167
178
 
168
179
  jctx.close()
169
180
  JacMachine.detach()
@@ -183,7 +194,7 @@ def build(filename: str) -> None:
183
194
  with open(filename[:-4] + ".jir", "wb") as f:
184
195
  pickle.dump(out.ir, f)
185
196
  else:
186
- print("Not a .jac file.")
197
+ print("Not a .jac file.", file=sys.stderr)
187
198
 
188
199
 
189
200
  @cmd_registry.register
@@ -202,10 +213,10 @@ def check(filename: str, print_errs: bool = True) -> None:
202
213
  warnings = len(out.warnings_had)
203
214
  if print_errs:
204
215
  for e in out.errors_had:
205
- print("Error:", e)
216
+ print("Error:", e, file=sys.stderr)
206
217
  print(f"Errors: {errs}, Warnings: {warnings}")
207
218
  else:
208
- print("Not a .jac file.")
219
+ print("Not a .jac file.", file=sys.stderr)
209
220
 
210
221
 
211
222
  @cmd_registry.register
@@ -262,7 +273,7 @@ def enter(
262
273
  elif filename.endswith(".jir"):
263
274
  with open(filename, "rb") as f:
264
275
  JacMachine(base).attach_program(
265
- JacProgram(mod_bundle=pickle.load(f), bytecode=None)
276
+ JacProgram(mod_bundle=pickle.load(f), bytecode=None, sem_ir=None)
266
277
  )
267
278
  ret_module = jac_import(
268
279
  target=mod,
@@ -278,7 +289,7 @@ def enter(
278
289
  if ret_module:
279
290
  (loaded_mod,) = ret_module
280
291
  if not loaded_mod:
281
- print("Errors occurred while importing the module.")
292
+ print("Errors occurred while importing the module.", file=sys.stderr)
282
293
  else:
283
294
  architype = getattr(loaded_mod, entrypoint)(*args)
284
295
 
@@ -344,10 +355,12 @@ def tool(tool: str, args: Optional[list] = None) -> None:
344
355
  else:
345
356
  print(getattr(AstTool(), tool)())
346
357
  except Exception as e:
347
- print(f"Error while running ast tool {tool}, check args: {e}")
358
+ print(
359
+ f"Error while running ast tool {tool}, check args: {e}", file=sys.stderr
360
+ )
348
361
  raise e
349
362
  else:
350
- print(f"Ast tool {tool} not found.")
363
+ print(f"Ast tool {tool} not found.", file=sys.stderr)
351
364
 
352
365
 
353
366
  @cmd_registry.register
@@ -385,9 +398,9 @@ def debug(filename: str, main: bool = True, cache: bool = False) -> None:
385
398
  db.runcall(func)
386
399
  print("Done debugging.")
387
400
  else:
388
- print(f"Error while generating bytecode in {filename}.")
401
+ print(f"Error while generating bytecode in {filename}.", file=sys.stderr)
389
402
  else:
390
- print("Not a .jac file.")
403
+ print("Not a .jac file.", file=sys.stderr)
391
404
 
392
405
 
393
406
  @cmd_registry.register
@@ -458,7 +471,7 @@ def dot(
458
471
  file.write(graph)
459
472
  print(f">>> Graph content saved to {os.path.join(os.getcwd(), file_name)}")
460
473
  else:
461
- print("Not a .jac file.")
474
+ print("Not a .jac file.", file=sys.stderr)
462
475
 
463
476
  jctx.close()
464
477
 
@@ -471,8 +484,12 @@ def py2jac(filename: str) -> None:
471
484
  """
472
485
  if filename.endswith(".py"):
473
486
  with open(filename, "r") as f:
487
+ file_source = f.read()
474
488
  code = PyastBuildPass(
475
- input_ir=ast.PythonModuleAst(ast3.parse(f.read()), mod_path=filename),
489
+ input_ir=ast.PythonModuleAst(
490
+ ast3.parse(file_source),
491
+ orig_src=ast.JacSource(file_source, filename),
492
+ ),
476
493
  ).ir.unparse()
477
494
  print(code)
478
495
  else:
@@ -490,7 +507,7 @@ def jac2py(filename: str) -> None:
490
507
  code = jac_file_to_pass(file_path=filename).ir.gen.py
491
508
  print(code)
492
509
  else:
493
- print("Not a .jac file.")
510
+ print("Not a .jac file.", file=sys.stderr)
494
511
 
495
512
 
496
513
  def start_cli() -> None:
@@ -59,7 +59,7 @@ TOKEN_MAP.update(
59
59
  "KW_OR": "|", "ARROW_BI": "<-->", "ARROW_L": "<--",
60
60
  "ARROW_R": "-->", "ARROW_L_P1": "<-:", "ARROW_R_P2": ":->",
61
61
  "ARROW_L_P2": ":-", "ARROW_R_P1": "-:", "CARROW_BI": "<++>",
62
- "CARROW_L": "<++", "CARROW_R": "++>", "CARROW_L_P1": "<+:",
62
+ "CARROW_L_P1": "<+:", "RSHIFT_EQ": ">>=", "ELLIPSIS": "...",
63
63
  "CARROW_R_P2": ":+>", "CARROW_L_P2": ":+", "CARROW_R_P1": "+:",
64
64
  "PIPE_FWD": "|>", "PIPE_BKWD": "<|", "A_PIPE_FWD": ":>",
65
65
  "A_PIPE_BKWD": "<:", "DOT_FWD": ".>", "STAR_POW": "**",
@@ -68,7 +68,7 @@ TOKEN_MAP.update(
68
68
  "STAR_POW_EQ": "**=", "MUL_EQ": "*=", "FLOOR_DIV_EQ": "//=",
69
69
  "DIV_EQ": "/=", "MOD_EQ": "%=", "BW_AND_EQ": "&=",
70
70
  "BW_OR_EQ": "|=", "BW_XOR_EQ": "^=", "BW_NOT_EQ": "~=",
71
- "LSHIFT_EQ": "<<=", "RSHIFT_EQ": ">>=", "ELLIPSIS": "...",
71
+ "LSHIFT_EQ": "<<=",
72
72
  }
73
73
  )
74
74
  # fmt: on
@@ -139,7 +139,7 @@ class AstNode:
139
139
  return Token(
140
140
  name=name,
141
141
  value=value,
142
- file_path=self.loc.mod_path,
142
+ orig_src=self.loc.orig_src,
143
143
  col_start=self.loc.col_start,
144
144
  col_end=0,
145
145
  line=self.loc.first_line,
@@ -248,9 +248,9 @@ class AstSymbolNode(AstNode):
248
248
  return self.name_spec.py_ctx_func
249
249
 
250
250
  @property
251
- def sym_type(self) -> str:
251
+ def expr_type(self) -> str:
252
252
  """Get symbol type."""
253
- return self.name_spec.sym_type
253
+ return self.name_spec.expr_type
254
254
 
255
255
  @property
256
256
  def type_sym_tab(self) -> Optional[SymbolTable]:
@@ -346,6 +346,32 @@ class WalkerStmtOnlyNode(AstNode):
346
346
  class Expr(AstNode):
347
347
  """Expr node type for Jac Ast."""
348
348
 
349
+ def __init__(self, type_src: Optional[Expr] = None) -> None:
350
+ """Initialize expression node."""
351
+ self.type_src = type_src or self # Only used for ArchRef
352
+ self._sym_type: str = "NoType"
353
+ self._type_sym_tab: Optional[SymbolTable] = None
354
+
355
+ @property
356
+ def expr_type(self) -> str:
357
+ """Get symbol type."""
358
+ return self.type_src._sym_type
359
+
360
+ @expr_type.setter
361
+ def expr_type(self, sym_type: str) -> None:
362
+ """Set symbol type."""
363
+ self.type_src._sym_type = sym_type
364
+
365
+ @property
366
+ def type_sym_tab(self) -> Optional[SymbolTable]:
367
+ """Get type symbol table."""
368
+ return self.type_src._type_sym_tab
369
+
370
+ @type_sym_tab.setter
371
+ def type_sym_tab(self, type_sym_tab: SymbolTable) -> None:
372
+ """Set type symbol table."""
373
+ self.type_src._type_sym_tab = type_sym_tab
374
+
349
375
 
350
376
  class AtomExpr(Expr, AstSymbolStubNode):
351
377
  """AtomExpr node type for Jac Ast."""
@@ -398,7 +424,7 @@ class AstImplOnlyNode(CodeBlockStmt, ElementStmt, AstSymbolNode):
398
424
  def create_impl_name_node(self) -> Name:
399
425
  """Create impl name."""
400
426
  ret = Name(
401
- file_path=self.target.archs[-1].loc.mod_path,
427
+ orig_src=self.target.archs[-1].loc.orig_src,
402
428
  name=Tok.NAME.value,
403
429
  value=self.target.py_resolve_name(),
404
430
  col_start=self.target.archs[0].loc.col_start,
@@ -435,8 +461,7 @@ class NameAtom(AtomExpr, EnumBlockStmt):
435
461
  self._sym_name: str = ""
436
462
  self._sym_category: SymbolType = SymbolType.UNKNOWN
437
463
  self._py_ctx_func: Type[ast3.AST] = ast3.Load
438
- self._sym_type: str = "NoType"
439
- self._type_sym_tab: Optional[SymbolTable] = None
464
+ AtomExpr.__init__(self)
440
465
 
441
466
  @property
442
467
  def sym(self) -> Optional[Symbol]:
@@ -461,7 +486,7 @@ class NameAtom(AtomExpr, EnumBlockStmt):
461
486
  @property
462
487
  def clean_type(self) -> str:
463
488
  """Get clean type."""
464
- ret_type = self.sym_type.replace("builtins.", "").replace("NoType", "")
489
+ ret_type = self.expr_type.replace("builtins.", "").replace("NoType", "")
465
490
  return ret_type
466
491
 
467
492
  @property
@@ -474,26 +499,6 @@ class NameAtom(AtomExpr, EnumBlockStmt):
474
499
  """Set python context function."""
475
500
  self._py_ctx_func = py_ctx_func
476
501
 
477
- @property
478
- def sym_type(self) -> str:
479
- """Get symbol type."""
480
- return self._sym_type
481
-
482
- @sym_type.setter
483
- def sym_type(self, sym_type: str) -> None:
484
- """Set symbol type."""
485
- self._sym_type = sym_type
486
-
487
- @property
488
- def type_sym_tab(self) -> Optional[SymbolTable]:
489
- """Get type symbol table."""
490
- return self._type_sym_tab
491
-
492
- @type_sym_tab.setter
493
- def type_sym_tab(self, type_sym_tab: SymbolTable) -> None:
494
- """Set type symbol table."""
495
- self._type_sym_tab = type_sym_tab
496
-
497
502
  @property
498
503
  def sem_token(self) -> Optional[tuple[SemTokType, SemTokMod]]:
499
504
  """Resolve semantic token."""
@@ -745,7 +750,7 @@ class Test(AstSymbolNode, ElementStmt):
745
750
  name
746
751
  if isinstance(name, Name)
747
752
  else Name(
748
- file_path=name.file_path,
753
+ orig_src=name.orig_src,
749
754
  name=Tok.NAME.value,
750
755
  value=f"_jac_gen_{Test.TEST_COUNT}",
751
756
  col_start=name.loc.col_start,
@@ -1261,6 +1266,9 @@ class Enum(ArchSpec, AstAccessNode, AstImplNeedingNode, ArchBlockStmt):
1261
1266
  res = res and self.semstr.normalize(deep) if self.semstr else res
1262
1267
  res = res and self.decorators.normalize(deep) if self.decorators else res
1263
1268
  new_kid: list[AstNode] = []
1269
+ if self.decorators:
1270
+ new_kid.append(self.gen_token(Tok.DECOR_OP))
1271
+ new_kid.append(self.decorators)
1264
1272
  if self.doc:
1265
1273
  new_kid.append(self.doc)
1266
1274
  new_kid.append(self.gen_token(Tok.KW_ENUM))
@@ -2527,6 +2535,7 @@ class AwaitExpr(Expr):
2527
2535
  """Initialize sync statement node."""
2528
2536
  self.target = target
2529
2537
  AstNode.__init__(self, kid=kid)
2538
+ Expr.__init__(self)
2530
2539
 
2531
2540
  def normalize(self, deep: bool = False) -> bool:
2532
2541
  """Normalize sync statement node."""
@@ -2655,6 +2664,7 @@ class BinaryExpr(Expr):
2655
2664
  self.right = right
2656
2665
  self.op = op
2657
2666
  AstNode.__init__(self, kid=kid)
2667
+ Expr.__init__(self)
2658
2668
 
2659
2669
  def normalize(self, deep: bool = False) -> bool:
2660
2670
  """Normalize ast node."""
@@ -2689,6 +2699,7 @@ class CompareExpr(Expr):
2689
2699
  self.rights = rights
2690
2700
  self.ops = ops
2691
2701
  AstNode.__init__(self, kid=kid)
2702
+ Expr.__init__(self)
2692
2703
 
2693
2704
  def normalize(self, deep: bool = False) -> bool:
2694
2705
  """Normalize ast node."""
@@ -2720,6 +2731,7 @@ class BoolExpr(Expr):
2720
2731
  self.values = values
2721
2732
  self.op = op
2722
2733
  AstNode.__init__(self, kid=kid)
2734
+ Expr.__init__(self)
2723
2735
 
2724
2736
  def normalize(self, deep: bool = False) -> bool:
2725
2737
  """Normalize ast node."""
@@ -2750,6 +2762,7 @@ class LambdaExpr(Expr):
2750
2762
  self.signature = signature
2751
2763
  self.body = body
2752
2764
  AstNode.__init__(self, kid=kid)
2765
+ Expr.__init__(self)
2753
2766
 
2754
2767
  def normalize(self, deep: bool = False) -> bool:
2755
2768
  """Normalize ast node."""
@@ -2782,6 +2795,7 @@ class UnaryExpr(Expr):
2782
2795
  self.operand = operand
2783
2796
  self.op = op
2784
2797
  AstNode.__init__(self, kid=kid)
2798
+ Expr.__init__(self)
2785
2799
 
2786
2800
  def normalize(self, deep: bool = False) -> bool:
2787
2801
  """Normalize ast node."""
@@ -2809,6 +2823,7 @@ class IfElseExpr(Expr):
2809
2823
  self.value = value
2810
2824
  self.else_value = else_value
2811
2825
  AstNode.__init__(self, kid=kid)
2826
+ Expr.__init__(self)
2812
2827
 
2813
2828
  def normalize(self, deep: bool = False) -> bool:
2814
2829
  """Normalize ast node."""
@@ -2839,6 +2854,7 @@ class MultiString(AtomExpr):
2839
2854
  """Initialize multi string expression node."""
2840
2855
  self.strings = strings
2841
2856
  AstNode.__init__(self, kid=kid)
2857
+ Expr.__init__(self)
2842
2858
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.STRING)
2843
2859
 
2844
2860
  def normalize(self, deep: bool = False) -> bool:
@@ -2865,6 +2881,7 @@ class FString(AtomExpr):
2865
2881
  """Initialize fstring expression node."""
2866
2882
  self.parts = parts
2867
2883
  AstNode.__init__(self, kid=kid)
2884
+ Expr.__init__(self)
2868
2885
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.STRING)
2869
2886
 
2870
2887
  def normalize(self, deep: bool = False) -> bool:
@@ -2906,6 +2923,7 @@ class ListVal(AtomExpr):
2906
2923
  """Initialize value node."""
2907
2924
  self.values = values
2908
2925
  AstNode.__init__(self, kid=kid)
2926
+ Expr.__init__(self)
2909
2927
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
2910
2928
 
2911
2929
  def normalize(self, deep: bool = False) -> bool:
@@ -2934,6 +2952,7 @@ class SetVal(AtomExpr):
2934
2952
  """Initialize value node."""
2935
2953
  self.values = values
2936
2954
  AstNode.__init__(self, kid=kid)
2955
+ Expr.__init__(self)
2937
2956
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
2938
2957
 
2939
2958
  def normalize(self, deep: bool = False) -> bool:
@@ -2962,6 +2981,7 @@ class TupleVal(AtomExpr):
2962
2981
  """Initialize tuple value node."""
2963
2982
  self.values = values
2964
2983
  AstNode.__init__(self, kid=kid)
2984
+ Expr.__init__(self)
2965
2985
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
2966
2986
 
2967
2987
  def normalize(self, deep: bool = False) -> bool:
@@ -3005,6 +3025,7 @@ class DictVal(AtomExpr):
3005
3025
  """Initialize dict expression node."""
3006
3026
  self.kv_pairs = kv_pairs
3007
3027
  AstNode.__init__(self, kid=kid)
3028
+ Expr.__init__(self)
3008
3029
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
3009
3030
 
3010
3031
  def normalize(self, deep: bool = False) -> bool:
@@ -3138,6 +3159,7 @@ class ListCompr(AtomExpr):
3138
3159
  self.out_expr = out_expr
3139
3160
  self.compr = compr
3140
3161
  AstNode.__init__(self, kid=kid)
3162
+ Expr.__init__(self)
3141
3163
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
3142
3164
 
3143
3165
  def normalize(self, deep: bool = False) -> bool:
@@ -3213,6 +3235,7 @@ class DictCompr(AtomExpr):
3213
3235
  self.kv_pair = kv_pair
3214
3236
  self.compr = compr
3215
3237
  AstNode.__init__(self, kid=kid)
3238
+ Expr.__init__(self)
3216
3239
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
3217
3240
 
3218
3241
  def normalize(self, deep: bool = False) -> bool:
@@ -3251,6 +3274,7 @@ class AtomTrailer(Expr):
3251
3274
  self.is_null_ok = is_null_ok
3252
3275
  self.is_genai = is_genai
3253
3276
  AstNode.__init__(self, kid=kid)
3277
+ Expr.__init__(self)
3254
3278
 
3255
3279
  def normalize(self, deep: bool = True) -> bool:
3256
3280
  """Normalize ast node."""
@@ -3296,6 +3320,7 @@ class AtomUnit(Expr):
3296
3320
  """Initialize atom unit expression node."""
3297
3321
  self.value = value
3298
3322
  AstNode.__init__(self, kid=kid)
3323
+ Expr.__init__(self)
3299
3324
 
3300
3325
  def normalize(self, deep: bool = True) -> bool:
3301
3326
  """Normalize ast node."""
@@ -3323,6 +3348,7 @@ class YieldExpr(Expr):
3323
3348
  self.expr = expr
3324
3349
  self.with_from = with_from
3325
3350
  AstNode.__init__(self, kid=kid)
3351
+ Expr.__init__(self)
3326
3352
 
3327
3353
  def normalize(self, deep: bool = False) -> bool:
3328
3354
  """Normalize yield statement node."""
@@ -3354,6 +3380,7 @@ class FuncCall(Expr):
3354
3380
  self.params = params
3355
3381
  self.genai_call = genai_call
3356
3382
  AstNode.__init__(self, kid=kid)
3383
+ Expr.__init__(self)
3357
3384
 
3358
3385
  def normalize(self, deep: bool = True) -> bool:
3359
3386
  """Normalize ast node."""
@@ -3388,6 +3415,7 @@ class IndexSlice(AtomExpr):
3388
3415
  self.step = step
3389
3416
  self.is_range = is_range
3390
3417
  AstNode.__init__(self, kid=kid)
3418
+ Expr.__init__(self)
3391
3419
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
3392
3420
 
3393
3421
  def normalize(self, deep: bool = True) -> bool:
@@ -3430,6 +3458,7 @@ class ArchRef(AtomExpr):
3430
3458
  self.arch_name = arch_name
3431
3459
  self.arch_type = arch_type
3432
3460
  AstNode.__init__(self, kid=kid)
3461
+ Expr.__init__(self, type_src=arch_name)
3433
3462
  AstSymbolNode.__init__(
3434
3463
  self,
3435
3464
  sym_name=arch_name.sym_name,
@@ -3460,6 +3489,7 @@ class EdgeRefTrailer(Expr):
3460
3489
  self.chain = chain
3461
3490
  self.edges_only = edges_only
3462
3491
  AstNode.__init__(self, kid=kid)
3492
+ Expr.__init__(self)
3463
3493
 
3464
3494
  def normalize(self, deep: bool = True) -> bool:
3465
3495
  """Normalize ast node."""
@@ -3489,6 +3519,7 @@ class EdgeOpRef(WalkerStmtOnlyNode, AtomExpr):
3489
3519
  self.filter_cond = filter_cond
3490
3520
  self.edge_dir = edge_dir
3491
3521
  AstNode.__init__(self, kid=kid)
3522
+ Expr.__init__(self)
3492
3523
  WalkerStmtOnlyNode.__init__(self)
3493
3524
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
3494
3525
 
@@ -3619,6 +3650,7 @@ class FilterCompr(AtomExpr):
3619
3650
  self.f_type = f_type
3620
3651
  self.compares = compares
3621
3652
  AstNode.__init__(self, kid=kid)
3653
+ Expr.__init__(self)
3622
3654
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
3623
3655
 
3624
3656
  def normalize(self, deep: bool = False) -> bool:
@@ -3656,6 +3688,7 @@ class AssignCompr(AtomExpr):
3656
3688
  """Initialize assign compr expression node."""
3657
3689
  self.assigns = assigns
3658
3690
  AstNode.__init__(self, kid=kid)
3691
+ Expr.__init__(self)
3659
3692
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
3660
3693
 
3661
3694
  def normalize(self, deep: bool = False) -> bool:
@@ -3813,7 +3846,7 @@ class MatchWild(MatchPattern):
3813
3846
  self,
3814
3847
  nodes=[
3815
3848
  Name(
3816
- file_path=self.loc.mod_path,
3849
+ orig_src=self.loc.orig_src,
3817
3850
  name=Tok.NAME,
3818
3851
  value="_",
3819
3852
  col_start=self.loc.col_start,
@@ -4023,7 +4056,7 @@ class Token(AstNode):
4023
4056
 
4024
4057
  def __init__(
4025
4058
  self,
4026
- file_path: str,
4059
+ orig_src: JacSource,
4027
4060
  name: str,
4028
4061
  value: str,
4029
4062
  line: int,
@@ -4034,7 +4067,7 @@ class Token(AstNode):
4034
4067
  pos_end: int,
4035
4068
  ) -> None:
4036
4069
  """Initialize token."""
4037
- self.file_path = file_path
4070
+ self.orig_src = orig_src
4038
4071
  self.name = name
4039
4072
  self.value = value
4040
4073
  self.line_no = line
@@ -4059,7 +4092,7 @@ class Name(Token, NameAtom):
4059
4092
 
4060
4093
  def __init__(
4061
4094
  self,
4062
- file_path: str,
4095
+ orig_src: JacSource,
4063
4096
  name: str,
4064
4097
  value: str,
4065
4098
  line: int,
@@ -4076,7 +4109,7 @@ class Name(Token, NameAtom):
4076
4109
  self.is_kwesc = is_kwesc
4077
4110
  Token.__init__(
4078
4111
  self,
4079
- file_path=file_path,
4112
+ orig_src=orig_src,
4080
4113
  name=name,
4081
4114
  value=value,
4082
4115
  line=line,
@@ -4107,7 +4140,7 @@ class Name(Token, NameAtom):
4107
4140
  ) -> Name:
4108
4141
  """Generate name from node."""
4109
4142
  ret = Name(
4110
- file_path=node.loc.mod_path,
4143
+ orig_src=node.loc.orig_src,
4111
4144
  name=Tok.NAME.value,
4112
4145
  value=name_str,
4113
4146
  col_start=node.loc.col_start,
@@ -4134,7 +4167,7 @@ class SpecialVarRef(Name):
4134
4167
  self.orig = var
4135
4168
  Name.__init__(
4136
4169
  self,
4137
- file_path=var.file_path,
4170
+ orig_src=var.orig_src,
4138
4171
  name=var.name,
4139
4172
  value=self.py_resolve_name(), # TODO: This shouldnt be necessary
4140
4173
  line=var.line_no,
@@ -4190,7 +4223,7 @@ class Literal(Token, AtomExpr):
4190
4223
 
4191
4224
  def __init__(
4192
4225
  self,
4193
- file_path: str,
4226
+ orig_src: JacSource,
4194
4227
  name: str,
4195
4228
  value: str,
4196
4229
  line: int,
@@ -4203,7 +4236,7 @@ class Literal(Token, AtomExpr):
4203
4236
  """Initialize token."""
4204
4237
  Token.__init__(
4205
4238
  self,
4206
- file_path=file_path,
4239
+ orig_src=orig_src,
4207
4240
  name=name,
4208
4241
  value=value,
4209
4242
  line=line,
@@ -4214,6 +4247,7 @@ class Literal(Token, AtomExpr):
4214
4247
  pos_end=pos_end,
4215
4248
  )
4216
4249
  AstSymbolStubNode.__init__(self, sym_type=self.SYMBOL_TYPE)
4250
+ Expr.__init__(self)
4217
4251
 
4218
4252
  @property
4219
4253
  def lit_value(
@@ -4278,10 +4312,9 @@ class String(Literal):
4278
4312
  elif self.value.startswith(("'", '"')):
4279
4313
  repr_str = self.value.encode().decode("unicode_escape")
4280
4314
  if (
4281
- self.value.startswith('"""')
4282
- and self.value.endswith('"""')
4283
- and not self.find_parent_of_type(FString)
4284
- ):
4315
+ (self.value.startswith('"""') and self.value.endswith('"""'))
4316
+ or (self.value.startswith("'''") and self.value.endswith("'''"))
4317
+ ) and not self.find_parent_of_type(FString):
4285
4318
  return repr_str[3:-3]
4286
4319
  if (not self.find_parent_of_type(FString)) or (
4287
4320
  not (
@@ -4343,11 +4376,11 @@ class Ellipsis(Literal):
4343
4376
  class EmptyToken(Token):
4344
4377
  """EmptyToken node type for Jac Ast."""
4345
4378
 
4346
- def __init__(self, file_path: str = "") -> None:
4379
+ def __init__(self, orig_src: JacSource | None = None) -> None:
4347
4380
  """Initialize empty token."""
4348
4381
  super().__init__(
4349
4382
  name="EmptyToken",
4350
- file_path=file_path,
4383
+ orig_src=orig_src or JacSource("", ""),
4351
4384
  value="",
4352
4385
  line=0,
4353
4386
  end_line=0,
@@ -4367,7 +4400,7 @@ class CommentToken(Token):
4367
4400
 
4368
4401
  def __init__(
4369
4402
  self,
4370
- file_path: str,
4403
+ orig_src: JacSource,
4371
4404
  name: str,
4372
4405
  value: str,
4373
4406
  line: int,
@@ -4384,7 +4417,7 @@ class CommentToken(Token):
4384
4417
 
4385
4418
  Token.__init__(
4386
4419
  self,
4387
- file_path=file_path,
4420
+ orig_src=orig_src,
4388
4421
  name=name,
4389
4422
  value=value,
4390
4423
  line=line,
@@ -4404,7 +4437,7 @@ class JacSource(EmptyToken):
4404
4437
 
4405
4438
  def __init__(self, source: str, mod_path: str) -> None:
4406
4439
  """Initialize source string."""
4407
- super().__init__()
4440
+ super().__init__(self)
4408
4441
  self.value = source
4409
4442
  self.hash = md5(source.encode()).hexdigest()
4410
4443
  self.file_path = mod_path
@@ -4419,8 +4452,14 @@ class JacSource(EmptyToken):
4419
4452
  class PythonModuleAst(EmptyToken):
4420
4453
  """SourceString node type for Jac Ast."""
4421
4454
 
4422
- def __init__(self, ast: ast3.Module, mod_path: str) -> None:
4455
+ def __init__(self, ast: ast3.Module, orig_src: JacSource) -> None:
4423
4456
  """Initialize source string."""
4424
4457
  super().__init__()
4425
4458
  self.ast = ast
4426
- self.file_path = mod_path
4459
+ self.orig_src = orig_src
4460
+
4461
+ # This bellow attribute is un-necessary since it already exists in the orig_src
4462
+ # however I'm keeping it here not to break existing code trying to access file_path.
4463
+ # We can remove this in the future once we safley remove all references to it and
4464
+ # use orig_src.
4465
+ self.file_path = orig_src.file_path