jaclang 0.7.0__py3-none-any.whl → 0.7.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 (29) hide show
  1. jaclang/compiler/absyntree.py +2 -36
  2. jaclang/compiler/compile.py +21 -0
  3. jaclang/compiler/passes/main/__init__.py +2 -2
  4. jaclang/compiler/passes/main/def_impl_match_pass.py +1 -5
  5. jaclang/compiler/passes/main/def_use_pass.py +14 -7
  6. jaclang/compiler/passes/main/import_pass.py +56 -10
  7. jaclang/compiler/passes/main/pyast_gen_pass.py +55 -2
  8. jaclang/compiler/passes/main/schedules.py +4 -3
  9. jaclang/compiler/passes/main/tests/fixtures/incautoimpl.jac +7 -0
  10. jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +4 -4
  11. jaclang/compiler/passes/main/tests/test_import_pass.py +13 -0
  12. jaclang/langserve/engine.py +193 -105
  13. jaclang/langserve/server.py +8 -1
  14. jaclang/langserve/tests/fixtures/circle.jac +73 -0
  15. jaclang/langserve/tests/fixtures/circle_err.jac +73 -0
  16. jaclang/langserve/tests/fixtures/circle_pure.impl.jac +28 -0
  17. jaclang/langserve/tests/fixtures/circle_pure.jac +34 -0
  18. jaclang/langserve/tests/fixtures/circle_pure_err.impl.jac +32 -0
  19. jaclang/langserve/tests/fixtures/circle_pure_err.jac +34 -0
  20. jaclang/langserve/tests/test_server.py +33 -1
  21. jaclang/langserve/utils.py +36 -1
  22. jaclang/tests/fixtures/type_info.jac +1 -1
  23. jaclang/tests/test_cli.py +1 -1
  24. jaclang/utils/helpers.py +3 -5
  25. jaclang/utils/test.py +1 -1
  26. {jaclang-0.7.0.dist-info → jaclang-0.7.1.dist-info}/METADATA +1 -1
  27. {jaclang-0.7.0.dist-info → jaclang-0.7.1.dist-info}/RECORD +29 -22
  28. {jaclang-0.7.0.dist-info → jaclang-0.7.1.dist-info}/WHEEL +0 -0
  29. {jaclang-0.7.0.dist-info → jaclang-0.7.1.dist-info}/entry_points.txt +0 -0
@@ -701,10 +701,12 @@ class ModuleItem(AstSymbolNode):
701
701
  name: Name,
702
702
  alias: Optional[Name],
703
703
  kid: Sequence[AstNode],
704
+ sub_module: Optional[Module] = None,
704
705
  ) -> None:
705
706
  """Initialize module item node."""
706
707
  self.name = name
707
708
  self.alias = alias
709
+ self.sub_module = sub_module
708
710
  AstNode.__init__(self, kid=kid)
