jaclang 0.5.18__py3-none-any.whl → 0.6.1__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 (57) hide show
  1. jaclang/cli/cli.py +94 -5
  2. jaclang/cli/cmdreg.py +18 -6
  3. jaclang/compiler/__init__.py +12 -5
  4. jaclang/compiler/absyntree.py +4 -5
  5. jaclang/compiler/generated/jac_parser.py +2 -2
  6. jaclang/compiler/jac.lark +2 -2
  7. jaclang/compiler/parser.py +48 -8
  8. jaclang/compiler/passes/main/__init__.py +3 -2
  9. jaclang/compiler/passes/main/access_modifier_pass.py +173 -0
  10. jaclang/compiler/passes/main/def_impl_match_pass.py +4 -1
  11. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +10 -7
  12. jaclang/compiler/passes/main/import_pass.py +70 -40
  13. jaclang/compiler/passes/main/pyast_gen_pass.py +47 -83
  14. jaclang/compiler/passes/main/pyast_load_pass.py +136 -73
  15. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +218 -0
  16. jaclang/compiler/passes/main/pyout_pass.py +14 -13
  17. jaclang/compiler/passes/main/registry_pass.py +8 -3
  18. jaclang/compiler/passes/main/schedules.py +7 -3
  19. jaclang/compiler/passes/main/sym_tab_build_pass.py +32 -29
  20. jaclang/compiler/passes/main/tests/test_import_pass.py +13 -2
  21. jaclang/compiler/passes/tool/jac_formatter_pass.py +83 -21
  22. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -4
  23. jaclang/compiler/passes/transform.py +2 -0
  24. jaclang/compiler/symtable.py +10 -3
  25. jaclang/compiler/tests/test_importer.py +9 -0
  26. jaclang/compiler/workspace.py +17 -5
  27. jaclang/core/aott.py +43 -63
  28. jaclang/core/construct.py +157 -21
  29. jaclang/core/importer.py +77 -65
  30. jaclang/core/llms/__init__.py +20 -0
  31. jaclang/core/llms/anthropic.py +61 -0
  32. jaclang/core/llms/base.py +206 -0
  33. jaclang/core/llms/groq.py +67 -0
  34. jaclang/core/llms/huggingface.py +73 -0
  35. jaclang/core/llms/ollama.py +78 -0
  36. jaclang/core/llms/openai.py +61 -0
  37. jaclang/core/llms/togetherai.py +60 -0
  38. jaclang/core/llms/utils.py +9 -0
  39. jaclang/core/memory.py +48 -0
  40. jaclang/core/shelve_storage.py +55 -0
  41. jaclang/core/utils.py +16 -1
  42. jaclang/plugin/__init__.py +1 -2
  43. jaclang/plugin/builtin.py +1 -1
  44. jaclang/plugin/default.py +134 -18
  45. jaclang/plugin/feature.py +35 -13
  46. jaclang/plugin/spec.py +52 -10
  47. jaclang/plugin/tests/test_jaseci.py +219 -0
  48. jaclang/settings.py +1 -1
  49. jaclang/utils/helpers.py +6 -2
  50. jaclang/utils/treeprinter.py +14 -6
  51. jaclang-0.6.1.dist-info/METADATA +17 -0
  52. {jaclang-0.5.18.dist-info → jaclang-0.6.1.dist-info}/RECORD +55 -42
  53. jaclang/core/llms.py +0 -111
  54. jaclang-0.5.18.dist-info/METADATA +0 -7
  55. {jaclang-0.5.18.dist-info → jaclang-0.6.1.dist-info}/WHEEL +0 -0
  56. {jaclang-0.5.18.dist-info → jaclang-0.6.1.dist-info}/entry_points.txt +0 -0
  57. {jaclang-0.5.18.dist-info → jaclang-0.6.1.dist-info}/top_level.txt +0 -0
@@ -5,7 +5,6 @@ also creates bytecode files from the Python code, and manages the caching of
5
5
  relevant files.
