vex-ast 0.2.2__py3-none-any.whl → 0.2.4__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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  from typing import Dict, List, Optional, Union, cast, Any
4
4
 
5
- from .interfaces import IAstNode, IExpression, IVisitor, T_VisitorResult, IIdentifier, IFunctionCall
5
+ from .interfaces import IAstNode, IExpression, IVisitor, T_VisitorResult, IIdentifier, IFunctionCall, IConditionalExpression
6
6
  from .core import Expression
7
7
  from .operators import Operator
8
8
  from ..utils.source_location import SourceLocation
@@ -173,6 +173,49 @@ class KeywordArgument(Expression):
173
173
  """Get the keyword value."""
174
174
  return self.value
175
175
 
176
+ class ConditionalExpression(Expression, IConditionalExpression):
177
+ """A conditional expression (ternary operator, e.g., a if condition else b)."""
178
+
179
+ _fields = ('condition', 'true_expr', 'false_expr')
180
+
181
+ def __init__(self, condition: IExpression, true_expr: IExpression, false_expr: IExpression,
182
+ location: Optional[SourceLocation] = None):
183
+ super().__init__(location)
184
+ self.condition = condition
185
+ self.true_expr = true_expr
186
+ self.false_expr = false_expr
187
+
188
+ # Set parent references
189
+ if isinstance(condition, Expression):
190
+ condition.set_parent(self)
191
+ if isinstance(true_expr, Expression):
192
+ true_expr.set_parent(self)
193
+ if isinstance(false_expr, Expression):
194
+ false_expr.set_parent(self)
195
+
196
+ def get_children(self) -> List[IAstNode]:
197
+ """Get child nodes."""
198
+ return [
199
+ cast(IAstNode, self.condition),
200
+ cast(IAstNode, self.true_expr),
201
+ cast(IAstNode, self.false_expr)
202
+ ]
203
+
204
+ def accept(self, visitor: IVisitor[T_VisitorResult]) -> T_VisitorResult:
205
+ return visitor.visit_conditionalexpression(self)
206
+
207
+ def get_condition(self) -> IExpression:
208
+ """Get the condition expression."""
209
+ return self.condition
210
+
211
+ def get_true_expression(self) -> IExpression:
212
+ """Get the expression to evaluate if condition is true."""
213
+ return self.true_expr
214
+
215
+ def get_false_expression(self) -> IExpression:
216
+ """Get the expression to evaluate if condition is false."""
217
+ return self.false_expr
218
+
176
219
  class FunctionCall(Expression, IFunctionCall):
177
220
  """A function call."""
178
221
 
vex_ast/ast/interfaces.py CHANGED
@@ -84,6 +84,22 @@ class IIdentifier(IExpression, Protocol):
84
84
  """Get the identifier name."""
85
85
  ...
86
86
 
87
+ @runtime_checkable
88
+ class IConditionalExpression(IExpression, Protocol):
89
+ """Protocol for conditional expression (ternary operator) nodes."""
90
+
91
+ def get_condition(self) -> IExpression:
92
+ """Get the condition expression."""
93
+ ...
94
+
95
+ def get_true_expression(self) -> IExpression:
96
+ """Get the expression to evaluate if condition is true."""
97
+ ...
98
+
99
+ def get_false_expression(self) -> IExpression:
100
+ """Get the expression to evaluate if condition is false."""
101
+ ...
102
+
87
103
  @runtime_checkable
88
104
  class IFunctionCall(IExpression, Protocol):
89
105
  """Protocol for function call nodes."""
vex_ast/ast/vex_nodes.py CHANGED
@@ -91,8 +91,21 @@ class VexAPICall(FunctionCall):
91
91
  return False, self._validation_error
92
92
 
93
93
  # Convert args and kwargs to appropriate format
