jaclang 0.7.22__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 (65) hide show
  1. jaclang/__init__.py +5 -10
  2. jaclang/cli/cli.py +50 -30
  3. jaclang/compiler/__init__.py +2 -2
  4. jaclang/compiler/absyntree.py +87 -48
  5. jaclang/compiler/codeloc.py +7 -2
  6. jaclang/compiler/compile.py +10 -3
  7. jaclang/compiler/parser.py +26 -23
  8. jaclang/compiler/passes/ir_pass.py +2 -2
  9. jaclang/compiler/passes/main/def_impl_match_pass.py +46 -0
  10. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +146 -123
  11. jaclang/compiler/passes/main/import_pass.py +6 -2
  12. jaclang/compiler/passes/main/pyast_load_pass.py +36 -35
  13. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -7
  14. jaclang/compiler/passes/main/registry_pass.py +3 -12
  15. jaclang/compiler/passes/main/tests/fixtures/defn_decl_mismatch.jac +19 -0
  16. jaclang/compiler/passes/main/tests/fixtures/fstrings.jac +2 -0
  17. jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +59 -0
  18. jaclang/compiler/passes/main/tests/test_registry_pass.py +2 -10
  19. jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
  20. jaclang/compiler/passes/main/type_check_pass.py +8 -6
  21. jaclang/compiler/passes/transform.py +27 -3
  22. jaclang/compiler/passes/utils/mypy_ast_build.py +246 -26
  23. jaclang/compiler/symtable.py +6 -0
  24. jaclang/compiler/tests/test_importer.py +2 -2
  25. jaclang/langserve/engine.py +14 -12
  26. jaclang/langserve/server.py +7 -2
  27. jaclang/langserve/tests/test_server.py +1 -1
  28. jaclang/langserve/utils.py +17 -3
  29. jaclang/plugin/builtin.py +3 -3
  30. jaclang/plugin/default.py +612 -236
  31. jaclang/plugin/feature.py +274 -99
  32. jaclang/plugin/plugin.md +471 -0
  33. jaclang/plugin/spec.py +231 -86
  34. jaclang/plugin/tests/fixtures/other_root_access.jac +9 -9
  35. jaclang/plugin/tests/test_features.py +2 -2
  36. jaclang/runtimelib/architype.py +1 -370
  37. jaclang/runtimelib/constructs.py +2 -0
  38. jaclang/runtimelib/context.py +2 -4
  39. jaclang/runtimelib/importer.py +7 -2
  40. jaclang/runtimelib/machine.py +78 -6
  41. jaclang/runtimelib/memory.py +2 -4
  42. jaclang/settings.py +3 -0
  43. jaclang/tests/fixtures/arch_create_util.jac +7 -0
  44. jaclang/tests/fixtures/arch_rel_import_creation.jac +30 -0
  45. jaclang/tests/fixtures/builtin_dotgen.jac +6 -6
  46. jaclang/tests/fixtures/create_dynamic_architype.jac +35 -0
  47. jaclang/tests/fixtures/edge_node_walk.jac +1 -1
  48. jaclang/tests/fixtures/edges_walk.jac +1 -1
  49. jaclang/tests/fixtures/enum_inside_archtype.jac +16 -11
  50. jaclang/tests/fixtures/expr_type.jac +54 -0
  51. jaclang/tests/fixtures/gendot_bubble_sort.jac +1 -1
  52. jaclang/tests/fixtures/glob_multivar_statement.jac +15 -0
  53. jaclang/tests/fixtures/registry.jac +20 -8
  54. jaclang/tests/fixtures/visit_order.jac +20 -0
  55. jaclang/tests/foo/__init__.jac +0 -0
  56. jaclang/tests/main.jac +2 -0
  57. jaclang/tests/test_cli.py +68 -4
  58. jaclang/tests/test_language.py +113 -27
  59. jaclang/utils/helpers.py +92 -14
  60. jaclang/utils/lang_tools.py +6 -2
  61. jaclang/utils/treeprinter.py +4 -2
  62. {jaclang-0.7.22.dist-info → jaclang-0.7.25.dist-info}/METADATA +2 -1
  63. {jaclang-0.7.22.dist-info → jaclang-0.7.25.dist-info}/RECORD +65 -55
  64. {jaclang-0.7.22.dist-info → jaclang-0.7.25.dist-info}/WHEEL +1 -1
  65. {jaclang-0.7.22.dist-info → jaclang-0.7.25.dist-info}/entry_points.txt +0 -0