709
711
  AstSymbolNode.__init__(
710
712
  self,
@@ -1027,16 +1029,6 @@ class Ability(
1027
1029
  AstDocNode.__init__(self, doc=doc)
1028
1030
  AstAsyncNode.__init__(self, is_async=is_async)
1029
1031
 
1030
- @property
1031
- def is_method(self) -> bool:
1032
- """Check if is method."""
1033
- check = isinstance(self.parent, SubNodeList) and isinstance(
1034
- self.parent.parent, Architype
1035
- )
1036
- if check:
1037
- self.sym_type = SymbolType.METHOD
1038
- return check
1039
-
1040
1032
  @property
1041
1033
  def is_func(self) -> bool:
1042
1034
  """Check if is func."""
@@ -1152,14 +1144,6 @@ class AbilityDef(AstSymbolNode, ElementStmt, AstImplOnlyNode, CodeBlockStmt):
1152
1144
  self.set_kids(nodes=new_kid)
1153
1145
  return res
1154
1146
 
1155
- @property
1156
- def is_method(self) -> bool:
1157
- """Check if is method."""
1158
- return (
1159
- len(self.target.archs) > 1
1160
- and self.target.archs[-2].arch.name != Tok.ABILITY_OP
1161
- )
1162
-
1163
1147
 
1164
1148
  class FuncSignature(AstSemStrNode):
1165
1149
  """FuncSignature node type for Jac Ast."""
@@ -1197,13 +1181,6 @@ class FuncSignature(AstSemStrNode):
1197
1181
  self.set_kids(nodes=new_kid)
1198
1182
  return res
1199
1183
 
1200
- @property
1201
- def is_method(self) -> bool:
1202
- """Check if is method."""
1203
- return (isinstance(self.parent, Ability) and self.parent.is_method) or (
1204
- isinstance(self.parent, AbilityDef) and self.parent.is_method
1205
- )
1206
-
1207
1184
  @property
1208
1185
  def is_static(self) -> bool:
1209
1186
  """Check if is static."""
@@ -1256,17 +1233,6 @@ class EventSignature(AstSemStrNode):
1256
1233
  self.set_kids(nodes=new_kid)
1257
1234
  return res
1258
1235
 
1259
- @property
1260
- def is_method(self) -> bool:
1261
- """Check if is method."""
1262
- if (isinstance(self.parent, Ability) and self.parent.is_method) or (
1263
- isinstance(self.parent, AbilityDef)
1264
- and isinstance(self.parent.decl_link, Ability)
1265
- and self.parent.decl_link.is_method
1266
- ):
1267
- return True
1268
- return False
1269
-
1270
1236
 
1271
1237
  class ArchRefChain(AstNode):
1272
1238
  """Arch ref list node type for Jac Ast."""
@@ -57,6 +57,27 @@ def jac_str_to_pass(
57
57
  return ast_ret
58
58
 
59
59
 
60
+ def jac_ir_to_pass(
61
+ ir: ast.AstNode,
62
+ target: Optional[Type[Pass]] = None,
63
+ schedule: list[Type[Pass]] = pass_schedule,
64
+ ) -> Pass:
65
+ """Convert a Jac file to an AST."""
66
+ if not target:
67
+ target = schedule[-1] if schedule else None
68
+ ast_ret = (
69
+ Pass(input_ir=ir, prior=None)
70
+ if not len(schedule)
71
+ else schedule[0](input_ir=ir, prior=None)
72
+ )
73
+ for i in schedule[1:]:
74
+ if i == target:
75
+ break
76
+ ast_ret = i(input_ir=ast_ret.ir, prior=ast_ret)
77
+ ast_ret = target(input_ir=ast_ret.ir, prior=ast_ret) if target else ast_ret
78
+ return ast_ret
79
+
80
+
60
81
  def jac_pass_to_pass(
61
82
  in_pass: Pass,
62
83
  target: Optional[Type[Pass]] = None,
@@ -3,7 +3,7 @@
3
3
  from .sub_node_tab_pass import SubNodeTabPass
4
4
  from .import_pass import JacImportPass, PyImportPass # noqa: I100
5
5
  from .sym_tab_build_pass import SymTabBuildPass # noqa: I100
6
- from .def_impl_match_pass import DeclDefMatchPass # noqa: I100
6
+ from .def_impl_match_pass import DeclImplMatchPass # noqa: I100
7
7
  from .def_use_pass import DefUsePass # noqa: I100
8
8
  from .pyout_pass import PyOutPass # noqa: I100
9
9
  from .pyast_load_pass import PyastBuildPass # type: ignore # noqa: I100
@@ -20,7 +20,7 @@ __all__ = [
20
20
  "JacImportPass",
21
21
  "PyImportPass",
22
22
  "SymTabBuildPass",
23
- "DeclDefMatchPass",
23
+ "DeclImplMatchPass",
24
24
  "DefUsePass",
25
25
  "PyOutPass",
26
26
  "PyastBuildPass",
@@ -12,7 +12,7 @@ from jaclang.compiler.passes.main import SubNodeTabPass
12
12
  from jaclang.compiler.symtable import Symbol, SymbolTable, SymbolType
13
13
 
14
14
 
15
- class DeclDefMatchPass(Pass):
15
+ class DeclImplMatchPass(Pass):
16
16
  """Decls and Def matching pass."""
17
17
 
18
18
  def enter_module(self, node: ast.Module) -> None:
@@ -76,10 +76,6 @@ class DeclDefMatchPass(Pass):
76
76
  continue
77
77
  decl_node.body = sym.decl # type: ignore
78
78
  sym.decl.decl_link = decl_node # type: ignore
79
- source_node = sym.decl.parent
80
- decl_node.add_kids_right([sym.decl]) # type: ignore
81
- if source_node and sym.decl in source_node.kid:
82
- source_node.kid.remove(sym.decl)
83
79
  decl_node.sym_tab.tab = sym.decl.sym_tab.tab # type: ignore
84
80
  for i in sym_tab.kid:
85
81
  self.connect_def_impl(i)
@@ -28,13 +28,20 @@ class DefUsePass(SymTabPass):
28
28
  sym_tab: Optional[SymbolTable],
29
29
  """
30
30
  if node.arch_type.name == Tok.KW_WALKER:
31
- for i in (
32
- self.get_all_sub_nodes(node, ast.VisitStmt)
33
- + self.get_all_sub_nodes(node, ast.IgnoreStmt)
34
- + self.get_all_sub_nodes(node, ast.DisengageStmt)
35
- + self.get_all_sub_nodes(node, ast.EdgeOpRef)
36
- ):
37
- i.from_walker = True
31
+ self.inform_from_walker(node)
32
+ for i in self.get_all_sub_nodes(node, ast.Ability):
33
+ if isinstance(i.body, ast.AbilityDef):
34
+ self.inform_from_walker(i.body)
35
+
36
+ def inform_from_walker(self, node: ast.AstNode) -> None:
37
+ """Inform all sub nodes that they are from a walker."""
38
+ for i in (
39
+ self.get_all_sub_nodes(node, ast.VisitStmt)
40
+ + self.get_all_sub_nodes(node, ast.IgnoreStmt)
41
+ + self.get_all_sub_nodes(node, ast.DisengageStmt)
42
+ + self.get_all_sub_nodes(node, ast.EdgeOpRef)
43
+ ):
44
+ i.from_walker = True
38
45
 
39
46
  def enter_arch_ref(self, node: ast.ArchRef) -> None:
40
47
  """Sub objects.
@@ -46,14 +46,20 @@ class JacImportPass(Pass):
46
46
  """Process an import."""
47
47
  lang = i.parent_of_type(ast.Import).hint.tag.value
48
48
  if lang == "jac" and not i.sub_module:
49
- mod = self.import_jac_module(
49
+ self.import_jac_module(
50
50
  node=i,
51
51
  mod_path=node.loc.mod_path,
52
52
  )
53
- if mod:
54
- self.run_again = True
55
- i.sub_module = mod
56
- i.add_kids_right([mod], pos_update=False)
53
+
54
+ def attach_mod_to_node(
55
+ self, node: ast.ModulePath | ast.ModuleItem, mod: ast.Module | None
56
+ ) -> None:
57
+ """Attach a module to a node."""
58
+ if mod:
59
+ self.run_again = True
60
+ node.sub_module = mod
61
+ self.__annex_impl(mod)
62
+ node.add_kids_right([mod], pos_update=False)
57
63
 
58
64
  def __annex_impl(self, node: ast.Module) -> None:
59
65
  """Annex impl and test modules."""
@@ -114,15 +120,55 @@ class JacImportPass(Pass):
114
120
  node.sub_module.name = node.alias.value
115
121
  # Items matched during def/decl pass
116
122
 
117
- def import_jac_module(
118
- self, node: ast.ModulePath, mod_path: str
119
- ) -> ast.Module | None:
123
+ def import_jac_module(self, node: ast.ModulePath, mod_path: str) -> None:
120
124
  """Import a module."""
121
125
  self.cur_node = node # impacts error reporting
122
126
  target = import_target_to_relative_path(
123
- node.level, node.path_str, os.path.dirname(node.loc.mod_path)
127
+ level=node.level,
128
+ target=node.path_str,
129
+ base_path=os.path.dirname(node.loc.mod_path),
124
130
  )
125
- return self.import_jac_mod_from_file(target)
131
+ # If the module is a package (dir)
132
+ if os.path.isdir(target):
133
+ self.attach_mod_to_node(node, self.import_jac_mod_from_dir(target))
134
+ import_node = node.parent_of_type(ast.Import)
135
+ # And the import is a from import and I am the from module
136
+ if node == import_node.from_loc:
137
+ # Import all from items as modules or packages
138
+ for i in import_node.items.items:
139
+ if isinstance(i, ast.ModuleItem):
140
+ from_mod_target = import_target_to_relative_path(
141
+ level=node.level,
142
+ target=node.path_str + "." + i.name.value,
143
+ base_path=os.path.dirname(node.loc.mod_path),
144
+ )
145
+ # If package
146
+ if os.path.isdir(from_mod_target):
147
+ self.attach_mod_to_node(
148
+ i, self.import_jac_mod_from_dir(from_mod_target)
149
+ )
150
+ # Else module
151
+ else:
152
+ self.attach_mod_to_node(
153
+ i, self.import_jac_mod_from_file(from_mod_target)
154
+ )
155
+ else:
156
+ self.attach_mod_to_node(node, self.import_jac_mod_from_file(target))
157
+
158
+ def import_jac_mod_from_dir(self, target: str) -> ast.Module | None:
159
+ """Import a module from a directory."""
160
+ with_init = os.path.join(target, "__init__.jac")
161
+ if os.path.exists(with_init):
162
+ return self.import_jac_mod_from_file(with_init)
163
+ else:
164
+ return ast.Module(
165
+ name=target.split(os.path.sep)[-1],
166
+ source=ast.JacSource("", mod_path=target),
167
+ doc=None,
168
+ body=[],
169
+ is_imported=False,
170
+ kid=[ast.EmptyToken()],
171
+ )
126
172
 
127
173
  def import_jac_mod_from_file(self, target: str) -> ast.Module | None:
128
174
  """Import a module from a file."""
@@ -42,6 +42,7 @@ class PyastGenPass(Pass):
42
42
  """Initialize pass."""
43
43
  self.debuginfo: dict[str, list[str]] = {"jac_mods": []}
44
44
  self.already_added: list[str] = []
45
+ self.method_sigs: list[ast.FuncSignature | ast.EventSignature] = []
45
46
  self.preamble: list[ast3.AST] = [
46
47
  self.sync(
47
48
  ast3.ImportFrom(
@@ -658,6 +659,28 @@ class PyastGenPass(Pass):
658
659
  )
659
660
  ]
660
661
 
662
+ def enter_architype(self, node: ast.Architype) -> None:
663
+ """Sub objects.
664
+
665
+ name: Name,
666
+ arch_type: Token,
667
+ access: Optional[SubTag[Token]],
668
+ base_classes: Optional[SubNodeList[AtomType]],
669
+ body: Optional[SubNodeList[ArchBlockStmt] | ArchDef],
670
+ doc: Optional[String],
671
+ decorators: Optional[SubNodeList[ExprType]],
672
+ """
673
+ # Record all signatures that are part of methods
674
+ for i in (
675
+ node.body.body.items
676
+ if isinstance(node.body, ast.ArchDef)
677
+ else node.body.items if node.body else []
678
+ ):
679
+ if isinstance(i, ast.Ability) and i.signature:
680
+ self.method_sigs.append(i.signature)
681
+ if isinstance(node.body, ast.ArchDef):
682
+ self.traverse(node.body)
683
+
661
684
  def exit_architype(self, node: ast.Architype) -> None:
662
685
  """Sub objects.
663
686
 
@@ -821,6 +844,19 @@ class PyastGenPass(Pass):
821
844
  decorators: Optional[SubNodeList[ExprType]],
822
845
  """
823
846
 
847
+ def enter_enum(self, node: ast.Enum) -> None:
848
+ """Sub objects.
849
+
850
+ name: Name,
851
+ access: Optional[SubTag[Token]],
852
+ base_classes: Optional[SubNodeList[AtomType]],
853
+ body: Optional[SubNodeList[EnumBlockStmt] | EnumDef],
854
+ doc: Optional[String],
855
+ decorators: Optional[SubNodeList[ExprType]],
856
+ """
857
+ if isinstance(node.body, ast.EnumDef):
858
+ self.traverse(node.body)
859
+
824
860
  def exit_enum(self, node: ast.Enum) -> None:
825
861
  """Sub objects.
826
862
 
@@ -870,6 +906,23 @@ class PyastGenPass(Pass):
870
906
  decorators: Optional[SubNodeList[ExprType]],
871
907
  """
872
908
 
909
+ def enter_ability(self, node: ast.Ability) -> None:
910
+ """Sub objects.
911
+
912
+ name_ref: NameType,
913
+ is_func: bool,
914
+ is_async: bool,
915
+ is_static: bool,
916
+ is_abstract: bool,
917
+ access: Optional[SubTag[Token]],
918
+ signature: Optional[FuncSignature | ExprType | EventSignature],
919
+ body: Optional[SubNodeList[CodeBlockStmt] | AbilityDef | FuncCall],
920
+ doc: Optional[String],
921
+ decorators: Optional[SubNodeList[ExprType]],
922
+ """
923
+ if isinstance(node.body, ast.AbilityDef):
924
+ self.traverse(node.body)
925
+
873
926
  def exit_ability(self, node: ast.Ability) -> None:
874
927
  """Sub objects.
875
928
 
@@ -1272,7 +1325,7 @@ class PyastGenPass(Pass):
1272
1325
  """
1273
1326
  params = (
1274
1327
  [self.sync(ast3.arg(arg="self", annotation=None))]
1275
- if node.is_method and not node.is_static
1328
+ if node in self.method_sigs and not node.is_static
1276
1329
  else []
1277
1330
  )
1278
1331
  vararg = None
@@ -1330,7 +1383,7 @@ class PyastGenPass(Pass):
1330
1383
  posonlyargs=[],
1331
1384
  args=(
1332
1385
  [self.sync(ast3.arg(arg="self", annotation=None)), here]
1333
- if node.is_method
1386
+ if node in self.method_sigs
1334
1387
  else [here]
1335
1388
  ),
1336
1389
  kwonlyargs=[],
@@ -9,7 +9,7 @@ from __future__ import annotations
9
9
  from .sub_node_tab_pass import SubNodeTabPass # noqa: I100
10
10
  from .import_pass import JacImportPass, PyImportPass # noqa: I100
11
11
  from .sym_tab_build_pass import SymTabBuildPass # noqa: I100
12
- from .def_impl_match_pass import DeclDefMatchPass # noqa: I100
12
+ from .def_impl_match_pass import DeclImplMatchPass # 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
@@ -25,7 +25,7 @@ py_code_gen = [
25
25
  JacImportPass,
26
26
  PyImportPass,
27
27
  SymTabBuildPass,
28
- DeclDefMatchPass,
28
+ DeclImplMatchPass,
29
29
  DefUsePass,
30
30
  RegistryPass,
31
31
  PyastGenPass,
@@ -33,5 +33,6 @@ py_code_gen = [
33
33
  PyBytecodeGenPass,
34
34
  ]
35
35
 
36
- py_code_gen_typed = [*py_code_gen, JacTypeCheckPass, FuseTypeInfoPass, AccessCheckPass]
36
+ type_checker_sched = [JacTypeCheckPass, FuseTypeInfoPass, AccessCheckPass]
37
+ py_code_gen_typed = [*py_code_gen, *type_checker_sched]
37
38
  py_compiler = [*py_code_gen, PyOutPass]
@@ -0,0 +1,7 @@
1
+ include:jac autoimpl;
2
+
3
+ with entry {
4
+ foo();
5
+ bar();
6
+ baz();
7
+ }
@@ -1,11 +1,11 @@
1
1
  """Test pass module."""
2
2
 
3
3
  from jaclang.compiler.compile import jac_file_to_pass
4
- from jaclang.compiler.passes.main import DeclDefMatchPass
4
+ from jaclang.compiler.passes.main import DeclImplMatchPass
5
5
  from jaclang.utils.test import TestCase
6
6
 
7
7
 
8
- class DeclDefMatchPassTests(TestCase):
8
+ class DeclImplMatchPassTests(TestCase):
9
9
  """Test pass module."""
10
10
 
11
11
  def setUp(self) -> None:
@@ -14,7 +14,7 @@ class DeclDefMatchPassTests(TestCase):
14
14
 
15
15
  def test_ability_connected_to_decl(self) -> None:
16
16
  """Basic test for pass."""
17
- state = jac_file_to_pass(self.fixture_abs_path("base.jac"), DeclDefMatchPass)
17
+ state = jac_file_to_pass(self.fixture_abs_path("base.jac"), DeclImplMatchPass)
18
18
  self.assertFalse(state.errors_had)
19
19
  self.assertIn("(o)Test.(c)say_hi", state.ir.sym_tab.tab)
20
20
  self.assertIsNotNone(state.ir.sym_tab.tab["(o)Test.(c)say_hi"].decl.body)
@@ -23,7 +23,7 @@ class DeclDefMatchPassTests(TestCase):
23
23
 
24
24
  def test_ability_connected_to_decl_post(self) -> None:
25
25
  """Basic test for pass."""
26
- state = jac_file_to_pass(self.fixture_abs_path("base2.jac"), DeclDefMatchPass)
26
+ state = jac_file_to_pass(self.fixture_abs_path("base2.jac"), DeclImplMatchPass)
27
27
  self.assertFalse(state.errors_had)
28
28
  self.assertIn("(o)Test.(c)say_hi", state.ir.sym_tab.tab)
29
29
  self.assertIsNotNone(state.ir.sym_tab.tab["(o)Test.(c)say_hi"].decl.body)
@@ -28,3 +28,16 @@ class ImportPassPassTests(TestCase):
28
28
  self.assertIn("getme.impl", mod_names)
29
29
  self.assertIn("autoimpl.impl", mod_names)
30
30
  self.assertIn("autoimpl.something.else.impl", mod_names)
31
+
32
+ def test_import_include_auto_impl(self) -> None:
33
+ """Basic test for pass."""
34
+ state = jac_file_to_pass(
35
+ self.fixture_abs_path("incautoimpl.jac"), JacImportPass
36
+ )
37
+ num_modules = len(state.ir.get_all_sub_nodes(ast.Module))
38
+ mod_names = [i.name for i in state.ir.get_all_sub_nodes(ast.Module)]
39
+ self.assertEqual(num_modules, 4)
40
+ self.assertIn("getme.impl", mod_names)
41
+ self.assertIn("autoimpl", mod_names)
42
+ self.assertIn("autoimpl.impl", mod_names)
43
+ self.assertIn("autoimpl.something.else.impl", mod_names)