94
- arg_values = [arg for arg in self.args]
95
- kwarg_values = {kw.name: kw.value for kw in self.keywords or []}
94
+ arg_values = []
95
+ for arg in self.args:
96
+ # For string literals, use their actual string value for validation
97
+ if hasattr(arg, 'value') and hasattr(arg, '__class__') and arg.__class__.__name__ == 'StringLiteral':
98
+ arg_values.append(arg.value)
99
+ else:
100
+ arg_values.append(arg)
101
+
102
+ kwarg_values = {}
103
+ for kw in (self.keywords or []):
104
+ # For string literals, use their actual string value for validation
105
+ if hasattr(kw.value, 'value') and hasattr(kw.value, '__class__') and kw.value.__class__.__name__ == 'StringLiteral':
106
+ kwarg_values[kw.name] = kw.value.value
107
+ else:
108
+ kwarg_values[kw.name] = kw.value
96
109
 
97
110
  # Validate against the signature
98
111
  valid, error = signature.validate_arguments(arg_values, kwarg_values)
vex_ast/parser/factory.py CHANGED
@@ -4,7 +4,7 @@ from typing import Any, Dict, Optional, Type, Union, cast, List
4
4
 
5
5
  from ..ast.core import Expression, Program, Statement
6
6
  from ..ast.expressions import (
7
- AttributeAccess, BinaryOperation, FunctionCall, Identifier, KeywordArgument,
7
+ AttributeAccess, BinaryOperation, ConditionalExpression, FunctionCall, Identifier, KeywordArgument,
8
8
  UnaryOperation, VariableReference
9
9
  )