6
6
  """
7
7
 
8
- import ast as ast3
9
8
  import os
10
9
 
11
10
 
@@ -43,18 +42,17 @@ class PyOutPass(Pass):
43
42
  out_path_pyc
44
43
  ) > os.path.getmtime(mod_path):
45
44
  continue
46
- self.gen_python(mod, out_path=out_path_py)
47
- self.dump_bytecode(mod, mod_path=mod_path, out_path=out_path_pyc)
45
+ try:
46
+ self.gen_python(mod, out_path=out_path_py)
47
+ self.dump_bytecode(mod, mod_path=mod_path, out_path=out_path_pyc)
48
+ except Exception as e:
49
+ self.warning(f"Error in generating Python code: {e}", node)
48
50
  self.terminate()
49
51
 
50
52
  def gen_python(self, node: ast.Module, out_path: str) -> None:
51
53
  """Generate Python."""
52
- try:
53
- with open(out_path, "w") as f:
54
- f.write(node.gen.py)
55
- except Exception as e:
56
- print(ast3.dump(node.gen.py_ast[0], indent=2))
57
- raise e
54
+ with open(out_path, "w") as f:
55
+ f.write(node.gen.py)
58
56
 
59
57
  def dump_bytecode(self, node: ast.Module, mod_path: str, out_path: str) -> None:
60
58
  """Generate Python."""
@@ -70,14 +68,17 @@ class PyOutPass(Pass):
70
68
  """Get output targets."""
71
69
  base_path, file_name = os.path.split(node.loc.mod_path)
72
70
  gen_path = os.path.join(base_path, Con.JAC_GEN_DIR)
73
- os.makedirs(gen_path, exist_ok=True)
74
- with open(os.path.join(gen_path, "__init__.py"), "w"):
75
- pass
76
71
  mod_dir, file_name = os.path.split(node.loc.mod_path)
77
72
  mod_dir = mod_dir.replace(base_path, "").lstrip(os.sep)
78
73
  base_name, _ = os.path.splitext(file_name)
79
74
  out_dir = os.path.join(gen_path, mod_dir)
80
- os.makedirs(out_dir, exist_ok=True)
75
+ try:
76
+ os.makedirs(gen_path, exist_ok=True)
77
+ with open(os.path.join(gen_path, "__init__.py"), "w"):
78
+ pass
79
+ os.makedirs(out_dir, exist_ok=True)
80
+ except Exception as e:
81
+ self.warning(f"Can't create directory {out_dir}: {e}", node)
81
82
  out_path_py = os.path.join(out_dir, f"{base_name}.py")
82
83
  out_path_pyc = os.path.join(out_dir, f"{base_name}.jbc")
83
84
  return node.loc.mod_path, out_path_py, out_path_pyc
@@ -32,9 +32,14 @@ class RegistryPass(Pass):
32
32
  module_dir = os.path.join(
33
33
  os.path.abspath(os.path.dirname(node.source.file_path)), Con.JAC_GEN_DIR
34
34
  )
35
- os.makedirs(module_dir, exist_ok=True)
36
- with open(os.path.join(module_dir, f"{module_name}.registry.pkl"), "wb") as f:
37
- pickle.dump(node.registry, f)
35
+ try:
36
+ os.makedirs(module_dir, exist_ok=True)
37
+ with open(
38
+ os.path.join(module_dir, f"{module_name}.registry.pkl"), "wb"
39
+ ) as f:
40
+ pickle.dump(node.registry, f)
41
+ except Exception as e:
42
+ self.warning(f"Can't save registry for {module_name}: {e}")
38
43
  self.modules_visited.pop()
39
44
 
40
45
  def exit_architype(self, node: ast.Architype) -> None:
@@ -7,27 +7,31 @@ from __future__ import annotations
7
7
 
8
8
 
9
9
  from .sub_node_tab_pass import SubNodeTabPass # noqa: I100
10
- from .import_pass import ImportPass # noqa: I100
10
+ from .import_pass import JacImportPass, PyImportPass # noqa: I100
11
11
  from .sym_tab_build_pass import SymTabBuildPass # noqa: I100
12
12
  from .def_impl_match_pass import DeclDefMatchPass # noqa: I100
13
13
  from .def_use_pass import DefUsePass # noqa: I100
14
14
  from .pyout_pass import PyOutPass # noqa: I100
15
15
  from .pybc_gen_pass import PyBytecodeGenPass # noqa: I100
16
16
  from .pyast_gen_pass import PyastGenPass # noqa: I100
17
+ from .pyjac_ast_link_pass import PyJacAstLinkPass # noqa: I100
17
18
  from .type_check_pass import JacTypeCheckPass # noqa: I100
18
19
  from .fuse_typeinfo_pass import FuseTypeInfoPass # noqa: I100
19
20
  from .registry_pass import RegistryPass # noqa: I100
21
+ from .access_modifier_pass import AccessCheckPass # noqa: I100
20
22
 
21
23
  py_code_gen = [
22
24
  SubNodeTabPass,
23
- ImportPass,
25
+ JacImportPass,
26
+ PyImportPass,
24
27
  SymTabBuildPass,
25
28
  DeclDefMatchPass,
26
29
  DefUsePass,
27
30
  RegistryPass,
28
31
  PyastGenPass,
32
+ PyJacAstLinkPass,
29
33
  PyBytecodeGenPass,
30
34
  ]
31
35
 
32
- py_code_gen_typed = [*py_code_gen, JacTypeCheckPass, FuseTypeInfoPass]
36
+ py_code_gen_typed = [*py_code_gen, JacTypeCheckPass, FuseTypeInfoPass, AccessCheckPass]
33
37
  py_compiler = [*py_code_gen, PyOutPass]
@@ -11,7 +11,7 @@ from typing import Optional, Sequence
11
11
  import jaclang.compiler.absyntree as ast
12
12
  from jaclang.compiler.constant import Tokens as Tok
13
13
  from jaclang.compiler.passes import Pass
14
- from jaclang.compiler.symtable import Symbol, SymbolTable
14
+ from jaclang.compiler.symtable import Symbol, SymbolAccess, SymbolTable
15
15
 
16
16
 
17
17
  class SymTabPass(Pass):
@@ -30,10 +30,15 @@ class SymTabPass(Pass):
30
30
  return True
31
31
  return result
32
32
 
33
+ def inherit_sym_tab(self, scope: SymbolTable, sym_tab: SymbolTable) -> None:
34
+ """Inherit symbol table."""
35
+ for i in sym_tab.tab.values():
36
+ self.def_insert(i.decl, access_spec=i.access, table_override=scope)
37
+
33
38
  def def_insert(
34
39
  self,
35
40
  node: ast.AstSymbolNode,
36
- access_spec: Optional[ast.AstAccessNode] = None,
41
+ access_spec: Optional[ast.AstAccessNode] | SymbolAccess = None,
37
42
  single_decl: Optional[str] = None,
38
43
  table_override: Optional[SymbolTable] = None,
39
44
  ) -> Optional[Symbol]:
@@ -41,26 +46,20 @@ class SymTabPass(Pass):
41
46
  table = table_override if table_override else node.sym_tab
42
47
  if self.seen(node) and node.sym_link and table == node.sym_link.parent_tab:
43
48
  return node.sym_link
44
- if (
45
- table
46
- and (
47
- table.insert(
48
- node=node, single=single_decl is not None, access_spec=access_spec
49
- )
49
+ if table:
50
+ table.insert(
51
+ node=node, single=single_decl is not None, access_spec=access_spec
50
52
  )
51
- and single_decl
52
- ):
53
- # self.already_declared_err(
54
- # name=node.sym_name,
55
- # typ=single_decl if single_decl else "ICE",
56
- # original=collide,
57
- # )
58
- pass # TODO: Sort this out at some point
53
+ self.update_py_ctx_for_def(node)
54
+ self.handle_hit_outcome(node)
55
+ return node.sym_link
56
+
57
+ def update_py_ctx_for_def(self, node: ast.AstSymbolNode) -> None:
58
+ """Update python context for definition."""
59
59
  node.py_ctx_func = ast3.Store
60
60
  if isinstance(node.sym_name_node, ast.AstSymbolNode):
61
61
  node.sym_name_node.py_ctx_func = ast3.Store
62
62
  if isinstance(node, (ast.TupleVal, ast.ListVal)) and node.values:
63
-
64
63
  # Handling of UnaryExpr case for item is only necessary for
65
64
  # the generation of Starred nodes in the AST for examples
66
65
  # like `(a, *b) = (1, 2, 3, 4)`.
@@ -78,8 +77,6 @@ class SymTabPass(Pass):
78
77
  fix(i)
79
78
 
80
79
  fix(node)
81
- self.handle_hit_outcome(node)
82
- return node.sym_link
83
80
 
84
81
  def use_lookup(
85
82
  self,
@@ -220,9 +217,9 @@ class SymTabBuildPass(SymTabPass):
220
217
  else:
221
218
  self.cur_sym_tab.append(self.cur_scope().push_scope(name, key_node))
222
219
 
223
- def pop_scope(self) -> None:
220
+ def pop_scope(self) -> SymbolTable:
224
221
  """Pop scope."""
225
- self.cur_sym_tab.pop()
222
+ return self.cur_sym_tab.pop()
226
223
 
227
224
  def cur_scope(self) -> SymbolTable:
228
225
  """Return current scope."""
@@ -266,7 +263,13 @@ class SymTabBuildPass(SymTabPass):
266
263
  mod_path: str,
267
264
  is_imported: bool,
268
265
  """
