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.
- jaclang/__init__.py +4 -0
- jaclang/cli/__init__.py +7 -0
- jaclang/cli/cli.jac +46 -0
- jaclang/cli/cmds.jac +14 -0
- jaclang/cli/impl/__init__.py +1 -0
- jaclang/cli/impl/cli_impl.jac +93 -0
- jaclang/cli/impl/cmds_impl.jac +26 -0
- jaclang/core/__init__.py +12 -0
- jaclang/core/impl/__init__.py +1 -0
- jaclang/core/impl/arch_impl.jac +112 -0
- jaclang/core/impl/element_impl.jac +95 -0
- jaclang/core/impl/exec_ctx_impl.jac +17 -0
- jaclang/core/impl/memory_impl.jac +57 -0
- jaclang/core/primitives.jac +104 -0
- jaclang/jac/__init__.py +1 -0
- jaclang/jac/absyntree.py +1787 -0
- jaclang/jac/constant.py +46 -0
- jaclang/jac/importer.py +130 -0
- jaclang/jac/lexer.py +538 -0
- jaclang/jac/parser.py +1474 -0
- jaclang/jac/passes/__init__.py +5 -0
- jaclang/jac/passes/blue/__init__.py +25 -0
- jaclang/jac/passes/blue/ast_build_pass.py +3190 -0
- jaclang/jac/passes/blue/blue_pygen_pass.py +1335 -0
- jaclang/jac/passes/blue/decl_def_match_pass.py +278 -0
- jaclang/jac/passes/blue/import_pass.py +75 -0
- jaclang/jac/passes/blue/sub_node_tab_pass.py +30 -0
- jaclang/jac/passes/blue/tests/__init__.py +1 -0
- jaclang/jac/passes/blue/tests/test_ast_build_pass.py +61 -0
- jaclang/jac/passes/blue/tests/test_blue_pygen_pass.py +117 -0
- jaclang/jac/passes/blue/tests/test_decl_def_match_pass.py +43 -0
- jaclang/jac/passes/blue/tests/test_import_pass.py +18 -0
- jaclang/jac/passes/blue/tests/test_sub_node_pass.py +26 -0
- jaclang/jac/passes/blue/tests/test_type_analyze_pass.py +53 -0
- jaclang/jac/passes/blue/type_analyze_pass.py +731 -0
- jaclang/jac/passes/ir_pass.py +154 -0
- jaclang/jac/passes/purple/__init__.py +17 -0
- jaclang/jac/passes/purple/impl/__init__.py +1 -0
- jaclang/jac/passes/purple/impl/purple_pygen_pass_impl.jac +289 -0
- jaclang/jac/passes/purple/purple_pygen_pass.jac +35 -0
- jaclang/jac/sym_table.py +127 -0
- jaclang/jac/tests/__init__.py +1 -0
- jaclang/jac/tests/fixtures/__init__.py +1 -0
- jaclang/jac/tests/fixtures/activity.py +10 -0
- jaclang/jac/tests/fixtures/fam.jac +68 -0
- jaclang/jac/tests/fixtures/hello_world.jac +5 -0
- jaclang/jac/tests/fixtures/lexer_fam.jac +61 -0
- jaclang/jac/tests/fixtures/stuff.jac +6 -0
- jaclang/jac/tests/test_importer.py +24 -0
- jaclang/jac/tests/test_lexer.py +57 -0
- jaclang/jac/tests/test_parser.py +50 -0
- jaclang/jac/tests/test_utils.py +12 -0
- jaclang/jac/transform.py +63 -0
- jaclang/jac/transpiler.py +69 -0
- jaclang/jac/utils.py +120 -0
- jaclang/utils/__init__.py +1 -0
- jaclang/utils/fstring_parser.py +73 -0
- jaclang/utils/log.py +9 -0
- jaclang/utils/sly/__init__.py +6 -0
- jaclang/utils/sly/docparse.py +62 -0
- jaclang/utils/sly/lex.py +510 -0
- jaclang/utils/sly/yacc.py +2398 -0
- jaclang/utils/test.py +81 -0
- jaclang/utils/tests/__init__.py +1 -0
- jaclang/utils/tests/test_fstring_parser.py +55 -0
- jaclang-0.0.3.dist-info/METADATA +12 -0
- jaclang-0.0.3.dist-info/RECORD +70 -0
- {jaclang-0.0.1.dist-info → jaclang-0.0.3.dist-info}/WHEEL +1 -1
- jaclang-0.0.3.dist-info/entry_points.txt +3 -0
- jaclang-0.0.3.dist-info/top_level.txt +1 -0
- jaclang-0.0.1.dist-info/METADATA +0 -7
- jaclang-0.0.1.dist-info/RECORD +0 -4
- jaclang-0.0.1.dist-info/top_level.txt +0 -1
|
@@ -0,0 +1,1335 @@
|
|
|
1
|
+
"""Jac Blue pass for Jaseci Ast."""
|
|
2
|
+
import jaclang.jac.absyntree as ast
|
|
3
|
+
from jaclang.jac.constant import Constants as Con
|
|
4
|
+
from jaclang.jac.lexer import Tokens as Tok
|
|
5
|
+
from jaclang.jac.passes import Pass
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BluePygenPass(Pass):
|
|
9
|
+
"""Jac blue transpilation to python pass."""
|
|
10
|
+
|
|
11
|
+
def before_pass(self) -> None:
|
|
12
|
+
"""Initialize pass."""
|
|
13
|
+
self.indent_size = 4
|
|
14
|
+
self.indent_level = 0
|
|
15
|
+
self.debuginfo = {"jac_mods": []}
|
|
16
|
+
self.preamble = ast.AstNode(parent=None, mod_link=None, kid=[], line=0)
|
|
17
|
+
self.preamble.meta["py_code"] = "from __future__ import annotations\n"
|
|
18
|
+
self.cur_arch = None # tracks current architype during transpilation
|
|
19
|
+
|
|
20
|
+
def enter_node(self, node: ast.AstNode) -> None:
|
|
21
|
+
"""Enter node."""
|
|
22
|
+
if node:
|
|
23
|
+
node.meta["py_code"] = ""
|
|
24
|
+
return Pass.enter_node(self, node)
|
|
25
|
+
|
|
26
|
+
def indent_str(self) -> str:
|
|
27
|
+
"""Return string for indent."""
|
|
28
|
+
return " " * self.indent_size * self.indent_level
|
|
29
|
+
|
|
30
|
+
def emit_ln(self, node: ast.AstNode, s: str) -> None:
|
|
31
|
+
"""Emit code to node."""
|
|
32
|
+
self.emit(node, s.strip().strip("\n"))
|
|
33
|
+
self.emit(node, f" # {self.get_mod_index(node)} {node.line}\n")
|
|
34
|
+
|
|
35
|
+
def emit_ln_unique(self, node: ast.AstNode, s: str) -> None:
|
|
36
|
+
"""Emit code to node."""
|
|
37
|
+
if s not in node.meta["py_code"]:
|
|
38
|
+
ilev = self.indent_level
|
|
39
|
+
self.indent_level = 0
|
|
40
|
+
self.emit_ln(node, s)
|
|
41
|
+
self.indent_level = ilev
|
|
42
|
+
|
|
43
|
+
def get_mod_index(self, node: ast.AstNode) -> int:
|
|
44
|
+
"""Get module index."""
|
|
45
|
+
path = node.mod_link.mod_path if node.mod_link else None
|
|
46
|
+
if not path:
|
|
47
|
+
return -1
|
|
48
|
+
if path not in self.debuginfo["jac_mods"]:
|
|
49
|
+
self.debuginfo["jac_mods"].append(path)
|
|
50
|
+
return self.debuginfo["jac_mods"].index(path)
|
|
51
|
+
|
|
52
|
+
def emit(self, node: ast.AstNode, s: str) -> None:
|
|
53
|
+
"""Emit code to node."""
|
|
54
|
+
node.meta["py_code"] += self.indent_str() + s.replace(
|
|
55
|
+
"\n", "\n" + self.indent_str()
|
|
56
|
+
)
|
|
57
|
+
if "\n" in node.meta["py_code"]:
|
|
58
|
+
node.meta["py_code"] = node.meta["py_code"].rstrip(" ")
|
|
59
|
+
|
|
60
|
+
def needs_jac_import(self) -> None:
|
|
61
|
+
"""Check if import is needed."""
|
|
62
|
+
self.emit_ln_unique(
|
|
63
|
+
self.preamble, "from jaclang import jac_blue_import as __jac_import__"
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def needs_enum(self) -> None:
|
|
67
|
+
"""Check if enum is needed."""
|
|
68
|
+
self.emit_ln_unique(
|
|
69
|
+
self.preamble,
|
|
70
|
+
"from enum import Enum as __jac_Enum__, auto as __jac_auto__",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
def emit_jac_error_handler(self, node: ast.AstNode) -> None:
|
|
74
|
+
"""Emit error handler."""
|
|
75
|
+
self.emit_ln_unique(self.preamble, "import traceback as __jac_traceback__")
|
|
76
|
+
self.emit_ln_unique(
|
|
77
|
+
self.preamble, "from jaclang import handle_jac_error as __jac_error__"
|
|
78
|
+
)
|
|
79
|
+
self.emit_ln(node, "except Exception as e:")
|
|
80
|
+
self.indent_level += 1
|
|
81
|
+
# self.emit_ln(node, "__jac_traceback__.print_exc()")
|
|
82
|
+
self.emit_ln(node, "tb = __jac_traceback__.extract_tb(e.__traceback__)")
|
|
83
|
+
self.emit_ln(node, "__jac_tmp__ = __jac_error__(_jac_pycodestring_, e, tb)")
|
|
84
|
+
self.emit_ln(node, "print(__jac_tmp__)\nraise e")
|
|
85
|
+
self.emit_ln(
|
|
86
|
+
node,
|
|
87
|
+
"raise type(e)(str(e) + '\\nOriginal Snippet:\\n' + __jac_tmp__) "
|
|
88
|
+
"if 'Original Snippet:' not in str(e) else e",
|
|
89
|
+
)
|
|
90
|
+
self.indent_level -= 1
|
|
91
|
+
|
|
92
|
+
def decl_def_missing(self, decl: str = "this") -> None:
|
|
93
|
+
"""Warn about declaration."""
|
|
94
|
+
self.error(
|
|
95
|
+
f"Unable to find definition for {decl} declaration. Perhaps there's an `include` missing?"
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def ds_feature_warn(self) -> None:
|
|
99
|
+
"""Warn about feature."""
|
|
100
|
+
self.warning("Data spatial features not supported in bootstrap Jac.")
|
|
101
|
+
|
|
102
|
+
def exit_parse(self, node: ast.Parse) -> None:
|
|
103
|
+
"""Sub objects.
|
|
104
|
+
|
|
105
|
+
name: str,
|
|
106
|
+
"""
|
|
107
|
+
self.error(f"Parse node should not be in this AST!! {node.name}")
|
|
108
|
+
raise ValueError("Parse node should not be in AST after being Built!!")
|
|
109
|
+
|
|
110
|
+
def exit_token(self, node: ast.Token) -> None:
|
|
111
|
+
"""Sub objects.
|
|
112
|
+
|
|
113
|
+
name: str,
|
|
114
|
+
value: str,
|
|
115
|
+
col_start: int,
|
|
116
|
+
col_end: int,
|
|
117
|
+
"""
|
|
118
|
+
self.emit(node, node.value)
|
|
119
|
+
|
|
120
|
+
def exit_name(self, node: ast.Name) -> None:
|
|
121
|
+
"""Sub objects.
|
|
122
|
+
|
|
123
|
+
name: str,
|
|
124
|
+
value: str,
|
|
125
|
+
col_start: int,
|
|
126
|
+
col_end: int,
|
|
127
|
+
already_declared: bool,
|
|
128
|
+
"""
|
|
129
|
+
self.emit(node, node.value)
|
|
130
|
+
|
|
131
|
+
def exit_constant(self, node: ast.Constant) -> None:
|
|
132
|
+
"""Sub objects.
|
|
133
|
+
|
|
134
|
+
name: str,
|
|
135
|
+
value: str,
|
|
136
|
+
col_start: int,
|
|
137
|
+
col_end: int,
|
|
138
|
+
typ: type,
|
|
139
|
+
"""
|
|
140
|
+
self.emit(node, node.value)
|
|
141
|
+
|
|
142
|
+
def exit_module(self, node: ast.Module) -> None:
|
|
143
|
+
"""Sub objects.
|
|
144
|
+
|
|
145
|
+
name: str,
|
|
146
|
+
doc: Token,
|
|
147
|
+
body: "Elements",
|
|
148
|
+
"""
|
|
149
|
+
self.emit_ln(node, node.doc.value)
|
|
150
|
+
self.emit(node, self.preamble.meta["py_code"])
|
|
151
|
+
if node.body:
|
|
152
|
+
self.emit(node, node.body.meta["py_code"])
|
|
153
|
+
self.emit(node, f'""" {Con.JAC_DEBUG_SPLITTER}\n')
|
|
154
|
+
for i in self.debuginfo["jac_mods"]:
|
|
155
|
+
self.emit(node, f"{i}\n")
|
|
156
|
+
self.emit(node, f'{Con.JAC_DEBUG_SPLITTER} """\n')
|
|
157
|
+
self.ir = node
|
|
158
|
+
self.ir.meta["py_code"] = self.ir.meta["py_code"].rstrip()
|
|
159
|
+
|
|
160
|
+
def exit_elements(self, node: ast.Elements) -> None:
|
|
161
|
+
"""Sub objects.
|
|
162
|
+
|
|
163
|
+
elements: list[GlobalVars | Test | ModuleCode | Import | Architype | Ability | AbilitySpec],
|
|
164
|
+
"""
|
|
165
|
+
for i in node.elements:
|
|
166
|
+
self.emit(node, i.meta["py_code"])
|
|
167
|
+
self.emit(node, "\n")
|
|
168
|
+
|
|
169
|
+
def exit_global_vars(self, node: ast.GlobalVars) -> None:
|
|
170
|
+
"""Sub objects.
|
|
171
|
+
|
|
172
|
+
doc: Optional["Token"],
|
|
173
|
+
access: Optional[Token],
|
|
174
|
+
assignments: "AssignmentList",
|
|
175
|
+
is_frozen: bool,
|
|
176
|
+
"""
|
|
177
|
+
if node.doc:
|
|
178
|
+
self.emit_ln(node, node.doc.value)
|
|
179
|
+
self.emit(node, node.assignments.meta["py_code"])
|
|
180
|
+
|
|
181
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
182
|
+
def exit_test(self, node: ast.Test) -> None:
|
|
183
|
+
"""Sub objects.
|
|
184
|
+
|
|
185
|
+
name: Token,
|
|
186
|
+
doc: Optional["Token"],
|
|
187
|
+
description: Token,
|
|
188
|
+
body: "CodeBlock",
|
|
189
|
+
"""
|
|
190
|
+
self.warning("Test feature not supported in bootstrap Jac.")
|
|
191
|
+
|
|
192
|
+
def exit_module_code(self, node: ast.ModuleCode) -> None:
|
|
193
|
+
"""Sub objects.
|
|
194
|
+
|
|
195
|
+
doc: Optional["Token"],
|
|
196
|
+
body: "CodeBlock",
|
|
197
|
+
"""
|
|
198
|
+
if node.doc:
|
|
199
|
+
self.emit_ln(node, node.doc.value)
|
|
200
|
+
self.emit(node, node.body.meta["py_code"])
|
|
201
|
+
|
|
202
|
+
def exit_import(self, node: ast.Import) -> None:
|
|
203
|
+
"""Sub objects.
|
|
204
|
+
|
|
205
|
+
lang: Token,
|
|
206
|
+
path: "ModulePath",
|
|
207
|
+
alias: Optional[Token],
|
|
208
|
+
items: Optional["ModuleItems"],
|
|
209
|
+
is_absorb: bool, # For includes
|
|
210
|
+
self.sub_module = None
|
|
211
|
+
"""
|
|
212
|
+
if node.lang.value == Con.JAC_LANG_IMP: # injects module into sys.modules
|
|
213
|
+
self.needs_jac_import()
|
|
214
|
+
self.emit_ln(
|
|
215
|
+
node,
|
|
216
|
+
f"__jac_import__(target='{node.path.meta['py_code']}', base_path=__file__)",
|
|
217
|
+
)
|
|
218
|
+
if node.is_absorb:
|
|
219
|
+
self.emit_ln(
|
|
220
|
+
node,
|
|
221
|
+
f"from {node.path.meta['py_code']} import *",
|
|
222
|
+
)
|
|
223
|
+
if node.items:
|
|
224
|
+
self.warning(
|
|
225
|
+
"Includes import * in target module into current namespace."
|
|
226
|
+
)
|
|
227
|
+
if not node.items:
|
|
228
|
+
if not node.alias:
|
|
229
|
+
self.emit_ln(node, f"import {node.path.meta['py_code']}")
|
|
230
|
+
else:
|
|
231
|
+
self.emit_ln(
|
|
232
|
+
node,
|
|
233
|
+
f"import {node.path.meta['py_code']} as {node.alias.meta['py_code']}",
|
|
234
|
+
)
|
|
235
|
+
else:
|
|
236
|
+
self.emit_ln(
|
|
237
|
+
node,
|
|
238
|
+
f"from {node.path.meta['py_code']} import {node.items.meta['py_code']}",
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
def exit_module_path(self, node: ast.ModulePath) -> None:
|
|
242
|
+
"""Sub objects.
|
|
243
|
+
|
|
244
|
+
path: list[Token],
|
|
245
|
+
"""
|
|
246
|
+
self.emit(node, "".join([i.value for i in node.path]))
|
|
247
|
+
|
|
248
|
+
def exit_module_items(self, node: ast.ModuleItems) -> None:
|
|
249
|
+
"""Sub objects.
|
|
250
|
+
|
|
251
|
+
items: list["ModuleItem"],
|
|
252
|
+
"""
|
|
253
|
+
self.emit(node, ", ".join([i.meta["py_code"] for i in node.items]))
|
|
254
|
+
|
|
255
|
+
def exit_module_item(self, node: ast.ModuleItem) -> None:
|
|
256
|
+
"""Sub objects.
|
|
257
|
+
|
|
258
|
+
name: Token,
|
|
259
|
+
alias: Optional[Token],
|
|
260
|
+
"""
|
|
261
|
+
if node.alias:
|
|
262
|
+
self.emit(node, node.name.value + " as " + node.alias.value)
|
|
263
|
+
else:
|
|
264
|
+
self.emit(node, node.name.value)
|
|
265
|
+
|
|
266
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
267
|
+
def exit_architype(self, node: ast.Architype) -> None:
|
|
268
|
+
"""Sub objects.
|
|
269
|
+
|
|
270
|
+
name: Name,
|
|
271
|
+
arch_type: Token,
|
|
272
|
+
doc: Optional[Token],
|
|
273
|
+
decorators: Optional["Decorators"],
|
|
274
|
+
access: Optional[Token],
|
|
275
|
+
base_classes: "BaseClasses",
|
|
276
|
+
body: Optional["ArchBlock"],
|
|
277
|
+
"""
|
|
278
|
+
if node.decorators:
|
|
279
|
+
self.emit(node, node.decorators.meta["py_code"])
|
|
280
|
+
if not len(node.base_classes.base_classes):
|
|
281
|
+
self.emit_ln(node, f"class {node.name.meta['py_code']}:")
|
|
282
|
+
else:
|
|
283
|
+
self.emit_ln(
|
|
284
|
+
node,
|
|
285
|
+
f"class {node.name.meta['py_code']}({node.base_classes.meta['py_code']}):",
|
|
286
|
+
)
|
|
287
|
+
self.indent_level += 1
|
|
288
|
+
if node.doc:
|
|
289
|
+
self.emit_ln(node, node.doc.value)
|
|
290
|
+
if node.body:
|
|
291
|
+
self.emit(node, node.body.meta["py_code"])
|
|
292
|
+
else:
|
|
293
|
+
self.decl_def_missing(node.name.meta["py_code"])
|
|
294
|
+
self.indent_level -= 1
|
|
295
|
+
|
|
296
|
+
def exit_arch_def(self, node: ast.ArchDef) -> None:
|
|
297
|
+
"""Sub objects.
|
|
298
|
+
|
|
299
|
+
doc: Optional[Token],
|
|
300
|
+
mod: Optional["NameList"],
|
|
301
|
+
arch: "ObjectRef | NodeRef | EdgeRef | WalkerRef",
|
|
302
|
+
body: "ArchBlock",
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
def exit_decorators(self, node: ast.Decorators) -> None:
|
|
306
|
+
"""Sub objects.
|
|
307
|
+
|
|
308
|
+
calls: list["ExprType"],
|
|
309
|
+
"""
|
|
310
|
+
for i in node.calls:
|
|
311
|
+
self.emit_ln(node, "@" + i.meta["py_code"])
|
|
312
|
+
|
|
313
|
+
def exit_base_classes(self, node: ast.BaseClasses) -> None:
|
|
314
|
+
"""Sub objects.
|
|
315
|
+
|
|
316
|
+
base_classes: list[NameList],
|
|
317
|
+
"""
|
|
318
|
+
self.emit(node, ", ".join([i.meta["py_code"] for i in node.base_classes]))
|
|
319
|
+
|
|
320
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
321
|
+
def exit_ability(self, node: ast.Ability) -> None:
|
|
322
|
+
"""Sub objects.
|
|
323
|
+
|
|
324
|
+
name: Name,
|
|
325
|
+
is_func: bool,
|
|
326
|
+
is_async: bool,
|
|
327
|
+
is_static: bool,
|
|
328
|
+
doc: Optional[Token],
|
|
329
|
+
decorators: Optional["Decorators"],
|
|
330
|
+
access: Optional[Token],
|
|
331
|
+
signature: Optional["FuncSignature | TypeSpec | EventSignature"],
|
|
332
|
+
body: Optional["CodeBlock"],
|
|
333
|
+
arch_attached: Optional["ArchBlock"] = None,
|
|
334
|
+
"""
|
|
335
|
+
if node.decorators:
|
|
336
|
+
self.emit(node, node.decorators.meta["py_code"])
|
|
337
|
+
if node.signature and node.is_func:
|
|
338
|
+
if node.arch_attached and not node.is_static:
|
|
339
|
+
self.emit_ln(
|
|
340
|
+
node, f"def {node.name.value}(self{node.signature.meta['py_code']}:"
|
|
341
|
+
)
|
|
342
|
+
else:
|
|
343
|
+
if node.arch_attached and node.is_static:
|
|
344
|
+
self.emit_ln(node, "@classmethod")
|
|
345
|
+
self.emit_ln(
|
|
346
|
+
node, f"def {node.name.value}({node.signature.meta['py_code']}:"
|
|
347
|
+
)
|
|
348
|
+
else:
|
|
349
|
+
if node.arch_attached:
|
|
350
|
+
self.emit_ln(node, f"def {node.name.value}(self):")
|
|
351
|
+
else:
|
|
352
|
+
self.emit_ln(node, f"def {node.name.value}():")
|
|
353
|
+
self.indent_level += 1
|
|
354
|
+
if node.doc:
|
|
355
|
+
self.emit_ln(node, node.doc.value)
|
|
356
|
+
if node.body:
|
|
357
|
+
self.emit_ln(node, "try:")
|
|
358
|
+
self.indent_level += 1
|
|
359
|
+
self.emit(node, node.body.meta["py_code"])
|
|
360
|
+
self.indent_level -= 1
|
|
361
|
+
self.emit_jac_error_handler(node)
|
|
362
|
+
else:
|
|
363
|
+
self.decl_def_missing(node.name.value)
|
|
364
|
+
self.indent_level -= 1
|
|
365
|
+
|
|
366
|
+
def exit_ability_def(self, node: ast.AbilityDef) -> None:
|
|
367
|
+
"""Sub objects.
|
|
368
|
+
|
|
369
|
+
doc: Optional[Token],
|
|
370
|
+
mod: Optional["NameList"],
|
|
371
|
+
ability: AbilityRef,
|
|
372
|
+
body: CodeBlock,
|
|
373
|
+
"""
|
|
374
|
+
|
|
375
|
+
def exit_arch_block(self, node: ast.ArchBlock) -> None:
|
|
376
|
+
"""Sub objects.
|
|
377
|
+
|
|
378
|
+
members: list["ArchHas | Ability"],
|
|
379
|
+
"""
|
|
380
|
+
init_func = None
|
|
381
|
+
for i in node.members:
|
|
382
|
+
if type(i) == ast.Ability and i.name.value == Con.INIT_FUNC:
|
|
383
|
+
init_func = i
|
|
384
|
+
break
|
|
385
|
+
if init_func and init_func.signature and init_func.is_func:
|
|
386
|
+
self.emit_ln(
|
|
387
|
+
node, f"def __init__(self{init_func.signature.meta['py_code']}:"
|
|
388
|
+
)
|
|
389
|
+
else:
|
|
390
|
+
self.emit_ln(node, "def __init__(self, *args, **kwargs):")
|
|
391
|
+
|
|
392
|
+
self.indent_level += 1
|
|
393
|
+
self.emit_ln(node, '"""Init generated by Jac."""')
|
|
394
|
+
for i in node.members:
|
|
395
|
+
if type(i) == ast.ArchHas and not i.is_static:
|
|
396
|
+
self.emit_ln(node, f"self.has_{i.h_id}()")
|
|
397
|
+
if init_func:
|
|
398
|
+
params = []
|
|
399
|
+
if (
|
|
400
|
+
type(init_func.signature) == ast.FuncSignature
|
|
401
|
+
and init_func.signature.params
|
|
402
|
+
):
|
|
403
|
+
params = [x.name.value for x in init_func.signature.params.params]
|
|
404
|
+
self.emit_ln(node, f"self.{Con.INIT_FUNC}({', '.join(params)})")
|
|
405
|
+
self.emit_ln(node, "super().__init__(*args, **kwargs)")
|
|
406
|
+
self.indent_level -= 1
|
|
407
|
+
for i in node.members:
|
|
408
|
+
self.emit(node, i.meta["py_code"])
|
|
409
|
+
self.emit(node, "\n")
|
|
410
|
+
|
|
411
|
+
def exit_arch_has(self, node: ast.ArchHas) -> None:
|
|
412
|
+
"""Sub objects.
|
|
413
|
+
|
|
414
|
+
doc: Optional[Token],
|
|
415
|
+
is_static: bool,
|
|
416
|
+
access: Optional[Token],
|
|
417
|
+
vars: "HasVarList",
|
|
418
|
+
is_frozen: bool,
|
|
419
|
+
"""
|
|
420
|
+
if node.is_static:
|
|
421
|
+
if node.doc:
|
|
422
|
+
self.emit_ln(node, node.doc.value)
|
|
423
|
+
self.emit_ln(node, node.vars.meta["py_code"].replace("self.", ""))
|
|
424
|
+
else:
|
|
425
|
+
self.emit_ln(node, f"def has_{node.h_id}(self):")
|
|
426
|
+
self.indent_level += 1
|
|
427
|
+
if node.doc:
|
|
428
|
+
self.emit_ln(node, node.doc.value)
|
|
429
|
+
self.emit(node, node.vars.meta["py_code"])
|
|
430
|
+
self.indent_level -= 1
|
|
431
|
+
|
|
432
|
+
def exit_has_var_list(self, node: ast.HasVarList) -> None:
|
|
433
|
+
"""Sub objects.
|
|
434
|
+
|
|
435
|
+
vars: list[HasVar],
|
|
436
|
+
"""
|
|
437
|
+
for i in node.vars:
|
|
438
|
+
self.emit_ln(node, i.meta["py_code"])
|
|
439
|
+
|
|
440
|
+
def exit_has_var(self, node: ast.HasVar) -> None:
|
|
441
|
+
"""Sub objects.
|
|
442
|
+
|
|
443
|
+
name: Token,
|
|
444
|
+
type_tag: TypeSpec,
|
|
445
|
+
value: Optional["ExprType"],
|
|
446
|
+
"""
|
|
447
|
+
if node.value:
|
|
448
|
+
self.emit(
|
|
449
|
+
node,
|
|
450
|
+
f"self.{node.name.value}: {node.type_tag.meta['py_code']} = {node.value.meta['py_code']}",
|
|
451
|
+
)
|
|
452
|
+
else:
|
|
453
|
+
self.emit(
|
|
454
|
+
node, f"self.{node.name.value}: {node.type_tag.meta['py_code']} = None"
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
def exit_type_spec_list(self, node: ast.TypeSpecList) -> None:
|
|
458
|
+
"""Sub objects.
|
|
459
|
+
|
|
460
|
+
types: list[TypeSpec],
|
|
461
|
+
"""
|
|
462
|
+
self.emit(node, "|".join([i.meta["py_code"] for i in node.types]))
|
|
463
|
+
|
|
464
|
+
def exit_type_spec(self, node: ast.TypeSpec) -> None:
|
|
465
|
+
"""Sub objects.
|
|
466
|
+
|
|
467
|
+
typ: "Token | NameList",
|
|
468
|
+
list_nest: TypeSpec,
|
|
469
|
+
dict_nest: TypeSpec,
|
|
470
|
+
"""
|
|
471
|
+
if node.dict_nest:
|
|
472
|
+
self.emit(
|
|
473
|
+
node,
|
|
474
|
+
f"dict[{node.list_nest.meta['py_code']}, {node.dict_nest.meta['py_code']}]",
|
|
475
|
+
)
|
|
476
|
+
elif node.list_nest:
|
|
477
|
+
self.emit(node, f"list[{node.list_nest.meta['py_code']}]")
|
|
478
|
+
else:
|
|
479
|
+
self.emit(node, node.spec_type.meta["py_code"])
|
|
480
|
+
|
|
481
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
482
|
+
def exit_event_signature(self, node: ast.EventSignature) -> None:
|
|
483
|
+
"""Sub objects.
|
|
484
|
+
|
|
485
|
+
event: Token,
|
|
486
|
+
arch_tag_info: Optional["TypeList | TypeSpec"],
|
|
487
|
+
return_type: Optional["TypeSpec"],
|
|
488
|
+
"""
|
|
489
|
+
self.error("Event style abilities not supported in bootstrap Jac")
|
|
490
|
+
|
|
491
|
+
def exit_name_list(self, node: ast.NameList) -> None:
|
|
492
|
+
"""Sub objects.
|
|
493
|
+
|
|
494
|
+
names: list[all_refs],
|
|
495
|
+
"""
|
|
496
|
+
self.emit(node, ".".join([i.meta["py_code"] for i in node.names]))
|
|
497
|
+
|
|
498
|
+
def exit_func_signature(self, node: ast.FuncSignature) -> None:
|
|
499
|
+
"""Sub objects.
|
|
500
|
+
|
|
501
|
+
params: Optional[FuncParams],
|
|
502
|
+
return_type: Optional[TypeSpec],
|
|
503
|
+
self.is_arch_attached = False
|
|
504
|
+
"""
|
|
505
|
+
if node.params:
|
|
506
|
+
if (
|
|
507
|
+
type(node.parent) == ast.Ability
|
|
508
|
+
and node.parent.arch_attached
|
|
509
|
+
and not node.parent.is_static
|
|
510
|
+
):
|
|
511
|
+
self.emit(node, ", ")
|
|
512
|
+
self.emit(node, node.params.meta["py_code"])
|
|
513
|
+
if (
|
|
514
|
+
type(node.parent) == ast.Ability
|
|
515
|
+
and node.parent.arch_attached
|
|
516
|
+
and node.parent.name.value == Con.INIT_FUNC
|
|
517
|
+
):
|
|
518
|
+
self.emit(node, ", *args, **kwargs")
|
|
519
|
+
self.emit(node, ")")
|
|
520
|
+
if node.return_type:
|
|
521
|
+
self.emit(node, f" -> {node.return_type.meta['py_code']}")
|
|
522
|
+
|
|
523
|
+
def exit_func_params(self, node: ast.FuncParams) -> None:
|
|
524
|
+
"""Sub objects.
|
|
525
|
+
|
|
526
|
+
params: list["ParamVar"],
|
|
527
|
+
"""
|
|
528
|
+
first_out = False
|
|
529
|
+
for i in node.params:
|
|
530
|
+
self.emit(node, ", ") if first_out else None
|
|
531
|
+
self.emit(node, i.meta["py_code"])
|
|
532
|
+
first_out = True
|
|
533
|
+
|
|
534
|
+
def exit_param_var(self, node: ast.ParamVar) -> None:
|
|
535
|
+
"""Sub objects.
|
|
536
|
+
|
|
537
|
+
name: Token,
|
|
538
|
+
unpack: Optional[Token],
|
|
539
|
+
type_tag: "TypeSpec",
|
|
540
|
+
value: Optional["ExprType"],
|
|
541
|
+
"""
|
|
542
|
+
if node.unpack:
|
|
543
|
+
self.emit(node, f"{node.unpack.value}")
|
|
544
|
+
if node.value:
|
|
545
|
+
self.emit(
|
|
546
|
+
node,
|
|
547
|
+
f"{node.name.value}: {node.type_tag.meta['py_code']} = {node.value.meta['py_code']}",
|
|
548
|
+
)
|
|
549
|
+
else:
|
|
550
|
+
self.emit(node, f"{node.name.value}: {node.type_tag.meta['py_code']}")
|
|
551
|
+
|
|
552
|
+
def exit_enum(self, node: ast.Enum) -> None:
|
|
553
|
+
"""Sub objects.
|
|
554
|
+
|
|
555
|
+
name: Name,
|
|
556
|
+
doc: Optional[Token],
|
|
557
|
+
decorators: Optional[Decorators],
|
|
558
|
+
access: Optional[Token],
|
|
559
|
+
base_classes: BaseClasses,
|
|
560
|
+
body: Optional[EnumBlock],
|
|
561
|
+
"""
|
|
562
|
+
if node.decorators:
|
|
563
|
+
self.emit_ln(node, node.decorators.meta["py_code"])
|
|
564
|
+
if len(node.base_classes.base_classes):
|
|
565
|
+
self.emit_ln(
|
|
566
|
+
node,
|
|
567
|
+
f"class {node.name.meta['py_code']}({node.base_classes.meta['py_code']}):",
|
|
568
|
+
)
|
|
569
|
+
else:
|
|
570
|
+
self.needs_enum()
|
|
571
|
+
self.emit_ln(node, f"class {node.name.value}(__jac_Enum__):")
|
|
572
|
+
self.indent_level += 1
|
|
573
|
+
if node.doc:
|
|
574
|
+
self.emit_ln(node, node.doc.value)
|
|
575
|
+
if node.body:
|
|
576
|
+
self.emit(node, node.body.meta["py_code"])
|
|
577
|
+
else:
|
|
578
|
+
self.decl_def_missing(node.name.meta["py_code"])
|
|
579
|
+
self.indent_level -= 1
|
|
580
|
+
|
|
581
|
+
def exit_enum_def(self, node: ast.EnumDef) -> None:
|
|
582
|
+
"""Sub objects.
|
|
583
|
+
|
|
584
|
+
doc: Optional[Token],
|
|
585
|
+
mod: Optional[NameList],
|
|
586
|
+
body: EnumBlock,
|
|
587
|
+
"""
|
|
588
|
+
|
|
589
|
+
def exit_enum_block(self, node: ast.EnumBlock) -> None:
|
|
590
|
+
"""Sub objects.
|
|
591
|
+
|
|
592
|
+
stmts: list['Name|Assignment'],
|
|
593
|
+
"""
|
|
594
|
+
for i in node.stmts:
|
|
595
|
+
if type(i) == ast.Name:
|
|
596
|
+
self.emit_ln(node, i.meta["py_code"] + " = __jac_auto__()")
|
|
597
|
+
else:
|
|
598
|
+
self.emit(node, i.meta["py_code"])
|
|
599
|
+
|
|
600
|
+
def exit_code_block(self, node: ast.CodeBlock) -> None:
|
|
601
|
+
"""Sub objects.
|
|
602
|
+
|
|
603
|
+
stmts: list["StmtType"],
|
|
604
|
+
"""
|
|
605
|
+
if len(node.stmts) == 0:
|
|
606
|
+
self.emit_ln(node, "pass")
|
|
607
|
+
for i in node.stmts:
|
|
608
|
+
self.emit(node, i.meta["py_code"])
|
|
609
|
+
if len(i.meta["py_code"]) and i.meta["py_code"][-1] != "\n":
|
|
610
|
+
self.emit_ln(node, "\n")
|
|
611
|
+
|
|
612
|
+
def exit_if_stmt(self, node: ast.IfStmt) -> None:
|
|
613
|
+
"""Sub objects.
|
|
614
|
+
|
|
615
|
+
condition: ExprType,
|
|
616
|
+
body: CodeBlock,
|
|
617
|
+
elseifs: Optional[ElseIfs],
|
|
618
|
+
else_body: Optional[ElseStmt],
|
|
619
|
+
"""
|
|
620
|
+
self.emit_ln(node, f"if {node.condition.meta['py_code']}:")
|
|
621
|
+
self.indent_level += 1
|
|
622
|
+
self.emit(node, node.body.meta["py_code"])
|
|
623
|
+
self.indent_level -= 1
|
|
624
|
+
self.emit(node, "\n")
|
|
625
|
+
if node.elseifs:
|
|
626
|
+
self.emit(node, node.elseifs.meta["py_code"])
|
|
627
|
+
if node.else_body:
|
|
628
|
+
self.emit(node, node.else_body.meta["py_code"])
|
|
629
|
+
|
|
630
|
+
def exit_typed_ctx_block(self, node: ast.TypedCtxBlock) -> None:
|
|
631
|
+
"""Sub objects.
|
|
632
|
+
|
|
633
|
+
type_ctx: TypeList,
|
|
634
|
+
body: CodeBlock,
|
|
635
|
+
"""
|
|
636
|
+
self.ds_feature_warn()
|
|
637
|
+
|
|
638
|
+
def exit_else_ifs(self, node: ast.ElseIfs) -> None:
|
|
639
|
+
"""Sub objects.
|
|
640
|
+
|
|
641
|
+
elseifs: list[IfStmt],
|
|
642
|
+
"""
|
|
643
|
+
for i in node.elseifs:
|
|
644
|
+
self.emit_ln(node, f"elif {i.condition.meta['py_code']}:")
|
|
645
|
+
self.indent_level += 1
|
|
646
|
+
self.emit(node, i.body.meta["py_code"])
|
|
647
|
+
self.indent_level -= 1
|
|
648
|
+
self.emit(node, "\n")
|
|
649
|
+
|
|
650
|
+
def exit_else_stmt(self, node: ast.ElseStmt) -> None:
|
|
651
|
+
"""Sub objects.
|
|
652
|
+
|
|
653
|
+
body: CodeBlock,
|
|
654
|
+
"""
|
|
655
|
+
self.emit_ln(node, "else:")
|
|
656
|
+
self.indent_level += 1
|
|
657
|
+
self.emit(node, node.body.meta["py_code"])
|
|
658
|
+
self.indent_level -= 1
|
|
659
|
+
self.emit(node, "\n")
|
|
660
|
+
|
|
661
|
+
def exit_try_stmt(self, node: ast.TryStmt) -> None:
|
|
662
|
+
"""Sub objects.
|
|
663
|
+
|
|
664
|
+
body: CodeBlock,
|
|
665
|
+
excepts: Optional[ExceptList],
|
|
666
|
+
finally_body: Optional[FinallyStmt],
|
|
667
|
+
"""
|
|
668
|
+
self.emit_ln(node, "try:")
|
|
669
|
+
self.indent_level += 1
|
|
670
|
+
self.emit_ln(node, node.body.meta["py_code"])
|
|
671
|
+
self.indent_level -= 1
|
|
672
|
+
if node.excepts:
|
|
673
|
+
self.emit_ln(node, node.excepts.meta["py_code"])
|
|
674
|
+
if node.finally_body:
|
|
675
|
+
self.emit_ln(node, node.finally_body.meta["py_code"])
|
|
676
|
+
|
|
677
|
+
def exit_except(self, node: ast.Except) -> None:
|
|
678
|
+
"""Sub objects.
|
|
679
|
+
|
|
680
|
+
typ: ExprType,
|
|
681
|
+
name: Optional[Token],
|
|
682
|
+
body: CodeBlock,
|
|
683
|
+
"""
|
|
684
|
+
if node.name:
|
|
685
|
+
self.emit_ln(
|
|
686
|
+
node, f"except {node.ex_type.meta['py_code']} as {node.name.value}:"
|
|
687
|
+
)
|
|
688
|
+
else:
|
|
689
|
+
self.emit_ln(node, f"except {node.ex_type.meta['py_code']}:")
|
|
690
|
+
self.indent_level += 1
|
|
691
|
+
self.emit_ln(node, node.body.meta["py_code"])
|
|
692
|
+
self.indent_level -= 1
|
|
693
|
+
|
|
694
|
+
def exit_except_list(self, node: ast.ExceptList) -> None:
|
|
695
|
+
"""Sub objects.
|
|
696
|
+
|
|
697
|
+
excepts: list[Except],
|
|
698
|
+
"""
|
|
699
|
+
for i in node.excepts:
|
|
700
|
+
self.emit_ln(node, i.meta["py_code"])
|
|
701
|
+
|
|
702
|
+
def exit_finally_stmt(self, node: ast.FinallyStmt) -> None:
|
|
703
|
+
"""Sub objects.
|
|
704
|
+
|
|
705
|
+
body: CodeBlock,
|
|
706
|
+
"""
|
|
707
|
+
self.emit_ln(node, "finally:")
|
|
708
|
+
self.indent_level += 1
|
|
709
|
+
self.emit_ln(node, node.body.meta["py_code"])
|
|
710
|
+
self.indent_level -= 1
|
|
711
|
+
|
|
712
|
+
def exit_iter_for_stmt(self, node: ast.IterForStmt) -> None:
|
|
713
|
+
"""Sub objects.
|
|
714
|
+
|
|
715
|
+
iter: Assignment,
|
|
716
|
+
condition: ExprType,
|
|
717
|
+
count_by: ExprType,
|
|
718
|
+
body: CodeBlock,
|
|
719
|
+
"""
|
|
720
|
+
self.emit_ln(node, f"{node.iter.meta['py_code']}")
|
|
721
|
+
self.emit_ln(node, f"while {node.condition.meta['py_code']}:")
|
|
722
|
+
self.indent_level += 1
|
|
723
|
+
self.emit_ln(node, node.body.meta["py_code"])
|
|
724
|
+
self.emit_ln(node, f"{node.count_by.meta['py_code']}")
|
|
725
|
+
self.indent_level -= 1
|
|
726
|
+
|
|
727
|
+
def exit_in_for_stmt(self, node: ast.InForStmt) -> None:
|
|
728
|
+
"""Sub objects.
|
|
729
|
+
|
|
730
|
+
name: Token,
|
|
731
|
+
collection: ExprType,
|
|
732
|
+
body: CodeBlock,
|
|
733
|
+
"""
|
|
734
|
+
self.emit_ln(
|
|
735
|
+
node, f"for {node.name.value} in {node.collection.meta['py_code']}:"
|
|
736
|
+
)
|
|
737
|
+
self.indent_level += 1
|
|
738
|
+
self.emit_ln(node, node.body.meta["py_code"])
|
|
739
|
+
self.indent_level -= 1
|
|
740
|
+
|
|
741
|
+
def exit_dict_for_stmt(self, node: ast.DictForStmt) -> None:
|
|
742
|
+
"""Sub objects.
|
|
743
|
+
|
|
744
|
+
k_name: Token,
|
|
745
|
+
v_name: Token,
|
|
746
|
+
collection: ExprType,
|
|
747
|
+
body: CodeBlock,
|
|
748
|
+
"""
|
|
749
|
+
self.emit_ln(
|
|
750
|
+
node,
|
|
751
|
+
f"for {node.k_name.value}, {node.v_name.value} in {node.collection.meta['py_code']}:",
|
|
752
|
+
)
|
|
753
|
+
self.indent_level += 1
|
|
754
|
+
self.emit_ln(node, node.body.meta["py_code"])
|
|
755
|
+
self.indent_level -= 1
|
|
756
|
+
|
|
757
|
+
def exit_while_stmt(self, node: ast.WhileStmt) -> None:
|
|
758
|
+
"""Sub objects.
|
|
759
|
+
|
|
760
|
+
condition: ExprType,
|
|
761
|
+
body: CodeBlock,
|
|
762
|
+
"""
|
|
763
|
+
self.emit_ln(node, f"while {node.condition.meta['py_code']}:")
|
|
764
|
+
self.indent_level += 1
|
|
765
|
+
self.emit_ln(node, node.body.meta["py_code"])
|
|
766
|
+
self.indent_level -= 1
|
|
767
|
+
|
|
768
|
+
def exit_with_stmt(self, node: ast.WithStmt) -> None:
|
|
769
|
+
"""Sub objects.
|
|
770
|
+
|
|
771
|
+
exprs: "ExprAsItemList",
|
|
772
|
+
body: "CodeBlock",
|
|
773
|
+
"""
|
|
774
|
+
self.emit_ln(node, f"with {node.exprs.meta['py_code']}:")
|
|
775
|
+
self.indent_level += 1
|
|
776
|
+
self.emit_ln(node, node.body.meta["py_code"])
|
|
777
|
+
self.indent_level -= 1
|
|
778
|
+
|
|
779
|
+
def exit_expr_as_item_list(self, node: ast.ExprAsItemList) -> None:
|
|
780
|
+
"""Sub objects.
|
|
781
|
+
|
|
782
|
+
items: list["ExprAsItem"],
|
|
783
|
+
"""
|
|
784
|
+
self.emit(node, ", ".join([i.meta["py_code"] for i in node.items]))
|
|
785
|
+
|
|
786
|
+
def exit_expr_as_item(self, node: ast.ExprAsItem) -> None:
|
|
787
|
+
"""Sub objects.
|
|
788
|
+
|
|
789
|
+
expr: "ExprType",
|
|
790
|
+
alias: Optional[Token],
|
|
791
|
+
"""
|
|
792
|
+
if node.alias:
|
|
793
|
+
self.emit(node, node.expr.meta["py_code"] + " as " + node.alias.value)
|
|
794
|
+
else:
|
|
795
|
+
self.emit(node, node.expr.meta["py_code"])
|
|
796
|
+
|
|
797
|
+
def exit_raise_stmt(self, node: ast.RaiseStmt) -> None:
|
|
798
|
+
"""Sub objects.
|
|
799
|
+
|
|
800
|
+
cause: Optional[ExprType],
|
|
801
|
+
"""
|
|
802
|
+
if node.cause:
|
|
803
|
+
self.emit_ln(node, f"raise {node.cause.meta['py_code']}")
|
|
804
|
+
else:
|
|
805
|
+
self.emit_ln(node, "raise")
|
|
806
|
+
|
|
807
|
+
def exit_assert_stmt(self, node: ast.AssertStmt) -> None:
|
|
808
|
+
"""Sub objects.
|
|
809
|
+
|
|
810
|
+
condition: ExprType,
|
|
811
|
+
error_msg: Optional[ExprType],
|
|
812
|
+
"""
|
|
813
|
+
if node.error_msg:
|
|
814
|
+
self.emit_ln(
|
|
815
|
+
node,
|
|
816
|
+
f"assert {node.condition.meta['py_code']}, {node.error_msg.meta['py_code']}",
|
|
817
|
+
)
|
|
818
|
+
else:
|
|
819
|
+
self.emit_ln(node, f"assert {node.condition.meta['py_code']}")
|
|
820
|
+
|
|
821
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
822
|
+
def exit_ctrl_stmt(self, node: ast.CtrlStmt) -> None:
|
|
823
|
+
"""Sub objects.
|
|
824
|
+
|
|
825
|
+
ctrl: Token,
|
|
826
|
+
"""
|
|
827
|
+
if node.ctrl.name == Tok.KW_SKIP:
|
|
828
|
+
self.error("skip is not supported in bootstrap Jac")
|
|
829
|
+
else:
|
|
830
|
+
self.emit_ln(node, node.ctrl.value)
|
|
831
|
+
|
|
832
|
+
def exit_delete_stmt(self, node: ast.DeleteStmt) -> None:
|
|
833
|
+
"""Sub objects.
|
|
834
|
+
|
|
835
|
+
target: ExprType,
|
|
836
|
+
"""
|
|
837
|
+
self.emit_ln(node, f"del {node.target.meta['py_code']}")
|
|
838
|
+
|
|
839
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
840
|
+
def exit_report_stmt(self, node: ast.ReportStmt) -> None:
|
|
841
|
+
"""Sub objects.
|
|
842
|
+
|
|
843
|
+
expr: ExprType,
|
|
844
|
+
"""
|
|
845
|
+
self.ds_feature_warn()
|
|
846
|
+
|
|
847
|
+
def exit_return_stmt(self, node: ast.ReturnStmt) -> None:
|
|
848
|
+
"""Sub objects.
|
|
849
|
+
|
|
850
|
+
expr: Optional[ExprType],
|
|
851
|
+
"""
|
|
852
|
+
if node.expr:
|
|
853
|
+
self.emit_ln(node, f"return {node.expr.meta['py_code']}")
|
|
854
|
+
else:
|
|
855
|
+
self.emit_ln(node, "return")
|
|
856
|
+
|
|
857
|
+
def exit_yield_stmt(self, node: ast.YieldStmt) -> None:
|
|
858
|
+
"""Sub objects.
|
|
859
|
+
|
|
860
|
+
expr: Optional[ExprType],
|
|
861
|
+
"""
|
|
862
|
+
if node.expr:
|
|
863
|
+
self.emit_ln(node, f"yield {node.expr.meta['py_code']}")
|
|
864
|
+
else:
|
|
865
|
+
self.emit_ln(node, "yield")
|
|
866
|
+
|
|
867
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
868
|
+
def exit_ignore_stmt(self, node: ast.IgnoreStmt) -> None:
|
|
869
|
+
"""Sub objects.
|
|
870
|
+
|
|
871
|
+
target: ExprType,
|
|
872
|
+
"""
|
|
873
|
+
self.ds_feature_warn()
|
|
874
|
+
|
|
875
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
876
|
+
def exit_visit_stmt(self, node: ast.VisitStmt) -> None:
|
|
877
|
+
"""Sub objects.
|
|
878
|
+
|
|
879
|
+
vis_type: Optional[Token],
|
|
880
|
+
target: Optional["ExprType"],
|
|
881
|
+
else_body: Optional["ElseStmt"],
|
|
882
|
+
"""
|
|
883
|
+
self.ds_feature_warn()
|
|
884
|
+
|
|
885
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
886
|
+
def exit_revisit_stmt(self, node: ast.RevisitStmt) -> None:
|
|
887
|
+
"""Sub objects.
|
|
888
|
+
|
|
889
|
+
hops: Optional[ExprType],
|
|
890
|
+
else_body: Optional[ElseStmt],
|
|
891
|
+
"""
|
|
892
|
+
self.ds_feature_warn()
|
|
893
|
+
|
|
894
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
895
|
+
def exit_disengage_stmt(self, node: ast.DisengageStmt) -> None:
|
|
896
|
+
"""Sub objects."""
|
|
897
|
+
self.ds_feature_warn()
|
|
898
|
+
|
|
899
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
900
|
+
def exit_await_stmt(self, node: ast.AwaitStmt) -> None:
|
|
901
|
+
"""Sub objects.
|
|
902
|
+
|
|
903
|
+
target: ExprType,
|
|
904
|
+
"""
|
|
905
|
+
self.ds_feature_warn()
|
|
906
|
+
|
|
907
|
+
def exit_assignment(self, node: ast.Assignment) -> None:
|
|
908
|
+
"""Sub objects.
|
|
909
|
+
|
|
910
|
+
is_static: bool,
|
|
911
|
+
target: AtomType,
|
|
912
|
+
value: ExprType,
|
|
913
|
+
"""
|
|
914
|
+
if node.is_static:
|
|
915
|
+
self.warning("Static variable semantics is not supported in bootstrap Jac")
|
|
916
|
+
self.emit(node, f"{node.target.meta['py_code']} = {node.value.meta['py_code']}")
|
|
917
|
+
|
|
918
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
919
|
+
def exit_binary_expr(self, node: ast.BinaryExpr) -> None:
|
|
920
|
+
"""Sub objects.
|
|
921
|
+
|
|
922
|
+
left: ExprType,
|
|
923
|
+
right: ExprType,
|
|
924
|
+
op: Token | DisconnectOp | ConnectOp,
|
|
925
|
+
"""
|
|
926
|
+
if type(node.op) in [ast.DisconnectOp, ast.ConnectOp]:
|
|
927
|
+
self.ds_feature_warn()
|
|
928
|
+
if type(node.op) == ast.Token:
|
|
929
|
+
if node.op.value in [
|
|
930
|
+
*["+", "-", "*", "/", "%", "**"],
|
|
931
|
+
*["+=", "-=", "*=", "/=", "%=", "**="],
|
|
932
|
+
*[">>", "<<", ">>=", "<<="],
|
|
933
|
+
*["//=", "&=", "|=", "^=", "~="],
|
|
934
|
+
*["//", "&", "|", "^"],
|
|
935
|
+
*[">", "<", ">=", "<=", "==", "!=", ":="],
|
|
936
|
+
*["and", "or", "in", "not in", "is", "is not"],
|
|
937
|
+
]:
|
|
938
|
+
self.emit(
|
|
939
|
+
node,
|
|
940
|
+
f"{node.left.meta['py_code']} {node.op.value} {node.right.meta['py_code']}",
|
|
941
|
+
)
|
|
942
|
+
elif (
|
|
943
|
+
node.op.name in [Tok.PIPE_FWD, Tok.KW_SPAWN, Tok.A_PIPE_FWD]
|
|
944
|
+
and type(node.left) == ast.TupleVal
|
|
945
|
+
):
|
|
946
|
+
params = node.left.meta["py_code"]
|
|
947
|
+
params = params.replace(",)", ")") if params[-2:] == ",)" else params
|
|
948
|
+
self.emit(node, f"{node.right.meta['py_code']}{params}")
|
|
949
|
+
elif (
|
|
950
|
+
node.op.name in [Tok.PIPE_BKWD, Tok.A_PIPE_BKWD]
|
|
951
|
+
and type(node.right) == ast.TupleVal
|
|
952
|
+
):
|
|
953
|
+
params = node.right.meta["py_code"]
|
|
954
|
+
params = params.replace(",)", ")") if params[-2:] == ",)" else params
|
|
955
|
+
self.emit(node, f"{node.left.meta['py_code']}{params}")
|
|
956
|
+
elif node.op.name == Tok.PIPE_FWD and type(node.right) == ast.TupleVal:
|
|
957
|
+
self.ds_feature_warn()
|
|
958
|
+
elif node.op.name == Tok.PIPE_FWD:
|
|
959
|
+
self.emit(
|
|
960
|
+
node, f"{node.right.meta['py_code']}({node.left.meta['py_code']}"
|
|
961
|
+
)
|
|
962
|
+
paren_count = (
|
|
963
|
+
node.meta["pipe_chain_count"]
|
|
964
|
+
if "pipe_chain_count" in node.meta
|
|
965
|
+
else 1
|
|
966
|
+
)
|
|
967
|
+
if (
|
|
968
|
+
type(node.parent) == ast.BinaryExpr
|
|
969
|
+
and type(node.parent.op) == ast.Token
|
|
970
|
+
and node.parent.op.name == Tok.PIPE_FWD
|
|
971
|
+
):
|
|
972
|
+
node.parent.meta["pipe_chain_count"] = paren_count + 1
|
|
973
|
+
else:
|
|
974
|
+
self.emit(node, ")" * paren_count)
|
|
975
|
+
|
|
976
|
+
elif node.op.name in [Tok.KW_SPAWN, Tok.A_PIPE_FWD]:
|
|
977
|
+
self.emit(
|
|
978
|
+
node, f"{node.right.meta['py_code']}({node.left.meta['py_code']}"
|
|
979
|
+
)
|
|
980
|
+
paren_count = (
|
|
981
|
+
node.meta["a_pipe_chain_count"]
|
|
982
|
+
if "a_pipe_chain_count" in node.meta
|
|
983
|
+
else 1
|
|
984
|
+
)
|
|
985
|
+
if (
|
|
986
|
+
type(node.parent) == ast.BinaryExpr
|
|
987
|
+
and type(node.parent.op) == ast.Token
|
|
988
|
+
and node.parent.op.name
|
|
989
|
+
in [
|
|
990
|
+
Tok.KW_SPAWN,
|
|
991
|
+
Tok.A_PIPE_FWD,
|
|
992
|
+
]
|
|
993
|
+
):
|
|
994
|
+
node.parent.meta["a_pipe_chain_count"] = paren_count + 1
|
|
995
|
+
else:
|
|
996
|
+
self.emit(node, ")" * paren_count)
|
|
997
|
+
|
|
998
|
+
elif node.op.name in [Tok.PIPE_BKWD, Tok.A_PIPE_BKWD]:
|
|
999
|
+
self.emit(
|
|
1000
|
+
node, f"{node.left.meta['py_code']}({node.right.meta['py_code']})"
|
|
1001
|
+
)
|
|
1002
|
+
elif node.op.name == Tok.ELVIS_OP:
|
|
1003
|
+
self.emit(
|
|
1004
|
+
node,
|
|
1005
|
+
f"{Con.JAC_TMP} "
|
|
1006
|
+
f"if ({Con.JAC_TMP} := ({node.left.meta['py_code']})) is not None "
|
|
1007
|
+
f"else {node.right.meta['py_code']}",
|
|
1008
|
+
)
|
|
1009
|
+
else:
|
|
1010
|
+
self.error(
|
|
1011
|
+
f"Binary operator {node.op.value} not supported in bootstrap Jac"
|
|
1012
|
+
)
|
|
1013
|
+
|
|
1014
|
+
def exit_if_else_expr(self, node: ast.IfElseExpr) -> None:
|
|
1015
|
+
"""Sub objects.
|
|
1016
|
+
|
|
1017
|
+
condition: BinaryExpr | IfElseExpr,
|
|
1018
|
+
value: ExprType,
|
|
1019
|
+
else_value: ExprType,
|
|
1020
|
+
"""
|
|
1021
|
+
self.emit(
|
|
1022
|
+
node,
|
|
1023
|
+
f"{node.value.meta['py_code']} if {node.condition.meta['py_code']} "
|
|
1024
|
+
f"else {node.else_value.meta['py_code']}",
|
|
1025
|
+
)
|
|
1026
|
+
|
|
1027
|
+
def exit_unary_expr(self, node: ast.UnaryExpr) -> None:
|
|
1028
|
+
"""Sub objects.
|
|
1029
|
+
|
|
1030
|
+
operand: ExprType,
|
|
1031
|
+
op: Token,
|
|
1032
|
+
"""
|
|
1033
|
+
if node.op.value in ["-", "~", "+"]:
|
|
1034
|
+
self.emit(node, f"{node.op.value}{node.operand.meta['py_code']}")
|
|
1035
|
+
elif node.op.value == "(": # (expression) reuses unary expr
|
|
1036
|
+
self.emit(node, f"({node.operand.meta['py_code']})")
|
|
1037
|
+
elif node.op.value == "not":
|
|
1038
|
+
self.emit(node, f"not {node.operand.meta['py_code']}")
|
|
1039
|
+
elif node.op.name in [Tok.PIPE_FWD, Tok.KW_SPAWN, Tok.A_PIPE_FWD]:
|
|
1040
|
+
self.emit(node, f"{node.operand.meta['py_code']}()")
|
|
1041
|
+
else:
|
|
1042
|
+
self.error(f"Unary operator {node.op.value} not supported in bootstrap Jac")
|
|
1043
|
+
|
|
1044
|
+
def exit_unpack_expr(self, node: ast.UnpackExpr) -> None:
|
|
1045
|
+
"""Sub objects.
|
|
1046
|
+
|
|
1047
|
+
target: ExprType,
|
|
1048
|
+
is_dict: bool,
|
|
1049
|
+
"""
|
|
1050
|
+
if node.is_dict:
|
|
1051
|
+
self.emit(node, f"**{node.target.meta['py_code']}")
|
|
1052
|
+
else:
|
|
1053
|
+
self.emit(node, f"*{node.target.meta['py_code']}")
|
|
1054
|
+
|
|
1055
|
+
def exit_multi_string(self, node: ast.MultiString) -> None:
|
|
1056
|
+
"""Sub objects.
|
|
1057
|
+
|
|
1058
|
+
strings: list[Token],
|
|
1059
|
+
"""
|
|
1060
|
+
for string in node.strings:
|
|
1061
|
+
self.emit(node, string.meta["py_code"])
|
|
1062
|
+
|
|
1063
|
+
def exit_list_val(self, node: ast.ListVal) -> None:
|
|
1064
|
+
"""Sub objects.
|
|
1065
|
+
|
|
1066
|
+
values: list[ExprType],
|
|
1067
|
+
"""
|
|
1068
|
+
self.emit(
|
|
1069
|
+
node, f"[{', '.join([value.meta['py_code'] for value in node.values])}]"
|
|
1070
|
+
)
|
|
1071
|
+
|
|
1072
|
+
def exit_set_val(self, node: ast.ListVal) -> None:
|
|
1073
|
+
"""Sub objects.
|
|
1074
|
+
|
|
1075
|
+
values: list[ExprType],
|
|
1076
|
+
"""
|
|
1077
|
+
self.emit(
|
|
1078
|
+
node, f"{{{', '.join([value.meta['py_code'] for value in node.values])}}}"
|
|
1079
|
+
)
|
|
1080
|
+
|
|
1081
|
+
def exit_tuple_val(self, node: ast.TupleVal) -> None:
|
|
1082
|
+
"""Sub objects.
|
|
1083
|
+
|
|
1084
|
+
first_expr: Optional["ExprType"],
|
|
1085
|
+
exprs: Optional[ExprList],
|
|
1086
|
+
assigns: Optional[AssignmentList],
|
|
1087
|
+
"""
|
|
1088
|
+
self.emit(node, "(")
|
|
1089
|
+
if node.first_expr:
|
|
1090
|
+
self.emit(node, f"{node.first_expr.meta['py_code']}")
|
|
1091
|
+
if not node.exprs and not node.assigns:
|
|
1092
|
+
self.emit(node, ",)")
|
|
1093
|
+
if node.exprs:
|
|
1094
|
+
self.emit(node, f", {node.exprs.meta['py_code']}")
|
|
1095
|
+
|
|
1096
|
+
if node.assigns:
|
|
1097
|
+
if node.first_expr:
|
|
1098
|
+
self.emit(node, f", {node.assigns.meta['py_code']}")
|
|
1099
|
+
else:
|
|
1100
|
+
self.emit(node, f"{node.assigns.meta['py_code']}")
|
|
1101
|
+
self.emit(node, ")")
|
|
1102
|
+
|
|
1103
|
+
def exit_expr_list(self, node: ast.ExprList) -> None:
|
|
1104
|
+
"""Sub objects.
|
|
1105
|
+
|
|
1106
|
+
values: list[ExprType],
|
|
1107
|
+
"""
|
|
1108
|
+
self.emit(
|
|
1109
|
+
node, f"{', '.join([value.meta['py_code'] for value in node.values])}"
|
|
1110
|
+
)
|
|
1111
|
+
|
|
1112
|
+
def exit_dict_val(self, node: ast.DictVal) -> None:
|
|
1113
|
+
"""Sub objects.
|
|
1114
|
+
|
|
1115
|
+
kv_pairs: list["KVPair"],
|
|
1116
|
+
"""
|
|
1117
|
+
self.emit(
|
|
1118
|
+
node,
|
|
1119
|
+
f"{{{', '.join([kv_pair.meta['py_code'] for kv_pair in node.kv_pairs])}}}",
|
|
1120
|
+
)
|
|
1121
|
+
|
|
1122
|
+
def exit_inner_compr(self, node: ast.InnerCompr) -> None:
|
|
1123
|
+
"""Sub objects.
|
|
1124
|
+
|
|
1125
|
+
out_expr: "ExprType",
|
|
1126
|
+
name: Name,
|
|
1127
|
+
collection: "ExprType",
|
|
1128
|
+
conditional: Optional["ExprType"],
|
|
1129
|
+
is_list: bool,
|
|
1130
|
+
is_gen: bool,
|
|
1131
|
+
is_set: bool,
|
|
1132
|
+
"""
|
|
1133
|
+
partial = (
|
|
1134
|
+
f"{node.out_expr.meta['py_code']} for {node.name.value} "
|
|
1135
|
+
f"in {node.collection.meta['py_code']}"
|
|
1136
|
+
)
|
|
1137
|
+
if node.conditional:
|
|
1138
|
+
partial += f" if {node.conditional.meta['py_code']}"
|
|
1139
|
+
if node.is_list:
|
|
1140
|
+
self.emit(node, f"[{partial}]")
|
|
1141
|
+
elif node.is_set:
|
|
1142
|
+
self.emit(node, f"{{{partial}}}")
|
|
1143
|
+
elif node.is_gen:
|
|
1144
|
+
self.emit(node, f"({partial})")
|
|
1145
|
+
|
|
1146
|
+
def exit_dict_compr(self, node: ast.DictCompr) -> None:
|
|
1147
|
+
"""Sub objects.
|
|
1148
|
+
|
|
1149
|
+
outk_expr: "ExprType",
|
|
1150
|
+
outv_expr: "ExprType",
|
|
1151
|
+
k_name: Token,
|
|
1152
|
+
v_name: Optional[Token],
|
|
1153
|
+
collection: "ExprType",
|
|
1154
|
+
conditional: Optional["ExprType"],
|
|
1155
|
+
"""
|
|
1156
|
+
partial = (
|
|
1157
|
+
f"{node.outk_expr.meta['py_code']}: {node.outv_expr.meta['py_code']} for "
|
|
1158
|
+
f"{node.k_name.value}"
|
|
1159
|
+
)
|
|
1160
|
+
if node.v_name:
|
|
1161
|
+
partial += f", {node.v_name.value}"
|
|
1162
|
+
partial += f" in {node.collection.meta['py_code']}"
|
|
1163
|
+
if node.conditional:
|
|
1164
|
+
partial += f" if {node.conditional.meta['py_code']}"
|
|
1165
|
+
self.emit(node, f"{{{partial}}}")
|
|
1166
|
+
|
|
1167
|
+
def exit_k_v_pair(self, node: ast.KVPair) -> None:
|
|
1168
|
+
"""Sub objects.
|
|
1169
|
+
|
|
1170
|
+
key: ExprType,
|
|
1171
|
+
value: ExprType,
|
|
1172
|
+
"""
|
|
1173
|
+
self.emit(node, f"{node.key.meta['py_code']}: {node.value.meta['py_code']}")
|
|
1174
|
+
|
|
1175
|
+
def exit_atom_trailer(self, node: ast.AtomTrailer) -> None:
|
|
1176
|
+
"""Sub objects.
|
|
1177
|
+
|
|
1178
|
+
target: AtomType,
|
|
1179
|
+
right: IndexSlice | ArchRefType | Token,
|
|
1180
|
+
null_ok: bool,
|
|
1181
|
+
"""
|
|
1182
|
+
if node.null_ok:
|
|
1183
|
+
if type(node.right) == ast.IndexSlice:
|
|
1184
|
+
self.emit(
|
|
1185
|
+
node,
|
|
1186
|
+
f"({node.target.meta['py_code']}{node.right.meta['py_code']} "
|
|
1187
|
+
f"if {node.target.meta['py_code']} is not None else None)",
|
|
1188
|
+
)
|
|
1189
|
+
else:
|
|
1190
|
+
self.emit(
|
|
1191
|
+
node,
|
|
1192
|
+
f"({node.target.meta['py_code']}.{node.right.meta['py_code']} "
|
|
1193
|
+
f"if {node.target.meta['py_code']} is not None else None)",
|
|
1194
|
+
)
|
|
1195
|
+
else:
|
|
1196
|
+
if type(node.right) == ast.IndexSlice:
|
|
1197
|
+
self.emit(
|
|
1198
|
+
node,
|
|
1199
|
+
f"{node.target.meta['py_code']}{node.right.meta['py_code']}",
|
|
1200
|
+
)
|
|
1201
|
+
else:
|
|
1202
|
+
self.emit(
|
|
1203
|
+
node,
|
|
1204
|
+
f"{node.target.meta['py_code']}.{node.right.meta['py_code']}",
|
|
1205
|
+
)
|
|
1206
|
+
|
|
1207
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
1208
|
+
def exit_func_call(self, node: ast.FuncCall) -> None:
|
|
1209
|
+
"""Sub objects.
|
|
1210
|
+
|
|
1211
|
+
target: AtomType,
|
|
1212
|
+
params: Optional[ParamList],
|
|
1213
|
+
"""
|
|
1214
|
+
if node.params:
|
|
1215
|
+
self.emit(
|
|
1216
|
+
node,
|
|
1217
|
+
f"{node.target.meta['py_code']}({node.params.meta['py_code']})",
|
|
1218
|
+
)
|
|
1219
|
+
else:
|
|
1220
|
+
self.emit(node, f"{node.target.meta['py_code']}()")
|
|
1221
|
+
|
|
1222
|
+
def exit_param_list(self, node: ast.ParamList) -> None:
|
|
1223
|
+
"""Sub objects.
|
|
1224
|
+
|
|
1225
|
+
p_args: Optional[ExprList],
|
|
1226
|
+
p_kwargs: Optional[AssignmentList],
|
|
1227
|
+
"""
|
|
1228
|
+
if node.p_args and node.p_kwargs:
|
|
1229
|
+
self.emit(
|
|
1230
|
+
node,
|
|
1231
|
+
f"{node.p_args.meta['py_code']}, {node.p_kwargs.meta['py_code']}",
|
|
1232
|
+
)
|
|
1233
|
+
elif node.p_args:
|
|
1234
|
+
self.emit(node, f"{node.p_args.meta['py_code']}")
|
|
1235
|
+
elif node.p_kwargs:
|
|
1236
|
+
self.emit(node, f"{node.p_kwargs.meta['py_code']}")
|
|
1237
|
+
|
|
1238
|
+
def exit_assignment_list(self, node: ast.AssignmentList) -> None:
|
|
1239
|
+
"""Sub objects.
|
|
1240
|
+
|
|
1241
|
+
values: list[Assignment],
|
|
1242
|
+
"""
|
|
1243
|
+
self.emit(
|
|
1244
|
+
node, f"{', '.join([value.meta['py_code'] for value in node.values])}"
|
|
1245
|
+
)
|
|
1246
|
+
|
|
1247
|
+
def exit_index_slice(self, node: ast.IndexSlice) -> None:
|
|
1248
|
+
"""Sub objects.
|
|
1249
|
+
|
|
1250
|
+
start: ExprType,
|
|
1251
|
+
stop: Optional[ExprType],
|
|
1252
|
+
"""
|
|
1253
|
+
if node.is_range:
|
|
1254
|
+
self.emit(
|
|
1255
|
+
node,
|
|
1256
|
+
f"[{node.start.meta['py_code'] if node.start else ''}:"
|
|
1257
|
+
f"{node.stop.meta['py_code'] if node.stop else ''}]",
|
|
1258
|
+
)
|
|
1259
|
+
elif node.start:
|
|
1260
|
+
self.emit(node, f"[{node.start.meta['py_code']}]")
|
|
1261
|
+
else:
|
|
1262
|
+
self.ice("Something went horribly wrong.")
|
|
1263
|
+
|
|
1264
|
+
def exit_special_var_ref(self, node: ast.SpecialVarRef) -> None:
|
|
1265
|
+
"""Sub objects.
|
|
1266
|
+
|
|
1267
|
+
var: Token,
|
|
1268
|
+
"""
|
|
1269
|
+
if node.var.name == Tok.SELF_OP:
|
|
1270
|
+
self.emit(node, "self")
|
|
1271
|
+
elif node.var.name == Tok.SUPER_OP:
|
|
1272
|
+
self.emit(node, "super()")
|
|
1273
|
+
elif node.var.name == Tok.ROOT_OP:
|
|
1274
|
+
self.emit(node, Con.ROOT)
|
|
1275
|
+
elif node.var.name == Tok.HERE_OP:
|
|
1276
|
+
self.emit(node, Con.HERE)
|
|
1277
|
+
else:
|
|
1278
|
+
self.ice("Special variable not handled.")
|
|
1279
|
+
|
|
1280
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
1281
|
+
def exit_arch_ref(self, node: ast.ArchRef) -> None:
|
|
1282
|
+
"""Sub objects.
|
|
1283
|
+
|
|
1284
|
+
name: Name,
|
|
1285
|
+
arch: Token,
|
|
1286
|
+
"""
|
|
1287
|
+
self.emit(node, f"{node.name.value}")
|
|
1288
|
+
|
|
1289
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
1290
|
+
def exit_edge_op_ref(self, node: ast.EdgeOpRef) -> None:
|
|
1291
|
+
"""Sub objects.
|
|
1292
|
+
|
|
1293
|
+
filter_cond: Optional[ExprType],
|
|
1294
|
+
edge_dir: EdgeDir,
|
|
1295
|
+
"""
|
|
1296
|
+
self.ds_feature_warn()
|
|
1297
|
+
|
|
1298
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
1299
|
+
def exit_disconnect_op(self, node: ast.DisconnectOp) -> None:
|
|
1300
|
+
"""Sub objects.
|
|
1301
|
+
|
|
1302
|
+
filter_cond: Optional[ExprType],
|
|
1303
|
+
edge_dir: EdgeDir,
|
|
1304
|
+
"""
|
|
1305
|
+
self.ds_feature_warn()
|
|
1306
|
+
|
|
1307
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
1308
|
+
def exit_connect_op(self, node: ast.ConnectOp) -> None:
|
|
1309
|
+
"""Sub objects.
|
|
1310
|
+
|
|
1311
|
+
spawn: Optional[ExprType],
|
|
1312
|
+
edge_dir: EdgeDir,
|
|
1313
|
+
"""
|
|
1314
|
+
self.ds_feature_warn()
|
|
1315
|
+
|
|
1316
|
+
# NOTE: Incomplete for Jac Purple and Red
|
|
1317
|
+
def exit_filter_compr(self, node: ast.FilterCompr) -> None:
|
|
1318
|
+
"""Sub objects.
|
|
1319
|
+
|
|
1320
|
+
compares: list[BinaryExpr],
|
|
1321
|
+
"""
|
|
1322
|
+
self.ds_feature_warn()
|
|
1323
|
+
|
|
1324
|
+
def exit_f_string(self, node: ast.FString) -> None:
|
|
1325
|
+
"""Sub objects.
|
|
1326
|
+
|
|
1327
|
+
parts: list["Token | ExprType"],
|
|
1328
|
+
"""
|
|
1329
|
+
self.emit(node, 'f"')
|
|
1330
|
+
for part in node.parts:
|
|
1331
|
+
if type(part) == ast.Token and part.name == "PIECE":
|
|
1332
|
+
self.emit(node, f"{part.meta['py_code']}")
|
|
1333
|
+
else:
|
|
1334
|
+
self.emit(node, "{" + part.meta["py_code"] + "}")
|
|
1335
|
+
self.emit(node, '"')
|