def is_top(self) -> bool: """The current store is top if `all` of its variables map to a top element.""" _store = all(element.is_top() for element in self.store.values()) _top = IntervalLattice(lower=0) _lengths = all( _top.less_equal(element) for element in self.lengths.values()) return _store and _lengths
def test_neg(self): self.assertEqual(IntervalLattice().neg(), IntervalLattice()) self.assertEqual(IntervalLattice(0, 1).neg(), IntervalLattice(-1, 0)) self.assertEqual( IntervalLattice(upper=2).neg(), IntervalLattice(lower=-2)) self.assertEqual( IntervalLattice(lower=3).neg(), IntervalLattice(upper=-3)) self.assertEqual(IntervalLattice(1, 0).neg(), IntervalLattice(1, 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" )
def test_init(self): self.assertFalse(IntervalLattice().is_bottom()) self.assertTrue(IntervalLattice().is_top()) self.assertFalse(IntervalLattice(0, 1).is_bottom()) self.assertFalse(IntervalLattice(0, 1).is_top()) self.assertEqual(IntervalLattice(upper=2), IntervalLattice(-inf, 2)) self.assertEqual(IntervalLattice(lower=3), IntervalLattice(3, inf)) self.assertTrue(IntervalLattice(1, 0).is_bottom()) self.assertFalse(IntervalLattice(1, 0).is_top())
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
def __init__(self, variables: Set[VariableIdentifier], lattices: Dict[LyraType, Type[Lattice]], arguments: Dict[LyraType, Dict[str, Any]] = None): """Create a mapping Var -> L from each variable in Var to the corresponding element in L. :param variables: set of program variables :param lattices: dictionary from variable types to the corresponding lattice types :param arguments: dictionary from variable types to arguments of the corresponding lattices """ super().__init__() self._variables = variables self._lattices = lattices self._arguments = defaultdict( lambda: dict()) if arguments is None else arguments try: self._store = { v: lattices[v.typ](**self._arguments[v.typ]) for v in variables } self._lengths, self._keys, self._values = dict(), dict(), dict() for v in variables: if v.has_length: self._lengths[v.length] = IntervalLattice(lower=0) if v.is_dictionary: _key = lattices[v.typ.key_typ]( **self._arguments[v.typ.key_typ]) self._keys[v.keys] = _key _value = lattices[v.typ.val_typ]( **self._arguments[v.typ.val_typ]) self._values[v.values] = _value except KeyError as key: error = f"Missing lattice for variable type {repr(key.args[0])}!" raise ValueError(error)
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" )
def top(self) -> 'Store': for var in self.store: self.store[var].top() for var in self.lengths: self.lengths[var] = IntervalLattice(lower=0) for var in self.keys: self.keys[var].top() for var in self.values: self.values[var].top() return self
def decomp(self, exclude: 'IntervalKWrapper') \ -> Set['IntervalKWrapper']: left = deepcopy(self) # left & right non-exclude right = deepcopy(self) k_state = self.store[self.k_var] k_exclude = exclude.store[self.k_var] if k_state.is_bottom(): left.store[self.k_var].bottom() right.store[self.k_var].bottom() elif k_exclude.is_bottom(): left.store[self.k_var] = IntervalLattice(k_state.lower, k_state.upper) right.store[self.k_var].bottom() elif k_exclude.is_top(): # exclude everything left.store[self.k_var].bottom() right.store[self.k_var].bottom() else: left.store[self.k_var] = IntervalLattice( k_state.lower, k_exclude.lower - 1) # bottom if empty right.store[self.k_var] = IntervalLattice( k_exclude.upper + 1, k_state.upper) # bottom if empty return {left, right}
def add_variable(self, variable: VariableIdentifier): self.variables.add(variable) typ = variable.typ self.store[variable] = self.lattices[typ]( **self.arguments[typ]).bottom() if variable.has_length: self.lengths[variable.length] = IntervalLattice(lower=0).bottom() if variable.is_dictionary: _key = self.lattices[typ.key_typ]( **self._arguments[typ.key_typ]).bottom() self._keys[variable.keys] = _key _value = self.lattices[typ.val_typ]( **self._arguments[typ.val_typ]).bottom() self._values[variable.values] = _value return self
def test_widening(self): self.assertEqual(IntervalLattice().widening(IntervalLattice(0, 1)), IntervalLattice()) self.assertEqual(IntervalLattice().widening(IntervalLattice(1, 0)), IntervalLattice()) self.assertEqual( IntervalLattice(0, 1).widening(IntervalLattice()), IntervalLattice()) widening1 = IntervalLattice(0, 1).widening(IntervalLattice(1, 0)) self.assertEqual(widening1, IntervalLattice(0, 1)) self.assertEqual( IntervalLattice(1, 0).widening(IntervalLattice()), IntervalLattice()) widening2 = IntervalLattice(1, 0).widening(IntervalLattice(0, 1)) self.assertEqual(widening2, IntervalLattice(0, 1)) widening3 = IntervalLattice(upper=3).widening(IntervalLattice(lower=2)) self.assertEqual(widening3, IntervalLattice()) widening4 = IntervalLattice(2, 4).widening(IntervalLattice(1, 3)) self.assertEqual(widening4, IntervalLattice(upper=4)) widening5 = IntervalLattice(1, 2).widening(IntervalLattice(3, 4)) self.assertEqual(widening5, IntervalLattice(lower=1))
def test_meet(self): self.assertEqual(IntervalLattice().meet(IntervalLattice(0, 1)), IntervalLattice(0, 1)) self.assertEqual(IntervalLattice().meet(IntervalLattice(1, 0)), IntervalLattice(1, 0)) self.assertEqual( IntervalLattice(0, 1).meet(IntervalLattice()), IntervalLattice(0, 1)) self.assertEqual( IntervalLattice(0, 1).meet(IntervalLattice(1, 0)), IntervalLattice(1, 0)) self.assertEqual( IntervalLattice(1, 0).meet(IntervalLattice()), IntervalLattice(1, 0)) self.assertEqual( IntervalLattice(1, 0).meet(IntervalLattice(0, 1)), IntervalLattice(1, 0)) meet = IntervalLattice(upper=3).meet(IntervalLattice(lower=2)) self.assertEqual(meet, IntervalLattice(2, 3)) self.assertEqual( IntervalLattice(2, 4).meet(IntervalLattice(1, 3)), IntervalLattice(2, 3)) self.assertEqual( IntervalLattice(1, 2).meet(IntervalLattice(3, 4)), IntervalLattice(1, 0))
def test_join(self): self.assertEqual(IntervalLattice().join(IntervalLattice(0, 1)), IntervalLattice()) self.assertEqual(IntervalLattice().join(IntervalLattice(1, 0)), IntervalLattice()) self.assertEqual( IntervalLattice(0, 1).join(IntervalLattice()), IntervalLattice()) self.assertEqual( IntervalLattice(0, 1).join(IntervalLattice(1, 0)), IntervalLattice(0, 1)) self.assertEqual( IntervalLattice(1, 0).join(IntervalLattice()), IntervalLattice()) self.assertEqual( IntervalLattice(1, 0).join(IntervalLattice(0, 1)), IntervalLattice(0, 1)) join = IntervalLattice(upper=3).join(IntervalLattice(lower=2)) self.assertEqual(join, IntervalLattice()) self.assertEqual( IntervalLattice(2, 4).join(IntervalLattice(1, 3)), IntervalLattice(1, 4)) self.assertEqual( IntervalLattice(1, 2).join(IntervalLattice(3, 4)), IntervalLattice(1, 4))
def test_leq(self): self.assertFalse(IntervalLattice().less_equal(IntervalLattice(0, 1))) self.assertFalse(IntervalLattice().less_equal(IntervalLattice(1, 0))) self.assertTrue(IntervalLattice(0, 1).less_equal(IntervalLattice())) self.assertFalse( IntervalLattice(0, 1).less_equal(IntervalLattice(1, 0))) self.assertTrue(IntervalLattice(1, 0).less_equal(IntervalLattice())) self.assertTrue( IntervalLattice(1, 0).less_equal(IntervalLattice(0, 1)))
def test_sub(self): self.assertEqual(IntervalLattice().sub(IntervalLattice(0, 1)), IntervalLattice()) self.assertEqual(IntervalLattice().sub(IntervalLattice(1, 0)), IntervalLattice(1, 0)) self.assertEqual( IntervalLattice(0, 1).sub(IntervalLattice()), IntervalLattice()) self.assertEqual( IntervalLattice(0, 1).sub(IntervalLattice(1, 0)), IntervalLattice(1, 0)) self.assertEqual( IntervalLattice(1, 0).sub(IntervalLattice()), IntervalLattice(1, 0)) self.assertEqual( IntervalLattice(1, 0).sub(IntervalLattice(0, 1)), IntervalLattice(1, 0)) sub = IntervalLattice(upper=3).sub(IntervalLattice(lower=2)) self.assertEqual(sub, IntervalLattice(upper=1)) self.assertEqual( IntervalLattice(2, 4).sub(IntervalLattice(1, 3)), IntervalLattice(-1, 3)) self.assertEqual( IntervalLattice(1, 2).sub(IntervalLattice(3, 4)), IntervalLattice(-3, -1))
def test_add(self): self.assertEqual(IntervalLattice().add(IntervalLattice(0, 1)), IntervalLattice()) self.assertEqual(IntervalLattice().add(IntervalLattice(1, 0)), IntervalLattice(1, 0)) self.assertEqual( IntervalLattice(0, 1).add(IntervalLattice()), IntervalLattice()) self.assertEqual( IntervalLattice(0, 1).add(IntervalLattice(1, 0)), IntervalLattice(1, 0)) self.assertEqual( IntervalLattice(1, 0).add(IntervalLattice()), IntervalLattice(1, 0)) self.assertEqual( IntervalLattice(1, 0).add(IntervalLattice(0, 1)), IntervalLattice(1, 0)) self.assertEqual( IntervalLattice(upper=3).add(IntervalLattice(lower=2)), IntervalLattice()) self.assertEqual( IntervalLattice(2, 4).add(IntervalLattice(1, 3)), IntervalLattice(3, 7)) self.assertEqual( IntervalLattice(1, 2).add(IntervalLattice(3, 4)), IntervalLattice(4, 6))