jaclang 0.0.1__py3-none-any.whl → 0.0.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 (73) hide show
  1. jaclang/__init__.py +4 -0
  2. jaclang/cli/__init__.py +7 -0
  3. jaclang/cli/cli.jac +46 -0
  4. jaclang/cli/cmds.jac +14 -0
  5. jaclang/cli/impl/__init__.py +1 -0
  6. jaclang/cli/impl/cli_impl.jac +93 -0
  7. jaclang/cli/impl/cmds_impl.jac +26 -0
  8. jaclang/core/__init__.py +12 -0
  9. jaclang/core/impl/__init__.py +1 -0
  10. jaclang/core/impl/arch_impl.jac +112 -0
  11. jaclang/core/impl/element_impl.jac +95 -0
  12. jaclang/core/impl/exec_ctx_impl.jac +17 -0
  13. jaclang/core/impl/memory_impl.jac +57 -0
  14. jaclang/core/primitives.jac +104 -0
  15. jaclang/jac/__init__.py +1 -0
  16. jaclang/jac/absyntree.py +1787 -0
  17. jaclang/jac/constant.py +46 -0
  18. jaclang/jac/importer.py +130 -0
  19. jaclang/jac/lexer.py +538 -0
  20. jaclang/jac/parser.py +1474 -0
  21. jaclang/jac/passes/__init__.py +5 -0
  22. jaclang/jac/passes/blue/__init__.py +25 -0
  23. jaclang/jac/passes/blue/ast_build_pass.py +3190 -0
  24. jaclang/jac/passes/blue/blue_pygen_pass.py +1335 -0
  25. jaclang/jac/passes/blue/decl_def_match_pass.py +278 -0
  26. jaclang/jac/passes/blue/import_pass.py +75 -0
  27. jaclang/jac/passes/blue/sub_node_tab_pass.py +30 -0
  28. jaclang/jac/passes/blue/tests/__init__.py +1 -0
  29. jaclang/jac/passes/blue/tests/test_ast_build_pass.py +61 -0
  30. jaclang/jac/passes/blue/tests/test_blue_pygen_pass.py +117 -0
  31. jaclang/jac/passes/blue/tests/test_decl_def_match_pass.py +43 -0
  32. jaclang/jac/passes/blue/tests/test_import_pass.py +18 -0
  33. jaclang/jac/passes/blue/tests/test_sub_node_pass.py +26 -0
  34. jaclang/jac/passes/blue/tests/test_type_analyze_pass.py +53 -0
  35. jaclang/jac/passes/blue/type_analyze_pass.py +731 -0
  36. jaclang/jac/passes/ir_pass.py +154 -0
  37. jaclang/jac/passes/purple/__init__.py +17 -0
  38. jaclang/jac/passes/purple/impl/__init__.py +1 -0
  39. jaclang/jac/passes/purple/impl/purple_pygen_pass_impl.jac +289 -0
  40. jaclang/jac/passes/purple/purple_pygen_pass.jac +35 -0
  41. jaclang/jac/sym_table.py +127 -0
  42. jaclang/jac/tests/__init__.py +1 -0
  43. jaclang/jac/tests/fixtures/__init__.py +1 -0
  44. jaclang/jac/tests/fixtures/activity.py +10 -0
  45. jaclang/jac/tests/fixtures/fam.jac +68 -0
  46. jaclang/jac/tests/fixtures/hello_world.jac +5 -0
  47. jaclang/jac/tests/fixtures/lexer_fam.jac +61 -0
  48. jaclang/jac/tests/fixtures/stuff.jac +6 -0
  49. jaclang/jac/tests/test_importer.py +24 -0
  50. jaclang/jac/tests/test_lexer.py +57 -0
  51. jaclang/jac/tests/test_parser.py +50 -0
  52. jaclang/jac/tests/test_utils.py +12 -0
  53. jaclang/jac/transform.py +63 -0
  54. jaclang/jac/transpiler.py +69 -0
  55. jaclang/jac/utils.py +120 -0
  56. jaclang/utils/__init__.py +1 -0
  57. jaclang/utils/fstring_parser.py +73 -0
  58. jaclang/utils/log.py +9 -0
  59. jaclang/utils/sly/__init__.py +6 -0
  60. jaclang/utils/sly/docparse.py +62 -0
  61. jaclang/utils/sly/lex.py +510 -0
  62. jaclang/utils/sly/yacc.py +2398 -0
  63. jaclang/utils/test.py +81 -0
  64. jaclang/utils/tests/__init__.py +1 -0
  65. jaclang/utils/tests/test_fstring_parser.py +55 -0
  66. jaclang-0.0.3.dist-info/METADATA +12 -0
  67. jaclang-0.0.3.dist-info/RECORD +70 -0
  68. {jaclang-0.0.1.dist-info → jaclang-0.0.3.dist-info}/WHEEL +1 -1
  69. jaclang-0.0.3.dist-info/entry_points.txt +3 -0
  70. jaclang-0.0.3.dist-info/top_level.txt +1 -0
  71. jaclang-0.0.1.dist-info/METADATA +0 -7
  72. jaclang-0.0.1.dist-info/RECORD +0 -4
  73. jaclang-0.0.1.dist-info/top_level.txt +0 -1
