def apply_z3_func(pred, tup): if not isinstance(pred, z3.FuncDeclRef): return pred(*tup) _args, sz = z3._to_ast_array(tup) fact = z3._to_expr_ref(z3.Z3_mk_app(pred.ctx_ref(), pred.ast, sz, _args), pred.ctx) return fact
def _tuple_create(self, asts, sort): ast_array = (z3.Ast * len(asts))() for x in range(len(asts)): ast_array[x] = asts[x].ast.ast tast = z3.Z3_mk_app(self.ctx.ctx, sort.decl_ref.ast, len(asts), ast_array) tref = z3.ExprRef(tast, self.ctx) return Z3ast(tref, self, sort)
def project(self, conv, elem): assert self.sort.id == esbmc.solve.smt_sort_kind.struct proj_decl = self.sort.proj_decls[elem] # We need to manually apply this function to project the elem out inp_array = (z3.Ast * 1)() inp_array[0] = self.ast.ast projected_ast = z3.Z3_mk_app(conv.ctx.ctx, proj_decl.ast, 1, inp_array) projected_ast = z3._to_ast_ref(projected_ast, conv.ctx) result = Z3ast(projected_ast, self.conv, self.sort.sub_sorts[elem]) # Also manually stash this ast self.conv.store_ast(result) return result
def update(self, conv, value, idx, idx_expr): # Either a tuple update or an array update. Alas, all the exprs baked # into ESBMC make no distinguishment. if self.sort.id == esbmc.solve.smt_sort_kind.array: # Use idx_expr idx_ast = conv.convert_ast(idx_expr) res = z3.Update(self.ast, idx_ast.ast, value.ast) result = Z3ast(res, self.conv, self.sort) else: assert self.sort.id == esbmc.solve.smt_sort_kind.struct # Hurrrr. Project all fields out except this one; update; create # new tuple. decls = self.sort.proj_decls # Place the tuple ast in an ast array inp_array = (z3.Ast * 1)() inp_array[0] = self.ast.ast # Now apply projection functions to the tuple ast. Need to apply # ExprRef immediately, or z3 will immediately gc it. projected = [ z3.ExprRef(z3.Z3_mk_app(conv.ctx.ctx, x.ast, 1, inp_array), conv.ctx) for x in decls ] # Zip with their sorts asts_and_sorts = zip(projected, self.sort.sub_sorts) # Put Z3ast around the outside projected = [Z3ast(ar, conv, sort) for ar, sort in asts_and_sorts] # We now have a list of all current tuple values. We need to update # the identified one with the designated value projected[idx] = value result = conv._tuple_create(projected, self.sort) self.conv.store_ast(result) return result
def walk_function(self, formula, args, **kwargs): z3func = self._z3_func_decl(formula.function_name()) _args, sz = self._to_ast_array(args) z3term = z3.Z3_mk_app(self.ctx.ref(), z3func, sz, _args) z3.Z3_inc_ref(self.ctx.ref(), z3term) return z3term