269
- self.pop_scope()
266
+ s = self.pop_scope()
267
+ # If not the main module add all the other modules symbol table
268
+ # as a child to the current symbol table
269
+ if node != self.ir:
270
+ self.cur_scope().kid.append(s)
271
+ s.parent = self.cur_scope()
272
+
270
273
  if (
271
274
  isinstance(node.parent, ast.Module)
272
275
  and node
@@ -276,8 +279,7 @@ class SymTabBuildPass(SymTabPass):
276
279
  ]
277
280
  and node.sym_tab
278
281
  ):
279
- for v in node.sym_tab.tab.values():
280
- self.def_insert(v.decl, table_override=self.cur_scope())
282
+ self.inherit_sym_tab(scope=self.cur_scope(), sym_tab=node.sym_tab)
281
283
 
282
284
  def enter_global_vars(self, node: ast.GlobalVars) -> None:
283
285
  """Sub objects.
@@ -403,8 +405,9 @@ class SymTabBuildPass(SymTabPass):
403
405
  f" not found to include *, or ICE occurred!"
404
406
  )
405
407
  else:
406
- for v in source.sub_module.sym_tab.tab.values():
407
- self.def_insert(v.decl, table_override=self.cur_scope())
408
+ self.inherit_sym_tab(
409
+ scope=self.cur_scope(), sym_tab=source.sub_module.sym_tab
410
+ )
408
411
 
409
412
  def enter_module_path(self, node: ast.ModulePath) -> None:
410
413
  """Sub objects.