10
10
  from ..ast.literals import (
@@ -77,6 +77,11 @@ class NodeFactory:
77
77
  """Create a unary operation node."""
78
78
  return UnaryOperation(op, operand, location)
79
79
 
80
+ def create_conditional_expression(self, condition: Expression, true_expr: Expression, false_expr: Expression,
81
+ location: Optional[SourceLocation] = None) -> ConditionalExpression:
82
+ """Create a conditional expression (ternary operator) node."""
83
+ return ConditionalExpression(condition, true_expr, false_expr, location)
84
+
80
85
  def create_function_call(self, function: Expression, args: List[Expression] = None,
81
86
  keywords: List[KeywordArgument] = None,
82
87
  location: Optional[SourceLocation] = None) -> FunctionCall:
@@ -123,6 +128,12 @@ class NodeFactory:
123
128
  """Create a function definition node."""
124
129
  return FunctionDefinition(name, args, body, return_annotation, location)
125
130
 
131
+ def create_argument(self, name: str, annotation: Optional[Expression] = None,
132
+ default: Optional[Expression] = None,
133
+ location: Optional[SourceLocation] = None) -> Argument:
134
+ """Create an argument node."""
135
+ return Argument(name, annotation, default, location)
136
+
126
137
  def create_return_statement(self, value: Optional[Expression] = None,
127
138
  location: Optional[SourceLocation] = None) -> ReturnStatement:
128
139
  """Create a return statement node."""
@@ -176,4 +187,4 @@ class NodeFactory:
176
187
  return Program(body, location)
177
188
 
178
189
  # Global factory instance for simple use cases
179
- default_factory = NodeFactory()
190
+ default_factory = NodeFactory()
@@ -294,21 +294,12 @@ class PythonParser(BaseParser):
294
294
  op_name = op_type.__name__
295
295
 
296
296
  op_map = {
297
- 'And': 'and',
298
- 'Or': 'or'
297
+ 'And': Operator.LOGICAL_AND,
298
+ 'Or': Operator.LOGICAL_OR
299
299
  }
300
300
 
301
301
  if op_name in op_map:
302
- op_str = op_map[op_name]
303
- vex_op = PYTHON_COMP_OP_MAP.get(op_str)
304
-
305
- if not vex_op:
306
- self.error_handler.add_error(
307
- ErrorType.PARSER_ERROR,
308
- f"Unsupported boolean operator: {op_name}",
309
- loc
310
- )
311
- vex_op = Operator.LOGICAL_AND # Fallback
302
+ vex_op = op_map[op_name]
312
303
  else:
313
304
  self.error_handler.add_error(
314
305
  ErrorType.PARSER_ERROR,
@@ -329,6 +320,15 @@ class PythonParser(BaseParser):
329
320
 
330
321
  return result
331
322
 
323
+ # Conditional expressions (ternary operators)
324
+ elif isinstance(node, ast.IfExp):
325
+ loc = self._get_location(node)
326
+ test = self._convert_expression(node.test)
327
+ body = self._convert_expression(node.body)
328
+ orelse = self._convert_expression(node.orelse)
329
+
330
+ return self.factory.create_conditional_expression(test, body, orelse, loc)
331
+
332
332
  # List literals
333
333
  elif isinstance(node, ast.List) or isinstance(node, ast.Tuple):
334
334
  # We don't have a dedicated list/tuple node, so use function call
@@ -607,22 +607,77 @@ class PythonParser(BaseParser):
607
607
  self._get_location(node)
608
608
  )
609
609
 
610
- # Import statements - not fully supported yet
611
- elif isinstance(node, (ast.Import, ast.ImportFrom)):
610
+ # Import statements
611
+ elif isinstance(node, ast.Import):
612
612
  loc = self._get_location(node)
613
- self.error_handler.add_error(
614
- ErrorType.PARSER_ERROR,
615
- "Import statements are not fully supported",
616
- loc
617
- )
618
- # Create a placeholder expression statement
619
- return self.factory.create_expression_statement(
620
- self.factory.create_identifier(
621
- f"<import:{getattr(node, 'names', [])}>",
613
+ # Create a list of assignments for each imported name
614
+ statements = []
615
+
616
+ for name in node.names:
617
+ # Create an identifier for the module
618
+ module_name = name.name
619
+ as_name = name.asname or module_name
620
+
621
+ # Create an assignment: as_name = module_name
622
+ target = self.factory.create_identifier(as_name, loc)
623
+ value = self.factory.create_identifier(f"<import:{module_name}>", loc)
624
+
625
+ statements.append(self.factory.create_assignment(target, value, loc))
626
+
627
+ # If there's only one statement, return it
628
+ if len(statements) == 1:
629
+ return statements[0]
630
+
631
+ # Otherwise, return the first one and add a warning
632
+ if len(statements) > 1:
633
+ self.error_handler.add_error(
634
+ ErrorType.PARSER_ERROR,
635
+ "Multiple imports in a single statement are not fully supported",
622
636
  loc
623
- ),
624
- loc
625
- )
637
+ )
638
+
639
+ return statements[0]
640
+
641
+ # Import from statements
642
+ elif isinstance(node, ast.ImportFrom):
643
+ loc = self._get_location(node)
644
+ module_name = node.module or ""
645
+
646
+ # Special case for "from vex import *"
647
+ if module_name == "vex" and any(name.name == "*" for name in node.names):
648
+ # Create a special identifier that represents "from vex import *"
649
+ return self.factory.create_expression_statement(
650
+ self.factory.create_identifier("<import:vex:*>", loc),
651
+ loc
652
+ )
653
+
654
+ # For other import from statements, create assignments
655
+ statements = []
656
+
657
+ for name in node.names:
658
+ # Create an identifier for the imported name
659
+ imported_name = name.name
660
+ as_name = name.asname or imported_name
661
+
662
+ # Create an assignment: as_name = module_name.imported_name
663
+ target = self.factory.create_identifier(as_name, loc)
664
+ value = self.factory.create_identifier(f"<import:{module_name}.{imported_name}>", loc)
665
+
666
+ statements.append(self.factory.create_assignment(target, value, loc))
667
+
668
+ # If there's only one statement, return it
669
+ if len(statements) == 1:
670
+ return statements[0]
671
+
672
+ # Otherwise, return the first one and add a warning
673
+ if len(statements) > 1:
674
+ self.error_handler.add_error(
675
+ ErrorType.PARSER_ERROR,
676
+ "Multiple imports in a single statement are not fully supported",
677
+ loc
678
+ )
679
+
680
+ return statements[0]
626
681
 
627
682
  # Class definitions - not supported yet
628
683
  elif isinstance(node, ast.ClassDef):
@@ -692,7 +747,13 @@ class PythonParser(BaseParser):
692
747
  f"Syntax error: {e.msg}",
693
748
  loc
694
749
  )