@@ -0,0 +1,278 @@
1
+ """Connect Decls and Defs in AST."""
2
+ import jaclang.jac.absyntree as ast
3
+ from jaclang.jac.lexer import Tokens as Tok
4
+ from jaclang.jac.passes import Pass
5
+ from jaclang.jac.sym_table import DefDeclSymbol, SymbolTable
6
+
7
+
8
+ class DeclDefMatchPass(Pass, SymbolTable):
9
+ """Decls and Def matching pass."""
10
+
11
+ def before_pass(self) -> None:
12
+ """Initialize pass."""
13
+ self.sym_tab = SymbolTable(scope_name="global")
14
+
15
+ def exit_global_vars(self, node: ast.GlobalVars) -> None:
16
+ """Sub objects.
17
+
18
+ doc: Optional[DocString],
19
+ access: Optional[Token],
20
+ assignments: AssignmentList,
21
+ """
22
+ for i in self.get_all_sub_nodes(node, ast.Assignment):
23
+ if type(i.target) != ast.Name:
24
+ self.ice("Only name targets should be possible to in global vars.")
25
+ else:
26
+ decl = self.sym_tab.lookup(i.target.value)
27
+ if decl:
28
+ if decl.has_def:
29
+ self.error(f"Name {i.target.value} already bound.")
30
+ else:
31
+ decl.has_def = True
32
+ decl.other_node = i
33
+ decl.node.body = i # TODO: I dont think this line makes sense
34
+ self.sym_tab.set(decl)
35
+
36
+ def exit_test(self, node: ast.Test) -> None:
37
+ """Sub objects.
38
+
39
+ name: Name,
40
+ doc: Optional[DocString],
41
+ description: Token,
42
+ body: CodeBlock,
43
+ """
44
+
45
+ def enter_import(self, node: ast.Import) -> None:
46
+ """Sub objects.
47
+
48
+ lang: Name,
49
+ path: ModulePath,
50
+ alias: Optional[Name],
51
+ items: Optional[ModuleItems],
52
+ is_absorb: bool,
53
+ sub_module: Optional[Module],
54
+ """
55
+ if not node.is_absorb:
56
+ self.sym_tab = self.sym_tab.push(node.path.path_str)
57
+
58
+ def exit_import(self, node: ast.Import) -> None:
59
+ """Sub objects.
60
+
61
+ lang: Name,
62
+ path: ModulePath,
63
+ alias: Optional[Name],
64
+ items: Optional[ModuleItems],
65
+ is_absorb: bool,
66
+ sub_module: Optional[Module],
67
+ """
68
+ if not node.is_absorb and not self.sym_tab.parent:
69
+ self.ice("Import should have a parent sym_table scope.")
70
+ elif not node.is_absorb:
71
+ self.sym_tab = self.sym_tab.pop()
72
+ if node.items: # now treat imported items as global
73
+ for i in node.items.items:
74
+ name = i.alias if i.alias else i.name
75
+ decl = self.sym_tab.lookup(name.value)
76
+ if not decl:
77
+ self.sym_tab.set(
78
+ DefDeclSymbol(name=name.value, node=i, has_def=True)
79
+ )
80
+
81
+ def exit_module_item(self, node: ast.ModuleItem) -> None:
82
+ """Sub objects.
83
+
84
+ name: Name,
85
+ alias: Optional[Token],
86
+ body: Optional[AstNode],
87
+ """
88
+ if not self.sym_tab.lookup(node.name.value):
89
+ self.sym_tab.set(
90
+ DefDeclSymbol(name=node.name.value, node=node, has_decl=True)
91
+ )
92
+
93
+ def exit_architype(self, node: ast.Architype) -> None:
94
+ """Sub objects.
95
+
96
+ name: Name,
97
+ arch_type: Token,
98
+ doc: Optional[DocString],
99
+ decorators: Optional[Decorators],
100
+ access: Optional[Token],
101
+ base_classes: BaseClasses,
102
+ body: Optional[ArchBlock],
103
+ """
104
+ # if no body, check for def
105
+ # if no def, register as decl
106
+ # if complete register as def
107
+ # nota: can allow static overriding perhaps?
108
+ # note: if arch has not body ok, imports body is the arch itself
109
+
110
+ def exit_arch_def(self, node: ast.ArchDef) -> None:
111
+ """Sub objects.
112
+
113
+ doc: Optional[DocString],
114
+ mod: Optional[NameList],
115
+ arch: ObjectRef | NodeRef | EdgeRef | WalkerRef,
116
+ body: ArchBlock,
117
+ """
118
+
119
+ def enter_ability(self, node: ast.Ability) -> None:
120
+ """Sub objects.
121
+
122
+ name: Name,
123
+ is_func: bool,
124
+ doc: Optional[DocString],
125
+ decorators: Optional["Decorators"],
126
+ access: Optional[Token],
127
+ signature: "FuncSignature | TypeSpec | EventSignature",
128
+ body: Optional["CodeBlock"],
129
+ arch_attached: Optional["ArchBlock"] = None,
130
+ """
131
+ self.sym_tab = self.sym_tab.push(node.name.value)
132
+
133
+ def exit_ability(self, node: ast.Ability) -> None:
134
+ """Sub objects.
135
+
136
+ name: Name,
137
+ is_func: bool,
138
+ doc: Optional[DocString],
139
+ decorators: Optional["Decorators"],
140
+ access: Optional[Token],
141
+ signature: "FuncSignature | TypeSpec | EventSignature",
142
+ body: Optional["CodeBlock"],
143
+ arch_attached: Optional["ArchBlock"] = None,
144
+ """
145
+ name = (
146
+ f"{node.arch_attached.parent.name.value}.{node.name.value}"
147
+ if node.arch_attached and type(node.arch_attached.parent) == ast.Architype
148
+ else node.name.value
149
+ )
150
+ decl = self.sym_tab.lookup(name)
151
+ if decl and decl.has_decl:
152
+ self.error(
153
+ f"Ability bound with name {name} already defined on "
154
+ f"Line {decl.node.line} in {decl.node.mod_link.rel_mod_path}."
155
+ )
156
+ elif decl and decl.has_def:
157
+ decl.has_decl = True
158
+ decl.node = node
159
+ decl.node.body = (
160
+ decl.other_node.body
161
+ if type(decl.other_node) == ast.AbilityDef
162
+ else self.ice("Expected node of type AbilityDef in symbol table.")
163
+ )
164
+ ast.append_node(decl.node, decl.other_node)
165
+ self.sym_tab.set(decl)
166
+ else:
167
+ decl = DefDeclSymbol(name=name, node=node, has_decl=True)
168
+ if node.body:
169
+ decl.has_def = True
170
+ decl.other_node = node
171
+ self.sym_tab.set(decl)
172
+ self.sym_tab = self.sym_tab.pop()
173
+
174
+ def exit_ability_def(self, node: ast.AbilityDef) -> None:
175
+ """Sub objects.
176
+
177
+ doc: Optional[DocString],
178
+ target: Optional["NameList"],
179
+ ability: "ArchRef",
180
+ signature: "FuncSignature | EventSignature",
181
+ body: "CodeBlock",
182
+ """
183
+ name = node.ability.name.value
184
+ if node.target:
185
+ owner = node.target.names[-1]
186
+ if not isinstance(owner, ast.ArchRef):
187
+ self.error("Expected reference to Architype!")
188
+ owner = ""
189
+ else:
190
+ owner = owner.name.value
191
+ name = f"{owner}.{name}"
192
+ decl = self.sym_tab.lookup(name)
193
+ if decl and decl.has_def:
194
+ self.error(
195
+ f"Ability bound with name {name} already defined on "
196
+ f"Line {decl.other_node.line} in {decl.other_node.mod_link.rel_mod_path}."
197
+ )
198
+ elif decl and decl.has_decl:
199
+ decl.has_def = True
200
+ decl.other_node = node
201
+ decl.node.body = decl.other_node.body
202
+ ast.append_node(decl.node, decl.other_node)
203
+ self.sym_tab.set(decl)
204
+ else:
205
+ self.sym_tab.set(DefDeclSymbol(name=name, other_node=node, has_def=True))
206
+
207
+ def enter_arch_block(self, node: ast.ArchBlock) -> None:
208
+ """Sub objects.
209
+
210
+ members: list['ArchHas | Ability'],
211
+ """
212
+ # Tags all function signatures whether method style or not
213
+ for i in self.get_all_sub_nodes(node, ast.Ability):
214
+ i.arch_attached = node
215
+ if (
216
+ type(node.parent) == ast.Architype
217
+ and node.parent.arch_type.name == Tok.KW_WALKER
218
+ ):
219
+ for i in self.get_all_sub_nodes(node, ast.VisitStmt):
220
+ i.from_walker = True
221
+ for i in self.get_all_sub_nodes(node, ast.DisengageStmt):
222
+ i.from_walker = True
223
+
224
+ def exit_enum(self, node: ast.Enum) -> None:
225
+ """Sub objects.
226
+
227
+ name: Name,
228
+ doc: Optional[DocString],
229
+ decorators: Optional[Decorators],
230
+ access: Optional[Token],
231
+ base_classes: BaseClasses,
232
+ body: Optional[EnumBlock],
233
+ """
234
+ name = node.name.value
235
+ decl = self.sym_tab.lookup(name)
236
+ if decl and decl.has_decl:
237
+ self.error(
238
+ f"Enum bound with name {name} already defined on Line {decl.node.line}."
239
+ )
240
+ elif decl and decl.has_def:
241
+ decl.has_decl = True
242
+ decl.node = node
243
+ decl.node.body = (
244
+ decl.other_node.body
245
+ if type(decl.other_node) == ast.EnumDef
246
+ else self.ice("Expected node of type EnumDef in symbol table.")
247
+ )
248
+ ast.append_node(decl.node, decl.other_node)
249
+ self.sym_tab.set(decl)
250
+ else:
251
+ decl = DefDeclSymbol(name=name, node=node, has_decl=True)
252
+ if node.body:
253
+ decl.has_def = True
254
+ decl.other_node = node
255
+ self.sym_tab.set(decl)
256
+
257
+ def exit_enum_def(self, node: ast.EnumDef) -> None:
258
+ """Sub objects.
259
+
260
+ doc: Optional[DocString],
261
+ enum: "EnumRef",
262
+ mod: Optional["NameList"],
263
+ body: "EnumBlock",
264
+ """
265
+ name = node.enum.name.value
266
+ decl = self.sym_tab.lookup(name)
267
+ if decl and decl.has_def:
268
+ self.error(
269
+ f"Enum bound with name {name} already defined on Line {decl.other_node.line}."
270
+ )
271
+ elif decl and decl.has_decl:
272
+ decl.has_def = True
273
+ decl.other_node = node
274
+ decl.node.body = decl.other_node.body
275
+ ast.append_node(decl.node, decl.other_node)
276
+ self.sym_tab.set(decl)
277
+ else:
278
+ self.sym_tab.set(DefDeclSymbol(name=name, other_node=node, has_def=True))
@@ -0,0 +1,75 @@
1
+ """Static Import Pass."""
2
+ from os import path
3
+
4
+ import jaclang.jac.absyntree as ast
5
+ from jaclang.jac.passes import Pass
6
+ from jaclang.jac.passes.blue import SubNodeTabPass
7
+
8
+
9
+ class ImportPass(Pass):
10
+ """Jac statically imports all modules."""
11
+
12
+ def before_pass(self) -> None:
13
+ """Run once before pass."""
14
+ self.import_table = {}
15
+
16
+ def enter_module(self, node: ast.Module) -> None:
17
+ """Run Importer."""
18
+ self.cur_node = node
19
+ self.terminate() # Turns off auto traversal for deliberate traversal
20
+ self.run_again = True
21
+ while self.run_again:
22
+ self.run_again = False
23
+ for i in self.get_all_sub_nodes(node, ast.Import):
24
+ if i.lang.value == "jac" and not i.sub_module:
25
+ self.run_again = True
26
+ ast.append_node(i, self.import_module(i, node.mod_path))
27
+ i.sub_module = i.kid[-1]
28
+ self.enter_import(i)
29
+ SubNodeTabPass(mod_path=node.mod_path, input_ir=node)
30
+
31
+ def enter_import(self, node: ast.Import) -> None:
32
+ """Sub objects.
33
+
34
+ lang: Name,
35
+ path: ModulePath,
36
+ alias: Optional[Name],
37
+ items: Optional[ModuleItems], # Items matched during def/decl pass
38
+ is_absorb: bool,
39
+ self.sub_module = None
40
+ """
41
+ self.cur_node = node
42
+ if node.alias and node.sub_module:
43
+ node.sub_module.name = node.alias.value
44
+ # Items matched during def/decl pass
45
+
46
+ # Utility functions
47
+ # -----------------
48
+
49
+ def import_module(self, node: ast.Import, mod_path: str) -> ast.AstNode:
50
+ """Import a module."""
51
+ from jaclang.jac.transpiler import jac_file_to_pass
52
+ from jaclang.jac.passes.blue.ast_build_pass import AstBuildPass
53
+
54
+ base_dir = path.dirname(mod_path)
55
+ target = path.normpath(
56
+ path.normpath(
57
+ path.join(base_dir, *(node.path.path_str.split("."))) + ".jac"
58
+ )
59
+ )
60
+ if target in self.import_table:
61
+ # self.warning(f"Circular import detected, module {target} already imported.")
62
+ return self.import_table[target]
63
+
64
+ if not path.exists(target):
65
+ self.error(f"Could not find module {target}")
66
+ mod = jac_file_to_pass(
67
+ file_path=target, base_dir=base_dir, target=AstBuildPass
68
+ ).ir
69
+ if isinstance(mod, ast.Module):
70
+ self.import_table[target] = mod
71
+ mod.is_imported = True
72
+ else:
73
+ self.error(f"Module {target} is not a valid Jac module.")
74
+ raise Exception(f"Module {target} is not a valid Jac module.")
75
+ return mod
@@ -0,0 +1,30 @@
1
+ """Subnode Table building pass."""
2
+ from copy import copy
3
+
4
+ import jaclang.jac.absyntree as ast
5
+ from jaclang.jac.passes import Pass
6
+
7
+
8
+ class SubNodeTabPass(Pass):
9
+ """AST Enrichment Pass for basic high level semantics."""
10
+
11
+ def enter_node(self, node: ast.AstNode) -> None:
12
+ """Table builder."""
13
+ super().enter_node(node)
14
+ node._sub_node_tab = {} # clears on entry
15
+
16
+ def exit_node(self, node: ast.AstNode) -> None:
17
+ """Table builder."""
18
+ super().exit_node(node)
19
+ for i in node.kid:
20
+ if not i:
21
+ continue
22
+ for k, v in i._sub_node_tab.items():
23
+ if k in node._sub_node_tab:
24
+ node._sub_node_tab[k].extend(v)
25
+ else:
26
+ node._sub_node_tab[k] = copy(v)
27
+ if type(i) in node._sub_node_tab:
28
+ node._sub_node_tab[type(i)].append(i)
29
+ else:
30
+ node._sub_node_tab[type(i)] = [i]
@@ -0,0 +1 @@
1
+ """Tests for Jac passes."""
@@ -0,0 +1,61 @@
1
+ """Test ast build pass module."""
2
+ import inspect
3
+
4
+ from jaclang.jac.lexer import JacLexer
5
+ from jaclang.jac.parser import JacParser
6
+ from jaclang.jac.passes.blue import AstBuildPass
7
+ from jaclang.utils.fstring_parser import FStringParser
8
+ from jaclang.utils.test import TestCaseMicroSuite
9
+
10
+
11
+ class AstBuildPassTests(TestCaseMicroSuite):
12
+ """Test pass module."""
13
+
14
+ def setUp(self) -> None:
15
+ """Set up test."""
16
+ return super().setUp()
17
+
18
+ def test_pass_grammar_complete(self) -> None:
19
+ """Test for enter/exit name diffs with parser."""
20
+ from jaclang.jac.parser import JacParser
21
+
22
+ parser_func_names = []
23
+ for name, value in [
24
+ *inspect.getmembers(JacParser),
25
+ *inspect.getmembers(FStringParser),
26
+ ]:
27
+ if (
28
+ inspect.isfunction(value)
29
+ and value.__qualname__.split(".")[0]
30
+ in [JacParser.__name__, FStringParser.__name__]
31
+ and name not in ["__init__", "error", "transform"]
32
+ ):
33
+ parser_func_names.append(name)
34
+ ast_build_func_names = []
35
+ for name, value in inspect.getmembers(AstBuildPass):
36
+ if (
37
+ (name.startswith("enter_") or name.startswith("exit_"))
38
+ and inspect.isfunction(value)
39
+ and not getattr(AstBuildPass.__base__, value.__name__, False)
40
+ and value.__qualname__.split(".")[0]
41
+ == AstBuildPass.__name__.replace("enter_", "").replace("exit_", "")
42
+ ):
43
+ ast_build_func_names.append(
44
+ name.replace("enter_", "").replace("exit_", "")
45
+ )
46
+ for name in ast_build_func_names:
47
+ self.assertIn(name, parser_func_names)
48
+ for name in parser_func_names:
49
+ self.assertIn(name, ast_build_func_names)
50
+
51
+ def micro_suite_test(self, filename: str) -> None:
52
+ """Parse micro jac file."""
53
+ lex = JacLexer(mod_path=f"{filename}", input_ir=self.file_to_str(filename)).ir
54
+ prse = JacParser(mod_path=f"{filename}", input_ir=lex).ir
55
+ build_pass = AstBuildPass(mod_path="", input_ir=prse).ir
56
+ self.assertIsNotNone(build_pass)
57
+ if build_pass:
58
+ self.assertGreater(len(str(build_pass.to_dict())), 200)
59
+
60
+
61
+ AstBuildPassTests.self_attach_micro_tests()
@@ -0,0 +1,117 @@
1
+ """Test ast build pass module."""
2
+ import inspect
3
+
4
+ from jaclang.jac.passes.blue import BluePygenPass
5
+ from jaclang.jac.transpiler import jac_file_to_pass, transpile_jac_blue
6
+ from jaclang.jac.utils import get_ast_nodes_as_snake_case as ast_snakes
7
+ from jaclang.utils.test import TestCaseMicroSuite
8
+
9
+
10
+ class BluePygenPassTests(TestCaseMicroSuite):
11
+ """Test pass module."""
12
+
13
+ def setUp(self) -> None:
14
+ """Set up test."""
15
+ return super().setUp()
16
+
17
+ def test_jac_cli(self) -> None:
18
+ """Basic test for pass."""
19
+ code_gen = jac_file_to_pass(
20
+ self.fixture_abs_path("../../../../../cli/cli.jac"), target=BluePygenPass
21
+ )
22
+ self.assertFalse(code_gen.errors_had)
23
+
24
+ def test_pipe_operator(self) -> None:
25
+ """Basic test for pass."""
26
+ code_gen = jac_file_to_pass(
27
+ self.fixture_abs_path("codegentext.jac"), target=BluePygenPass
28
+ )
29
+ self.assertFalse(code_gen.errors_had)
30
+ self.assertIn(
31
+ 'say((dump(print(len)))({"name": "value"}))', code_gen.ir.meta["py_code"]
32
+ )
33
+ self.assertIn(
34
+ '{"name": "value"}(len(print(print(print))))', code_gen.ir.meta["py_code"]
35
+ )
36
+ self.assertIn("a = (5 + 10) * 2", code_gen.ir.meta["py_code"])
37
+
38
+ def test_atomic_pipe_operator(self) -> None:
39
+ """Basic test for pass."""
40
+ code_gen = jac_file_to_pass(
41
+ self.fixture_abs_path("codegentext.jac"), target=BluePygenPass
42
+ )
43
+ self.assertFalse(code_gen.errors_had)
44
+ self.assertIn(
45
+ 'say((dump(print)(len))({"name": "value"}))', code_gen.ir.meta["py_code"]
46
+ )
47
+
48
+ def test_pipe_operator_multi_param(self) -> None:
49
+ """Basic test for pass."""
50
+ code_gen = jac_file_to_pass(
51
+ self.fixture_abs_path("codegentext.jac"), target=BluePygenPass
52
+ )
53
+ self.assertFalse(code_gen.errors_had)
54
+ self.assertIn("self.func(*args, **kwargs)", code_gen.ir.meta["py_code"])
55
+ self.assertIn("inspect.signature(func)", code_gen.ir.meta["py_code"])
56
+ self.assertIn("self.registry.items()", code_gen.ir.meta["py_code"])
57
+
58
+ def test_with_stmt(self) -> None:
59
+ """Basic test for pass."""
60
+ code_gen = jac_file_to_pass(
61
+ self.fixture_abs_path("codegentext.jac"), target=BluePygenPass
62
+ )
63
+ self.assertFalse(code_gen.errors_had)
64
+ self.assertIn(
65
+ 'with open("file.txt") as f, open("file2.txt") as f:',
66
+ code_gen.ir.meta["py_code"],
67
+ )
68
+
69
+ def test_empty_codeblock(self) -> None:
70
+ """Basic test for pass."""
71
+ code_gen = jac_file_to_pass(
72
+ self.fixture_abs_path("codegentext.jac"), target=BluePygenPass
73
+ )
74
+ self.assertFalse(code_gen.errors_had)
75
+ self.assertIn("pass", code_gen.ir.meta["py_code"])
76
+
77
+ def test_enum_gen(self) -> None:
78
+ """Basic test for pass."""
79
+ code_gen = jac_file_to_pass(
80
+ self.fixture_abs_path("codegentext.jac"), target=BluePygenPass
81
+ )
82
+ self.assertFalse(code_gen.errors_had)
83
+ self.assertIn(
84
+ "from enum import Enum as __jac_Enum__, auto as __jac_auto__",
85
+ code_gen.ir.meta["py_code"],
86
+ )
87
+ self.assertIn("class Color(__jac_Enum__):", code_gen.ir.meta["py_code"])
88
+ self.assertIn("GREEN = __jac_auto__()", code_gen.ir.meta["py_code"])
89
+ self.assertIn("RED = 1", code_gen.ir.meta["py_code"])
90
+
91
+ def test_pass_ast_complete(self) -> None:
92
+ """Test for enter/exit name diffs with parser."""
93
+ ast_func_names = [
94
+ x for x in ast_snakes() if x not in ["ast_node", "o_o_p_access_node"]
95
+ ]
96
+ pygen_func_names = []
97
+ for name, value in inspect.getmembers(BluePygenPass):
98
+ if (
99
+ (name.startswith("enter_") or name.startswith("exit_"))
100
+ and inspect.isfunction(value)
101
+ and not getattr(BluePygenPass.__base__, value.__name__, False)
102
+ and value.__qualname__.split(".")[0]
103
+ == BluePygenPass.__name__.replace("enter_", "").replace("exit_", "")
104
+ ):
105
+ pygen_func_names.append(name.replace("enter_", "").replace("exit_", ""))
106
+ for name in pygen_func_names:
107
+ self.assertIn(name, ast_func_names)
108
+ for name in ast_func_names:
109
+ self.assertIn(name, pygen_func_names)
110
+
111
+ def micro_suite_test(self, filename: str) -> None:
112
+ """Parse micro jac file."""
113
+ code_gen = transpile_jac_blue(filename, "")
114
+ self.assertGreater(len(code_gen), 10)
115
+
116
+
117
+ BluePygenPassTests.self_attach_micro_tests()
@@ -0,0 +1,43 @@
1
+ """Test pass module."""
2
+ from jaclang.jac.passes.blue import DeclDefMatchPass
3
+ from jaclang.jac.transpiler import jac_file_to_pass
4
+ from jaclang.utils.test import TestCase
5
+
6
+
7
+ class DeclDefMatchPassTests(TestCase):
8
+ """Test pass module."""
9
+
10
+ def setUp(self) -> None:
11
+ """Set up test."""
12
+ return super().setUp()
13
+
14
+ def test_import_values_avail(self) -> None:
15
+ """Basic test for pass."""
16
+ state = jac_file_to_pass(
17
+ self.fixture_abs_path("base.jac"), "", DeclDefMatchPass
18
+ )
19
+ self.assertFalse(state.errors_had)
20
+ self.assertIn("mine", state.sym_tab.tab)
21
+ self.assertIsNotNone(state.sym_tab.tab["mine"].node.body)
22
+
23
+ def test_ability_connected_to_decl(self) -> None:
24
+ """Basic test for pass."""
25
+ state = jac_file_to_pass(
26
+ self.fixture_abs_path("base.jac"), "", DeclDefMatchPass
27
+ )
28
+ self.assertFalse(state.errors_had)
29
+ self.assertIn("Test.say_hi", state.sym_tab.tab)
30
+ self.assertIsNotNone(state.sym_tab.tab["Test.say_hi"].node.body)
31
+ self.assertIn("Test.init", state.sym_tab.tab)
32
+ self.assertIsNotNone(state.sym_tab.tab["Test.init"].node.body)
33
+
34
+ def test_collision_error_correct(self) -> None:
35
+ """Basic test for multi defs."""
36
+ state = jac_file_to_pass(
37
+ self.fixture_abs_path("decls.jac"), "", DeclDefMatchPass
38
+ )
39
+ self.assertTrue(state.errors_had)
40
+ self.assertIn("/impl/defs2.jac", state.errors_had[0])
41
+ self.assertIn("/impl/defs1.jac", state.errors_had[0])
42
+ self.assertIn("/impl/defs2.jac", state.errors_had[1])
43
+ self.assertIn("/impl/defs1.jac", state.errors_had[1])
@@ -0,0 +1,18 @@
1
+ """Test pass module."""
2
+ from jaclang.jac.passes.blue import ImportPass
3
+ from jaclang.jac.transpiler import jac_file_to_pass
4
+ from jaclang.utils.test import TestCase
5
+
6
+
7
+ class ImportPassPassTests(TestCase):
8
+ """Test pass module."""
9
+
10
+ def setUp(self) -> None:
11
+ """Set up test."""
12
+ return super().setUp()
13
+
14
+ def test_pygen_jac_cli(self) -> None:
15
+ """Basic test for pass."""
16
+ state = jac_file_to_pass(self.fixture_abs_path("base.jac"), "", ImportPass)
17
+ self.assertFalse(state.errors_had)
18
+ self.assertIn("56", str(state.ir.to_dict()))
@@ -0,0 +1,26 @@
1
+ """Test sub node pass module."""
2
+
3
+ from jaclang.jac.passes.blue import SubNodeTabPass
4
+ from jaclang.jac.transpiler import jac_file_to_pass
5
+ from jaclang.utils.test import TestCase
6
+
7
+
8
+ class SubNodePassTests(TestCase):
9
+ """Test pass module."""
10
+
11
+ def setUp(self) -> None:
12
+ """Set up test."""
13
+ return super().setUp()
14
+
15
+ def test_sub_node_pass(self) -> None:
16
+ """Basic test for pass."""
17
+ code_gen = jac_file_to_pass(
18
+ file_path=self.fixture_abs_path("../../../../../cli/cli.jac"),
19
+ base_dir="",
20
+ target=SubNodeTabPass,
21
+ )
22
+ for i in code_gen.ir.kid[1].kid:
23
+ for k, v in i._sub_node_tab.items():
24
+ for n in v:
25
+ self.assertIn(n, code_gen.get_all_sub_nodes(i, k, brute_force=True))
26
+ self.assertFalse(code_gen.errors_had)