コード例 #1
0
 def query(self, atom):
     """Query a relation on the compiled theory"""
     self.compiler.substitutes_constants_in_array(atom.args)
     if atom.table not in self.compiler.typed_tables:
         raise base.Z3NotWellFormed(
             "Unknown relation {}".format(atom.table))
     atom.types = self.compiler.typed_tables[atom.table]
     if len(atom.types) != len(atom.args):
         raise base.Z3NotWellFormed(
             "Arity of predicate inconsistency in {}".format(atom))
     for i in moves.xrange(len(atom.types)):
         atom.args[i].type = atom.types[i]
     ast_vars = list(OrderedDict.fromkeys([
         arg for arg in atom.args if isinstance(arg, ast.Variable)
     ]))
     vars = {}
     self.compiler.project = None
     query = self.compile_atom(vars, atom, {})
     if vars != {}:
         compiled_vars = [vars[ast_var.full_id()] for ast_var in ast_vars]
         query = z3.Exists(compiled_vars, query)
     self.context.query(query)
     types = [self.datasource.types[ast_var.type] for ast_var in ast_vars]
     variables = [ast_var.id for ast_var in ast_vars]
     raw_answer = self.context.get_answer()
     logging.getLogger().debug("Raw answer:\n%s", raw_answer)
     answer = z3r.z3_to_array(raw_answer, types)
     return variables, answer
コード例 #2
0
def extract_equal(eq):
    """Transform equals in a triple: var index, value, mask"""
    if isinstance(eq.children()[0], z3.BitVecNumRef):
        rhs = eq.children()[0]
        lhs = eq.children()[1]
    else:
        rhs = eq.children()[1]
        lhs = eq.children()[0]
    if z3.is_var(lhs):
        return ResultItem(
            var=z3.get_var_index(lhs),
            value=rhs,
            mask=None)
    else:
        kind = lhs.decl().kind()
        if kind == z3.Z3_OP_EXTRACT:
            [high, low] = lhs.params()
            sort = lhs.children()[0].sort()
            val = rhs.as_long() << low
            mask = (1 << (high + 1)) - (1 << low)
            return ResultItem(
                var=z3.get_var_index(lhs.children()[0]),
                value=z3.BitVecVal(val, sort),
                mask=z3.BitVecVal(mask, sort))
        else:
            raise base.Z3NotWellFormed(
                "Bad lhs for equal  {}".format(eq))
コード例 #3
0
    def flatten(self, atom, fields):
        """Replace named arguments with positional args.

        Knowing the columns in use for extensible tables, column names are
        replaced by positions as regular tables.
        """
        dict_arg = {}

        def new_var():
            """Create a new var with unique name"""
            self.var_count += 1
            return ast.Variable("::{}".format(self.var_count))

        for (label, arg) in zip(atom.labels, atom.args):
            if label in dict_arg:
                raise base.Z3NotWellFormed(
                    "Duplicate label '{}' in atom {}".format(label, atom))
            dict_arg[label] = arg

        atom.args = [
            dict_arg[label] if label in dict_arg else new_var()
            for label in fields
        ]
        # Hide labels for pretty printing.
        atom.labels = None
コード例 #4
0
def extract_and(item, types):
    """Extract a row"""
    kind = item.decl().kind()
    if kind == z3.Z3_OP_AND:
        return split_cubes(item.children(), types)
    elif kind == z3.Z3_OP_EQ or kind == z3.Z3_OP_NOT:
        return split_cubes([item], types)
    else:
        raise base.Z3NotWellFormed(
            "Bad result  {}: {}".format(item, kind))
コード例 #5
0
 def get_field_from_cache(field):
     """Get a field compilation functions for csv access"""
     type_name, _ = accessor.fields[field]
     type_field = self.types[type_name]
     try:
         pos = index.index(field)
     except ValueError:
         raise base.Z3NotWellFormed(
             "Field {} was not saved for table {}".format(
                 field, table_name))
     return (type_field.to_z3,
             lambda row: type_field.unmarshall(row[pos]),
             type_field.marshall)