695
- raise VexSyntaxError(f"Syntax error: {e.msg}", loc) from e
750
+
751
+ # Only raise if the error handler is configured to do so
752
+ if self.error_handler._raise_on_error:
753
+ raise VexSyntaxError(f"Syntax error: {e.msg}", loc) from e
754
+
755
+ # Return an empty program if we're not raising
756
+ return self.factory.create_program([])
696
757
 
697
758
  except Exception as e:
698
759
  # Handle other parsing errors
@@ -24,6 +24,11 @@ class VexFunctionParameter:
24
24
  self.description = description
25
25
  self.is_optional = default_value is not None
26
26
 
27
+ @property
28
+ def optional(self) -> bool:
29
+ """Alias for is_optional for compatibility."""
30
+ return self.is_optional
31
+
27
32
  def __str__(self) -> str:
28
33
  mode_str = ""
29
34
  if self.mode == ParameterMode.REFERENCE:
@@ -138,6 +143,49 @@ class VexFunctionSignature:
138
143
  if param_name in kwargs:
139
144
  return False, f"Duplicate argument '{param_name}' for {self.name}"
140
145
 
141
- # TODO: Add type checking for arguments
146
+ # Type checking for arguments
147
+ from ..types.type_checker import type_checker
148
+ from ..types.enums import EnumType
149
+
150
+ # Check positional arguments
151
+ for i, arg in enumerate(args):
152
+ if i >= len(self.parameters):
153
+ break
154
+
155
+ param = self.parameters[i]
156
+ expected_type = param.type
157
+
158
+ # Handle string literals for enum types
159
+ if isinstance(expected_type, EnumType) and isinstance(arg, str):
160
+ if arg not in expected_type.values:
161
+ return False, f"Invalid enum value '{arg}' for parameter '{param.name}' in {self.name}"
162
+ continue
163
+
164
+ # Handle other types
165
+ if hasattr(arg, 'get_type'):
166
+ arg_type = arg.get_type()
167
+ if arg_type and not type_checker.is_compatible(arg_type, expected_type):
168
+ return False, f"Type mismatch for parameter '{param.name}' in {self.name}: expected {expected_type}, got {arg_type}"
169
+
170
+ # Check keyword arguments
171
+ for kwarg_name, kwarg_value in kwargs.items():
172
+ # Find the parameter
173
+ param = next((p for p in self.parameters if p.name == kwarg_name), None)
174
+ if not param:
175
+ continue # Already checked for unknown kwargs above
176
+
177
+ expected_type = param.type
178
+
179
+ # Handle string literals for enum types
180
+ if isinstance(expected_type, EnumType) and isinstance(kwarg_value, str):
181
+ if kwarg_value not in expected_type.values:
182
+ return False, f"Invalid enum value '{kwarg_value}' for parameter '{param.name}' in {self.name}"
183
+ continue
184
+
185
+ # Handle other types
186
+ if hasattr(kwarg_value, 'get_type'):
187
+ kwarg_type = kwarg_value.get_type()
188
+ if kwarg_type and not type_checker.is_compatible(kwarg_type, expected_type):
189
+ return False, f"Type mismatch for parameter '{param.name}' in {self.name}: expected {expected_type}, got {kwarg_type}"
142
190
 
143
191
  return True, None
@@ -10,7 +10,7 @@ from typing import Any, Dict, List, Optional, Type, Union, cast
10
10
  from ..ast.interfaces import IAstNode
11
11
  from ..parser.factory import NodeFactory
12
12
  from ..utils.source_location import SourceLocation
13
- from ..utils.errors import ErrorHandler
13
+ from ..utils.errors import ErrorHandler, ErrorType
14
14
 
15
15
 
16
16
  class DeserializationFactory:
@@ -153,6 +153,7 @@ class DeserializationFactory:
153
153
  "WhileLoop": self.node_factory.create_while_loop,
154
154
  "ForLoop": self.node_factory.create_for_loop,
155
155
  "FunctionDefinition": self.node_factory.create_function_definition,
156
+ "Argument": self.node_factory.create_argument,
156
157
  "ReturnStatement": self.node_factory.create_return_statement,
157
158
  "BreakStatement": self.node_factory.create_break_statement,
158
159
  "ContinueStatement": self.node_factory.create_continue_statement,
@@ -198,11 +199,21 @@ class DeserializationFactory:
198
199
  except TypeError as e:
