[docs]classUses:""" Describes uses (including the use location and the use expression) for definitions. """__slots__=("_uses_by_definition","_uses_by_location")
[docs]defadd_use(self,definition:"Definition",codeloc:CodeLocation,expr:Any|None=None):""" Add a use for a given definition. :param definition: The definition that is used. :param codeloc: The code location where the use occurs. :param expr: The expression that uses the specified definition at this location. """self._uses_by_definition=self._uses_by_definition.clean()self._uses_by_definition[definition].add((codeloc,expr))self._uses_by_location=self._uses_by_location.clean()self._uses_by_location[codeloc].add((definition,expr))
[docs]defget_uses(self,definition:"Definition")->set[CodeLocation]:""" Retrieve the uses of a given definition. :param definition: The definition for which we get the uses. """return{codelocforcodeloc,_inself._uses_by_definition.get(definition,set())}
[docs]defget_uses_with_expr(self,definition:"Definition")->set[tuple[CodeLocation,Any|None]]:""" Retrieve the uses and the corresponding expressions of a given definition. :param definition: The definition for which we get the uses and the corresponding expressions. """returnself._uses_by_definition.get(definition,set())
[docs]defremove_use(self,definition:"Definition",codeloc:"CodeLocation",expr:Any|None=None)->None:""" Remove one use of a given definition. :param definition: The definition of which to remove the uses. :param codeloc: The code location where the use is. :param expr: The expression that uses the definition at the given location. :return: None """ifdefinitioninself._uses_by_definition:ifcodelocinself._uses_by_definition[definition]:self._uses_by_definition=self._uses_by_definition.clean()ifexprisNone:forcodeloc_,expr_inlist(self._uses_by_definition[definition]):ifcodeloc_==codeloc:self._uses_by_definition[definition].remove((codeloc_,expr_))else:self._uses_by_definition[definition].remove((codeloc,expr))ifcodelocinself._uses_by_location:self._uses_by_location=self._uses_by_location.clean()foriteminlist(self._uses_by_location[codeloc]):ifitem[0]==definition:self._uses_by_location[codeloc].remove(item)
[docs]defremove_uses(self,definition:"Definition"):""" Remove all uses of a given definition. :param definition: The definition of which to remove the uses. :return: None """ifdefinitioninself._uses_by_definition:self._uses_by_definition=self._uses_by_definition.clean()codeloc_and_ids=self._uses_by_definition[definition]delself._uses_by_definition[definition]self._uses_by_location=self._uses_by_location.clean()forcodeloc,_incodeloc_and_ids:foriteminlist(self._uses_by_location[codeloc]):ifitem[0]==definition:self._uses_by_location[codeloc].remove(item)
[docs]defget_uses_by_location(self,codeloc:CodeLocation,exprs:bool=False)->set["Definition"]|set[tuple["Definition",Any|None]]:""" Retrieve all definitions that are used at a given location. :param codeloc: The code location. :return: A set of definitions that are used at the given location. """ifexprs:returnself._uses_by_location.get(codeloc,set())return{item[0]foriteminself._uses_by_location.get(codeloc,set())}
[docs]defget_uses_by_insaddr(self,ins_addr:int,exprs:bool=False)->set["Definition"]|set[tuple["Definition",Any|None]]:""" Retrieve all definitions that are used at a given location specified by the instruction address. :param ins_addr: The instruction address. :return: A set of definitions that are used at the given location. """all_uses=set()forcodeloc,usesinself._uses_by_location.items():ifcodeloc.ins_addr==ins_addr:all_uses|=usesifexprs:returnall_usesreturn{item[0]foriteminall_uses}
[docs]defcopy(self)->"Uses":""" Copy the instance. :return: Return a new <Uses> instance containing the same data. """u=Uses(uses_by_definition=self._uses_by_definition.copy(),uses_by_location=self._uses_by_location.copy(),)returnu
[docs]defmerge(self,other:"Uses")->bool:""" Merge an instance of <Uses> into the current instance. :param other: The other <Uses> from which the data will be added to the current instance. :return: True if any merge occurred, False otherwise """merge_occurred=Falsefork,vinother._uses_by_definition.items():ifknotinself._uses_by_definition:self._uses_by_definition=self._uses_by_definition.clean()self._uses_by_definition[k]=vmerge_occurred=Trueelifnotv.issubset(self._uses_by_definition[k]):merge_occurred=Trueself._uses_by_definition=self._uses_by_definition.clean()self._uses_by_definition[k]=self._uses_by_definition[k]|vfork,vinother._uses_by_location.items():ifknotinself._uses_by_location:self._uses_by_location=self._uses_by_location.clean()self._uses_by_location[k]=vmerge_occurred=Trueelifnotv.issubset(self._uses_by_location[k]):merge_occurred=Trueself._uses_by_location=self._uses_by_location.clean()self._uses_by_location[k]=self._uses_by_location[k]|vreturnmerge_occurred