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/registry/signature.py
CHANGED
@@ -1,191 +1,269 @@
|
|
1
|
-
from typing import Optional, List, Dict, Any, Union, Callable, Tuple
|
2
|
-
from enum import Enum, auto
|
3
|
-
from ..types.base import VexType, VOID, ANY
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
self.
|
22
|
-
self.
|
23
|
-
self.
|
24
|
-
self.
|
25
|
-
self.
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
self.
|
98
|
-
self.
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
#
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
1
|
+
from typing import Optional, List, Dict, Any, Union, Callable, Tuple
|
2
|
+
from enum import Enum, auto
|
3
|
+
from ..types.base import VexType, VOID, ANY
|
4
|
+
from .categories import VexCategory, BehaviorType, SubCategory
|
5
|
+
|
6
|
+
class ParameterMode(Enum):
|
7
|
+
"""Parameter passing modes"""
|
8
|
+
VALUE = auto() # Pass by value
|
9
|
+
REFERENCE = auto() # Pass by reference
|
10
|
+
OUTPUT = auto() # Output parameter
|
11
|
+
|
12
|
+
class VexFunctionParameter:
|
13
|
+
"""Represents a parameter in a VEX function signature"""
|
14
|
+
|
15
|
+
def __init__(self,
|
16
|
+
name: str,
|
17
|
+
type_: VexType,
|
18
|
+
default_value: Optional[Any] = None,
|
19
|
+
mode: ParameterMode = ParameterMode.VALUE,
|
20
|
+
description: str = ""):
|
21
|
+
self.name = name
|
22
|
+
self.type = type_
|
23
|
+
self.default_value = default_value
|
24
|
+
self.mode = mode
|
25
|
+
self.description = description
|
26
|
+
self.is_optional = default_value is not None
|
27
|
+
|
28
|
+
@property
|
29
|
+
def optional(self) -> bool:
|
30
|
+
"""Alias for is_optional for compatibility."""
|
31
|
+
return self.is_optional
|
32
|
+
|
33
|
+
def __str__(self) -> str:
|
34
|
+
mode_str = ""
|
35
|
+
if self.mode == ParameterMode.REFERENCE:
|
36
|
+
mode_str = "&"
|
37
|
+
elif self.mode == ParameterMode.OUTPUT:
|
38
|
+
mode_str = "*"
|
39
|
+
|
40
|
+
default_str = ""
|
41
|
+
if self.is_optional:
|
42
|
+
default_str = f" = {self.default_value}"
|
43
|
+
|
44
|
+
return f"{self.type}{mode_str} {self.name}{default_str}"
|
45
|
+
|
46
|
+
# For backward compatibility
|
47
|
+
class SimulationCategory(Enum):
|
48
|
+
"""Categories for simulation behavior (deprecated, use VexCategory and BehaviorType instead)"""
|
49
|
+
MOTOR_CONTROL = auto()
|
50
|
+
SENSOR_READING = auto()
|
51
|
+
DISPLAY_OUTPUT = auto()
|
52
|
+
TIMING_CONTROL = auto()
|
53
|
+
COMPETITION = auto()
|
54
|
+
CONFIGURATION = auto()
|
55
|
+
CALCULATION = auto()
|
56
|
+
EVENT_HANDLING = auto()
|
57
|
+
OTHER = auto()
|
58
|
+
|
59
|
+
SimulationBehaviorFunc = Callable[..., Any]
|
60
|
+
|
61
|
+
class VexFunctionSignature:
|
62
|
+
"""Represents the signature of a VEX function"""
|
63
|
+
|
64
|
+
def __init__(self,
|
65
|
+
name: str,
|
66
|
+
return_type: VexType = VOID,
|
67
|
+
parameters: List[Union[VexFunctionParameter, Tuple[str, str, Optional[Any]]]] = None,
|
68
|
+
description: str = "",
|
69
|
+
category: Union[VexCategory, SimulationCategory] = None,
|
70
|
+
behavior: BehaviorType = None,
|
71
|
+
subcategory: Optional[SubCategory] = None,
|
72
|
+
simulation_behavior: Optional[SimulationBehaviorFunc] = None,
|
73
|
+
python_name: Optional[str] = None,
|
74
|
+
cpp_name: Optional[str] = None,
|
75
|
+
object_type: Optional[VexType] = None,
|
76
|
+
method_name: Optional[str] = None):
|
77
|
+
self.name = name
|
78
|
+
self.return_type = return_type
|
79
|
+
|
80
|
+
# Convert tuple parameters to VexFunctionParameter objects
|
81
|
+
processed_params = []
|
82
|
+
if parameters:
|
83
|
+
for param in parameters:
|
84
|
+
if isinstance(param, VexFunctionParameter):
|
85
|
+
processed_params.append(param)
|
86
|
+
elif isinstance(param, tuple) and len(param) >= 2:
|
87
|
+
# Extract tuple values
|
88
|
+
param_name = param[0]
|
89
|
+
param_type = param[1]
|
90
|
+
default_value = param[2] if len(param) > 2 else None
|
91
|
+
processed_params.append(VexFunctionParameter(
|
92
|
+
name=param_name,
|
93
|
+
type_=param_type,
|
94
|
+
default_value=default_value
|
95
|
+
))
|
96
|
+
|
97
|
+
self.parameters = processed_params
|
98
|
+
self.description = description
|
99
|
+
|
100
|
+
# Handle category and behavior
|
101
|
+
from .categories import categorizer
|
102
|
+
|
103
|
+
# For backward compatibility with SimulationCategory
|
104
|
+
if isinstance(category, SimulationCategory):
|
105
|
+
# Convert SimulationCategory to BehaviorType
|
106
|
+
sim_cat_name = category.name
|
107
|
+
self._simulation_category = category # Store original for backward compatibility
|
108
|
+
|
109
|
+
# Determine category and behavior from function name and description
|
110
|
+
self.category, self.behavior, self.subcategory = categorizer.categorize_function(
|
111
|
+
name, description
|
112
|
+
)
|
113
|
+
|
114
|
+
# Override behavior based on simulation category mapping
|
115
|
+
if sim_cat_name in categorizer.simulation_to_behavior:
|
116
|
+
self.behavior = categorizer.simulation_to_behavior[sim_cat_name]
|
117
|
+
else:
|
118
|
+
# Use provided category and behavior or determine from function name
|
119
|
+
if category is None or behavior is None:
|
120
|
+
self.category, self.behavior, self.subcategory = categorizer.categorize_function(
|
121
|
+
name, description
|
122
|
+
)
|
123
|
+
if category is not None:
|
124
|
+
self.category = category
|
125
|
+
if behavior is not None:
|
126
|
+
self.behavior = behavior
|
127
|
+
if subcategory is not None:
|
128
|
+
self.subcategory = subcategory
|
129
|
+
else:
|
130
|
+
self.category = category
|
131
|
+
self.behavior = behavior
|
132
|
+
self.subcategory = subcategory
|
133
|
+
|
134
|
+
# For backward compatibility, map to SimulationCategory
|
135
|
+
if self.behavior == BehaviorType.CONTROL and self.category == VexCategory.MOTOR:
|
136
|
+
self._simulation_category = SimulationCategory.MOTOR_CONTROL
|
137
|
+
elif self.behavior == BehaviorType.READ and self.category == VexCategory.SENSOR:
|
138
|
+
self._simulation_category = SimulationCategory.SENSOR_READING
|
139
|
+
elif self.behavior == BehaviorType.OUTPUT and self.category == VexCategory.DISPLAY:
|
140
|
+
self._simulation_category = SimulationCategory.DISPLAY_OUTPUT
|
141
|
+
elif self.behavior == BehaviorType.CONTROL and self.category == VexCategory.TIMING:
|
142
|
+
self._simulation_category = SimulationCategory.TIMING_CONTROL
|
143
|
+
elif self.category == VexCategory.COMPETITION:
|
144
|
+
self._simulation_category = SimulationCategory.COMPETITION
|
145
|
+
elif self.behavior == BehaviorType.CONFIG:
|
146
|
+
self._simulation_category = SimulationCategory.CONFIGURATION
|
147
|
+
elif self.behavior == BehaviorType.EVENT:
|
148
|
+
self._simulation_category = SimulationCategory.EVENT_HANDLING
|
149
|
+
else:
|
150
|
+
self._simulation_category = SimulationCategory.OTHER
|
151
|
+
|
152
|
+
self.simulation_behavior = simulation_behavior
|
153
|
+
self.python_name = python_name or name
|
154
|
+
self.cpp_name = cpp_name or name
|
155
|
+
self.object_type = object_type # For methods, this is the class type
|
156
|
+
self.method_name = method_name # For methods, this is the method name
|
157
|
+
|
158
|
+
# Validate there are no duplicate parameter names
|
159
|
+
param_names = [param.name for param in self.parameters]
|
160
|
+
if len(param_names) != len(set(param_names)):
|
161
|
+
raise ValueError(f"Duplicate parameter names in function {name}")
|
162
|
+
|
163
|
+
# Ensure optional parameters come after required parameters
|
164
|
+
has_optional = False
|
165
|
+
for param in self.parameters:
|
166
|
+
if param.is_optional:
|
167
|
+
has_optional = True
|
168
|
+
elif has_optional:
|
169
|
+
raise ValueError(f"Required parameter after optional parameter in function {name}")
|
170
|
+
|
171
|
+
@property
|
172
|
+
def simulation_category(self) -> SimulationCategory:
|
173
|
+
"""Get the simulation category (for backward compatibility)"""
|
174
|
+
if hasattr(self, '_simulation_category'):
|
175
|
+
return self._simulation_category
|
176
|
+
return SimulationCategory.OTHER
|
177
|
+
|
178
|
+
# Alias for backward compatibility
|
179
|
+
@property
|
180
|
+
def category(self) -> Union[VexCategory, SimulationCategory]:
|
181
|
+
"""Get the category (for backward compatibility)"""
|
182
|
+
return self.simulation_category
|
183
|
+
|
184
|
+
@category.setter
|
185
|
+
def category(self, value: Union[VexCategory, SimulationCategory]):
|
186
|
+
"""Set the category"""
|
187
|
+
if isinstance(value, SimulationCategory):
|
188
|
+
# For backward compatibility
|
189
|
+
self._simulation_category = value
|
190
|
+
else:
|
191
|
+
# New category system
|
192
|
+
self.vex_category = value
|
193
|
+
|
194
|
+
def __str__(self) -> str:
|
195
|
+
params_str = ", ".join(str(param) for param in self.parameters)
|
196
|
+
return f"{self.return_type} {self.name}({params_str})"
|
197
|
+
|
198
|
+
def validate_arguments(self,
|
199
|
+
args: List[Any],
|
200
|
+
kwargs: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
|
201
|
+
"""Validate function arguments against this signature"""
|
202
|
+
# Check if we have too many positional arguments
|
203
|
+
if len(args) > len(self.parameters):
|
204
|
+
return False, f"Too many positional arguments for {self.name}"
|
205
|
+
|
206
|
+
# Check if we have unknown keyword arguments
|
207
|
+
param_names = {param.name for param in self.parameters}
|
208
|
+
for kwarg_name in kwargs:
|
209
|
+
if kwarg_name not in param_names:
|
210
|
+
return False, f"Unknown keyword argument '{kwarg_name}' for {self.name}"
|
211
|
+
|
212
|
+
# Check if we have the required number of arguments
|
213
|
+
required_params = [p for p in self.parameters if not p.is_optional]
|
214
|
+
if len(args) + len(kwargs) < len(required_params):
|
215
|
+
return False, f"Missing required arguments for {self.name}"
|
216
|
+
|
217
|
+
# Check if we have duplicate arguments
|
218
|
+
args_used = min(len(args), len(self.parameters))
|
219
|
+
for i in range(args_used):
|
220
|
+
param_name = self.parameters[i].name
|
221
|
+
if param_name in kwargs:
|
222
|
+
return False, f"Duplicate argument '{param_name}' for {self.name}"
|
223
|
+
|
224
|
+
# Type checking for arguments
|
225
|
+
from ..types.type_checker import type_checker
|
226
|
+
from ..types.enums import EnumType
|
227
|
+
|
228
|
+
# Check positional arguments
|
229
|
+
for i, arg in enumerate(args):
|
230
|
+
if i >= len(self.parameters):
|
231
|
+
break
|
232
|
+
|
233
|
+
param = self.parameters[i]
|
234
|
+
expected_type = param.type
|
235
|
+
|
236
|
+
# Handle string literals for enum types
|
237
|
+
if isinstance(expected_type, EnumType) and isinstance(arg, str):
|
238
|
+
if arg not in expected_type.values:
|
239
|
+
return False, f"Invalid enum value '{arg}' for parameter '{param.name}' in {self.name}"
|
240
|
+
continue
|
241
|
+
|
242
|
+
# Handle other types
|
243
|
+
if hasattr(arg, 'get_type'):
|
244
|
+
arg_type = arg.get_type()
|
245
|
+
if arg_type and not type_checker.is_compatible(arg_type, expected_type):
|
246
|
+
return False, f"Type mismatch for parameter '{param.name}' in {self.name}: expected {expected_type}, got {arg_type}"
|
247
|
+
|
248
|
+
# Check keyword arguments
|
249
|
+
for kwarg_name, kwarg_value in kwargs.items():
|
250
|
+
# Find the parameter
|
251
|
+
param = next((p for p in self.parameters if p.name == kwarg_name), None)
|
252
|
+
if not param:
|
253
|
+
continue # Already checked for unknown kwargs above
|
254
|
+
|
255
|
+
expected_type = param.type
|
256
|
+
|
257
|
+
# Handle string literals for enum types
|
258
|
+
if isinstance(expected_type, EnumType) and isinstance(kwarg_value, str):
|
259
|
+
if kwarg_value not in expected_type.values:
|
260
|
+
return False, f"Invalid enum value '{kwarg_value}' for parameter '{param.name}' in {self.name}"
|
261
|
+
continue
|
262
|
+
|
263
|
+
# Handle other types
|
264
|
+
if hasattr(kwarg_value, 'get_type'):
|
265
|
+
kwarg_type = kwarg_value.get_type()
|
266
|
+
if kwarg_type and not type_checker.is_compatible(kwarg_type, expected_type):
|
267
|
+
return False, f"Type mismatch for parameter '{param.name}' in {self.name}: expected {expected_type}, got {kwarg_type}"
|
268
|
+
|
269
|
+
return True, None
|
@@ -1,9 +1,9 @@
|
|
1
|
-
# vex_ast/registry/simulation_behavior.py
|
2
|
-
from enum import Enum, auto
|
3
|
-
|
4
|
-
class SimulationBehavior(Enum):
|
5
|
-
"""Categories of simulation behaviors for VEX functions"""
|
6
|
-
AFFECTS_MOTOR = "AFFECTS_MOTOR"
|
7
|
-
READS_SENSOR = "READS_SENSOR"
|
8
|
-
AFFECTS_TIMING = "AFFECTS_TIMING"
|
1
|
+
# vex_ast/registry/simulation_behavior.py
|
2
|
+
from enum import Enum, auto
|
3
|
+
|
4
|
+
class SimulationBehavior(Enum):
|
5
|
+
"""Categories of simulation behaviors for VEX functions"""
|
6
|
+
AFFECTS_MOTOR = "AFFECTS_MOTOR"
|
7
|
+
READS_SENSOR = "READS_SENSOR"
|
8
|
+
AFFECTS_TIMING = "AFFECTS_TIMING"
|
9
9
|
AFFECTS_DISPLAY = "AFFECTS_DISPLAY"
|
vex_ast/registry/validation.py
CHANGED
@@ -1,44 +1,44 @@
|
|
1
|
-
from typing import Dict, List, Optional, Set, Tuple, Any, Union
|
2
|
-
from ..types.base import VexType
|
3
|
-
from ..types.type_checker import type_checker
|
4
|
-
from .registry import registry, VexFunctionRegistry
|
5
|
-
from .signature import VexFunctionSignature, VexFunctionParameter
|
6
|
-
|
7
|
-
class FunctionCallValidator:
|
8
|
-
"""Validates function calls against the registry"""
|
9
|
-
|
10
|
-
def __init__(self, registry: VexFunctionRegistry = registry):
|
11
|
-
self.registry = registry
|
12
|
-
|
13
|
-
def validate_call(self,
|
14
|
-
function_name: str,
|
15
|
-
args: List[Any] = None,
|
16
|
-
kwargs: Dict[str, Any] = None,
|
17
|
-
language: str = "python") -> Tuple[bool, Optional[str]]:
|
18
|
-
"""Validate a function call"""
|
19
|
-
args = args or []
|
20
|
-
kwargs = kwargs or {}
|
21
|
-
return self.registry.validate_call(function_name, args, kwargs, language)
|
22
|
-
|
23
|
-
def validate_method_call(self,
|
24
|
-
object_type: Union[VexType, str],
|
25
|
-
method_name: str,
|
26
|
-
args: List[Any] = None,
|
27
|
-
kwargs: Dict[str, Any] = None) -> Tuple[bool, Optional[str]]:
|
28
|
-
"""Validate a method call on an object"""
|
29
|
-
args = args or []
|
30
|
-
kwargs = kwargs or {}
|
31
|
-
return self.registry.validate_method_call(object_type, method_name, args, kwargs)
|
32
|
-
|
33
|
-
def validate_ast_function_call(self, function_call_node: Any) -> Tuple[bool, Optional[str]]:
|
34
|
-
"""Validate a function call AST node"""
|
35
|
-
# This would need to be implemented based on the actual AST node structure
|
36
|
-
# For now, just a placeholder showing the interface
|
37
|
-
function_name = function_call_node.function.name
|
38
|
-
args = [arg.value for arg in function_call_node.args]
|
39
|
-
kwargs = {kw.name: kw.value for kw in function_call_node.keywords}
|
40
|
-
|
41
|
-
return self.validate_call(function_name, args, kwargs)
|
42
|
-
|
43
|
-
# Singleton instance
|
1
|
+
from typing import Dict, List, Optional, Set, Tuple, Any, Union
|
2
|
+
from ..types.base import VexType
|
3
|
+
from ..types.type_checker import type_checker
|
4
|
+
from .registry import registry, VexFunctionRegistry
|
5
|
+
from .signature import VexFunctionSignature, VexFunctionParameter
|
6
|
+
|
7
|
+
class FunctionCallValidator:
|
8
|
+
"""Validates function calls against the registry"""
|
9
|
+
|
10
|
+
def __init__(self, registry: VexFunctionRegistry = registry):
|
11
|
+
self.registry = registry
|
12
|
+
|
13
|
+
def validate_call(self,
|
14
|
+
function_name: str,
|
15
|
+
args: List[Any] = None,
|
16
|
+
kwargs: Dict[str, Any] = None,
|
17
|
+
language: str = "python") -> Tuple[bool, Optional[str]]:
|
18
|
+
"""Validate a function call"""
|
19
|
+
args = args or []
|
20
|
+
kwargs = kwargs or {}
|
21
|
+
return self.registry.validate_call(function_name, args, kwargs, language)
|
22
|
+
|
23
|
+
def validate_method_call(self,
|
24
|
+
object_type: Union[VexType, str],
|
25
|
+
method_name: str,
|
26
|
+
args: List[Any] = None,
|
27
|
+
kwargs: Dict[str, Any] = None) -> Tuple[bool, Optional[str]]:
|
28
|
+
"""Validate a method call on an object"""
|
29
|
+
args = args or []
|
30
|
+
kwargs = kwargs or {}
|
31
|
+
return self.registry.validate_method_call(object_type, method_name, args, kwargs)
|
32
|
+
|
33
|
+
def validate_ast_function_call(self, function_call_node: Any) -> Tuple[bool, Optional[str]]:
|
34
|
+
"""Validate a function call AST node"""
|
35
|
+
# This would need to be implemented based on the actual AST node structure
|
36
|
+
# For now, just a placeholder showing the interface
|
37
|
+
function_name = function_call_node.function.name
|
38
|
+
args = [arg.value for arg in function_call_node.args]
|
39
|
+
kwargs = {kw.name: kw.value for kw in function_call_node.keywords}
|
40
|
+
|
41
|
+
return self.validate_call(function_name, args, kwargs)
|
42
|
+
|
43
|
+
# Singleton instance
|
44
44
|
validator = FunctionCallValidator()
|