199
200
  # If the factory method doesn't accept the kwargs, report an error
200
201
  if self.error_handler:
201
- self.error_handler.report_error(f"Failed to create {node_type}: {str(e)}")
202
+ self.error_handler.add_error(
203
+ error_type=ErrorType.INTERNAL_ERROR,
204
+ message=f"Failed to create {node_type}: {str(e)}"
205
+ )
202
206
  raise ValueError(f"Failed to deserialize {node_type}: {str(e)}")
203
207
 
204
208
  # Specific node creation methods for complex cases
205
209
 
210
+ def _create_attributeaccess(self, data: Dict[str, Any],
211
+ location: Optional[SourceLocation]) -> IAstNode:
212
+ """Create an AttributeAccess node from serialized data."""
213
+ object_expr = self._deserialize_value(data.get("object"))
214
+ attribute = data.get("attribute", "")
215
+ return self.node_factory.create_attribute_access(object_expr, attribute, location)
216
+
206
217
  def _create_program(self, data: Dict[str, Any],
207
218
  location: Optional[SourceLocation]) -> IAstNode:
208
219
  """Create a Program node from serialized data."""
@@ -453,16 +453,15 @@ def _generate_definitions() -> Dict[str, Any]:
453
453
  return definitions
454
454
 
455
455
 
456
- def export_schema_to_file(filepath: str, indent: int = 2) -> None:
456
+ def export_schema_to_file(schema: Dict[str, Any], filepath: str, indent: int = 2) -> None:
457
457
  """
458
- Save the generated schema to a file.
458
+ Save the schema to a file.
459
459
 
460
460
  Args:
461
+ schema: The schema to save
461
462
  filepath: The path to save the schema to
462
463
  indent: The indentation level for pretty-printing
463
464
  """
464
- schema = generate_ast_schema()
465
-
466
465
  # Ensure the directory exists
467
466
  os.makedirs(os.path.dirname(os.path.abspath(filepath)), exist_ok=True)
468
467
 
vex_ast/utils/errors.py CHANGED
@@ -50,7 +50,7 @@ class ErrorObserver(Protocol[T_Error]):
50
50
  class ErrorHandler:
51
51
  """Manages error collection and notification."""
52
52
 
53
- def __init__(self, raise_on_error: bool = False):
53
+ def __init__(self, raise_on_error: bool = True):
54
54
  self._errors: List[Error] = []
55
55
  self._raise_on_error = raise_on_error
56
56
  self._observers: List[ErrorObserver] = []
@@ -109,4 +109,4 @@ class VexSyntaxError(VexAstError):
109
109
 
110
110
  def __init__(self, message: str, location: Optional[SourceLocation] = None):
111
111
  self.location = location
112
- super().__init__(message)
112
+ super().__init__(message)
vex_ast/visitors/base.py CHANGED
@@ -47,6 +47,9 @@ class AstVisitor(Generic[T_VisitorResult], ABC):
47
47
  def visit_unaryoperation(self, node: Any) -> T_VisitorResult:
48
48
  return self.generic_visit(node)
49
49
 
50
+ def visit_conditionalexpression(self, node: Any) -> T_VisitorResult:
51
+ return self.generic_visit(node)
52
+
50
53
  def visit_functioncall(self, node: Any) -> T_VisitorResult:
51
54
  return self.generic_visit(node)
52
55
 
@@ -127,4 +130,4 @@ class TypedVisitorMixin:
127
130
  method_name = self.node_type_to_method_name(type(node))
128
131
  if hasattr(self, method_name):
129
132
  return getattr(self, method_name)(node)
130
- return self.generic_visit(node)
133
+ return self.generic_visit(node)
@@ -126,6 +126,7 @@ class PrintVisitor(AstVisitor[str]):
126
126
  visit_variablereference = generic_visit
127
127
  visit_binaryoperation = generic_visit
128
128
  visit_unaryoperation = generic_visit
129
+ visit_conditionalexpression = generic_visit
129
130
  visit_functioncall = generic_visit
130
131
  visit_keywordargument = generic_visit
131
132
  visit_expressionstatement = generic_visit
