jaclang 0.7.14__py3-none-any.whl → 0.7.16__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 (92) hide show
  1. jaclang/cli/cli.py +15 -10
  2. jaclang/cli/cmdreg.py +9 -12
  3. jaclang/compiler/__init__.py +19 -53
  4. jaclang/compiler/absyntree.py +86 -13
  5. jaclang/compiler/jac.lark +4 -3
  6. jaclang/compiler/parser.py +31 -23
  7. jaclang/compiler/passes/ir_pass.py +4 -13
  8. jaclang/compiler/passes/main/access_modifier_pass.py +1 -1
  9. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +4 -5
  10. jaclang/compiler/passes/main/import_pass.py +18 -23
  11. jaclang/compiler/passes/main/pyast_gen_pass.py +307 -559
  12. jaclang/compiler/passes/main/pyast_load_pass.py +32 -6
  13. jaclang/compiler/passes/main/registry_pass.py +37 -3
  14. jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -1
  15. jaclang/compiler/passes/main/tests/__init__.py +1 -1
  16. jaclang/compiler/passes/main/type_check_pass.py +7 -0
  17. jaclang/compiler/passes/tool/jac_formatter_pass.py +124 -86
  18. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +0 -1
  19. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/architype_test.jac +13 -0
  20. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comment_alignment.jac +11 -0
  21. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comments.jac +13 -0
  22. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/decorator_stack.jac +37 -0
  23. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/esc_keywords.jac +5 -0
  24. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/long_names.jac +19 -0
  25. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +6 -0
  26. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -0
  27. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +33 -39
  28. jaclang/compiler/passes/transform.py +4 -0
  29. jaclang/compiler/semtable.py +31 -7
  30. jaclang/compiler/tests/test_importer.py +12 -5
  31. jaclang/langserve/engine.py +65 -118
  32. jaclang/langserve/sem_manager.py +379 -0
  33. jaclang/langserve/server.py +8 -10
  34. jaclang/langserve/tests/fixtures/base_module_structure.jac +27 -6
  35. jaclang/langserve/tests/fixtures/circle.jac +3 -3
  36. jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
  37. jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
  38. jaclang/langserve/tests/fixtures/import_include_statements.jac +1 -1
  39. jaclang/langserve/tests/test_sem_tokens.py +277 -0
  40. jaclang/langserve/tests/test_server.py +72 -16
  41. jaclang/langserve/utils.py +163 -96
  42. jaclang/plugin/builtin.py +1 -1
  43. jaclang/plugin/default.py +212 -24
  44. jaclang/plugin/feature.py +59 -11
  45. jaclang/plugin/spec.py +58 -6
  46. jaclang/{core → runtimelib}/architype.py +1 -1
  47. jaclang/{core → runtimelib}/context.py +8 -1
  48. jaclang/runtimelib/importer.py +361 -0
  49. jaclang/runtimelib/machine.py +94 -0
  50. jaclang/{core → runtimelib}/utils.py +13 -5
  51. jaclang/settings.py +4 -1
  52. jaclang/tests/fixtures/abc.jac +3 -3
  53. jaclang/tests/fixtures/byllmissue.jac +1 -5
  54. jaclang/tests/fixtures/chandra_bugs2.jac +11 -10
  55. jaclang/tests/fixtures/cls_method.jac +41 -0
  56. jaclang/tests/fixtures/dblhello.jac +6 -0
  57. jaclang/tests/fixtures/deep/one_lev.jac +3 -3
  58. jaclang/tests/fixtures/deep/one_lev_dup.jac +2 -3
  59. jaclang/tests/fixtures/deep_import_mods.jac +13 -0
  60. jaclang/tests/fixtures/err.impl.jac +3 -0
  61. jaclang/tests/fixtures/err.jac +4 -2
  62. jaclang/tests/fixtures/err.test.jac +3 -0
  63. jaclang/tests/fixtures/err_runtime.jac +15 -0
  64. jaclang/tests/fixtures/game1.jac +1 -1
  65. jaclang/tests/fixtures/hello.jac +4 -0
  66. jaclang/tests/fixtures/impl_grab.impl.jac +2 -1
  67. jaclang/tests/fixtures/impl_grab.jac +4 -1
  68. jaclang/tests/fixtures/jp_importer_auto.jac +14 -0
  69. jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
  70. jaclang/tests/fixtures/needs_import.jac +2 -2
  71. jaclang/tests/fixtures/pyfunc_2.py +3 -0
  72. jaclang/tests/fixtures/registry.jac +9 -0
  73. jaclang/tests/fixtures/run_test.jac +4 -4
  74. jaclang/tests/fixtures/semstr.jac +1 -4
  75. jaclang/tests/fixtures/simple_archs.jac +1 -1
  76. jaclang/tests/test_cli.py +65 -2
  77. jaclang/tests/test_language.py +74 -7
  78. jaclang/tests/test_reference.py +6 -0
  79. jaclang/utils/helpers.py +45 -21
  80. jaclang/utils/test.py +9 -0
  81. jaclang/utils/treeprinter.py +0 -4
  82. {jaclang-0.7.14.dist-info → jaclang-0.7.16.dist-info}/METADATA +3 -2
  83. {jaclang-0.7.14.dist-info → jaclang-0.7.16.dist-info}/RECORD +89 -74
  84. jaclang/core/importer.py +0 -344
  85. jaclang/tests/fixtures/aott_raise.jac +0 -25
  86. jaclang/tests/fixtures/package_import.jac +0 -6
  87. /jaclang/{core → runtimelib}/__init__.py +0 -0
  88. /jaclang/{core → runtimelib}/constructs.py +0 -0
  89. /jaclang/{core → runtimelib}/memory.py +0 -0
  90. /jaclang/{core → runtimelib}/test.py +0 -0
  91. {jaclang-0.7.14.dist-info → jaclang-0.7.16.dist-info}/WHEEL +0 -0
  92. {jaclang-0.7.14.dist-info → jaclang-0.7.16.dist-info}/entry_points.txt +0 -0