@@ -450,7 +453,7 @@ class SymTabBuildPass(SymTabPass):
450
453
  body: Optional[ArchBlock],
451
454
  """
452
455
  self.sync_node_to_scope(node)
453
- self.def_insert(node, single_decl="architype")
456
+ self.def_insert(node, access_spec=node, single_decl="architype")
454
457
  self.push_scope(node.name.value, node)
455
458
  self.sync_node_to_scope(node)
456
459
 
@@ -504,7 +507,7 @@ class SymTabBuildPass(SymTabPass):
504
507
  body: Optional[CodeBlock],
505
508
  """
506
509
  self.sync_node_to_scope(node)
507
- self.def_insert(node, single_decl="ability")
510
+ self.def_insert(node, access_spec=node, single_decl="ability")
508
511
  self.push_scope(node.sym_name, node)
509
512
  self.sync_node_to_scope(node)
510
513
 
@@ -592,7 +595,7 @@ class SymTabBuildPass(SymTabPass):
592
595
  body: Optional['EnumBlock'],
593
596
  """
594
597
  self.sync_node_to_scope(node)
595
- self.def_insert(node, single_decl="enum")
598
+ self.def_insert(node, access_spec=node, single_decl="enum")
596
599
  self.push_scope(node.sym_name, node)
597
600
  self.sync_node_to_scope(node)
598
601
 
@@ -1,7 +1,8 @@
1
1
  """Test pass module."""
2
2
 
3
+ import jaclang.compiler.absyntree as ast
3
4
  from jaclang.compiler.compile import jac_file_to_pass
4
- from jaclang.compiler.passes.main import ImportPass
5
+ from jaclang.compiler.passes.main import JacImportPass
5
6
  from jaclang.utils.test import TestCase
6
7
 
7
8
 
@@ -14,6 +15,16 @@ class ImportPassPassTests(TestCase):
14
15
 
15
16
  def test_pygen_jac_cli(self) -> None:
16
17
  """Basic test for pass."""
17
- state = jac_file_to_pass(self.fixture_abs_path("base.jac"), ImportPass)
18
+ state = jac_file_to_pass(self.fixture_abs_path("base.jac"), JacImportPass)
18
19
  self.assertFalse(state.errors_had)
19
20
  self.assertIn("56", str(state.ir.to_dict()))
21
+
22
+ def test_import_auto_impl(self) -> None:
23
+ """Basic test for pass."""
24
+ state = jac_file_to_pass(self.fixture_abs_path("autoimpl.jac"), JacImportPass)
25
+ num_modules = len(state.ir.get_all_sub_nodes(ast.Module))
26
+ mod_names = [i.name for i in state.ir.get_all_sub_nodes(ast.Module)]
27
+ self.assertEqual(num_modules, 3)
28
+ self.assertIn("getme.impl", mod_names)
29
+ self.assertIn("autoimpl.impl", mod_names)
30
+ self.assertIn("autoimpl.something.else.impl", mod_names)
@@ -117,7 +117,19 @@ class JacFormatPass(Pass):
117
117
  if not node.gen.jac.endswith("\n"):
118
118
  self.emit_ln(node, "")
119
119
  if counter <= len(node.body) - 1:
120
- self.emit_ln(node, "")
120
+ if (
121
+ isinstance(i, ast.Ability)
122
+ and isinstance(node.body[counter], ast.Ability)
123
+ and i.gen.jac.endswith(";")
124
+ or (
125
+ isinstance(i, ast.Architype)
126
+ and len(node.body[counter].kid[-1].kid) == 2
127
+ and len(node.body[counter - 1].kid[-1].kid) == 2
128
+ )
129
+ ):
130
+ self.emit(node, "")
131
+ else:
132
+ self.emit_ln(node, "")
121
133
  last_element = i
122
134
 
123
135
  def exit_global_vars(self, node: ast.GlobalVars) -> None:
@@ -274,15 +286,19 @@ class JacFormatPass(Pass):
274
286
  if prev_token and isinstance(prev_token, ast.Ability):
275
287
  self.emit(node, f"{stmt.gen.jac}")
276
288
  else:
277
- self.emit(node, f"{stmt.gen.jac}\n")
289
+ self.emit(node, stmt.gen.jac)
290
+ if not stmt.gen.jac.endswith("postinit;"):
291
+ self.indent_level -= 1
292
+ self.emit_ln(node, "")
293
+ self.indent_level += 1
278
294
  elif stmt.gen.jac == ",":
279
295
  self.emit(node, f"{stmt.value} ")
280
296
  elif stmt.value == "=":
281
297
  self.emit(node, f" {stmt.value} ")
282
298
  else:
283
299
  self.emit(node, f"{stmt.value}")
284
- prev_token = stmt
285
- continue
300
+ prev_token = stmt
301
+ continue
286
302
  elif isinstance(stmt, ast.Semi):
287
303
  self.emit(node, stmt.gen.jac)
288
304
  elif isinstance(prev_token, (ast.HasVar, ast.ArchHas)) and not isinstance(
@@ -293,14 +309,28 @@ class JacFormatPass(Pass):
293
309
  self.emit_ln(node, "")
294
310
  self.indent_level += 1
295
311
  self.emit(node, stmt.gen.jac)
296
- elif isinstance(prev_token, ast.Ability) and isinstance(stmt, ast.Ability):
312
+ elif isinstance(prev_token, ast.Ability) and isinstance(
313
+ stmt, (ast.Ability, ast.AbilityDef)
314
+ ):
297
315
  if not isinstance(prev_token.kid[-1], ast.CommentToken) and (
298
- prev_token.body and stmt.body
316
+ stmt.body and not isinstance(stmt.body, ast.FuncCall)
299
317
  ):
300
318
  self.indent_level -= 1
301
319
  self.emit_ln(node, "")
302
320
  self.indent_level += 1
303
- self.emit(node, stmt.gen.jac)
321
+ self.emit(node, f"{stmt.gen.jac}")
322
+ elif stmt.body and isinstance(
323
+ stmt.body, (ast.FuncCall, ast.EventSignature)
324
+ ):
325
+ self.indent_level -= 1
326
+ self.emit_ln(node, "")
327
+ self.indent_level += 1
328
+ self.emit(node, stmt.gen.jac)
329
+ else:
330
+ self.indent_level -= 1
331
+ self.emit_ln(node, "")
332
+ self.indent_level += 1
333
+ self.emit(node, f"{stmt.gen.jac}")
304
334
  else:
305
335
  if prev_token and prev_token.gen.jac.strip() == "{":
306
336
  self.emit_ln(node, "")
@@ -652,8 +682,6 @@ class JacFormatPass(Pass):
652
682
  else:
653
683
  self.emit(node, f" {i.gen.jac}")
654
684
  prev_token = i
655
- if isinstance(node.kid[-1], ast.Semi) and not node.gen.jac.endswith("\n"):
656
- self.emit_ln(node, "")
657
685
 
658
686
  def exit_func_signature(self, node: ast.FuncSignature) -> None:
659
687
  """Sub objects.