@@ -142,4 +143,4 @@ class PrintVisitor(AstVisitor[str]):
142
143
  visit_motorcontrol = generic_visit
143
144
  visit_sensorreading = generic_visit
144
145
  visit_timingcontrol = generic_visit
145
- visit_displayoutput = generic_visit
146
+ visit_displayoutput = generic_visit
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vex_ast
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: A Python package for generating Abstract Syntax Trees for VEX V5 code.
5
5
  Home-page: https://github.com/heartx2/vex_ast
6
6
  Author: Chaze
@@ -4,19 +4,19 @@ vex_ast/__init__.py,sha256=0xxA3UL3UMPB1Vlf1jL99bNUnvm41yJEoG5sMeylptY,1757
4
4
  vex_ast/ast/README.md,sha256=7IQDHEXmKyJ8zfJNwa3pMGTDZKVPMFD0YeHT06ATRyM,3205
5
5
  vex_ast/ast/__init__.py,sha256=_KT8R_WG9_DLvPlDhVCNWz-yw0OtdoKxxWZYbtloCzU,2434
6
6
  vex_ast/ast/core.py,sha256=q-15q5VfGIVPAmFsSiWeFAZ55MPsXfCRa21rrt2hmlM,2670
7
- vex_ast/ast/expressions.py,sha256=b0cDs239wvygCIL9s0W8uuyuPeMZz3DwxQ0wmBta_XM,7758
8
- vex_ast/ast/interfaces.py,sha256=DXKdAzts0EBWjCRgYkz_kVSMcYbNIyPdwYpTr7c6P2A,5928
7
+ vex_ast/ast/expressions.py,sha256=FGGWyNpJynnXqw0W_M08pGwa8wplF0oucbqk4x2W7SI,9404
8
+ vex_ast/ast/interfaces.py,sha256=KR_3jM5J97vQb6O5cgDzBi7IIQHjr2uXTobaVCT6RSg,6448
9
9
  vex_ast/ast/literals.py,sha256=PXbOH5Y2fxEngWk_FOiFsx3PC2SEqcx0bcfOGJ3SdbI,2618
10
10
  vex_ast/ast/navigator.py,sha256=9DaVXrknBbBr4omAAMHQnZL9Wpj5wjtoCS6_lni8MYM,7529
11
11
  vex_ast/ast/operators.py,sha256=I-yWvhsrz-OxmBZs5zIss_GTZF5S-nwcSmIzvAVtddM,3160
12
12
  vex_ast/ast/statements.py,sha256=OWRthjYGmTuNozYAHjh_Enp5t-hR1PphtPnFg31FeWw,11841
13
13
  vex_ast/ast/validators.py,sha256=ySpi5H0XRdGXXMFAfmuVEyc3Q9mMXhubZAkP4N8NL3c,4717
14
- vex_ast/ast/vex_nodes.py,sha256=HmUPfiogz0rnObyhg1XEsxPIDdM5xbNxl_kW9NND8pQ,11345
14
+ vex_ast/ast/vex_nodes.py,sha256=8Wq9vl8Mp70E3fxEut9tB6WZE1z0Q_i5V0qh_5Zoeag,11981
15
15
  vex_ast/parser/README.md,sha256=P1qq_97skpgluLDpNu9V_pAdkuF9StjkzOEXJJYpEuM,2565
16
16
  vex_ast/parser/__init__.py,sha256=LGHnFm3UzR4Nw7royGH3c_2RqeY66y8O6DdXHbm9yL4,504
17
- vex_ast/parser/factory.py,sha256=gaje0jOPu5lpndgX9c3VuQ_q-FJuFz9yC5y2bD69lL4,8770
17
+ vex_ast/parser/factory.py,sha256=tcEYSgMNrjqhFDx3tYX22a68Qsxv3fcQpefki_tB8lE,9498
18
18
  vex_ast/parser/interfaces.py,sha256=Ttc0bD_5X420ZCT9MLUf_wE1aZLWLkaJRQqCwBy9wIs,956
