def combine_states(self, left, right): state = State(left.name, [left], left.type, 'branch', self.locate(), read=left.read, set=left.set, over=left.over, over_position=left.over_position) if right is None: state.read = 'no' if left.read == 'no' else 'maybe' state.set = 'no' if left.set == 'no' else 'maybe' state.over = 'no' if left.over == 'no' else 'maybe' else: if not are_types_equal(left.type, right.type): self.report_issue("Type changes", { 'name': left.name, 'old': left.type, 'new': right.type }) state.read = Tifa.match_rso(left.read, right.read) state.set = Tifa.match_rso(left.set, right.set) state.over = Tifa.match_rso(left.over, right.over) if left.over == 'no': state.over_position = right.over_position state.trace.append(right) return state
def combine_states(self, left, right): """ Args: left: right: Returns: """ state = State(left.name, [left], left.type, 'branch', self.locate(), read=left.read, set=left.set, over=left.over, over_position=left.over_position) if right is None: state.read = 'no' if left.read == 'no' else 'maybe' state.set = 'no' if left.set == 'no' else 'maybe' state.over = 'no' if left.over == 'no' else 'maybe' else: if not are_types_equal(left.type, right.type): self._issue(type_changes(self.locate(), left.name, left.type, right.type)) state.read = self.match_rso(left.read, right.read) state.set = self.match_rso(left.set, right.set) state.over = self.match_rso(left.over, right.over) if left.over == 'no': state.over_position = right.over_position state.trace.append(right) return state
def load_variable(self, name, position=None): """ Retrieve the variable with the given name. Args: position: name (str): The unqualified name of the variable. If the variable is not found in the current scope or an enclosing scope, all other scopes will be searched to see if it was read out of scope. Returns: State: The current state of the variable. """ full_name = self._scope_chain_str(name) current_path = self.path_chain[0] variable = self.find_variable_scope(name) if position is None: position = self.locate() if not variable.exists: out_of_scope_var = self.find_variable_out_of_scope(name) # Create a new instance of the variable on the current path if out_of_scope_var.exists: self._issue(read_out_of_scope(self.locate(), name)) else: self._issue(initialization_problem(self.locate(), name)) new_state = State(name, [], UnknownType(), 'load', position, read='yes', set='no', over='no') self.name_map[current_path][full_name] = new_state else: new_state = self.trace_state(variable.state, "load", position) if variable.state.set == 'no': self._issue(initialization_problem(self.locate(), name)) if variable.state.set == 'maybe': if name != '*return': self._issue( possible_initialization_problem(self.locate(), name)) new_state.read = 'yes' if not variable.in_scope: self.name_map[current_path][variable.scoped_name] = new_state else: self.name_map[current_path][full_name] = new_state return new_state
def store_variable(self, name, store_type, position=None, force_create=False): """ Update the variable with the given name to now have the new type. Args: name (str): The unqualified name of the variable. The variable will be assumed to be in the current scope. store_type (Type): The new type of this variable. position: The location that this store occurred at Returns: State: The new state of the variable. """ if position is None: position = self.locate() full_name = self._scope_chain_str(name) current_path = self.path_chain[0] variable = self.find_variable_scope(name) if not variable.exists or force_create: # Create a new instance of the variable on the current path new_state = State(name, [], store_type, 'store', position, read='no', set='yes', over='no') self.name_map[current_path][full_name] = new_state else: new_state = self.trace_state(variable.state, "store", position) if not variable.in_scope: self._issue( write_out_of_scope(self.locate(), name, report=self.report)) # Type change? if not are_types_equal(store_type, variable.state.type): self._issue( type_changes(position, name, variable.state.type, store_type)) new_state.type = store_type # Overwritten? if variable.state.set == 'yes' and variable.state.read == 'no': new_state.over_position = position new_state.over = 'yes' else: new_state.set = 'yes' new_state.read = 'no' self.name_map[current_path][full_name] = new_state # If this is a class scope... current_scope = self.scope_chain[0] if current_scope in self.class_scopes: self.class_scopes[current_scope].add_attr(name, new_state.type) return new_state
def load_variable(self, name, position=None): """ Retrieve the variable with the given name. Args: name (str): The unqualified name of the variable. If the variable is not found in the current scope or an enclosing sope, all other scopes will be searched to see if it was read out of scope. Returns: State: The current state of the variable. """ full_name = self._scope_chain_str(name) current_path = self.path_chain[0] variable = self.find_variable_scope(name) if position is None: position = self.locate() if not variable.exists: out_of_scope_var = self.find_variable_out_of_scope(name) # Create a new instance of the variable on the current path if out_of_scope_var.exists: self.report_issue("Read out of scope", {'name': name}) else: self.report_issue("Initialization Problem", {'name': name}) new_state = State(name, [], UnknownType(), 'load', position, read='yes', set='no', over='no') self.name_map[current_path][full_name] = new_state else: new_state = self.trace_state(variable.state, "load", position) if variable.state.set == 'no': self.report_issue("Initialization Problem", {'name': name}) if variable.state.set == 'maybe': self.report_issue("Possible Initialization Problem", {'name': name}) new_state.read = 'yes' if not variable.in_scope: self.name_map[current_path][variable.scoped_name] = new_state else: self.name_map[current_path][full_name] = new_state return new_state
def store_variable(self, name, type, position=None): ''' Update the variable with the given name to now have the new type. Args: name (str): The unqualified name of the variable. The variable will be assumed to be in the current scope. type (Type): The new type of this variable. Returns: State: The new state of the variable. ''' if position is None: position = self.locate() full_name = self._scope_chain_str(name) current_path = self.path_chain[0] variable = self.find_variable_scope(name) if not variable.exists: # Create a new instance of the variable on the current path new_state = State(name, [], type, 'store', position, read='no', set='yes', over='no') self.name_map[current_path][full_name] = new_state else: new_state = self.trace_state(variable.state, "store", position) if not variable.in_scope: self.report_issue("Write out of scope", {'name': name}) # Type change? if not are_types_equal(type, variable.state.type): self.report_issue( "Type changes", { 'name': name, 'old': variable.state.type, 'new': type, 'position': position }) new_state.type = type # Overwritten? if variable.state.set == 'yes' and variable.state.read == 'no': new_state.over_position = position new_state.over = 'yes' else: new_state.set = 'yes' new_state.read = 'no' self.name_map[current_path][full_name] = new_state return new_state
def combine_states(self, left, right): state = State(left.name, [left], left.type, 'branch', self.locate(), read=left.read, set=left.set, over=left.over, over_position=left.over_position) if right is None: state.read = 'no' if left.read == 'no' else 'maybe' state.set = 'no' if left.set == 'no' else 'maybe' state.over = 'no' if left.over == 'no' else 'maybe' else: if not are_types_equal(left.type, right.type): self.report_issue("Type changes", {'name': left.name, 'old': left.type, 'new': right.type}) state.read = Tifa.match_rso(left.read, right.read) state.set = Tifa.match_rso(left.set, right.set) state.over = Tifa.match_rso(left.over, right.over) if left.over == 'no': state.over_position = right.over_position state.trace.append(right) return state
def store_variable(self, name, type, position=None): """ Update the variable with the given name to now have the new type. Args: name (str): The unqualified name of the variable. The variable will be assumed to be in the current scope. type (Type): The new type of this variable. Returns: State: The new state of the variable. """ if position is None: position = self.locate() full_name = self._scope_chain_str(name) current_path = self.path_chain[0] variable = self.find_variable_scope(name) if not variable.exists: # Create a new instance of the variable on the current path new_state = State(name, [], type, 'store', position, read='no', set='yes', over='no') self.name_map[current_path][full_name] = new_state else: new_state = self.trace_state(variable.state, "store", position) if not variable.in_scope: self.report_issue("Write out of scope", {'name': name}) # Type change? if not are_types_equal(type, variable.state.type): self.report_issue("Type changes", {'name': name, 'old': variable.state.type, 'new': type, 'position': position}) new_state.type = type # Overwritten? if variable.state.set == 'yes' and variable.state.read == 'no': new_state.over_position = position new_state.over = 'yes' else: new_state.set = 'yes' new_state.read = 'no' self.name_map[current_path][full_name] = new_state # If this is a class scope... current_scope = self.scope_chain[0] if current_scope in self.class_scopes: self.class_scopes[current_scope].add_attr(name, new_state.type) return new_state