def bind_struct_type(base_type: symbols.BasicType, symbol_table: symbols.SymbolTable = None, lineno: int = None): if isinstance(base_type, symbols.StructType): struct_name = base_type.struct_name base_type.set_symbol(symbol_table) if base_type.struct_symbol is None: raise errors.AtomCDomainError(f"Undefined symbol {struct_name}", lineno) if not isinstance(base_type.struct_symbol, symbols.StructSymbol): raise errors.AtomCDomainError(f"{struct_name} is not a struct", lineno)
def add_symbol(self, symbol: Symbol): existing = self._get_symbol_this(symbol.name) if existing: raise errors.AtomCDomainError( "Attempt to redefine existing symbol {} in scope {}".format( existing, self.scope_name), symbol.lineno) physical_storages = (StorageType.GLOBAL, StorageType.LOCAL, StorageType.STRUCT) if symbol.storage == StorageType.ARG: last_arg = next((s for s in reversed(self._symbols.values()) if s.storage == StorageType.ARG), None) # type: Symbol symbol.offset = last_arg.offset - symbol.type.sizeof if last_arg else -TYPE_INT.sizeof - symbol.type.sizeof elif symbol.storage in physical_storages: last_symbol = next((s for s in reversed(self._symbols.values()) if s.storage in physical_storages), None) # type: Symbol if last_symbol and last_symbol.storage != symbol.storage: raise ValueError( f"Mixed storage types in symbol table - {symbol.storage} and {last_symbol.storage}" ) symbol.offset = last_symbol.offset + last_symbol.type.sizeof if last_symbol else 0 self._symbols[symbol.name] = symbol symbol.table = self
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) -> 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.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): if self.current_loop is None: raise errors.AtomCDomainError("break statement outside loop", self.lineno) return True