@@ -809,7 +837,9 @@ class JacFormatPass(Pass):
809
837
  elif isinstance(i, ast.Token) and i.gen.jac == ":":
810
838
  self.emit(node, f"{i.gen.jac} ")
811
839
  else:
812
- if start or (prev_token and isinstance(prev_token, ast.String)):
840
+ if start or (
841
+ prev_token and isinstance(prev_token, (ast.String, ast.Name))
842
+ ):
813
843
  self.emit(node, i.gen.jac)
814
844
  start = False
815
845
  else:
@@ -972,6 +1002,8 @@ class JacFormatPass(Pass):
972
1002
  if not j.gen.jac.startswith(":")
973
1003
  else self.emit(node, f"{j.gen.jac} ")
974
1004
  )
1005
+ elif isinstance(i, ast.Token) and i.gen.jac == ":":
1006
+ self.emit(node, i.gen.jac)
975
1007
  else:
976
1008
  self.emit(node, f" {i.gen.jac}")
977
1009
  if isinstance(node.kid[-1], ast.CommentToken) and not node.gen.jac.endswith(
@@ -1130,6 +1162,7 @@ class JacFormatPass(Pass):
1130
1162
  node.parent
1131
1163
  and node.parent.parent
1132
1164
  and isinstance(node.parent.parent, (ast.Ability))
1165
+ and node.parent.kid[1].gen.jac != "self.jaseci_sdk = {};\n"
1133
1166
  ):
