vex-ast 0.2.4__py3-none-any.whl → 0.2.6__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.
- vex_ast/README.md +101 -51
- vex_ast/READMEAPI.md +133 -318
- vex_ast/__init__.py +81 -72
- vex_ast/ast/README.md +87 -87
- vex_ast/ast/__init__.py +74 -74
- vex_ast/ast/core.py +71 -71
- vex_ast/ast/expressions.py +276 -276
- vex_ast/ast/interfaces.py +208 -208
- vex_ast/ast/literals.py +80 -80
- vex_ast/ast/navigator.py +225 -225
- vex_ast/ast/operators.py +135 -135
- vex_ast/ast/statements.py +351 -351
- vex_ast/ast/validators.py +121 -120
- vex_ast/ast/vex_nodes.py +279 -279
- vex_ast/parser/README.md +47 -47
- vex_ast/parser/__init__.py +26 -26
- vex_ast/parser/factory.py +190 -190
- vex_ast/parser/interfaces.py +34 -34
- vex_ast/parser/python_parser.py +831 -786
- vex_ast/registry/README.md +107 -29
- vex_ast/registry/__init__.py +51 -51
- vex_ast/registry/api.py +190 -155
- vex_ast/registry/categories.py +179 -136
- vex_ast/registry/functions/__init__.py +10 -10
- vex_ast/registry/functions/constructors.py +71 -0
- vex_ast/registry/functions/display.py +146 -146
- vex_ast/registry/functions/drivetrain.py +163 -163
- vex_ast/registry/functions/initialize.py +31 -28
- vex_ast/registry/functions/motor.py +140 -140
- vex_ast/registry/functions/sensors.py +194 -194
- vex_ast/registry/functions/timing.py +103 -103
- vex_ast/registry/language_map.py +77 -77
- vex_ast/registry/registry.py +164 -153
- vex_ast/registry/signature.py +269 -191
- vex_ast/registry/simulation_behavior.py +8 -8
- vex_ast/registry/validation.py +43 -43
- vex_ast/serialization/__init__.py +37 -37
- vex_ast/serialization/json_deserializer.py +284 -275
- vex_ast/serialization/json_serializer.py +148 -148
- vex_ast/serialization/schema.py +492 -470
- vex_ast/types/README.md +78 -26
- vex_ast/types/__init__.py +140 -140
- vex_ast/types/base.py +83 -83
- vex_ast/types/enums.py +122 -97
- vex_ast/types/objects.py +64 -64
- vex_ast/types/primitives.py +68 -68
- vex_ast/types/type_checker.py +31 -31
- vex_ast/utils/README.md +39 -39
- vex_ast/utils/__init__.py +37 -37
- vex_ast/utils/errors.py +112 -112
- vex_ast/utils/source_location.py +38 -38
- vex_ast/utils/type_definitions.py +8 -8
- vex_ast/visitors/README.md +49 -49
- vex_ast/visitors/__init__.py +27 -27
- vex_ast/visitors/analyzer.py +102 -102
- vex_ast/visitors/base.py +133 -133
- vex_ast/visitors/printer.py +196 -146
- {vex_ast-0.2.4.dist-info → vex_ast-0.2.6.dist-info}/METADATA +206 -174
- vex_ast-0.2.6.dist-info/RECORD +64 -0
- vex_ast-0.2.4.dist-info/RECORD +0 -63
- {vex_ast-0.2.4.dist-info → vex_ast-0.2.6.dist-info}/WHEEL +0 -0
- {vex_ast-0.2.4.dist-info → vex_ast-0.2.6.dist-info}/licenses/LICENSE +0 -0
- {vex_ast-0.2.4.dist-info → vex_ast-0.2.6.dist-info}/top_level.txt +0 -0
vex_ast/visitors/printer.py
CHANGED
@@ -1,146 +1,196 @@
|
|
1
|
-
"""AST printing visitor implementation."""
|
2
|
-
|
3
|
-
import io
|
4
|
-
from typing import Any, List, Optional
|
5
|
-
|
6
|
-
from .base import AstVisitor
|
7
|
-
from ..ast.interfaces import IAstNode
|
8
|
-
|
9
|
-
class PrintVisitor(AstVisitor[str]):
|
10
|
-
"""Visitor that generates a readable string representation of the AST."""
|
11
|
-
|
12
|
-
def __init__(self):
|
13
|
-
self._output = io.StringIO()
|
14
|
-
self._indent_level = 0
|
15
|
-
|
16
|
-
def _indent(self) -> None:
|
17
|
-
"""Write the current indentation."""
|
18
|
-
self._output.write(' ' * self._indent_level)
|
19
|
-
|
20
|
-
def _write_node_header(self, node: IAstNode, name: str) -> None:
|
21
|
-
"""Write a standard node header with location info."""
|
22
|
-
self._indent()
|
23
|
-
self._output.write(f"{name}")
|
24
|
-
if node.location:
|
25
|
-
self._output.write(f" (at {node.location})")
|
26
|
-
self._output.write(":\n")
|
27
|
-
|
28
|
-
def _format_value(self, value: Any) -> str:
|
29
|
-
"""Format a basic value for display."""
|
30
|
-
return repr(value)
|
31
|
-
|
32
|
-
def generic_visit(self, node: IAstNode) -> str:
|
33
|
-
"""Default node visitor that displays type and attributes."""
|
34
|
-
node_name = node.__class__.__name__
|
35
|
-
self._write_node_header(node, node_name)
|
36
|
-
|
37
|
-
# Visit fields if present
|
38
|
-
if hasattr(node, '_fields'):
|
39
|
-
self._indent_level += 1
|
40
|
-
for field_name in node._fields:
|
41
|
-
value = getattr(node, field_name, None)
|
42
|
-
|
43
|
-
# Skip None values
|
44
|
-
if value is None:
|
45
|
-
continue
|
46
|
-
|
47
|
-
self._indent()
|
48
|
-
self._output.write(f"{field_name} = ")
|
49
|
-
|
50
|
-
if isinstance(value, IAstNode):
|
51
|
-
self._output.write("\n")
|
52
|
-
self.visit(value)
|
53
|
-
elif isinstance(value, list):
|
54
|
-
if not value:
|
55
|
-
self._output.write("[]\n")
|
56
|
-
else:
|
57
|
-
self._output.write("[\n")
|
58
|
-
self._indent_level += 1
|
59
|
-
for i, item in enumerate(value):
|
60
|
-
self._indent()
|
61
|
-
self._output.write(f"[{i}]: ")
|
62
|
-
if isinstance(item, IAstNode):
|
63
|
-
self._output.write("\n")
|
64
|
-
self.visit(item)
|
65
|
-
else:
|
66
|
-
self._output.write(f"{self._format_value(item)}\n")
|
67
|
-
self._indent_level -= 1
|
68
|
-
self._indent()
|
69
|
-
self._output.write("]\n")
|
70
|
-
else:
|
71
|
-
self._output.write(f"{self._format_value(value)}\n")
|
72
|
-
self._indent_level -= 1
|
73
|
-
|
74
|
-
# At the root level, return the accumulated output
|
75
|
-
if self._indent_level == 0:
|
76
|
-
return self._output.getvalue()
|
77
|
-
return ""
|
78
|
-
|
79
|
-
# Simple node visitors for concise output
|
80
|
-
def visit_identifier(self, node: Any) -> str:
|
81
|
-
self._output.write(f"Identifier(name={node.name!r})")
|
82
|
-
if node.location:
|
83
|
-
self._output.write(f" (at {node.location})")
|
84
|
-
return ""
|
85
|
-
|
86
|
-
def visit_numberliteral(self, node: Any) -> str:
|
87
|
-
self._output.write(f"NumberLiteral(value={node.value!r})")
|
88
|
-
if node.location:
|
89
|
-
self._output.write(f" (at {node.location})")
|
90
|
-
return ""
|
91
|
-
|
92
|
-
def visit_stringliteral(self, node: Any) -> str:
|
93
|
-
self._output.write(f"StringLiteral(value={node.value!r})")
|
94
|
-
if node.location:
|
95
|
-
self._output.write(f" (at {node.location})")
|
96
|
-
return ""
|
97
|
-
|
98
|
-
def visit_booleanliteral(self, node: Any) -> str:
|
99
|
-
self._output.write(f"BooleanLiteral(value={node.value!r})")
|
100
|
-
if node.location:
|
101
|
-
self._output.write(f" (at {node.location})")
|
102
|
-
return ""
|
103
|
-
|
104
|
-
def visit_noneliteral(self, node: Any) -> str:
|
105
|
-
self._output.write(f"NoneLiteral()")
|
106
|
-
if node.location:
|
107
|
-
self._output.write(f" (at {node.location})")
|
108
|
-
return ""
|
109
|
-
|
110
|
-
# Program node is the entry point
|
111
|
-
def visit_program(self, node: Any) -> str:
|
112
|
-
self._output.write("Program:\n")
|
113
|
-
self._indent_level += 1
|
114
|
-
for i, stmt in enumerate(node.body):
|
115
|
-
self._indent()
|
116
|
-
self._output.write(f"[{i}]: \n")
|
117
|
-
self._indent_level += 1
|
118
|
-
self.visit(stmt)
|
119
|
-
self._indent_level -= 1
|
120
|
-
self._indent_level -= 1
|
121
|
-
return self._output.getvalue()
|
122
|
-
|
123
|
-
# Delegate all other methods to generic_visit
|
124
|
-
visit_expression = generic_visit
|
125
|
-
visit_statement = generic_visit
|
126
|
-
visit_variablereference = generic_visit
|
127
|
-
visit_binaryoperation = generic_visit
|
128
|
-
visit_unaryoperation = generic_visit
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
1
|
+
"""AST printing visitor implementation."""
|
2
|
+
|
3
|
+
import io
|
4
|
+
from typing import Any, List, Optional
|
5
|
+
|
6
|
+
from .base import AstVisitor
|
7
|
+
from ..ast.interfaces import IAstNode
|
8
|
+
|
9
|
+
class PrintVisitor(AstVisitor[str]):
|
10
|
+
"""Visitor that generates a readable string representation of the AST."""
|
11
|
+
|
12
|
+
def __init__(self):
|
13
|
+
self._output = io.StringIO()
|
14
|
+
self._indent_level = 0
|
15
|
+
|
16
|
+
def _indent(self) -> None:
|
17
|
+
"""Write the current indentation."""
|
18
|
+
self._output.write(' ' * self._indent_level)
|
19
|
+
|
20
|
+
def _write_node_header(self, node: IAstNode, name: str) -> None:
|
21
|
+
"""Write a standard node header with location info."""
|
22
|
+
self._indent()
|
23
|
+
self._output.write(f"{name}")
|
24
|
+
if node.location:
|
25
|
+
self._output.write(f" (at {node.location})")
|
26
|
+
self._output.write(":\n")
|
27
|
+
|
28
|
+
def _format_value(self, value: Any) -> str:
|
29
|
+
"""Format a basic value for display."""
|
30
|
+
return repr(value)
|
31
|
+
|
32
|
+
def generic_visit(self, node: IAstNode) -> str:
|
33
|
+
"""Default node visitor that displays type and attributes."""
|
34
|
+
node_name = node.__class__.__name__
|
35
|
+
self._write_node_header(node, node_name)
|
36
|
+
|
37
|
+
# Visit fields if present
|
38
|
+
if hasattr(node, '_fields'):
|
39
|
+
self._indent_level += 1
|
40
|
+
for field_name in node._fields:
|
41
|
+
value = getattr(node, field_name, None)
|
42
|
+
|
43
|
+
# Skip None values
|
44
|
+
if value is None:
|
45
|
+
continue
|
46
|
+
|
47
|
+
self._indent()
|
48
|
+
self._output.write(f"{field_name} = ")
|
49
|
+
|
50
|
+
if isinstance(value, IAstNode):
|
51
|
+
self._output.write("\n")
|
52
|
+
self.visit(value)
|
53
|
+
elif isinstance(value, list):
|
54
|
+
if not value:
|
55
|
+
self._output.write("[]\n")
|
56
|
+
else:
|
57
|
+
self._output.write("[\n")
|
58
|
+
self._indent_level += 1
|
59
|
+
for i, item in enumerate(value):
|
60
|
+
self._indent()
|
61
|
+
self._output.write(f"[{i}]: ")
|
62
|
+
if isinstance(item, IAstNode):
|
63
|
+
self._output.write("\n")
|
64
|
+
self.visit(item)
|
65
|
+
else:
|
66
|
+
self._output.write(f"{self._format_value(item)}\n")
|
67
|
+
self._indent_level -= 1
|
68
|
+
self._indent()
|
69
|
+
self._output.write("]\n")
|
70
|
+
else:
|
71
|
+
self._output.write(f"{self._format_value(value)}\n")
|
72
|
+
self._indent_level -= 1
|
73
|
+
|
74
|
+
# At the root level, return the accumulated output
|
75
|
+
if self._indent_level == 0:
|
76
|
+
return self._output.getvalue()
|
77
|
+
return ""
|
78
|
+
|
79
|
+
# Simple node visitors for concise output
|
80
|
+
def visit_identifier(self, node: Any) -> str:
|
81
|
+
self._output.write(f"Identifier(name={node.name!r})")
|
82
|
+
if node.location:
|
83
|
+
self._output.write(f" (at {node.location})")
|
84
|
+
return ""
|
85
|
+
|
86
|
+
def visit_numberliteral(self, node: Any) -> str:
|
87
|
+
self._output.write(f"NumberLiteral(value={node.value!r})")
|
88
|
+
if node.location:
|
89
|
+
self._output.write(f" (at {node.location})")
|
90
|
+
return ""
|
91
|
+
|
92
|
+
def visit_stringliteral(self, node: Any) -> str:
|
93
|
+
self._output.write(f"StringLiteral(value={node.value!r})")
|
94
|
+
if node.location:
|
95
|
+
self._output.write(f" (at {node.location})")
|
96
|
+
return ""
|
97
|
+
|
98
|
+
def visit_booleanliteral(self, node: Any) -> str:
|
99
|
+
self._output.write(f"BooleanLiteral(value={node.value!r})")
|
100
|
+
if node.location:
|
101
|
+
self._output.write(f" (at {node.location})")
|
102
|
+
return ""
|
103
|
+
|
104
|
+
def visit_noneliteral(self, node: Any) -> str:
|
105
|
+
self._output.write(f"NoneLiteral()")
|
106
|
+
if node.location:
|
107
|
+
self._output.write(f" (at {node.location})")
|
108
|
+
return ""
|
109
|
+
|
110
|
+
# Program node is the entry point
|
111
|
+
def visit_program(self, node: Any) -> str:
|
112
|
+
self._output.write("Program:\n")
|
113
|
+
self._indent_level += 1
|
114
|
+
for i, stmt in enumerate(node.body):
|
115
|
+
self._indent()
|
116
|
+
self._output.write(f"[{i}]: \n")
|
117
|
+
self._indent_level += 1
|
118
|
+
self.visit(stmt)
|
119
|
+
self._indent_level -= 1
|
120
|
+
self._indent_level -= 1
|
121
|
+
return self._output.getvalue()
|
122
|
+
|
123
|
+
# Delegate all other methods to generic_visit
|
124
|
+
visit_expression = generic_visit
|
125
|
+
visit_statement = generic_visit
|
126
|
+
visit_variablereference = generic_visit
|
127
|
+
visit_binaryoperation = generic_visit
|
128
|
+
visit_unaryoperation = generic_visit
|
129
|
+
|
130
|
+
def visit_conditionalexpression(self, node: Any) -> str:
|
131
|
+
"""Custom visitor for conditional expressions to make them more readable."""
|
132
|
+
self._output.write("ConditionalExpression:\n")
|
133
|
+
self._indent_level += 1
|
134
|
+
|
135
|
+
# Print condition
|
136
|
+
self._indent()
|
137
|
+
self._output.write("condition = ")
|
138
|
+
self.visit(node.condition)
|
139
|
+
self._output.write("\n")
|
140
|
+
|
141
|
+
# Print true expression
|
142
|
+
self._indent()
|
143
|
+
self._output.write("true_expr = ")
|
144
|
+
self.visit(node.true_expr)
|
145
|
+
self._output.write("\n")
|
146
|
+
|
147
|
+
# Print false expression
|
148
|
+
self._indent()
|
149
|
+
self._output.write("false_expr = ")
|
150
|
+
self.visit(node.false_expr)
|
151
|
+
self._output.write("\n")
|
152
|
+
|
153
|
+
# Add the formatted Python conditional expression with if/else keywords
|
154
|
+
self._indent()
|
155
|
+
self._output.write("formatted = ")
|
156
|
+
|
157
|
+
# Capture the string representation of each part
|
158
|
+
true_str = io.StringIO()
|
159
|
+
old_output = self._output
|
160
|
+
self._output = true_str
|
161
|
+
self.visit(node.true_expr)
|
162
|
+
|
163
|
+
cond_str = io.StringIO()
|
164
|
+
self._output = cond_str
|
165
|
+
self.visit(node.condition)
|
166
|
+
|
167
|
+
false_str = io.StringIO()
|
168
|
+
self._output = false_str
|
169
|
+
self.visit(node.false_expr)
|
170
|
+
|
171
|
+
# Restore the original output
|
172
|
+
self._output = old_output
|
173
|
+
|
174
|
+
# Write the formatted conditional expression with if/else keywords
|
175
|
+
self._output.write(f"{true_str.getvalue()} if {cond_str.getvalue()} else {false_str.getvalue()}\n")
|
176
|
+
|
177
|
+
self._indent_level -= 1
|
178
|
+
return ""
|
179
|
+
|
180
|
+
visit_functioncall = generic_visit
|
181
|
+
visit_keywordargument = generic_visit
|
182
|
+
visit_expressionstatement = generic_visit
|
183
|
+
visit_assignment = generic_visit
|
184
|
+
visit_ifstatement = generic_visit
|
185
|
+
visit_whileloop = generic_visit
|
186
|
+
visit_forloop = generic_visit
|
187
|
+
visit_functiondefinition = generic_visit
|
188
|
+
visit_argument = generic_visit
|
189
|
+
visit_returnstatement = generic_visit
|
190
|
+
visit_breakstatement = generic_visit
|
191
|
+
visit_continuestatement = generic_visit
|
192
|
+
visit_vexapicall = generic_visit
|
193
|
+
visit_motorcontrol = generic_visit
|
194
|
+
visit_sensorreading = generic_visit
|
195
|
+
visit_timingcontrol = generic_visit
|
196
|
+
visit_displayoutput = generic_visit
|