jaclang 0.8.1__py3-none-any.whl → 0.8.3__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 (84) hide show
  1. jaclang/__init__.py +6 -0
  2. jaclang/cli/cli.py +21 -50
  3. jaclang/compiler/codeinfo.py +0 -1
  4. jaclang/compiler/constant.py +2 -0
  5. jaclang/compiler/jac.lark +17 -10
  6. jaclang/compiler/larkparse/jac_parser.py +2 -2
  7. jaclang/compiler/parser.py +34 -10
  8. jaclang/compiler/passes/main/__init__.py +2 -14
  9. jaclang/compiler/passes/main/annex_pass.py +2 -8
  10. jaclang/compiler/passes/main/cfg_build_pass.py +38 -12
  11. jaclang/compiler/passes/main/import_pass.py +3 -11
  12. jaclang/compiler/passes/main/pyast_gen_pass.py +246 -592
  13. jaclang/compiler/passes/main/sem_def_match_pass.py +67 -0
  14. jaclang/compiler/passes/main/sym_tab_build_pass.py +8 -0
  15. jaclang/compiler/passes/main/sym_tab_link_pass.py +2 -5
  16. jaclang/compiler/passes/main/tests/fixtures/sem_def_match.impl.jac +12 -0
  17. jaclang/compiler/passes/main/tests/fixtures/sem_def_match.jac +31 -0
  18. jaclang/compiler/passes/main/tests/test_cfg_build_pass.py +2 -8
  19. jaclang/compiler/passes/main/tests/test_decl_impl_match_pass.py +7 -8
  20. jaclang/compiler/passes/main/tests/test_import_pass.py +5 -18
  21. jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +2 -6
  22. jaclang/compiler/passes/main/tests/test_sem_def_match_pass.py +38 -0
  23. jaclang/compiler/passes/main/tests/test_sub_node_pass.py +1 -3
  24. jaclang/compiler/passes/main/tests/test_sym_tab_link_pass.py +20 -17
  25. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +259 -106
  26. jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -0
  27. jaclang/compiler/passes/tool/tests/fixtures/archetype_frmt.jac +14 -0
  28. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +5 -4
  29. jaclang/compiler/passes/tool/tests/fixtures/has_frmt.jac +13 -0
  30. jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +6 -0
  31. jaclang/compiler/passes/tool/tests/fixtures/simple_walk_fmt.jac +3 -3
  32. jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +9 -0
  33. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +25 -3
  34. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +2 -2
  35. jaclang/compiler/program.py +23 -60
  36. jaclang/compiler/tests/fixtures/pkg_import_lib_py/__init__.py +2 -8
  37. jaclang/compiler/tests/fixtures/pkg_import_lib_py/sub/__init__.py +1 -5
  38. jaclang/compiler/tests/test_importer.py +10 -13
  39. jaclang/compiler/unitree.py +88 -16
  40. jaclang/langserve/__init__.jac +1 -1
  41. jaclang/langserve/engine.jac +113 -108
  42. jaclang/langserve/server.jac +17 -2
  43. jaclang/langserve/tests/server_test/test_lang_serve.py +138 -46
  44. jaclang/langserve/tests/server_test/utils.py +35 -9
  45. jaclang/langserve/tests/test_sem_tokens.py +1 -1
  46. jaclang/langserve/tests/test_server.py +3 -7
  47. jaclang/runtimelib/archetype.py +127 -5
  48. jaclang/runtimelib/importer.py +51 -94
  49. jaclang/runtimelib/machine.py +391 -268
  50. jaclang/runtimelib/meta_importer.py +86 -0
  51. jaclang/runtimelib/tests/fixtures/graph_purger.jac +24 -26
  52. jaclang/runtimelib/tests/fixtures/other_root_access.jac +25 -16
  53. jaclang/runtimelib/tests/test_jaseci.py +3 -1
  54. jaclang/tests/fixtures/arch_rel_import_creation.jac +23 -23
  55. jaclang/tests/fixtures/async_ability.jac +43 -10
  56. jaclang/tests/fixtures/async_function.jac +18 -0
  57. jaclang/tests/fixtures/async_walker.jac +17 -12
  58. jaclang/tests/fixtures/create_dynamic_archetype.jac +25 -28
  59. jaclang/tests/fixtures/deep/deeper/deep_outer_import.jac +7 -4
  60. jaclang/tests/fixtures/deep/deeper/snd_lev.jac +2 -2
  61. jaclang/tests/fixtures/deep/deeper/snd_lev_dup.jac +6 -0
  62. jaclang/tests/fixtures/deep/one_lev.jac +2 -2
  63. jaclang/tests/fixtures/deep/one_lev_dup.jac +4 -3
  64. jaclang/tests/fixtures/dynamic_archetype.jac +19 -12
  65. jaclang/tests/fixtures/foo.jac +14 -22
  66. jaclang/tests/fixtures/jac_from_py.py +1 -1
  67. jaclang/tests/fixtures/jp_importer.jac +6 -6
  68. jaclang/tests/fixtures/jp_importer_auto.jac +5 -3
  69. jaclang/tests/fixtures/unicode_strings.jac +24 -0
  70. jaclang/tests/fixtures/walker_update.jac +5 -7
  71. jaclang/tests/test_language.py +138 -140
  72. jaclang/tests/test_reference.py +9 -4
  73. jaclang/tests/test_typecheck.py +13 -26
  74. jaclang/utils/lang_tools.py +7 -5
  75. jaclang/utils/module_resolver.py +23 -0
  76. {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/METADATA +1 -1
  77. {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/RECORD +79 -72
  78. jaclang/compiler/passes/main/tests/fixtures/main_err.jac +0 -6
  79. jaclang/compiler/passes/main/tests/fixtures/second_err.jac +0 -4
  80. jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +0 -644
  81. jaclang/compiler/passes/tool/tests/test_doc_ir_gen_pass.py +0 -29
  82. jaclang/tests/fixtures/deep/deeper/__init__.jac +0 -1
  83. {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/WHEEL +0 -0
  84. {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/entry_points.txt +0 -0
@@ -546,6 +546,22 @@ class JacParser(Transform[uni.Source, uni.Module]):
546
546
  )
547
547
  return impl
548
548
 
549
+ def sem_def(self, _: None) -> uni.SemDef:
550
+ """Grammar rule.
551
+
552
+ sem_def: KW_SEM dotted_name EQ multistring SEMI
553
+ """
554
+ self.consume_token(Tok.KW_SEM)
555
+ target = self.extract_from_list(self.consume(list), uni.NameAtom)
556
+ self.consume_token(Tok.EQ)
557
+ value = self.consume(uni.String)
558
+ self.consume_token(Tok.SEMI)
559
+ return uni.SemDef(
560
+ target=target,
561
+ value=value,
562
+ kid=self.flat_cur_nodes,
563
+ )
564
+
549
565
  def impl_spec(
550
566
  self, _: None
551
567
  ) -> Sequence[uni.Expr] | uni.FuncSignature | uni.EventSignature:
@@ -1749,10 +1765,10 @@ class JacParser(Transform[uni.Source, uni.Module]):
1749
1765
  """
1750
1766
  return self._binary_expr_unwind(self.cur_nodes)
1751
1767
 
1752
- def ds_spawn(self, _: None) -> uni.Expr:
1768
+ def os_spawn(self, _: None) -> uni.Expr:
1753
1769
  """Grammar rule.
1754
1770
 
1755
- ds_spawn: (ds_spawn KW_SPAWN)? unpack
1771
+ os_spawn: (os_spawn KW_SPAWN)? unpack
1756
1772
  """
1757
1773
  return self._binary_expr_unwind(self.cur_nodes)
1758
1774
 
@@ -1862,15 +1878,16 @@ class JacParser(Transform[uni.Source, uni.Module]):
1862
1878
  def atomic_call(self, _: None) -> uni.FuncCall:
1863
1879
  """Grammar rule.
1864
1880
 
1865
- atomic_call: atomic_chain LPAREN param_list? (KW_BY atomic_call)? RPAREN
1881
+ atomic_call: atomic_chain LPAREN param_list? by_call? RPAREN by_call?
1866
1882
  """
1867
1883
  genai_call: uni.FuncCall | None = None
1868
1884
  target = self.consume(uni.Expr)
1869
1885
  self.consume_token(Tok.LPAREN)
1870
1886
  params_sn = self.match(list)
1871
- if self.match_token(Tok.KW_BY):
1872
- genai_call = self.consume(uni.FuncCall)
1887
+ genai_call = self.match(uni.FuncCall)
1873
1888
  self.consume_token(Tok.RPAREN)
1889
+ body_genai_call = self.match(uni.FuncCall)
1890
+
1874
1891
  return uni.FuncCall(
1875
1892
  target=target,
1876
1893
  params=(
@@ -1879,9 +1896,20 @@ class JacParser(Transform[uni.Source, uni.Module]):
1879
1896
  else []
1880
1897
  ),
1881
1898
  genai_call=genai_call,
1899
+ body_genai_call=body_genai_call,
1882
1900
  kid=self.flat_cur_nodes,
1883
1901
  )
1884
1902
 
1903
+ def by_call(self, _: None) -> uni.FuncCall:
1904
+ """Grammar rule.
1905
+
1906
+ by_call: KW_BY expression
1907
+ """
1908
+ self.consume_token(Tok.KW_BY)
1909
+ if call := self.match(uni.FuncCall):
1910
+ return call
1911
+ raise ValueError("Expected a function call")
1912
+
1885
1913
  def index_slice(self, _: None) -> uni.IndexSlice:
1886
1914
  """Grammar rule.
1887
1915
 
@@ -2896,18 +2924,14 @@ class JacParser(Transform[uni.Source, uni.Module]):
2896
2924
  def event_clause(self, _: None) -> uni.EventSignature:
2897
2925
  """Grammar rule.
2898
2926
 
2899
- event_clause: KW_WITH expression? (KW_EXIT | KW_ENTRY) (RETURN_HINT expression)?
2927
+ event_clause: KW_WITH expression? (KW_EXIT | KW_ENTRY)
2900
2928
  """
2901
- return_spec: uni.Expr | None = None
2902
2929
  self.consume_token(Tok.KW_WITH)
2903
2930
  type_specs = self.match(uni.Expr)
2904
2931
  event = self.match_token(Tok.KW_EXIT) or self.consume_token(Tok.KW_ENTRY)
2905
- if self.match_token(Tok.RETURN_HINT):
2906
- return_spec = self.consume(uni.Expr)
2907
2932
  return uni.EventSignature(
2908
2933
  event=event,
2909
2934
  arch_tag_info=type_specs,
2910
- return_type=return_spec,
2911
2935
  kid=self.cur_nodes,
2912
2936
  )
2913
2937
 
@@ -1,12 +1,11 @@
1
1
  """Collection of passes for Jac IR."""
2
2
 
3
- from enum import Enum
4
-
5
3
  from ..transform import Alert, Transform # noqa: I100
6
4
  from .annex_pass import JacAnnexPass # noqa: I100
7
5
  from .sym_tab_build_pass import SymTabBuildPass, UniPass # noqa: I100
8
6
  from .sym_tab_link_pass import SymTabLinkPass # noqa: I100
9
7
  from .def_use_pass import DefUsePass # noqa: I100
8
+ from .sem_def_match_pass import SemDefMatchPass # noqa: I100
10
9
  from .import_pass import JacImportDepsPass, PyImportDepsPass # noqa: I100
11
10
  from .def_impl_match_pass import DeclImplMatchPass # noqa: I100
12
11
  from .pyast_load_pass import PyastBuildPass # type: ignore # noqa: I100
@@ -17,17 +16,6 @@ from .pyjac_ast_link_pass import PyJacAstLinkPass # noqa: I100
17
16
  from .inheritance_pass import InheritancePass # noqa: I100
18
17
 
19
18
 
20
- class CompilerMode(Enum):
21
- """Compiler modes."""
22
-
23
- PARSE = "PARSE"
24
- NO_CGEN = "NO_CGEN"
25
- NO_CGEN_SINGLE = "NO_CGEN_SINGLE"
26
- COMPILE = "COMPILE"
27
- COMPILE_SINGLE = "COMPILE_SINGLE"
28
- TYPECHECK = "TYPECHECK"
29
-
30
-
31
19
  __all__ = [
32
20
  "Alert",
33
21
  "Transform",
@@ -39,10 +27,10 @@ __all__ = [
39
27
  "SymTabLinkPass",
40
28
  "DeclImplMatchPass",
41
29
  "DefUsePass",
30
+ "SemDefMatchPass",
42
31
  "PyastBuildPass",
43
32
  "PyastGenPass",
44
33
  "PyBytecodeGenPass",
45
- "CompilerMode",
46
34
  "CFGBuildPass",
47
35
  "PyJacAstLinkPass",
48
36
  "InheritancePass",
@@ -48,8 +48,6 @@ class JacAnnexPass(Transform[uni.Module, uni.Module]):
48
48
 
49
49
  def load_annexes(self, jac_program: JacProgram, node: uni.Module) -> None:
50
50
  """Parse and attach annex modules to the node."""
51
- from jaclang.compiler.program import CompilerMode
52
-
53
51
  if node.stub_only or not self.mod_path.endswith(".jac"):
54
52
  return
55
53
  if not self.mod_path:
@@ -64,9 +62,7 @@ class JacAnnexPass(Transform[uni.Module, uni.Module]):
64
62
  path.startswith(f"{self.base_path}.")
65
63
  or os.path.dirname(path) == self.impl_folder
66
64
  ):
67
- mod = jac_program.compile(
68
- file_path=path, mode=CompilerMode.NO_CGEN_SINGLE
69
- )
65
+ mod = jac_program.compile(file_path=path, no_cgen=True)
70
66
  if mod:
71
67
  node.impl_mod.append(mod)
72
68
 
@@ -78,8 +74,6 @@ class JacAnnexPass(Transform[uni.Module, uni.Module]):
78
74
  or os.path.dirname(path) == self.test_folder
79
75
  )
80
76
  ):
81
- mod = jac_program.compile(
82
- file_path=path, mode=CompilerMode.NO_CGEN_SINGLE
83
- )
77
+ mod = jac_program.compile(file_path=path, no_cgen=True)
84
78
  if mod:
85
79
  node.test_mod.append(mod)
@@ -10,6 +10,8 @@ The CFG provides a foundation for data flow analysis, optimization, and understa
10
10
  The pass also includes functionality to coalesce basic blocks and generate visual representations of the CFG.
11
11
  """
12
12
 
13
+ from typing import Sequence
14
+
13
15
  import jaclang.compiler.unitree as uni
14
16
  from jaclang.compiler.passes import UniPass
15
17
 
@@ -65,26 +67,48 @@ class CFGBuildPass(UniPass):
65
67
  else:
66
68
  target.bb_in = [source]
67
69
 
70
+ def get_code_block_sequence(
71
+ self, node: uni.CodeBlockStmt
72
+ ) -> list[uni.UniCFGNode] | None:
73
+ """Get code block sequence."""
74
+ sequence: list[uni.UniCFGNode] = []
75
+ if hasattr(node, "body") and isinstance(node.body, Sequence):
76
+ for bbs in node.body:
77
+ if isinstance(bbs, uni.UniCFGNode):
78
+ sequence.append(bbs)
79
+ if sequence:
80
+ return sequence
81
+ else:
82
+ return None
83
+ else:
84
+ return None
85
+
68
86
  def enter_node(self, node: uni.UniNode) -> None:
69
87
  """Enter BasicBlockStmt nodes."""
70
88
  if isinstance(node, uni.UniCFGNode) and not isinstance(node, uni.Semi):
71
- if node.parent and isinstance(node, uni.CodeBlockStmt) and self.first_exit:
72
- bb_stmts = [
73
- bbs for bbs in node.parent.kid if isinstance(bbs, uni.UniCFGNode)
74
- ]
89
+ # check if the current node is a CodeBlockStmt in a sequence of statements
90
+ bb_stmts = self.get_code_block_sequence(node.parent)
91
+ if (
92
+ isinstance(node, uni.CodeBlockStmt)
93
+ and node.parent
94
+ and (not (isinstance(node, (uni.ElseIf, uni.ElseStmt))))
95
+ and bb_stmts
96
+ and self.first_exit
97
+ ):
98
+ # bb_stmts = self.get_code_block_sequence(node.parent)
99
+ # bb_stmts = [
100
+ # bbs for bbs in node.parent.body if isinstance(bbs, uni.UniCFGNode)
101
+ # ]
75
102
  if (
76
- node.parent.parent
77
- and isinstance(node.parent.parent, uni.Archetype)
103
+ node.parent
104
+ and isinstance(node.parent, uni.Archetype)
78
105
  # and isinstance(node.parent.parent, uni.BasicBlockStmt)
79
106
  ):
80
- parent_obj = node.parent.parent
107
+ parent_obj = node.parent
81
108
  if parent_obj:
82
109
  self.link_bbs(parent_obj, node)
83
110
  elif bb_stmts[0] == node:
84
- if (
85
- isinstance(node.parent.parent, uni.ModuleCode)
86
- and self.to_connect
87
- ):
111
+ if isinstance(node.parent, uni.ModuleCode) and self.to_connect:
88
112
  for bb in self.to_connect:
89
113
  self.link_bbs(bb, node)
90
114
  self.to_connect.remove(bb) # if self.to_connect:
@@ -92,7 +116,9 @@ class CFGBuildPass(UniPass):
92
116
  parent_bb = self.get_parent_bb_stmt(node)
93
117
  if parent_bb:
94
118
  self.link_bbs(parent_bb, node)
95
- elif self.to_connect:
119
+ elif self.to_connect and not isinstance(
120
+ node, (uni.ElseIf, uni.ElseStmt)
121
+ ):
96
122
  to_remove = []
97
123
  for parent in self.to_connect:
98
124
  if isinstance(parent, uni.UniCFGNode):
@@ -63,8 +63,6 @@ class JacImportDepsPass(Transform[uni.Module, uni.Module]):
63
63
 
64
64
  def import_jac_module(self, node: uni.ModulePath) -> None:
65
65
  """Import a module."""
66
- from jaclang.compiler.passes.main import CompilerMode as CMode
67
-
68
66
  target = node.resolve_relative_path()
69
67
  # If the module is a package (dir)
70
68
  if os.path.isdir(target):
@@ -83,15 +81,11 @@ class JacImportDepsPass(Transform[uni.Module, uni.Module]):
83
81
  else:
84
82
  if from_mod_target in self.prog.mod.hub:
85
83
  return
86
- self.load_mod(
87
- self.prog.compile(
88
- file_path=from_mod_target, mode=CMode.PARSE
89
- )
90
- )
84
+ self.load_mod(self.prog.compile(file_path=from_mod_target))
91
85
  else:
92
86
  if target in self.prog.mod.hub:
93
87
  return
94
- self.load_mod(self.prog.compile(file_path=target, mode=CMode.PARSE))
88
+ self.load_mod(self.prog.compile(file_path=target))
95
89
 
96
90
  def load_mod(self, mod: uni.Module) -> None:
97
91
  """Attach a module to a node."""
@@ -102,13 +96,11 @@ class JacImportDepsPass(Transform[uni.Module, uni.Module]):
102
96
 
103
97
  def import_jac_mod_from_dir(self, target: str) -> uni.Module:
104
98
  """Import a module from a directory."""
105
- from jaclang.compiler.passes.main import CompilerMode as CMode
106
-
107
99
  jac_init_path = os.path.join(target, "__init__.jac")
108
100
  if os.path.exists(jac_init_path):
109
101
  if jac_init_path in self.prog.mod.hub:
110
102
  return self.prog.mod.hub[jac_init_path]
111
- return self.prog.compile(file_path=jac_init_path, mode=CMode.PARSE)
103
+ return self.prog.compile(file_path=jac_init_path)
112
104
  elif os.path.exists(py_init_path := os.path.join(target, "__init__.py")):
113
105
  with open(py_init_path, "r") as f:
114
106
  file_source = f.read()