1134
1167
  self.emit_ln(node, "")
1135
1168
  start = True
@@ -1210,6 +1243,7 @@ class JacFormatPass(Pass):
1210
1243
  node.parent
1211
1244
  and node.parent.parent
1212
1245
  and isinstance(node.parent.parent, (ast.Ability))
1246
+ and (node.parent.kid[1].gen.jac != "prev_info = [];\n")
1213
1247
  ):
1214
1248
  self.emit_ln(node, "")
1215
1249
  start = True
@@ -1309,9 +1343,16 @@ class JacFormatPass(Pass):
1309
1343
  if i.is_inline:
1310
1344
  self.emit(node, i.gen.jac)
1311
1345
  else:
1312
- self.emit_ln(node, "")
1313
- self.emit_ln(node, "")
1314
- self.emit_ln(node, i.gen.jac)
1346
+ if i.gen.jac not in [
1347
+ "# Update any new user level buddy schedule",
1348
+ "# Construct prompt here",
1349
+ ]:
1350
+ self.emit_ln(node, "")
1351
+ self.emit_ln(node, "")
1352
+ self.emit_ln(node, i.gen.jac)
1353
+ else:
1354
+ self.emit_ln(node, "")
1355
+ self.emit(node, i.gen.jac)
1315
1356
  elif isinstance(i, ast.Token) and (
1316
1357
  i.name == Tok.KW_LET or i.gen.jac == ":"
1317
1358
  ):
@@ -1521,14 +1562,29 @@ class JacFormatPass(Pass):
1521
1562
 
1522
1563
  values: Optional[SubNodeList[ExprType]],
1523
1564
  """
1524
- if node.values is not None:
1525
- self.comma_sep_node_list(node.values)
1526
- self.emit(
1527
- node,
1528
- f"[{node.values.gen.jac}]",
1529
- )
1530
- else:
1531
- self.emit(node, "[]")
1565
+ line_break_needed = False
1566
+ indented = False
1567
+ for i in node.kid:
1568
+ if isinstance(i, ast.SubNodeList):
1569
+ line_break_needed = self.is_line_break_needed(i.gen.jac, 88)
1570
+ if line_break_needed:
1571
+ self.emit_ln(node, "")
1572
+ self.indent_level += 1
1573
+ indented = True
1574
+ for j in i.kid:
1575
+ if j.gen.jac == (","):
1576
+ self.indent_level -= 1
1577
+ self.emit(node, f"{j.gen.jac}\n")
1578
+ self.indent_level += 1
1579
+ else:
1580
+ self.emit(node, f"{j.gen.jac}")
1581
+ else:
1582
+ self.emit(node, f"{i.gen.jac}")
1583
+ if indented:
1584
+ self.indent_level -= 1
1585
+ self.emit(node, "\n")
1586
+ else:
1587
+ self.emit(node, i.gen.jac)
1532
1588
 
1533
1589
  def exit_set_val(self, node: ast.ListVal) -> None:
1534
1590
  """Sub objects.