19
- vex_ast/parser/python_parser.py,sha256=e1owk-c6Rb4Bt5SYcgB-urZzqsX5xC9tzcK1sB8gkr4,29687
19
+ vex_ast/parser/python_parser.py,sha256=c36vfmzZvGGNDdi6g4kwQnESaKxVF8cSpaRoGVp_lBo,32428
20
20
  vex_ast/parser/strategies.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  vex_ast/registry/README.md,sha256=J8xEXEscEZhWa6wmn05kjE395AjrV7p2h7nq4SXI5uE,1535
22
22
  vex_ast/registry/__init__.py,sha256=dXT8OS7uLyBSdQKZDWrtbANzgSWcg9HUQDA1EaLOvjQ,1188
@@ -24,7 +24,7 @@ vex_ast/registry/api.py,sha256=yyW-TsCIULTzePAoyMvEqD_RNlkFSb4PLpiSkw6ueQk,5460
24
24
  vex_ast/registry/categories.py,sha256=y5tnCzHQ9PPg9hOzOMgyE1ZAhcsjgeFSrgqdJrdqHEg,4885
25
25
  vex_ast/registry/language_map.py,sha256=eekN3k-K9g90GFi4--If3nfJCyarUJxDWDCDvLm7mdU,2656
26
26
  vex_ast/registry/registry.py,sha256=gvsQKyeXWp84T2uDB4O_WQgKCeq8W9udl8TD5MnPZzc,6661
27
- vex_ast/registry/signature.py,sha256=m8gQKdc5IaORDdfdBX6_qH1OL5LoTzveGoWlIIaOES0,5763
27
+ vex_ast/registry/signature.py,sha256=xMMay6zycjf4a0XMVJuyjqZxTuK6X2bLeyW4HAS0suQ,8019
28
28
  vex_ast/registry/simulation_behavior.py,sha256=WwkVKae0owtv3WTrfnVH93rpsh9lbqJ_RSAVmpIVA_k,313
29
29
  vex_ast/registry/validation.py,sha256=xq5UjSWYAcRxjxsCGg3WU5RtPN-DB-JAqKqDNGvnJGk,1973
30
30
  vex_ast/registry/functions/__init__.py,sha256=X9aw0-Y9Q6Gcx01zepP8G_20ybfwC-LDPQfkK2RDOrE,207
@@ -35,9 +35,9 @@ vex_ast/registry/functions/motor.py,sha256=Vby44hV1goNFgFQEFDlv7z_9uGQeuvLMABplO
35
35
  vex_ast/registry/functions/sensors.py,sha256=BdhLV5gSWD5HO-o3JRXhbGQF7s1Ybk3b6VLLqVau1i0,6410
36
36
  vex_ast/registry/functions/timing.py,sha256=DqwMVPk7VKDeZB4S3NI7wOYgM1R52dcdgaVIb9135Jg,3204
37
37
  vex_ast/serialization/__init__.py,sha256=qPTEiMjU8hpVxNH5z4MY7Yj60AxuFurjXZStjhWWf6o,835
38
- vex_ast/serialization/json_deserializer.py,sha256=m_xiEUEoFXGfFylK3M8BVs7F2EieQJ9wbUa_ZTpkHtQ,10523
38
+ vex_ast/serialization/json_deserializer.py,sha256=GCfm8XAF_90FswlizFy59fyZwjZtE94yPR_FWWWAE20,11108
39
39
  vex_ast/serialization/json_serializer.py,sha256=YvMRUpqXjtbxlIvathEIywUqbH3Ne6GSRODfFB0QCGM,4465
40
- vex_ast/serialization/schema.py,sha256=zpKujT7u3Qw2kNbwjV09lNzeQAsCxvMx-uAdaRMEstA,14431
40
+ vex_ast/serialization/schema.py,sha256=BNBYruht3fmuGoVGv5fuMwdIEqLu7OZ1XZS8gzdom0w,14440
41
41
  vex_ast/types/README.md,sha256=Wd3jBShiNXNc3iJ69Qps5_0mBq8QVEd_Gz5OachfS34,1029
42
42
  vex_ast/types/__init__.py,sha256=naLOT_-qHWxzYj4nwxjCB5dfL6tcIt7TjMEaRaXMWbU,2163