jaclang/cli/cli.py CHANGED
@@ -19,10 +19,11 @@ from jaclang.compiler.constant import Constants
19
19
  from jaclang.compiler.passes.main.pyast_load_pass import PyastBuildPass
20
20
  from jaclang.compiler.passes.main.schedules import py_code_gen_typed
21
21
  from jaclang.compiler.passes.tool.schedules import format_pass
22
- from jaclang.core.constructs import Architype
23
22
  from jaclang.plugin.builtin import dotgen
24
23
  from jaclang.plugin.feature import JacCmd as Cmd
25
24
  from jaclang.plugin.feature import JacFeature as Jac
25
+ from jaclang.runtimelib.constructs import Architype
26
+ from jaclang.runtimelib.machine import JacProgram
26
27
  from jaclang.utils.helpers import debugger as db
27
28
  from jaclang.utils.lang_tools import AstTool
28
29
 
@@ -86,11 +87,10 @@ def run(
86
87
  else ""
87
88
  )
88
89
 
89
- Jac.context().init_memory(session)
90
-
91
90
  base, mod = os.path.split(filename)
92
91
  base = base if base else "./"
93
92
  mod = mod[:-4]
93
+ Jac.context().init_memory(base_path=base, session=session)
94
94
  if filename.endswith(".jac"):
