예제 #1
0
    def process_assignment(self, ref: z3.BoolRef) -> None:
        """
        Create a RE constraint or a fresh equation for literal assignment.

        Assignment is `var = str_cons`.
        If there is no RE constraint for `var`, we create one of the form
        `var → RE(str_cons)`. Otherwise we introduce a fresh variable (`x`)
        and create a new equation `var = x`, and introduce a constraint
        `x → RE(str_cons)`.

        Parameters
        ----------
        ref: z3.BoolRef of the form `var = string_const`

        Returns
        -------
        None
        """
        assert is_assignment(ref)
        var, const = (c.as_string() for c in ref.children())
        const_re: RE = self.create_awali_re(const)

        if var not in self.constraints:
            self.constraints[var] = const_re
        else:
            # Introduce a fresh variable and a new equation
            new_var = self.fresh_variable()
            self.constraints[new_var] = const_re
            self.equations.append(StringEquation([var], [new_var]))
예제 #2
0
    def parse_equation(self, ref: z3.BoolRef) -> StringEquation:
        left, right = ref.children()
        # TODO This restricts only to assignment-form of equations (like SSA-fragment)
        assert is_string_variable(left)
        assert right.sort_kind() == z3.Z3_SEQ_SORT

        res_left = [left.as_string()]

        def z3_concat_to_var_list(z3_ref: z3.SeqRef) -> Collection[str]:
            """
            Convert concatenation of string variables into list of vars.

            Parameters
            ----------
            z3_ref

            Returns
            -------
            List of variables from Z3_ref
            """
            if is_string_variable(z3_ref):
                return [z3_ref.as_string()]
            children = [
                z3_concat_to_var_list(child) for child in z3_ref.children()
            ]
            return itertools.chain(*children)

        res_right = z3_concat_to_var_list(right)
        return StringEquation(res_left, list(res_right))
예제 #3
0
def is_assignment(ref: z3.BoolRef) -> bool:
    """
    Detect assignment.

    Assignment is an equation of the form `var = str_const`.

    Parameters
    ----------
    ref: z3 reference

    Returns
    -------
    True if `ref` is an assignment.
    """
    if ref.decl().kind() != z3.Z3_OP_EQ:
        return False

    left, right = ref.children()
    return is_string_variable(left) and is_string_constant(right)
예제 #4
0
    def parse_re_constraint(self, ref: z3.BoolRef) -> REConstraints:
        """
        Translate one regular constraint into REConstraints dict.

        The reference should point to a Z3_OP_SEQ_IN_RE operator.

        Parameters
        ----------
        ref: z3.BoolRef to a in_re operator to translate

        Returns
        -------
        REConstraint
            Mapping `var -> RE`
        """
        assert is_inre(ref)
        left, right = ref.children()
        assert is_string_variable(left) and left.as_string() in self.variables

        return {left.as_string(): self.z3_re_to_awali(right)}
예제 #5
0
def mk_eq(e1, e2):
    # type: (ExprRef, ExprRef) -> ExprRef
    """Return a z3 expression equivalent to e1 == e2"""
    return BoolRef(Z3_mk_eq(e1.ctx_ref(), e1.as_ast(), e2.as_ast()), e1.ctx)
예제 #6
0
 def _ge_no_coerce(self, left, right):
     # TODO: add assertions for noncoerce
     return BoolRef(Z3_mk_ge(left.ctx_ref(), left.as_ast(), right.as_ast()), left.ctx)
예제 #7
0
def eq_no_coerce(left, right):
    #TODO add assertion for coercion-free
    return BoolRef(Z3_mk_eq(left.ctx_ref(), left.as_ast(), right.as_ast()),
                   left.ctx)
예제 #8
0
def fast_ne(a: ExprRef, b: ExprRef):
  """Equivalent of z3 __ne__."""
  z3args = (Ast * 2)()
  z3args[0], z3args[1] = a.as_ast(), b.as_ast()
  return BoolRef(Z3_mk_distinct(CTX.ref(), 2, z3args), CTX)
예제 #9
0
def fast_eq(a: ExprRef, b: ExprRef):
  """Equivalent of z3 __eq__."""
  return BoolRef(Z3_mk_eq(CTX.ref(), a.as_ast(), b.as_ast()), CTX)
예제 #10
0
def fast_and(*args: BoolRef):
  """Equivalent of z3 And."""
  z3args = (Ast * len(args))()
  for i, a in enumerate(args):
    z3args[i] = a.as_ast()
  return BoolRef(Z3_mk_and(CTX.ref(), len(z3args), z3args), CTX)