43
43
  vex_ast/types/base.py,sha256=hCPCeBNnD5p29Mim-ouRTkG6Lfa8NXrsdYLO8xsbFtM,2258
@@ -47,17 +47,17 @@ vex_ast/types/primitives.py,sha256=t_4kEVyPSmKRHEIRQcp-X5Yq46JbG1SxzlvHb0vL4IA,1
47
47
  vex_ast/types/type_checker.py,sha256=emzhmc6AlH71w0DrKLlZRMBlJNZAuENihvRXTenqg_Q,1083
48
48
  vex_ast/utils/README.md,sha256=Y9RJMQTqQbpjVkvYJmpeRihD1zfW9PhNL_LgoDJ84ak,1945
49
49
  vex_ast/utils/__init__.py,sha256=azzhhFoMykqOkVVm6X2V7dFW3jGBkOvEgnEP1JTCS3g,621
50
- vex_ast/utils/errors.py,sha256=uq_jyu-YasifXjKSpPbVxup-XFf0XSHmp7A0Zd87TUY,3850
50
+ vex_ast/utils/errors.py,sha256=T1sOqWR3-0dYqmXAKDwO7VXIHCGZMnF_gEIGmFWy8Ps,3850
51
51
  vex_ast/utils/source_location.py,sha256=r857ypqUBqex2y_R0RzZo7pz5di9qtEeWFFQ4HwzYQE,1297
52
52
  vex_ast/utils/type_definitions.py,sha256=2rB85B1vZL1GLWItBuJJpyr-vmp3W346EMMX2TPZ99Q,313
53
53
  vex_ast/visitors/README.md,sha256=BKDj8LMuBlCrzgSSLmCkbET7WIqgxe-oCkqQbqXekrE,2725
54
54
  vex_ast/visitors/__init__.py,sha256=cndW3yp0Mu9w5vzwqqS2N5EqS0Ioh0V5UCDDrwCO0_Q,492
55
55
  vex_ast/visitors/analyzer.py,sha256=cBT5PRbtfQ_Dt1qiHN-wdO5KnC2yl-Ul5RasXg9geHY,3668
56
- vex_ast/visitors/base.py,sha256=Ph0taTIVMHV_QjXfDd0ipZnCXVJErkyRtPpfwfzo-kY,4859
57
- vex_ast/visitors/printer.py,sha256=CUY_73hxm7MoC-63JeIXaVYnZ8QqtfMqbek2R2HMEmE,5411
56
+ vex_ast/visitors/base.py,sha256=fLeMuIXJEHsag17PDM33he79x7Mp4V0wgtnF_8LuFpc,4978
57
+ vex_ast/visitors/printer.py,sha256=kofemEXvGBXEm1wy57R-Pgj2QBnSp_lNjFk3p2hNU2o,5460
58
58
  vex_ast/visitors/transformer.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
- vex_ast-0.2.2.dist-info/licenses/LICENSE,sha256=IOSlfCuxGv4OAg421BRDKVi16RZ7-5kCMJ4B16r4kuc,69
60
- vex_ast-0.2.2.dist-info/METADATA,sha256=Rftzrxm-exQp3zpV5wcNVkErbkQn1ww0pz65tXOQhDw,5295
61
- vex_ast-0.2.2.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
62
- vex_ast-0.2.2.dist-info/top_level.txt,sha256=MoZGrpKgNUDiqL9gWp4q3wMw3q93XPEEjmBNPJQcNAs,8
63
- vex_ast-0.2.2.dist-info/RECORD,,
59
+ vex_ast-0.2.4.dist-info/licenses/LICENSE,sha256=IOSlfCuxGv4OAg421BRDKVi16RZ7-5kCMJ4B16r4kuc,69
60
+ vex_ast-0.2.4.dist-info/METADATA,sha256=_cjCd-H6a70oJPJ8X-P_m7NiAwikUQiAX2aLRUDDfFo,5295
61
+ vex_ast-0.2.4.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
62
+ vex_ast-0.2.4.dist-info/top_level.txt,sha256=MoZGrpKgNUDiqL9gWp4q3wMw3q93XPEEjmBNPJQcNAs,8
63
+ vex_ast-0.2.4.dist-info/RECORD,,