95
95
  ret_module = jac_import(
96
96
  target=mod,
@@ -105,12 +105,13 @@ def run(
105
105
  elif filename.endswith(".jir"):
106
106
  with open(filename, "rb") as f:
107
107
  ir = pickle.load(f)
108
+ jac_program = JacProgram(mod_bundle=ir, bytecode=None)
109
+ Jac.context().jac_machine.attach_program(jac_program)
108
110
  ret_module = jac_import(
109
111
  target=mod,
110
112
  base_path=base,
111
113
  cachable=cache,
112
114
  override_name="__main__" if main else None,
113
- mod_bundle=ir,
114
115
  )
115
116
  if ret_module is None:
116
117
  loaded_mod = None
@@ -146,7 +147,7 @@ def get_object(id: str, session: str = "") -> dict:
146
147
  if session == "":
147
148
  session = cmd_registry.args.session if "session" in cmd_registry.args else ""
148
149
 
149
- Jac.context().init_memory(session)
150
+ Jac.context().init_memory(session=session)
150
151
 
151
152
  if id == "root":
152
153
  id_uuid = UUID(int=0)
@@ -221,7 +222,7 @@ def enter(filename: str, entrypoint: str, args: list) -> None:
221
222
  base, mod_name = os.path.split(filename)
222
223
  base = base if base else "./"
223
224
  mod_name = mod_name[:-4]
224
- mod = jac_import(target=mod_name, base_path=base)
225
+ (mod,) = jac_import(target=mod_name, base_path=base)
225
226
  if not mod:
226
227
  print("Errors occurred while importing the module.")
227
228
  return
@@ -357,11 +358,10 @@ def dot(
357
358
  else ""
358
359
  )
359
360
 
360
- Jac.context().init_memory(session)
361
-
362
361
  base, mod = os.path.split(filename)
363
362
  base = base if base else "./"
364
363
  mod = mod[:-4]
364
+ Jac.context().init_memory(base_path=base, session=session)
365
365
  if filename.endswith(".jac"):
366
366
  jac_import(
367
367
  target=mod,
@@ -437,12 +437,17 @@ def start_cli() -> None:
437
437
  parser = cmd_registry.parser
438
438
  args = parser.parse_args()
439
439
  cmd_registry.args = args
440
+
441
+ if args.version:
442
+ version = importlib.metadata.version("jaclang")
443
+ print(f"Jac version {version}")
444
+ return
445
+
440
446
  command = cmd_registry.get(args.command)
441
447
  if command:
442
448
  args_dict = vars(args)
443
449
  args_dict.pop("command")
444
- if command not in ["run"]:
445
- args_dict.pop("session")
450
+ args_dict.pop("version", None)
446
451
  ret = command.call(**args_dict)
447
452
  if ret:
448
453
  print(ret)
jaclang/cli/cmdreg.py CHANGED
@@ -38,7 +38,7 @@ class CommandRegistry:
38
38
  self.registry = {}
39
39
  self.parser = argparse.ArgumentParser(prog="jac")
40
40
  self.parser.add_argument(
41
- "--session", help="Session file path", nargs="?", default=""
41
+ "-V", "--version", action="store_true", help="Show the Jac version"
42
42
  )
43
43
  self.sub_parsers = self.parser.add_subparsers(title="commands", dest="command")
44
44
  self.args = argparse.Namespace()
@@ -172,17 +172,14 @@ class CommandShell(cmd.Cmd):
172
172
 
173
173
  def default(self, line: str) -> None:
174
174
  """Process the command line input."""
175
- try:
176
- args = vars(self.cmd_reg.parser.parse_args(line.split()))
177
- command = self.cmd_reg.get(args["command"])
178
- if command:
179
- args.pop("command")
180
- ret = command.call(**args)
181
- if ret:
182
- ret_str = pprint.pformat(ret, indent=2)
183
- self.stdout.write(f"{ret_str}\n")
184
- except Exception as e:
185
- print(e)
175
+ args = vars(self.cmd_reg.parser.parse_args(line.split()))
176
+ command = self.cmd_reg.get(args["command"])
177
+ if command:
178
+ args.pop("command")
179
+ ret = command.call(**args)
180
+ if ret:
181
+ ret_str = pprint.pformat(ret, indent=2)
182
+ self.stdout.write(f"{ret_str}\n")
186
183
 
187
184
  def do_help(self, arg: str) -> None:
188
185
  """Jac CLI 'help' implementaion."""
@@ -35,7 +35,6 @@ def generate_static_parser(force: bool = False) -> None:
35
35
  logging.error(f"Error generating reference files: {e}")
36
36
 
37
37
 
38
- generate_static_parser()
39
38
  try:
40
39
  from jaclang.compiler.generated import jac_parser as jac_lark
41
40
  except ModuleNotFoundError:
@@ -50,62 +49,29 @@ TOKEN_MAP = {
50
49
  for x in jac_lark.Lark_StandAlone().parser.lexer_conf.terminals
51
50
  }
52
51
 
52
+ # fmt: off
53
53
  TOKEN_MAP.update(
54
54
  {
55
- "CARROW_L": "<++",
56
- "CARROW_R": "++>",
57
- "GLOBAL_OP": ":global:",
58
- "NONLOCAL_OP": ":nonlocal:",
59
- "WALKER_OP": ":walker:",
60
- "NODE_OP": ":node:",
61
- "EDGE_OP": ":edge:",
62
- "CLASS_OP": ":class:",
63
- "OBJECT_OP": ":obj:",
64
- "TYPE_OP": "`",
65
- "ABILITY_OP": ":can:",
66
- "ELVIS_OP": "?:",
67
- "NULL_OK": "?",
68
- "KW_OR": "|",
69
- "ARROW_BI": "<-->",
70
- "ARROW_L": "<--",
71
- "ARROW_R": "-->",
72
- "ARROW_L_P1": "<-:",
73
- "ARROW_R_P2": ":->",
74
- "ARROW_L_P2": ":-",
75
- "ARROW_R_P1": "-:",
76
- "CARROW_BI": "<++>",
77
- "CARROW_L": "<++",
78
- "CARROW_R": "++>",
79
- "CARROW_L_P1": "<+:",
80
- "CARROW_R_P2": ":+>",
81
- "CARROW_L_P2": ":+",
82
- "CARROW_R_P1": "+:",
83
- "PIPE_FWD": "|>",
84
- "PIPE_BKWD": "<|",
85
- "A_PIPE_FWD": ":>",
86
- "A_PIPE_BKWD": "<:",
87
- "DOT_FWD": ".>",
88
- "STAR_POW": "**",
89
- "STAR_MUL": "*",
90
- "FLOOR_DIV": "//",
91
- "DIV": "/",
92
- "PYNLINE": "::py::",
93
- "ADD_EQ": "+=",
94
- "SUB_EQ": "-=",
95
- "STAR_POW_EQ": "**=",
96
- "MUL_EQ": "*=",
97
- "FLOOR_DIV_EQ": "//=",
98
- "DIV_EQ": "/=",
99
- "MOD_EQ": "%=",
100
- "BW_AND_EQ": "&=",
101
- "BW_OR_EQ": "|=",
102
- "BW_XOR_EQ": "^=",
103
- "BW_NOT_EQ": "~=",
104
- "LSHIFT_EQ": "<<=",
105
- "RSHIFT_EQ": ">>=",
106
- "ELLIPSIS": "...",
55
+ "CARROW_L": "<++", "CARROW_R": "++>", "GLOBAL_OP": ":global:",
56
+ "NONLOCAL_OP": ":nonlocal:", "WALKER_OP": ":walker:", "NODE_OP": ":node:",
57
+ "EDGE_OP": ":edge:", "CLASS_OP": ":class:", "OBJECT_OP": ":obj:",
58
+ "TYPE_OP": "`", "ABILITY_OP": ":can:", "ELVIS_OP": "?:", "NULL_OK": "?",
59
+ "KW_OR": "|", "ARROW_BI": "<-->", "ARROW_L": "<--",
60
+ "ARROW_R": "-->", "ARROW_L_P1": "<-:", "ARROW_R_P2": ":->",
61
+ "ARROW_L_P2": ":-", "ARROW_R_P1": "-:", "CARROW_BI": "<++>",
62
+ "CARROW_L": "<++", "CARROW_R": "++>", "CARROW_L_P1": "<+:",
63
+ "CARROW_R_P2": ":+>", "CARROW_L_P2": ":+", "CARROW_R_P1": "+:",
64
+ "PIPE_FWD": "|>", "PIPE_BKWD": "<|", "A_PIPE_FWD": ":>",
65
+ "A_PIPE_BKWD": "<:", "DOT_FWD": ".>", "STAR_POW": "**",
66
+ "STAR_MUL": "*", "FLOOR_DIV": "//", "DIV": "/",
67
+ "PYNLINE": "::py::", "ADD_EQ": "+=", "SUB_EQ": "-=",
68
+ "STAR_POW_EQ": "**=", "MUL_EQ": "*=", "FLOOR_DIV_EQ": "//=",
69
+ "DIV_EQ": "/=", "MOD_EQ": "%=", "BW_AND_EQ": "&=",
70
+ "BW_OR_EQ": "|=", "BW_XOR_EQ": "^=", "BW_NOT_EQ": "~=",
71
+ "LSHIFT_EQ": "<<=", "RSHIFT_EQ": ">>=", "ELLIPSIS": "...",
107
72
  }
108
73
  )
74
+ # fmt: on
109
75
 
110
76
 
111
77
  __all__ = ["jac_lark", "TOKEN_MAP"]
@@ -55,15 +55,10 @@ class AstNode:
55
55
  """Get symbol table."""
56
56
  # sym_tab should never be accessed without being set in codebase
57
57
  if not self._sym_tab:
58
- import traceback
59
-
60
- if self.parent:
61
- print(f"Parent: {self.parent.pp()}")
62
- print("Node: ", self.pp())
63
- stack_trace = traceback.format_stack()
64
- print("".join(stack_trace))
65
58
  raise ValueError(
66
- f"Symbol table not set for {type(self).__name__}. Impossible."
59
+ f"Symbol table not set for {type(self).__name__}. Impossible.\n"
60
+ f"Node: {self.pp()}\n"
61
+ f"Parent: {self.parent.pp() if self.parent else None}\n"
67
62
  )
68
63
  return self._sym_tab
69
64
 
@@ -163,7 +158,7 @@ class AstNode:
163
158
  """Get parent of type."""
164
159
  from jaclang.compiler.passes import Pass
165
160
 
166
- return Pass.has_parent_of_type(node=self, typ=typ)
161
+ return Pass.find_parent_of_type(node=self, typ=typ)
167
162
 
168
163
  def parent_of_type(self, typ: Type[T]) -> T:
169
164
  """Get parent of type."""
@@ -863,7 +858,7 @@ class Import(ElementStmt, CodeBlockStmt):
863
858
 
864
859
  def __init__(
865
860
  self,
866
- hint: SubTag[Name],
861
+ hint: Optional[SubTag[Name]],
867
862
  from_loc: Optional[ModulePath],
868
863
  items: SubNodeList[ModuleItem] | SubNodeList[ModulePath],
869
864
  is_absorb: bool, # For includes
@@ -878,11 +873,52 @@ class Import(ElementStmt, CodeBlockStmt):
878
873
  AstNode.__init__(self, kid=kid)
879
874
  AstDocNode.__init__(self, doc=doc)
880
875
 
876
+ @property
877
+ def is_py(self) -> bool:
878
+ """Check if import is python."""
879
+ if self.hint and self.hint.tag.value == "py":
880
+ return True
881
+ if not self.hint:
882
+ return not self.__jac_detected
883
+ return False
884
+
885
+ @property
886
+ def is_jac(self) -> bool:
887
+ """Check if import is jac."""
888
+ if self.hint and self.hint.tag.value == "jac":
889
+ return True
890
+ if not self.hint:
891
+ return self.__jac_detected
892
+ return False
893
+
894
+ @property
895
+ def __jac_detected(self) -> bool:
896
+ """Check if import is jac."""
897
+ if self.from_loc:
898
+ if self.from_loc.resolve_relative_path().endswith(".jac"):
899
+ return True
900
+ if os.path.isdir(self.from_loc.resolve_relative_path()):
901
+ if os.path.exists(
902
+ os.path.join(self.from_loc.resolve_relative_path(), "__init__.jac")
903
+ ):
904
+ return True
905
+ for i in self.items.items:
906
+ if isinstance(
907
+ i, ModuleItem
908
+ ) and self.from_loc.resolve_relative_path(i.name.value).endswith(
909
+ ".jac"
910
+ ):
911
+ return True
912
+ return any(
913
+ isinstance(i, ModulePath) and i.resolve_relative_path().endswith(".jac")
914
+ for i in self.items.items
915
+ )
916
+
881
917
  def normalize(self, deep: bool = False) -> bool:
882
918
  """Normalize import node."""
883
919
  res = True
884
920
  if deep:
885
- res = self.hint.normalize(deep)
921
+ res = self.hint.normalize(deep) if self.hint else res
886
922
  res = res and self.from_loc.normalize(deep) if self.from_loc else res
887
923
  res = res and self.items.normalize(deep)
888
924
  res = res and self.doc.normalize(deep) if self.doc else res
@@ -893,7 +929,8 @@ class Import(ElementStmt, CodeBlockStmt):
893
929
  new_kid.append(self.gen_token(Tok.KW_INCLUDE))
894
930
  else:
895
931
  new_kid.append(self.gen_token(Tok.KW_IMPORT))
896
- new_kid.append(self.hint)
932
+ if self.hint:
933
+ new_kid.append(self.hint)
897
934
  if self.from_loc:
898
935
  new_kid.append(self.gen_token(Tok.KW_FROM))
899
936
  new_kid.append(self.from_loc)
@@ -946,6 +983,26 @@ class ModulePath(AstSymbolNode):
946
983
  [p.value for p in self.path] if self.path else [self.name_spec.sym_name]
947
984
  )
948
985
 
986
+ def resolve_relative_path(self, target_item: Optional[str] = None) -> str:
987
+ """Convert an import target string into a relative file path."""
988
+ target = self.path_str
989
+ if target_item:
990
+ target += f".{target_item}"
991
+ base_path = os.path.dirname(self.loc.mod_path)
992
+ base_path = base_path if base_path else os.getcwd()
993
+ parts = target.split(".")
994
+ traversal_levels = self.level - 1 if self.level > 0 else 0
995
+ actual_parts = parts[traversal_levels:]
996
+ for _ in range(traversal_levels):
997
+ base_path = os.path.dirname(base_path)
998
+ relative_path = os.path.join(base_path, *actual_parts)
999
+ relative_path = (
1000
+ relative_path + ".jac"
1001
+ if os.path.exists(relative_path + ".jac")
1002
+ else relative_path
1003
+ )
1004
+ return relative_path
1005
+
949
1006
  def normalize(self, deep: bool = False) -> bool:
950
1007
  """Normalize module path node."""
951
1008
  res = True
@@ -1132,7 +1189,6 @@ class ArchDef(AstImplOnlyNode):
1132
1189
  body: SubNodeList[ArchBlockStmt],
1133
1190
  kid: Sequence[AstNode],
1134
1191
  doc: Optional[String] = None,
1135
- decorators: Optional[SubNodeList[Expr]] = None,
1136
1192
  decl_link: Optional[Architype] = None,
1137
1193
  ) -> None:
1138
1194
  """Initialize arch def node."""
@@ -1473,6 +1529,23 @@ class FuncSignature(AstSemStrNode):
1473
1529
  and self.parent.decl_link.is_static
1474
1530
  )
1475
1531
 
1532
+ @property
1533
+ def is_in_py_class(self) -> bool:
1534
+ """Check if the ability belongs to a class."""
1535
+ is_archi = self.find_parent_of_type(Architype)
1536
+ is_class = is_archi is not None and is_archi.arch_type.name == Tok.KW_CLASS
1537
+
1538
+ return (
1539
+ isinstance(self.parent, Ability)
1540
+ and self.parent.is_method is not None
1541
+ and is_class
1542
+ ) or (
1543
+ isinstance(self.parent, AbilityDef)
1544
+ and isinstance(self.parent.decl_link, Ability)
1545
+ and self.parent.decl_link.is_method
1546
+ and is_class
1547
+ )
1548
+
1476
1549
 
1477
1550
  class EventSignature(AstSemStrNode):
1478
1551
  """EventSignature node type for Jac Ast."""
jaclang/compiler/jac.lark CHANGED
@@ -16,8 +16,9 @@ element: import_stmt
16
16
  | test
17
17
 
18
18
  // Import/Include Statements
19
- import_stmt: KW_IMPORT sub_name KW_FROM from_path COMMA import_items SEMI
20
- | KW_IMPORT sub_name import_path (COMMA import_path)* SEMI
19
+ import_stmt: KW_IMPORT sub_name? KW_FROM from_path LBRACE import_items RBRACE
20
+ | KW_IMPORT sub_name? KW_FROM from_path COMMA import_items SEMI //Deprecated
21
+ | KW_IMPORT sub_name? import_path (COMMA import_path)* SEMI
21
22
  | include_stmt
22
23
 
23
24
  from_path: (DOT | ELLIPSIS)* import_path
@@ -27,7 +28,7 @@ import_path: named_ref (DOT named_ref)* (KW_AS NAME)?
27
28
  import_items: (import_item COMMA)* import_item
28
29
  import_item: named_ref (KW_AS NAME)?
29
30
  sub_name: COLON NAME
30
- include_stmt: KW_INCLUDE sub_name import_path SEMI
31
+ include_stmt: KW_INCLUDE sub_name? import_path SEMI
31
32
 
32
33
  // Architypes
33
34
  architype: decorators? architype_decl
@@ -298,26 +298,29 @@ class JacParser(Pass):
298
298
  def import_stmt(self, kid: list[ast.AstNode]) -> ast.Import:
299
299
  """Grammar rule.
300
300
 
301
- import_stmt: KW_IMPORT sub_name KW_FROM from_path COMMA import_items SEMI
302
- | KW_IMPORT sub_name import_path (COMMA import_path)* SEMI
301
+ import_stmt: KW_IMPORT sub_name? KW_FROM from_path LBRACE import_items RBRACE
302
+ | KW_IMPORT sub_name? KW_FROM from_path COMMA import_items SEMI //Deprecated
303
+ | KW_IMPORT sub_name? import_path (COMMA import_path)* SEMI
303
304
  | include_stmt
304
305
  """
305
306
  if len(kid) == 1 and isinstance(kid[0], ast.Import):
306
307
  return self.nu(kid[0])
307
- lang = kid[1]
308
- from_path = kid[3] if isinstance(kid[3], ast.ModulePath) else None
308
+ chomp = [*kid]
309
+ lang = kid[1] if isinstance(kid[1], ast.SubTag) else None
310
+ chomp = chomp[2:] if lang else chomp[1:]
311
+ from_path = chomp[1] if isinstance(chomp[1], ast.ModulePath) else None
309
312
  if from_path:
310
313
  items = kid[-2] if isinstance(kid[-2], ast.SubNodeList) else None
311
314
  else:
312
315
  paths = [i for i in kid if isinstance(i, ast.ModulePath)]
313
316
  items = ast.SubNodeList[ast.ModulePath](
314
- items=paths, delim=Tok.COMMA, kid=kid[2:-1]
317
+ items=paths, delim=Tok.COMMA, kid=kid[2 if lang else 1 : -1]
315
318
  )
316
- kid = kid[:2] + [items] + kid[-1:]
319
+ kid = (kid[:2] if lang else kid[:1]) + [items] + kid[-1:]
317
320
 
318
321
  is_absorb = False
319
- if isinstance(lang, ast.SubTag) and (isinstance(items, ast.SubNodeList)):
320
- return self.nu(
322
+ if isinstance(items, ast.SubNodeList):
323
+ ret = self.nu(
321
324
  ast.Import(
322
325
  hint=lang,
323
326
  from_loc=from_path,
@@ -326,7 +329,15 @@ class JacParser(Pass):
326
329
  kid=kid,
327
330
  )
328
331
  )
329
-
332
+ if (
333
+ from_path
334
+ and isinstance(kid[-1], ast.Token)
335
+ and kid[-1].name == Tok.SEMI
336
+ ):
337
+ self.parse_ref.warning(
338
+ "Deprecated syntax, use braces for multiple imports (e.g, import from mymod {a, b, c})",
339
+ )
340
+ return ret
330
341
  else:
331
342
  raise self.ice()
332
343
 
@@ -364,27 +375,24 @@ class JacParser(Pass):
364
375
 
365
376
  include_stmt: KW_INCLUDE sub_name import_path SEMI
366
377
  """
367
- lang = kid[1]
368
- from_path = kid[2]
378
+ lang = kid[1] if isinstance(kid[1], ast.SubTag) else None
379
+ from_path = kid[2] if lang else kid[1]
369
380
  if not isinstance(from_path, ast.ModulePath):
370
381
  raise self.ice()
371
382
  items = ast.SubNodeList[ast.ModulePath](
372
383
  items=[from_path], delim=Tok.COMMA, kid=[from_path]
373
384
  )
374
- kid = kid[:2] + [items] + kid[3:]
385
+ kid = (kid[:2] if lang else kid[:1]) + [items] + kid[-1:]
375
386
  is_absorb = True
376
- if isinstance(lang, ast.SubTag):
377
- return self.nu(
378
- ast.Import(
379
- hint=lang,
380
- from_loc=None,
381
- items=items,
382
- is_absorb=is_absorb,
383
- kid=kid,
384
- )
387
+ return self.nu(
388
+ ast.Import(
389
+ hint=lang,
390
+ from_loc=None,
391
+ items=items,
392
+ is_absorb=is_absorb,
393
+ kid=kid,
385
394
  )
386
- else:
387
- raise self.ice()
395
+ )
388
396
 
389
397
  def import_path(self, kid: list[ast.AstNode]) -> ast.ModulePath:
390
398
  """Grammar rule.
@@ -74,7 +74,7 @@ class Pass(Transform[T]):
74
74
  return result
75
75
 
76
76
  @staticmethod
77
- def has_parent_of_type(node: ast.AstNode, typ: Type[T]) -> Optional[T]:
77
+ def find_parent_of_type(node: ast.AstNode, typ: Type[T]) -> Optional[T]:
78
78
  """Check if node has parent of type."""
79
79
  while node.parent:
80
80
  if isinstance(node.parent, typ):
@@ -115,7 +115,7 @@ class Pass(Transform[T]):
115
115
  self.after_pass()
116
116
  self.time_taken = time.time() - start_time
117
117
  if settings.pass_timer:
118
- print(
118
+ self.log_info(
119
119
  f"Time taken in {self.__class__.__name__}: {self.time_taken:.4f} seconds"
120
120
  )
121
121
  return self.ir
@@ -136,21 +136,12 @@ class Pass(Transform[T]):
136
136
  self.exit_node(node)
137
137
  return node
138
138
 
139
- def update_code_loc(self, node: Optional[ast.AstNode] = None) -> None:
140
- """Update code location."""
141
- if node is None:
142
- node = self.cur_node
143
- if not isinstance(node, ast.AstNode):
144
- self.ice("Current node is not an AstNode.")
145
-
146
139
  def error(self, msg: str, node_override: Optional[ast.AstNode] = None) -> None:
147
140
  """Pass Error."""
148
- self.update_code_loc(node_override)
149
141
  self.log_error(f"{msg}", node_override=node_override)
150
142
 
151
143
  def warning(self, msg: str, node_override: Optional[ast.AstNode] = None) -> None:
152
144
  """Pass Error."""
153
- self.update_code_loc(node_override)
154
145
  self.log_warning(f"{msg}", node_override=node_override)
155
146
 
156
147
  def ice(self, msg: str = "Something went horribly wrong!") -> RuntimeError:
@@ -166,10 +157,10 @@ class PrinterPass(Pass):
166
157
 
167
158
  def enter_node(self, node: ast.AstNode) -> None:
168
159
  """Run on entering node."""
169
- print("Entering:", node)
160
+ self.log_info(f"Entering: {node.__class__.__name__}: {node.loc}")
170
161
  super().enter_node(node)
171
162
 
172
163
  def exit_node(self, node: ast.AstNode) -> None:
173
164
  """Run on exiting node."""
174
165
  super().exit_node(node)
175
- print("Exiting:", node)
166
+ self.log_info(f"Exiting: {node.__class__.__name__}: {node.loc}")
@@ -175,7 +175,7 @@ class AccessCheckPass(Pass):
175
175
  if isinstance(node.parent, ast.FuncCall):
176
176
  self.access_check(node)
177
177
 
178
- if node.sym and Pass.has_parent_of_type(
178
+ if node.sym and Pass.find_parent_of_type(
179
179
  node=node.sym.defn[-1], typ=ast.GlobalVars
180
180
  ):
181
181
  self.access_check(node)
@@ -6,7 +6,6 @@ mypy apis into Jac and use jac py ast in it.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- import traceback
10
9
  from typing import Callable, TypeVar
11
10
 
12
11
  import jaclang.compiler.absyntree as ast
@@ -32,7 +31,7 @@ class FuseTypeInfoPass(Pass):
32
31
 
33
32
  def __debug_print(self, *argv: object) -> None:
34
33
  if settings.fuse_type_info_debug:
35
- print("FuseTypeInfo::", *argv)
34
+ self.log_info("FuseTypeInfo::", *argv)
36
35
 
37
36
  def __call_type_handler(
38
37
  self, node: ast.AstSymbolNode, mypy_type: MypyTypes.ProperType
@@ -72,7 +71,9 @@ class FuseTypeInfoPass(Pass):
72
71
  ) -> Callable[[FuseTypeInfoPass, T], None]:
73
72
  def node_handler(self: FuseTypeInfoPass, node: T) -> None:
74
73
  if not isinstance(node, ast.AstSymbolNode):
75
- print(f"Warning {node.__class__.__name__} is not an AstSymbolNode")
74
+ self.__debug_print(
75
+ f"Warning {node.__class__.__name__} is not an AstSymbolNode"
76
+ )
76
77
 
77
78
  try:
78
79
  jac_node_str = f'jac node "{node.loc}::{node.__class__.__name__}'
@@ -119,8 +120,6 @@ class FuseTypeInfoPass(Pass):
119
120
  self.__debug_print(
120
121
  f'Internal error happened while parsing "{e.obj.__class__.__name__}"'
121
122
  )
122
- traceback.print_exc()
123
- print(e)
124
123
 
125
124
  return node_handler
126
125