@@ -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
@@ -9,7 +9,7 @@ from typing import Optional, TYPE_CHECKING
9
9
  from jaclang.vendor.mypy.nodes import Node as MypyNode
10
10
 
11
11
  if TYPE_CHECKING:
12
- from jaclang.compiler.absyntree import Token
12
+ from jaclang.compiler.absyntree import JacSource, Token
13
13
 
14
14
 
15
15
  @dataclass
@@ -42,10 +42,15 @@ class CodeLocInfo:
42
42
  self.first_tok = first_tok
43
43
  self.last_tok = last_tok
44
44
 
45
+ @property
46
+ def orig_src(self) -> JacSource:
47
+ """Get file source."""
48
+ return self.first_tok.orig_src
49
+
45
50
  @property
46
51
  def mod_path(self) -> str:
47
52
  """Get line number."""
48
- return self.first_tok.file_path
53
+ return self.first_tok.orig_src.file_path
49
54
 
50
55
  @property
51
56
  def first_line(self) -> int:
@@ -16,11 +16,13 @@ def compile_jac(file_path: str, cache_result: bool = False) -> Pass:
16
16
  file_path=file_path,
17
17
  schedule=pass_schedule,
18
18
  )
19
- if cache_result and isinstance(code.ir, ast.Module):
19
+ # If there is syntax error, the code will be an instance of JacParser as there is
20
+ # no more passes were processed, in that case we can ignore it.
21
+ had_syntax_error = isinstance(code, JacParser) and len(code.errors_had) != 0
22
+ if cache_result and (not had_syntax_error) and isinstance(code.ir, ast.Module):
20
23
  print_pass = PyOutPass(input_ir=code.ir, prior=code)
21
24
  return print_pass
22
- else:
23
- return code
25
+ return code
24
26
 
25
27
 
