vex-ast 0.1.0__py3-none-any.whl → 0.2.1__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.
@@ -0,0 +1,104 @@
1
+ from ..registry import registry
2
+ from ..signature import VexFunctionSignature, VexFunctionParameter, ParameterMode, SimulationCategory
3
+ from ...types.base import VOID, ANY
4
+ from ...types.primitives import INT, FLOAT, BOOL
5
+ from ...types.enums import TIME_UNITS
6
+ from ...types.objects import TIMER
7
+
8
+ def register_timing_functions():
9
+ """Register timing-related functions in the registry"""
10
+
11
+ # Global wait function
12
+ wait_params = [
13
+ VexFunctionParameter("time", FLOAT, description="Time to wait"),
14
+ VexFunctionParameter("units", TIME_UNITS, "MSEC", description="Time units")
15
+ ]
16
+
17
+ wait_signature = VexFunctionSignature(
18
+ name="wait",
19
+ return_type=VOID,
20
+ parameters=wait_params,
21
+ description="Wait for a specified amount of time",
22
+ category=SimulationCategory.TIMING_CONTROL,
23
+ python_name="wait",
24
+ cpp_name="wait"
25
+ )
26
+
27
+ registry.register_function(wait_signature)
28
+
29
+ # Timer functions
30
+
31
+ # Timer.time() method
32
+ time_params = [
33
+ VexFunctionParameter("units", TIME_UNITS, "MSEC", description="Time units")
34
+ ]
35
+
36
+ time_signature = VexFunctionSignature(
37
+ name="time",
38
+ return_type=FLOAT,
39
+ parameters=time_params,
40
+ description="Get the current time of the timer",
41
+ category=SimulationCategory.TIMING_CONTROL,
42
+ python_name="time",
43
+ cpp_name="time",
44
+ object_type=TIMER,
45
+ method_name="time"
46
+ )
47
+
48
+ registry.register_function(time_signature)
49
+
50
+ # Timer.clear() method
51
+ clear_signature = VexFunctionSignature(
52
+ name="clear",
53
+ return_type=VOID,
54
+ parameters=[],
55
+ description="Clear the timer",
56
+ category=SimulationCategory.TIMING_CONTROL,
57
+ python_name="clear",
58
+ cpp_name="clear",
59
+ object_type=TIMER,
60
+ method_name="clear"
61
+ )
62
+
63
+ registry.register_function(clear_signature)
64
+
65
+ # Timer.reset() method
66
+ reset_signature = VexFunctionSignature(
67
+ name="reset",
68
+ return_type=VOID,
69
+ parameters=[],
70
+ description="Reset the timer",
71
+ category=SimulationCategory.TIMING_CONTROL,
72
+ python_name="reset",
73
+ cpp_name="reset",
74
+ object_type=TIMER,
75
+ method_name="reset"
76
+ )
77
+
78
+ registry.register_function(reset_signature)
79
+
80
+ # Timer.event() method
81
+ event_params = [
82
+ VexFunctionParameter("callback", ANY, description="Callback function to execute"),
83
+ VexFunctionParameter("delay", FLOAT, description="Time delay before callback execution"),
84
+ VexFunctionParameter("units", TIME_UNITS, "MSEC", description="Time units")
85
+ ]
86
+
87
+ event_signature = VexFunctionSignature(
88
+ name="event",
89
+ return_type=VOID,
90
+ parameters=event_params,
91
+ description="Register a callback function to be called after a delay",
92
+ category=SimulationCategory.EVENT_HANDLING,
93
+ python_name="event",
94
+ cpp_name="event",
95
+ object_type=TIMER,
96
+ method_name="event"
97
+ )
98
+
99
+ registry.register_function(event_signature)
100
+
101
+ # Add more timing functions as needed...
102
+
103
+ if __name__ == "__main__":
104
+ register_timing_functions()
@@ -0,0 +1,26 @@
1
+ # VEX AST Types Package (vex_ast.types)
2
+
3
+ This package defines the type system used for the VEX V5 Robot Python language.
4
+
5
+ Purpose
6
+
7
+ The type system provides a way to represent and reason about the types of values in VEX code. This information is used for type checking, code optimization, and other purposes.
8
+
9
+ Structure
10
+
11
+ The package is organized into several modules:
12
+
13
+ * `base.py`: Defines base classes for types.
14
+ * `enums.py`: Defines enums for different type categories.
15
+ * `objects.py`: Defines classes for representing objects.
16
+ * `primitives.py`: Defines classes for representing primitive types (e.g., int, float, string, boolean).
17
+ * `type_checker.py`: Implements the type checking logic.
18
+
19
+ Key Concepts
20
+
21
+ * Types: Represent the kind of value that a variable or expression can have.
22
+ * Type checking: The process of verifying that the types in a program are consistent.
23
+
24
+ Usage
25
+
26
+ The type system is used internally by the VEX AST parser, type checker, and other tools. It is not typically accessed directly by users.
@@ -0,0 +1,140 @@
1
+ """
2
+ Types package for VEX AST.
3
+
4
+ This package provides type definitions and type checking functionality for VEX AST.
5
+ """
6
+
7
+ from .base import (
8
+ VexType,
9
+ VoidType,
10
+ AnyType,
11
+ TypeRegistry,
12
+ VOID,
13
+ ANY,
14
+ type_registry
15
+ )
16
+
17
+ from .primitives import (
18
+ PrimitiveType,
19
+ IntegerType,
20
+ FloatType,
21
+ BooleanType,
22
+ StringType,
23
+ INT,
24
+ FLOAT,
25
+ BOOL,
26
+ STRING
27
+ )
28
+
29
+ from .objects import (
30
+ ObjectType,
31
+ MOTOR,
32
+ MOTOR_GROUP,
33
+ DRIVETRAIN,
34
+ BRAIN,
35
+ CONTROLLER,
36
+ INERTIAL,
37
+ DISTANCE,
38
+ ROTATION,
39
+ OPTICAL,
40
+ GPS,
41
+ ELECTROMAGNETIC,
42
+ BRAIN_BATTERY,
43
+ BRAIN_SCREEN,
44
+ BRAIN_LCD,
45
+ COMPETITION,
46
+ TIMER,
47
+ BUMPER,
48
+ LIMIT_SWITCH,
49
+ ENCODER,
50
+ SONAR,
51
+ GYRO,
52
+ PNEUMATIC,
53
+ VISION
54
+ )
55
+
56
+ from .enums import (
57
+ EnumType,
58
+ DIRECTION_TYPE,
59
+ TURN_TYPE,
60
+ BRAKE_TYPE,
61
+ VELOCITY_UNITS,
62
+ ROTATION_UNITS,
63
+ TIME_UNITS,
64
+ DISTANCE_UNITS,
65
+ CURRENT_UNITS,
66
+ TORQUE_UNITS,
67
+ TEMPERATURE_UNITS,
68
+ ANALOG_UNITS
69
+ )
70
+
71
+ from .type_checker import (
72
+ TypeChecker,
73
+ type_checker as check_type_compatibility
74
+ )
75
+
76
+ __all__ = [
77
+ # Base types
78
+ "VexType",
79
+ "VoidType",
80
+ "AnyType",
81
+ "TypeRegistry",
82
+ "VOID",
83
+ "ANY",
84
+ "type_registry",
85
+
86
+ # Primitive types
87
+ "PrimitiveType",
88
+ "IntegerType",
89
+ "FloatType",
90
+ "BooleanType",
91
+ "StringType",
92
+ "INT",
93
+ "FLOAT",
94
+ "BOOL",
95
+ "STRING",
96
+
97
+ # Object types
98
+ "ObjectType",
99
+ "MOTOR",
100
+ "MOTOR_GROUP",
101
+ "DRIVETRAIN",
102
+ "BRAIN",
103
+ "CONTROLLER",
104
+ "INERTIAL",
105
+ "DISTANCE",
106
+ "ROTATION",
107
+ "OPTICAL",
108
+ "GPS",
109
+ "ELECTROMAGNETIC",
110
+ "BRAIN_BATTERY",
111
+ "BRAIN_SCREEN",
112
+ "BRAIN_LCD",
113
+ "COMPETITION",
114
+ "TIMER",
115
+ "BUMPER",
116
+ "LIMIT_SWITCH",
117
+ "ENCODER",
118
+ "SONAR",
119
+ "GYRO",
120
+ "PNEUMATIC",
121
+ "VISION",
122
+
123
+ # Enum types
124
+ "EnumType",
125
+ "DIRECTION_TYPE",
126
+ "TURN_TYPE",
127
+ "BRAKE_TYPE",
128
+ "VELOCITY_UNITS",
129
+ "ROTATION_UNITS",
130
+ "TIME_UNITS",
131
+ "DISTANCE_UNITS",
132
+ "CURRENT_UNITS",
133
+ "TORQUE_UNITS",
134
+ "TEMPERATURE_UNITS",
135
+ "ANALOG_UNITS",
136
+
137
+ # Type checking
138
+ "TypeChecker",
139
+ "check_type_compatibility"
140
+ ]
vex_ast/types/base.py ADDED
@@ -0,0 +1,84 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Optional, Union, List, Type, Set, TypeVar, Generic
3
+
4
+ class VexType(ABC):
5
+ """Base abstract class for all VEX types"""
6
+
7
+ @property
8
+ @abstractmethod
9
+ def name(self) -> str:
10
+ """Return the canonical name of this type"""
11
+ pass
12
+
13
+ @abstractmethod
14
+ def is_compatible_with(self, other: 'VexType') -> bool:
15
+ """Check if this type is compatible with another type"""
16
+ pass
17
+
18
+ @abstractmethod
19
+ def __str__(self) -> str:
20
+ """String representation of the type"""
21
+ pass
22
+
23
+ def __eq__(self, other) -> bool:
24
+ if not isinstance(other, VexType):
25
+ return False
26
+ return self.name == other.name
27
+
28
+ class VoidType(VexType):
29
+ """Represents the void type (no return value)"""
30
+
31
+ @property
32
+ def name(self) -> str:
33
+ return "void"
34
+
35
+ def is_compatible_with(self, other: VexType) -> bool:
36
+ return isinstance(other, VoidType)
37
+
38
+ def __str__(self) -> str:
39
+ return "void"
40
+
41
+ class AnyType(VexType):
42
+ """Represents any type (for generic functions)"""
43
+
44
+ @property
45
+ def name(self) -> str:
46
+ return "any"
47
+
48
+ def is_compatible_with(self, other: VexType) -> bool:
49
+ return True # Any type is compatible with all types
50
+
51
+ def __str__(self) -> str:
52
+ return "any"
53
+
54
+ class TypeRegistry:
55
+ """Global registry of types to ensure type uniqueness"""
56
+
57
+ _instance = None
58
+
59
+ def __new__(cls):
60
+ if cls._instance is None:
61
+ cls._instance = super(TypeRegistry, cls).__new__(cls)
62
+ cls._instance._types = {}
63
+ return cls._instance
64
+
65
+ def register_type(self, type_: VexType) -> None:
66
+ """Register a type in the registry"""
67
+ self._types[type_.name] = type_
68
+
69
+ def get_type(self, name: str) -> Optional[VexType]:
70
+ """Get a type by name"""
71
+ return self._types.get(name)
72
+
73
+ def get_all_types(self) -> List[VexType]:
74
+ """Get all registered types"""
75
+ return list(self._types.values())
76
+
77
+ # Singleton instances
78
+ VOID = VoidType()
79
+ ANY = AnyType()
80
+
81
+ # Global registry
82
+ type_registry = TypeRegistry()
83
+ type_registry.register_type(VOID)
84
+ type_registry.register_type(ANY)
vex_ast/types/enums.py ADDED
@@ -0,0 +1,97 @@
1
+ from typing import Dict, List, Any, Optional, Set
2
+ from .base import VexType, type_registry
3
+ from .primitives import StringType, IntegerType, INT
4
+
5
+ class EnumType(VexType):
6
+ """Represents a VEX enum type"""
7
+
8
+ def __init__(self, name: str, values: Dict[str, Any] = None):
9
+ self._name = name
10
+ self._values = values or {}
11
+ type_registry.register_type(self)
12
+
13
+ @property
14
+ def name(self) -> str:
15
+ return self._name
16
+
17
+ @property
18
+ def values(self) -> Dict[str, Any]:
19
+ return self._values.copy()
20
+
21
+ def is_compatible_with(self, other: VexType) -> bool:
22
+ """Enums are compatible with themselves or with integers"""
23
+ return isinstance(other, EnumType) and self.name == other.name or isinstance(other, IntegerType)
24
+
25
+ def __str__(self) -> str:
26
+ return f"enum {self._name}"
27
+
28
+ def add_value(self, name: str, value: Any) -> None:
29
+ """Add a value to the enum"""
30
+ self._values[name] = value
31
+
32
+ def is_valid_value(self, value: Any) -> bool:
33
+ """Check if a value is valid for this enum"""
34
+ return value in self._values.values() or value in self._values
35
+
36
+ # Create VEX enum types
37
+ DIRECTION_TYPE = EnumType("DirectionType", {
38
+ "FORWARD": 0,
39
+ "REVERSE": 1
40
+ })
41
+
42
+ TURN_TYPE = EnumType("TurnType", {
43
+ "LEFT": 0,
44
+ "RIGHT": 1
45
+ })
46
+
47
+ BRAKE_TYPE = EnumType("BrakeType", {
48
+ "COAST": 0,
49
+ "BRAKE": 1,
50
+ "HOLD": 2
51
+ })
52
+
53
+ VELOCITY_UNITS = EnumType("VelocityUnits", {
54
+ "PCT": 0, # Percentage
55
+ "RPM": 1, # Revolutions per minute
56
+ "DPS": 2 # Degrees per second
57
+ })
58
+
59
+ ROTATION_UNITS = EnumType("RotationUnits", {
60
+ "DEG": 0, # Degrees
61
+ "REV": 1, # Revolutions
62
+ "RAW": 2 # Raw data
63
+ })
64
+
65
+ TIME_UNITS = EnumType("TimeUnits", {
66
+ "SEC": 0, # Seconds
67
+ "MSEC": 1 # Milliseconds
68
+ })
69
+
70
+ DISTANCE_UNITS = EnumType("DistanceUnits", {
71
+ "MM": 0, # Millimeters
72
+ "IN": 1 # Inches
73
+ })
74
+
75
+ CURRENT_UNITS = EnumType("CurrentUnits", {
76
+ "AMP": 0 # Amperes
77
+ })
78
+
79
+ TORQUE_UNITS = EnumType("TorqueUnits", {
80
+ "NM": 0, # Newton meters
81
+ "INLB": 1 # Inch pounds
82
+ })
83
+
84
+ TEMPERATURE_UNITS = EnumType("TemperatureUnits", {
85
+ "CELSIUS": 0,
86
+ "FAHRENHEIT": 1
87
+ })
88
+
89
+ ANALOG_UNITS = EnumType("AnalogUnits", {
90
+ "PCT": 0, # Percentage
91
+ "EIGHTBIT": 1, # 8-bit (0-255)
92
+ "TENBIT": 2, # 10-bit (0-1023)
93
+ "TWELVEBIT": 3, # 12-bit (0-4095)
94
+ "MV": 4 # Millivolts
95
+ })
96
+
97
+ # Add more VEX enum types as needed
@@ -0,0 +1,64 @@
1
+ from typing import Optional, List, Dict, Any, Set, TYPE_CHECKING
2
+ from .base import VexType, type_registry
3
+
4
+ # Use TYPE_CHECKING to avoid circular imports
5
+ if TYPE_CHECKING:
6
+ from ..registry.signature import VexFunctionSignature
7
+
8
+ class ObjectType(VexType):
9
+ """Base class for all VEX object types (motors, sensors, etc.)"""
10
+
11
+ def __init__(self, name: str, methods: Dict[str, 'VexFunctionSignature'] = None):
12
+ self._name = name
13
+ self._methods = methods or {}
14
+ type_registry.register_type(self)
15
+
16
+ @property
17
+ def name(self) -> str:
18
+ return self._name
19
+
20
+ @property
21
+ def methods(self) -> Dict[str, Any]: # Use Any instead of forward reference
22
+ return self._methods
23
+
24
+ def add_method(self, method_name: str, signature: Any) -> None: # Use Any instead of forward reference
25
+ """Add a method to this object type"""
26
+ self._methods[method_name] = signature
27
+
28
+ def get_method(self, method_name: str) -> Optional[Any]: # Use Any instead of forward reference
29
+ """Get a method by name"""
30
+ return self._methods.get(method_name)
31
+
32
+ def is_compatible_with(self, other: VexType) -> bool:
33
+ """Objects are compatible only with the same type"""
34
+ return isinstance(other, ObjectType) and self.name == other.name
35
+
36
+ def __str__(self) -> str:
37
+ return self._name
38
+
39
+ # VEX object types - define basic types here, methods will be added later
40
+ MOTOR = ObjectType("Motor")
41
+ MOTOR_GROUP = ObjectType("MotorGroup")
42
+ DRIVETRAIN = ObjectType("Drivetrain")
43
+ BRAIN = ObjectType("Brain")
44
+ CONTROLLER = ObjectType("Controller")
45
+ INERTIAL = ObjectType("Inertial")
46
+ DISTANCE = ObjectType("Distance")
47
+ ROTATION = ObjectType("Rotation")
48
+ OPTICAL = ObjectType("Optical")
49
+ GPS = ObjectType("GPS")
50
+ ELECTROMAGNETIC = ObjectType("Electromagnetic")
51
+ BRAIN_BATTERY = ObjectType("BrainBattery")
52
+ BRAIN_SCREEN = ObjectType("BrainScreen")
53
+ BRAIN_LCD = ObjectType("BrainLcd")
54
+ COMPETITION = ObjectType("Competition")
55
+ TIMER = ObjectType("Timer")
56
+ BUMPER = ObjectType("Bumper")
57
+ LIMIT_SWITCH = ObjectType("LimitSwitch")
58
+ ENCODER = ObjectType("Encoder")
59
+ SONAR = ObjectType("Sonar")
60
+ GYRO = ObjectType("Gyro")
61
+ PNEUMATIC = ObjectType("Pneumatic")
62
+ VISION = ObjectType("Vision")
63
+
64
+ # Add additional object types as needed
@@ -0,0 +1,69 @@
1
+ from typing import Optional, Union, List, Set, Dict, Any
2
+ from .base import VexType, type_registry
3
+
4
+ class PrimitiveType(VexType):
5
+ """Base class for primitive types like int, float, string, etc."""
6
+
7
+ def __init__(self, name: str):
8
+ self._name = name
9
+ type_registry.register_type(self)
10
+
11
+ @property
12
+ def name(self) -> str:
13
+ return self._name
14
+
15
+ def __str__(self) -> str:
16
+ return self._name
17
+
18
+ class NumericType(PrimitiveType):
19
+ """Base class for numeric types"""
20
+
21
+ def is_compatible_with(self, other: VexType) -> bool:
22
+ """Numeric types are compatible with other numeric types"""
23
+ return isinstance(other, NumericType)
24
+
25
+ class IntegerType(NumericType):
26
+ """Integer type"""
27
+
28
+ def __init__(self):
29
+ super().__init__("int")
30
+
31
+ def is_compatible_with(self, other: VexType) -> bool:
32
+ """Integers are compatible with numeric types"""
33
+ return isinstance(other, NumericType)
34
+
35
+ class FloatType(NumericType):
36
+ """Float type"""
37
+
38
+ def __init__(self):
39
+ super().__init__("float")
40
+
41
+ def is_compatible_with(self, other: VexType) -> bool:
42
+ """Floats are compatible with numeric types"""
43
+ return isinstance(other, NumericType)
44
+
45
+ class BooleanType(PrimitiveType):
46
+ """Boolean type"""
47
+
48
+ def __init__(self):
49
+ super().__init__("bool")
50
+
51
+ def is_compatible_with(self, other: VexType) -> bool:
52
+ """Booleans are only compatible with booleans"""
53
+ return isinstance(other, BooleanType)
54
+
55
+ class StringType(PrimitiveType):
56
+ """String type"""
57
+
58
+ def __init__(self):
59
+ super().__init__("string")
60
+
61
+ def is_compatible_with(self, other: VexType) -> bool:
62
+ """Strings are only compatible with strings"""
63
+ return isinstance(other, StringType)
64
+
65
+ # Singleton instances
66
+ INT = IntegerType()
67
+ FLOAT = FloatType()
68
+ BOOL = BooleanType()
69
+ STRING = StringType()
@@ -0,0 +1,32 @@
1
+ from typing import Optional, Any, List, Dict, Union, Tuple
2
+ from .base import VexType, ANY
3
+ from .primitives import INT, FLOAT, BOOL, STRING
4
+
5
+ class TypeChecker:
6
+ """Utility for checking type compatibility"""
7
+
8
+ def is_compatible(self, value_type: VexType, expected_type: VexType) -> bool:
9
+ """Check if value_type is compatible with expected_type"""
10
+ # Any type is compatible with anything
11
+ if expected_type == ANY:
12
+ return True
13
+
14
+ return value_type.is_compatible_with(expected_type)
15
+
16
+ def get_python_type(self, value: Any) -> Optional[VexType]:
17
+ """Convert a Python value to a VEX type"""
18
+ if value is None:
19
+ return None
20
+ if isinstance(value, bool):
21
+ return BOOL
22
+ if isinstance(value, int):
23
+ return INT
24
+ if isinstance(value, float):
25
+ return FLOAT
26
+ if isinstance(value, str):
27
+ return STRING
28
+ # Complex objects would need additional mapping logic
29
+ return None
30
+
31
+ # Singleton instance
32
+ type_checker = TypeChecker()
@@ -0,0 +1,39 @@
1
+ Utilities (vex_ast.utils)
2
+
3
+ This directory contains utility modules that provide supporting functionality for the VEX AST parser and other components.
4
+
5
+ Purpose
6
+
7
+ These modules encapsulate common tasks and data structures needed across the vex_ast package, promoting code reuse and separation of concerns.
8
+
9
+ Modules
10
+
11
+ Error Handling (errors.py):
12
+
13
+ ErrorType: An enum defining categories of errors (e.g., PARSER_ERROR, SEMANTIC_ERROR).
14
+
15
+ Error: A class representing a single error instance, containing the type, message, optional source location, and optional suggestion.
16
+
17
+ ErrorHandler: A central class for collecting and managing errors encountered during parsing or AST processing. It allows registering observers and can optionally raise exceptions immediately upon error detection.
18
+
19
+ VexAstError, VexSyntaxError: Custom exception classes for AST-related errors, with VexSyntaxError specifically for parsing issues.
20
+
21
+ Importance: Provides a robust way to handle and report problems found in the source code or during AST processing, crucial for user feedback and debugging.
22
+
23
+ Source Location (source_location.py):
24
+
25
+ SourceLocation: A dataclass representing a position or span within the original source code file. It includes line and column numbers (and optionally end line/column and filename).
26
+
27
+ Importance: Allows AST nodes and errors to be linked back to their origin in the source code, which is essential for accurate error reporting, debugging tools, and source mapping.
28
+
29
+ Usage
30
+
31
+ These utilities are primarily used internally by other parts of the vex_ast package:
32
+
33
+ The PythonParser uses the ErrorHandler to report syntax errors or issues during AST conversion. It uses SourceLocation to tag generated AST nodes with their origin.
34
+
35
+ AST Node classes store SourceLocation objects.
36
+
37
+ Visitors might use the ErrorHandler if they perform analysis that detects semantic errors.
38
+
39
+ Error messages often include the string representation of a SourceLocation.
vex_ast/utils/__init__.py CHANGED
@@ -0,0 +1,38 @@
1
+ """
2
+ Utilities package for VEX AST.
3
+
4
+ This package provides utility functions and classes for working with the AST.
5
+ """
6
+
7
+ from .errors import (
8
+ ErrorHandler,
9
+ ErrorType,
10
+ VexSyntaxError,
11
+ VexAstError,
12
+ Error
13
+ )
14
+ from .source_location import (
15
+ SourceLocation,
16
+ )
17
+ from .type_definitions import (
18
+ NodeType,
19
+ VisitorType,
20
+ TransformerType
21
+ )
22
+
23
+ __all__ = [
24
+ # Error handling
25
+ "ErrorHandler",
26
+ "ErrorType",
27
+ "VexSyntaxError",
28
+ "VexAstError",
29
+ "Error",
30
+
31
+ # Source location
32
+ "SourceLocation",
33
+
34
+ # Type definitions
35
+ "NodeType",
36
+ "VisitorType",
37
+ "TransformerType"
38
+ ]