def resolve_type(base_type: symbols.BasicType, is_array: bool, array_size_expr: 'tree.ExpressionNode' = None, lineno: int = None): real_type = base_type if is_array: if base_type == symbols.TYPE_VOID: raise errors.AtomCTypeError("array of type void", lineno) array_size = None if array_size_expr: if not array_size_expr.is_const(): raise errors.AtomCTypeError( "array size must be a constant expression", array_size_expr.lineno) if array_size_expr.type != symbols.TYPE_INT: raise errors.AtomCTypeError( "array size must be an integer expression", array_size_expr.lineno) array_size = array_size_expr.calculate_const() if array_size <= 0: raise errors.AtomCTypeError( "array size must be strictly positive", array_size_expr.lineno) real_type = symbols.ArrayType(base_type, array_size) return real_type
def _on_validate(self): if not self.operand_left.is_lval(): raise errors.AtomCTypeError( f"assignment requires lvalue as left operand; {self.operand_left} is not an lvalue", self.lineno) implicit_cast_error = typecheck.check_cast_implicit( self.operand_right.type, self.operand_left.type) if implicit_cast_error: raise errors.AtomCTypeError( f"invalid assignment - {implicit_cast_error}", self.lineno) return True
def _on_validate(self) -> bool: array_type = self.array_variable.type if not isinstance(array_type, symbols.ArrayType): raise errors.AtomCTypeError( "Subscript operator [] applied to non-array expression", self.lineno) if typecheck.check_cast_implicit(self.index_expression.type, symbols.TYPE_INT): raise errors.AtomCTypeError( "Array index expression must be of integer type", self.lineno) return True
def _on_validate(self): left_type = self.operand_left.type right_type = self.operand_left.type if not typecheck.is_numeric(left_type): raise errors.AtomCTypeError( "logical comparison operators can only be applied to numeric types", self.lineno) if not typecheck.is_numeric(right_type): raise errors.AtomCTypeError( "logical comparison operators can only be applied to numeric types", self.lineno) return True
def _on_validate(self): if self.return_type != symbols.TYPE_VOID and not any( isinstance(child, ReturnStatementNode) for child in self._children): raise errors.AtomCTypeError( "missing return from non-void function", self.lineno) return True
def _on_validate(self): condition_type = self.condition.type if not typecheck.is_numeric(condition_type): raise errors.AtomCTypeError( f"expression of type {condition_type} cannot be used as a logical test", self.condition.lineno) return True
def _on_validate(self): operand_type = self.operand.type if not typecheck.is_numeric(operand_type): raise errors.AtomCTypeError( "arithmetic operators can only be applied to numeric types", self.lineno) return True
def _get_type(self) -> symbols.SymbolType: if not typecheck.is_numeric( self.operand_left.type) or not typecheck.is_numeric( self.operand_right.type): raise errors.AtomCTypeError( "Arithmetic expressions only support numeric operands", self.lineno) return typecheck.greatest_type(self.operand_left.type, self.operand_left.type)
def _on_validate(self): operand_type = self.operand.type if not typecheck.is_numeric(operand_type) and not isinstance( operand_type, symbols.ArrayType): raise errors.AtomCTypeError( "logical operators can only be applied to numeric and array types", self.lineno) return True
def _on_validate(self) -> bool: var = self.symbol_table.get_symbol(self.symbol_name) if var is None: raise errors.AtomCDomainError( f"undefined variable {self.symbol_name}", self.lineno) if not isinstance(var, symbols.VariableSymbol): raise errors.AtomCTypeError( f"symbol {var} cannot be used as a value", self.lineno) return True
def _on_validate(self): if self.current_function is None: raise errors.AtomCDomainError("return statement outside function", self.lineno) if self.value is None and self.current_function.return_type != symbols.TYPE_VOID: raise errors.AtomCTypeError("void return in non-void function", self.lineno) if self.value is not None: if self.current_function.return_type == symbols.TYPE_VOID: raise errors.AtomCTypeError("non-void return in void function", self.lineno) implicit_cast_error = typecheck.check_cast_implicit( self.value.type, self.current_function.return_type) if implicit_cast_error: raise errors.AtomCTypeError( f"bad return type - {implicit_cast_error}", self.lineno) return True
def _on_validate(self) -> bool: function_symbol = self.symbol_table.get_symbol(self.function_name) if function_symbol is None: raise errors.AtomCDomainError( f"undefined function {self.function_name}", self.lineno) if not isinstance(function_symbol, symbols.FunctionSymbol): raise errors.AtomCDomainError( f"{self.function_name} is not a function", self.lineno) if len(self.args) != len(function_symbol.args): raise errors.AtomCTypeError( f"not enough arguments in call to function {self.function_name}", self.lineno) for narg, (arg_value, arg_def) in enumerate(zip(self.args, function_symbol.args)): implicit_cast_error = typecheck.check_cast_implicit( arg_value.type, arg_def.type) if implicit_cast_error: raise errors.AtomCTypeError( f"in call to {self.function_name} - argument {narg} type mismatch; {implicit_cast_error}", self.lineno) return True
def _on_validate(self): struct_type = self.struct_variable.type if isinstance(struct_type, symbols.StructType): struct_symbol = struct_type.struct_symbol member_symbol = struct_symbol.get_member_symbol(self.member_name) if member_symbol is None: raise errors.AtomCDomainError( f"struct {struct_symbol.name} has no field named {self.member_name}", self.lineno) return member_symbol.type else: raise errors.AtomCTypeError( "Dot notation member access requires a struct as left operand", self.lineno)
def _on_validate(self): if self.base_type == symbols.TYPE_VOID: raise errors.AtomCTypeError( "Cannot declare variables of type void", self.lineno) return True
def _on_validate(self): explicit_cast_error = typecheck.check_cast_explicit( self.cast_expr.type, self.type) if explicit_cast_error: raise errors.AtomCTypeError(explicit_cast_error, self.lineno) return True