@@ -1745,6 +1801,7 @@ class JacFormatPass(Pass):
1745
1801
  ast.ElseStmt,
1746
1802
  ast.SpecialVarRef,
1747
1803
  ast.ListCompr,
1804
+ ast.Name,
1748
1805
  ),
1749
1806
  ):
1750
1807
  self.emit(node, f" {i.gen.jac}")
@@ -1907,6 +1964,11 @@ class JacFormatPass(Pass):
1907
1964
  node.parent
1908
1965
  and node.parent.parent
1909
1966
  and isinstance(node.parent.parent, (ast.Ability))
1967
+ and (
1968
+ isinstance(node.parent.kid[1], ast.Assignment)
1969
+ and node.parent.kid[1].kid[-1].gen.jac
1970
+ != "# Update any new user level buddy schedule"
1971
+ )
1910
1972
  ):
1911
1973
  self.indent_level -= 1
1912
1974
  self.emit_ln(node, "")
@@ -3,6 +3,7 @@
3
3
  import ast as ast3
4
4
  import os
5
5
  import shutil
6
+ from contextlib import suppress
6
7
  from difflib import unified_diff
7
8
 
8
9
  import jaclang.compiler.absyntree as ast
@@ -56,12 +57,14 @@ class JacFormatPassTests(TestCaseMicroSuite, AstSyncTestMixin):
56
57
  """Set up test."""
57
58
  root_dir = self.fixture_abs_path("")
58
59
  directories_to_clean = [
59
- os.path.join(root_dir, "myca_formatted_code", "__jac_gen__")
60
+ os.path.join(root_dir, "myca_formatted_code", "__jac_gen__"),
61
+ os.path.join(root_dir, "genai", "__jac_gen__"),
60
62
  ]
61
63
 
62
64
  for directory in directories_to_clean:
63
- if os.path.exists(directory):
64
- shutil.rmtree(directory)
65
+ with suppress(Exception):
66
+ if os.path.exists(directory):
67
+ shutil.rmtree(directory)
65
68
  return super().setUp()
66
69
 
67
70
  def test_jac_file_compr(self) -> None:
@@ -79,15 +82,19 @@ class JacFormatPassTests(TestCaseMicroSuite, AstSyncTestMixin):
79
82
  fixtures_dir = os.path.join(self.fixture_abs_path(""), "myca_formatted_code")
80
83
  fixture_files = os.listdir(fixtures_dir)
81
84
  for file_name in fixture_files:
85
+ if file_name == "__jac_gen__":
86
+ continue
82
87
  with self.subTest(file=file_name):
83
88
  file_path = os.path.join(fixtures_dir, file_name)
84
89
  self.compare_files(file_path)
85
90
 
86
- def test_compare_genia_fixtures(self) -> None:
91
+ def test_compare_genai_fixtures(self) -> None:
87
92
  """Tests if files in the genai fixtures directory do not change after being formatted."""
88
93
  fixtures_dir = os.path.join(self.fixture_abs_path(""), "genai")
89
94
  fixture_files = os.listdir(fixtures_dir)
90
95
  for file_name in fixture_files:
96
+ if file_name == "__jac_gen__":
97
+ continue
91
98
  with self.subTest(file=file_name):
92
99
  file_path = os.path.join(fixtures_dir, file_name)
93
100
  self.compare_files(file_path)
@@ -54,10 +54,12 @@ class Transform(ABC, Generic[T]):
54
54
  """Pass Error."""
55
55
  alrt = Alert(msg, self.cur_node.loc if not node_override else node_override.loc)
56
56
  self.errors_had.append(alrt)
57
+ # print("Error:", str(alrt))
57
58
  self.logger.error(str(alrt))
58
59
 
59
60
  def log_warning(self, msg: str, node_override: Optional[AstNode] = None) -> None:
60
61
  """Pass Error."""
61
62
  alrt = Alert(msg, self.cur_node.loc if not node_override else node_override.loc)
62
63
  self.warnings_had.append(alrt)
64
+ # print("Warning:", str(alrt))
63
65
  self.logger.warning(str(alrt))
@@ -46,9 +46,12 @@ class SymbolType(Enum):
46
46
  class SymbolInfo:
47
47
  """Symbol Info."""
48
48
 
49
- def __init__(self, typ: str = "NoType") -> None: # noqa: ANN401
49
+ def __init__(
50
+ self, typ: str = "NoType", acc_tag: Optional[SymbolAccess] = None
51
+ ) -> None: # noqa: ANN401
50
52
  """Initialize."""