26
28
  def jac_file_to_pass(
@@ -49,6 +51,11 @@ def jac_str_to_pass(
49
51
  target = schedule[-1] if schedule else None
50
52
  source = ast.JacSource(jac_str, mod_path=file_path)
51
53
  ast_ret: Pass = JacParser(input_ir=source)
54
+
55
+ # If there is syntax error, no point in processing in further passes.
56
+ if len(ast_ret.errors_had) != 0:
57
+ return ast_ret
58
+
52
59
  for i in schedule:
53
60
  if i == target:
54
61
  break
@@ -43,14 +43,22 @@ class JacParser(Pass):
43
43
  raise self.ice()
44
44
  except jl.UnexpectedInput as e:
45
45
  catch_error = ast.EmptyToken()
46
- catch_error.file_path = self.mod_path
46
+ catch_error.orig_src = self.source
47
47
  catch_error.line_no = e.line
48
48
  catch_error.end_line = e.line
49
49
  catch_error.c_start = e.column
50
50
  catch_error.c_end = e.column + 1
51
- self.error(f"Syntax Error: {e}", node_override=catch_error)
51
+ catch_error.pos_start = e.pos_in_stream or 0
52
+ catch_error.pos_end = catch_error.pos_start + 1
53
+
54
+ error_msg = "Syntax Error"
55
+ if len(e.args) >= 1 and isinstance(e.args[0], str):
56
+ error_msg += e.args[0]
57
+ self.error(error_msg, node_override=catch_error)
58
+
52
59
  except Exception as e:
53
60
  self.error(f"Internal Error: {e}")
61
+
54
62
  return ast.Module(
55
63
  name="",
56
64
  source=self.source,
@@ -65,7 +73,7 @@ class JacParser(Pass):
65
73
  def proc_comment(token: jl.Token, mod: ast.AstNode) -> ast.CommentToken:
66
74
  """Process comment."""
67
75
  return ast.CommentToken(
68
- file_path=mod.loc.mod_path,
76
+ orig_src=mod.loc.orig_src,
69
77
  name=token.type,
70
78
  value=token.value,
71
79
  line=token.line if token.line is not None else 0,
@@ -166,7 +174,7 @@ class JacParser(Pass):
166
174
  kid=(
167
175
  kid
168
176
  if len(kid)
169
- else [ast.EmptyToken(file_path=self.parse_ref.mod_path)]
177
+ else [ast.EmptyToken(ast.JacSource("", self.parse_ref.mod_path))]
170
178
  ),
171
179
  )
172
180
  return self.nu(mod)
@@ -706,10 +714,12 @@ class JacParser(Pass):
706
714
  | NAME (COLON STRING)?
707
715
  | py_code_block
708
716
  | free_code
717
+ | abstract_ability
718
+ | ability
709
719
  """
710
- if isinstance(kid[0], ast.PyInlineCode):
720
+ if isinstance(kid[0], (ast.PyInlineCode, ast.Ability)):
711
721
  return self.nu(kid[0])
712
- if isinstance(kid[0], (ast.Name)):
722
+ elif isinstance(kid[0], (ast.Name)):
713
723
  if (
714
724
  len(kid) >= 3
715
725
  and isinstance(kid[-1], ast.Expr)
@@ -1010,7 +1020,11 @@ class JacParser(Pass):
1010
1020
  kid=(
1011
1021
  kid
1012
1022
  if len(kid)
1013
- else [ast.EmptyToken(file_path=self.parse_ref.mod_path)]
1023
+ else [
1024
+ ast.EmptyToken(
1025
+ ast.JacSource("", self.parse_ref.mod_path)
1026
+ )
1027
+ ]
1014
1028
  ),
1015
1029
  )
1016
1030
  )
@@ -1228,7 +1242,7 @@ class JacParser(Pass):
1228
1242
  return self.nu(
1229
1243
  ast.BuiltinType(
1230
1244
  name=kid[0].name,
1231
- file_path=self.parse_ref.mod_path,
1245
+ orig_src=self.parse_ref.source,
1232
1246
  value=kid[0].value,
1233
1247
  line=kid[0].loc.first_line,
1234
1248
  end_line=kid[0].loc.last_line,
@@ -2786,25 +2800,14 @@ class JacParser(Pass):
2786
2800
  def name_list(self, kid: list[ast.AstNode]) -> ast.SubNodeList[ast.Name]:
2787
2801
  """Grammar rule.
2788
2802
 
2789
- name_list: (name_list COMMA)? NAME
2803
+ name_list: (named_ref COMMA)* named_ref
2790
2804
  """
2791
- consume = None
2792
- name = None
2793
- comma = None
2794
- if isinstance(kid[0], ast.SubNodeList):
2795
- consume = kid[0]
2796
- comma = kid[1]
2797
- name = kid[2]
2798
- new_kid = [*consume.kid, comma, name]
2799
- else:
2800
- name = kid[0]
2801
- new_kid = [name]
2802
- valid_kid = [i for i in new_kid if isinstance(i, ast.Name)]
2805
+ valid_kid = [i for i in kid if isinstance(i, ast.Name)]
2803
2806
  return self.nu(
2804
2807
  ast.SubNodeList[ast.Name](
2805
2808
  items=valid_kid,
2806
2809
  delim=Tok.COMMA,
2807
- kid=new_kid,
2810
+ kid=kid,
2808
2811
  )
2809
2812
  )
2810
2813
 
@@ -3996,7 +3999,7 @@ class JacParser(Pass):
3996
3999
  elif token.type == Tok.PYNLINE and isinstance(token.value, str):
3997
4000
  token.value = token.value.replace("::py::", "")
3998
4001
  ret = ret_type(
3999
- file_path=self.parse_ref.mod_path,
4002
+ orig_src=self.parse_ref.source,
4000
4003
  name=token.type,
4001
4004
  value=token.value[2:] if token.type == Tok.KWESC_NAME else token.value,
4002
4005
  line=token.line if token.line is not None else 0,
@@ -140,11 +140,11 @@ class Pass(Transform[T]):
140
140
 
141
141
  def error(self, msg: str, node_override: Optional[ast.AstNode] = None) -> None:
142
142
  """Pass Error."""
143
- self.log_error(f"{msg}", node_override=node_override)
143
+ self.log_error(msg, node_override=node_override)
144
144
 
145
145
  def warning(self, msg: str, node_override: Optional[ast.AstNode] = None) -> None:
146
146
  """Pass Error."""
147
- self.log_warning(f"{msg}", node_override=node_override)
147
+ self.log_warning(msg, node_override=node_override)
148
148
 
149
149
  def ice(self, msg: str = "Something went horribly wrong!") -> RuntimeError:
150
150
  """Pass Error."""