コード例 #6
0
 def find_base_relations(self):
     """Extracts base relations of the theory"""
     aux_counter = 0
     new_rules = []
     for rule in self.rules:
         if self.datasource.is_extensible(rule.head):
             raise base.Z3NotWellFormed(
                 "No base predicate allowed in head: " + rule.head.table)
         for i, atom in enumerate(rule.body):
             if not self.datasource.is_extensible(atom):
                 continue
             fields = self.extensible_tables.setdefault(atom.table, [])
             if atom.labels is None:
                 raise base.Z3NotWellFormed(
                     "No labels for extensible atom {}".format(atom))
             for label in atom.labels:
                 if label not in fields:
                     fields.append(label)
             if atom.negated:
                 new_table = "_negated_%d" % aux_counter
                 aux_counter += 1
                 new_atom = ast.Atom(new_table, atom.args, negated=True)
                 var_row = [
                     ast.Variable("V%d" % i) for i in range(len(atom.args))
                 ]
                 atom_head = ast.Atom(new_table, var_row)
                 atom_body = ast.Atom(atom.table,
                                      var_row,
                                      labels=atom.labels)
                 new_rule = ast.Rule(atom_head, [atom_body])
                 new_rules.append(new_rule)
                 rule.body[i] = new_atom
     self.rules.extend(new_rules)
     for fields in self.extensible_tables.values():
         fields.sort()
     for rule in self.rules:
         for atom in rule.body:
             if self.datasource.is_extensible(atom):
                 self.flatten(atom, self.extensible_tables[atom.table])
コード例 #7
0
    def substitutes_constants_in_array(self, args):
        """Substitute constants in arguments arrays"""
        for i in moves.range(len(args)):
            oarg = args[i]
            if isinstance(oarg, ast.Constant):
                arg = self.constants.get(args[i].name, None)
                if arg is None:
                    raise base.Z3NotWellFormed("Unknown constant: {}".format(
                        args[i].name))
                args[i] = copy.deepcopy(arg)

            elif isinstance(args[i], ast.Operation):
                nb_vars = operations.OPERATIONS[args[i].operation].ty_vars
                args[i].var_types = [None] * nb_vars
                self.substitutes_constants_in_array(args[i].args)
コード例 #8
0
def z3_to_array(expr, types):
    """Compiles back a Z3 result to a matrix of values"""

    kind = expr.decl().kind()
    if kind == z3.Z3_OP_OR:
        return [extract_and(item, types) for item in expr.children()]
    elif kind == z3.Z3_OP_AND:
        return [split_cubes(expr.children(), types)]
    elif kind == z3.Z3_OP_EQ or kind == z3.Z3_OP_NOT:
        return [split_cubes([expr], types)]
    elif kind == z3.Z3_OP_FALSE:
        return False
    elif kind == z3.Z3_OP_TRUE:
        return True
    else:
        raise base.Z3NotWellFormed("Bad result {}: {}".format(expr, kind))
コード例 #9
0
 def compile_expr(self, variables, expr, env):
     """Compile an expression to Z3"""
     if isinstance(expr, (ast.NumConstant, ast.StringConstant,
                          ast.BoolConstant, ast.IpConstant)):
         return self.datasource.types[expr.type].to_z3(expr.val)
     elif isinstance(expr, ast.Variable):
         full_id = expr.full_id()
         if full_id in env:
             return env[full_id]
         if full_id in variables:
             return variables[full_id]
         expr_type = self.datasource.types[expr.type].type()
         var = z3.Const(expr.id, expr_type)
         variables[full_id] = var
         return var
     elif isinstance(expr, ast.Operation):
         operator = operations.OPERATIONS[expr.operation].z3
         return operator(
             *(self.compile_expr(variables, arg, env) for arg in expr.args))
     else:
         raise base.Z3NotWellFormed(
             "cannot proceed with {}".format(expr))