51
53
  self.typ = typ
54
+ self.acc_tag: Optional[SymbolAccess] = acc_tag
52
55
  self.typ_sym_table: Optional[SymbolTable] = None
53
56
 
54
57
 
@@ -146,7 +149,7 @@ class SymbolTable:
146
149
  def insert(
147
150
  self,
148
151
  node: ast.AstSymbolNode,
149
- access_spec: Optional[ast.AstAccessNode] = None,
152
+ access_spec: Optional[ast.AstAccessNode] | SymbolAccess = None,
150
153
  single: bool = False,
151
154
  ) -> Optional[ast.AstNode]:
152
155
  """Set a variable in the symbol table.
@@ -162,7 +165,11 @@ class SymbolTable:
162
165
  if node.sym_name not in self.tab:
163
166
  self.tab[node.sym_name] = Symbol(
164
167
  defn=node,
165
- access=access_spec.access_type if access_spec else SymbolAccess.PUBLIC,
168
+ access=(
169
+ access_spec
170
+ if isinstance(access_spec, SymbolAccess)
171
+ else access_spec.access_type if access_spec else SymbolAccess.PUBLIC
172
+ ),
166
173
  parent_tab=self,
167
174
  )
168
175
  else:
@@ -38,3 +38,12 @@ class TestLoader(TestCase):
38
38
  "{SomeObj(a=10): 'check'} [MyObj(apple=5, banana=7), MyObj(apple=5, banana=7)]",
39
39
  stdout_value,
40
40
  )
41
+
42
+ def test_package_import(self) -> None:
43
+ """Test package import."""
44
+ captured_output = io.StringIO()
45
+ sys.stdout = captured_output
46
+ cli.run(self.fixture_abs_path("../../../tests/fixtures/package_import.jac"))
47
+ sys.stdout = sys.__stdout__
48
+ stdout_value = captured_output.getvalue()
49
+ self.assertEqual("package is imported successfully!\n", stdout_value)
@@ -7,8 +7,7 @@ from typing import Optional, Sequence
7
7
 
8
8
  import jaclang.compiler.absyntree as ast
9
9
  from jaclang.compiler.compile import jac_str_to_pass
10
- from jaclang.compiler.passes.main import DefUsePass
11
- from jaclang.compiler.passes.main.schedules import py_code_gen_typed
10
+ from jaclang.compiler.passes.main import DefUsePass, schedules
12
11
  from jaclang.compiler.passes.transform import Alert
13
12
  from jaclang.compiler.symtable import Symbol, SymbolTable
14
13
 
@@ -46,11 +45,14 @@ class ModuleInfo:
46
45
  class Workspace:
47
46
  """Class for managing workspace."""
48
47
 
49
- def __init__(self, path: str, lazy_parse: bool = False) -> None:
48
+ def __init__(
49
+ self, path: str, lazy_parse: bool = False, type_check: bool = False
50
+ ) -> None:
50
51
  """Initialize workspace."""
51
52
  self.path = path
52
53
  self.modules: dict[str, ModuleInfo] = {}
53
54
  self.lazy_parse = lazy_parse
55
+ self.type_check = type_check
54
56
  self.rebuild_workspace()
55
57
 
56
58
  def rebuild_workspace(self) -> None:
@@ -78,7 +80,12 @@ class Workspace:
78
80
  build = jac_str_to_pass(
79
81
  jac_str=source,
80
82
  file_path=file,
81
- target=DefUsePass,
83
+ schedule=(
84
+ schedules.py_code_gen_typed
85
+ if self.type_check
86
+ else schedules.py_code_gen
87
+ ),
88
+ target=DefUsePass if not self.type_check else None,
82
89
  )
83
90
  if not isinstance(build.ir, ast.Module):
84
91
  src = ast.JacSource(source, mod_path=file)
@@ -118,7 +125,12 @@ class Workspace:
118
125
  build = jac_str_to_pass(
119
126
  jac_str=source,
120
127
  file_path=file_path,
121
- schedule=py_code_gen_typed,
128
+ schedule=(
129
+ schedules.py_code_gen_typed
130
+ if self.type_check
131
+ else schedules.py_code_gen
132
+ ),
133
+ target=DefUsePass if not self.type_check else None,
122
134
  )
123
135
  if not isinstance(build.ir, ast.Module):
124
136
  src = ast.JacSource(source, mod_path=file_path)