예제 #1
0
파일: runner.py 프로젝트: radwasherif/Lyra
 def variables(self) -> Set[VariableIdentifier]:
     variables = set()
     visited, worklist = set(), Queue()
     worklist.put(self.cfg.in_node)
     while not worklist.empty():
         current = worklist.get()
         if current.identifier not in visited:
             visited.add(current.identifier)
             for stmt in current.stmts:
                 if isinstance(stmt, Assignment) and isinstance(stmt.left, VariableAccess):
                     variable = stmt.left.variable
                     variables.add(variable)
                     if isinstance(variable.typ, (StringLyraType, ListLyraType)):
                         variables.add(LengthIdentifier(variable))
             if isinstance(current, Loop):
                 edges = self.cfg.edges.items()
                 conds = [edge.condition for nodes, edge in edges if nodes[0] == current]
                 for cond in [c for c in conds if isinstance(c, Call)]:
                     for arg in [a for a in cond.arguments if isinstance(a, VariableAccess)]:
                         variable = arg.variable
                         variables.add(arg.variable)
                         if isinstance(variable.typ, (StringLyraType, ListLyraType)):
                             variables.add(LengthIdentifier(variable))
             for node in self.cfg.successors(current):
                 worklist.put(node)
     return variables
예제 #2
0
 def visit_Literal(self, expr, state=None, evaluation=None):
     if expr in evaluation:
         return evaluation
     evaluation[expr] = state.lattices[expr.typ].from_literal(expr)
     if isinstance(expr.typ, StringLyraType):
         evaluation[LengthIdentifier(expr)] = IntervalLattice(len(expr.val), len(expr.val))
     return evaluation
예제 #3
0
 def forget_variable(self, var: VariableIdentifier):
     if var in self.store.keys():
         self.store[var].top()
         if isinstance(var.typ, SequenceLyraType):
             length = LengthIdentifier(var)
             self.store[length] = IntervalLattice(lower=0)
     else:
         raise ValueError(
             f"Variable can only be forgotten if it is abstracted in the store"
         )
예제 #4
0
    def __init__(self, variables: Set[VariableIdentifier], precursory: InputMixin = None):
        """Map each program variable to the interval representing its value.

        :param variables: set of program variables
        """
        lattices = defaultdict(lambda: RangeLattice)
        super(IntervalStateWithSummarization, self).__init__(variables, lattices)
        InputMixin.__init__(self, precursory)
        for v in self.variables:
            if isinstance(v.typ, SequenceLyraType):
                self.lengths[LengthIdentifier(v)] = lattices[IntegerLyraType()](lower=0)
예제 #5
0
 def remove_variable(self, var: VariableIdentifier):
     if var in self.store.keys():
         self.variables.remove(var)
         del self.store[var]
         if isinstance(var.typ, SequenceLyraType):
             length = LengthIdentifier(var)
             self.variables.remove(length)
             del self.store[length]
     else:
         raise ValueError(
             f"Variable can only be removed from a store if it is already present"
         )
예제 #6
0
 def add_variable(self, var: VariableIdentifier):
     if var not in self.store.keys():
         self.variables.add(var)
         self.store[var] = IntervalLattice()  # top
         if isinstance(var.typ, SequenceLyraType):
             length = LengthIdentifier(var)
             self.variables.add(length)
             self.store[length] = IntervalLattice(lower=0)
     else:
         raise ValueError(
             f"Variable can not be added to a store if it is already present"
         )
예제 #7
0
    def len_call_semantics(self, stmt: Call, state: State) -> State:
        """Semantics of a call to 'len'.

        :param stmt: call to 'len' to be executed
        :param state: state before executing the call statement
        :return: state modified by the call statement
        """
        assert len(stmt.arguments) == 1  # unary operations have exactly one argument
        argument = stmt.arguments[0]
        if isinstance(argument, VariableAccess):
            variable = argument.variable
            state.result = {LengthIdentifier(variable)}
            return state
        error = f"Semantics for length of {argument} is not yet implemented!"
        raise NotImplementedError(error)
예제 #8
0
 def visit_LengthIdentifier(self, expr: LengthIdentifier):
     return LengthIdentifier(expr.variable)
예제 #9
0
    def len_call_semantics(self, stmt: Call, state: State,
                           interpreter: Interpreter) -> State:
        """Semantics of a call to 'len'.

        :param stmt: call to 'len' to be executed
        :param state: state before executing the call statement
        :return: state modified by the call statement
        """
        assert len(
            stmt.arguments) == 1  # unary operations have exactly one argument
        argument = stmt.arguments[0]
        if isinstance(argument, VariableAccess):
            variable = argument.variable
            state.result = {LengthIdentifier(variable)}
            return state
        elif isinstance(argument, ListDisplayAccess):
            items = [
                self.semantics(item, state, interpreter).result
                for item in argument.items
            ]
            result = set()
            for combination in itertools.product(*items):
                display = ListDisplay(argument.typ, list(combination))
                result.add(LengthIdentifier(display))
            state.result = result
            return state
        elif isinstance(argument, TupleDisplayAccess):
            items = [
                self.semantics(item, state, interpreter).result
                for item in argument.items
            ]
            result = set()
            for combination in itertools.product(*items):
                display = TupleDisplay(argument.typ, list(combination))
                result.add(LengthIdentifier(display))
            state.result = result
            return state
        elif isinstance(argument, SetDisplayAccess):
            items = [
                self.semantics(item, state, interpreter).result
                for item in argument.items
            ]
            result = set()
            for combination in itertools.product(*items):
                display = SetDisplay(argument.typ, list(combination))
                result.add(LengthIdentifier(display))
            state.result = result
            return state
        elif isinstance(argument, DictDisplayAccess):
            keys = [
                self.semantics(k, state, interpreter).result
                for k in argument.keys
            ]
            values = [
                self.semantics(v, state, interpreter).result
                for v in argument.values
            ]
            result = set()
            if keys:  # not empty List[Set[Expression]]
                for combination in itertools.product(
                        *map(itertools.product, keys, values)):
                    unzip = list(zip(*combination))
                    display = DictDisplay(argument.typ, list(unzip[0]),
                                          list(unzip[1]))
                    result.add(LengthIdentifier(display))
            else:
                result.add(
                    LengthIdentifier(DictDisplay(argument.typ, list(),
                                                 list())))
            state.result = result
            return state
        error = f"Semantics for length of {argument} is not yet implemented!"
        raise NotImplementedError(error)