def check_return_type(function: FunctionDefinition, result, context): if str(function.return_type) == 'void' and result.type_ is not None: raise RunTimeError( function.return_type.pos_start, f'Expected return type: {str(function.return_type)} got {result.type_}', context) elif result.type_ != str(function.return_type.type): raise RunTimeError( function.return_type.pos_start, f'Expected return type: {str(function.return_type)} got {result.type_}', context)
def _verify_assignment(self, variable_name: ValueToken, value, expected_type): self._check_type_match(expected_type, value) if expected_type is None: current_value = self.get_variable(variable_name) if not current_value: raise RunTimeError(variable_name.pos_start, 'This variable has not been defined yet. Put a type.', self.current_context) if current_value.type_ != value.type_: raise RunTimeError(value.pos_start, f'Tried to put a value of type {value.type_}' f' to a variable of type {current_value.type_}', self.current_context)
def divide(self, other): if isinstance(other, Number): if other.value == 0: raise RunTimeError(other.pos_start, 'Division by zero.', self.context) return DoubleValue(self.value / other.value, context=self.context) else: raise self._raise_runtime_error_for_action('/', other)
def check_arguments_amount(function: FunctionDefinition, actual_arguments, context): if len(actual_arguments) != len(function.argument_definitions): raise RunTimeError( function.pos_start, f'Wrong amount of arguments. Expected: {len(function.argument_definitions)}.' f' Got: {len(actual_arguments)}', context)
def check_argument_types(function: FunctionDefinition, actual_arguments, context): for argument, defined_argument in zip(actual_arguments, function.argument_definitions): if argument.type_ != defined_argument.type: raise RunTimeError( function.pos_start, f'Wrong type of argument. Expected {defined_argument.type} ' f'got: {argument.type_}', context)
def add(self, other): if isinstance(other, PhysValue): if self.unit.is_equal(other.unit): sum = self.value.add(other.value) return PhysValue(sum, self.unit, self.pos_start, other.pos_end, context=self.context) else: raise RunTimeError(self.pos_start, f"Tried to add Phys with units: {self.unit}, {other.unit}", self.context) else: raise self._raise_runtime_error_for_action('+', other)
def subtract(self, other): if isinstance(other, PhysValue): if self.unit.is_equal(other.unit): difference = self.value.subtract(other.value) return PhysValue(difference, self.unit, self.pos_start, other.pos_end, context=self.context) else: raise RunTimeError(self.pos_start, f"Tried to subtract Phys with units: {self.unit}, {other.unit}", self.context) else: raise self._raise_runtime_error_for_action('-', other)
def not_(self): raise RunTimeError(self.pos_start, f"'not' not defined for type: {self.type_}", self.context)
def _raise_runtime_error_for_action(self, operator, other): raise RunTimeError(self.pos_start, f'{operator} not defined for type {self.type_} and {other.type_}', self.context)
def _check_type_match(self, expected_type, actual_value): if expected_type and actual_value and not actual_value.type_ == str(expected_type): raise RunTimeError(expected_type.pos_start, f'Expected type: {str(expected_type)} got {actual_value.type_} instead.', self.current_context)
def switch_to_parent_context(self): if not self.current_context.parent: raise RunTimeError(self.current_context.position, f'No parent for context: {self.current_context.name}', self) self.current_context = self.current_context.parent
def get_variable(self, variable_name: ValueToken): variable = self.symbol_table.get(variable_name.value) if variable is None: raise RunTimeError(variable_name.pos_start, f'{variable_name.value} not defined.', self) return variable