1 /*++
2 Copyright (c) 2012 Microsoft Corporation
3 
4 Module Name:
5 
6     api_datalog.cpp
7 
8 Abstract:
9     Datalog API
10 
11 Author:
12 
13     Leonardo de Moura (leonardo) 2012-02-29.
14 
15 Revision History:
16 
17 --*/
18 #include "api/api_datalog.h"
19 #include "api/api_context.h"
20 #include "api/api_util.h"
21 #include "ast/ast_pp.h"
22 #include "api/api_ast_vector.h"
23 #include "api/api_log_macros.h"
24 #include "api/api_stats.h"
25 #include "muz/fp/datalog_parser.h"
26 #include "util/cancel_eh.h"
27 #include "util/scoped_ctrl_c.h"
28 #include "util/scoped_timer.h"
29 #include "muz/fp/dl_cmds.h"
30 #include "cmd_context/cmd_context.h"
31 #include "parsers/smt2/smt2parser.h"
32 #include "muz/base/dl_context.h"
33 #include "muz/fp/dl_register_engine.h"
34 #include "muz/rel/dl_external_relation.h"
35 #include "ast/dl_decl_plugin.h"
36 #include "muz/rel/rel_context.h"
37 
38 namespace api {
39 
40     class fixedpoint_context : public datalog::external_relation_context {
41         void *                       m_state;
42         reduce_app_callback_fptr     m_reduce_app;
43         reduce_assign_callback_fptr  m_reduce_assign;
44         datalog::register_engine     m_register_engine;
45         datalog::context             m_context;
46         ast_ref_vector               m_trail;
47     public:
fixedpoint_context(ast_manager & m,smt_params & p)48         fixedpoint_context(ast_manager& m, smt_params& p):
49             m_state(nullptr),
50             m_reduce_app(nullptr),
51             m_reduce_assign(nullptr),
52             m_context(m, m_register_engine, p),
53             m_trail(m) {}
54 
~fixedpoint_context()55         ~fixedpoint_context() override {}
get_family_id() const56         family_id get_family_id() const override { return const_cast<datalog::context&>(m_context).get_decl_util().get_family_id(); }
set_state(void * state)57         void set_state(void* state) {
58             SASSERT(!m_state);
59             m_state = state;
60             symbol name("datalog_relation");
61             ast_manager& m = m_context.get_manager();
62             if (!m.has_plugin(name)) {
63                 m.register_plugin(name, alloc(datalog::dl_decl_plugin));
64             }
65             datalog::rel_context_base* rel = m_context.get_rel_context();
66             if (rel) {
67                 datalog::relation_manager& r = rel->get_rmanager();
68                 r.register_plugin(alloc(datalog::external_relation_plugin, *this, r));
69             }
70         }
set_reduce_app(reduce_app_callback_fptr f)71         void set_reduce_app(reduce_app_callback_fptr f) {
72             m_reduce_app = f;
73         }
set_reduce_assign(reduce_assign_callback_fptr f)74         void set_reduce_assign(reduce_assign_callback_fptr f) {
75             m_reduce_assign = f;
76         }
reduce(func_decl * f,unsigned num_args,expr * const * args,expr_ref & result)77         void reduce(func_decl* f, unsigned num_args, expr * const* args, expr_ref& result) override {
78             expr* r = nullptr;
79             if (m_reduce_app) {
80                 m_reduce_app(m_state, f, num_args, args, &r);
81                 result = r;
82                 m_trail.push_back(f);
83                 for (unsigned i = 0; i < num_args; ++i) {
84                     m_trail.push_back(args[i]);
85                 }
86                 m_trail.push_back(r);
87             }
88             // allow fallthrough.
89             if (r == nullptr) {
90                 ast_manager& m = m_context.get_manager();
91                 result = m.mk_app(f, num_args, args);
92             }
93         }
reduce_assign(func_decl * f,unsigned num_args,expr * const * args,unsigned num_out,expr * const * outs)94         void reduce_assign(func_decl* f, unsigned num_args, expr * const* args, unsigned num_out, expr* const* outs) override {
95             if (m_reduce_assign) {
96                 m_trail.push_back(f);
97                 for (unsigned i = 0; i < num_args; ++i) {
98                     m_trail.push_back(args[i]);
99                 }
100                 m_reduce_assign(m_state, f, num_args, args, num_out, outs);
101             }
102         }
ctx()103         datalog::context& ctx() { return m_context; }
add_rule(expr * rule,symbol const & name)104         void add_rule(expr* rule, symbol const& name) {
105             m_context.add_rule(rule, name);
106         }
update_rule(expr * rule,symbol const & name)107         void update_rule(expr* rule, symbol const& name) {
108             m_context.update_rule(rule, name);
109         }
add_table_fact(func_decl * r,unsigned num_args,unsigned args[])110         void add_table_fact(func_decl* r, unsigned num_args, unsigned args[]) {
111             m_context.add_table_fact(r, num_args, args);
112         }
get_last_status()113         std::string get_last_status() {
114             datalog::execution_result status = m_context.get_status();
115             switch(status) {
116             case datalog::INPUT_ERROR:
117                 return "input error";
118             case datalog::OK:
119                 return "ok";
120             case datalog::TIMEOUT:
121                 return "timeout";
122             case datalog::APPROX:
123                 return "approximated";
124             default:
125                 UNREACHABLE();
126                 return "unknown";
127             }
128         }
to_string(unsigned num_queries,expr * const * queries)129         std::string to_string(unsigned num_queries, expr* const* queries) {
130             std::stringstream str;
131             m_context.display_smt2(num_queries, queries, str);
132             return str.str();
133         }
get_num_levels(func_decl * pred)134         unsigned get_num_levels(func_decl* pred) {
135             return m_context.get_num_levels(pred);
136         }
get_cover_delta(int level,func_decl * pred)137         expr_ref get_cover_delta(int level, func_decl* pred) {
138             return m_context.get_cover_delta(level, pred);
139         }
add_cover(int level,func_decl * pred,expr * predicate)140         void add_cover(int level, func_decl* pred, expr* predicate) {
141             m_context.add_cover(level, pred, predicate);
142         }
collect_param_descrs(param_descrs & p)143         void collect_param_descrs(param_descrs & p) { m_context.collect_params(p); }
updt_params(params_ref const & p)144         void updt_params(params_ref const& p) { m_context.updt_params(p); }
145     };
146 };
147 
148 extern "C" {
149 
150     ////////////////////////////////////
151     // Datalog utilities
152     //
153 
154 
Z3_get_relation_arity(Z3_context c,Z3_sort s)155     unsigned Z3_API Z3_get_relation_arity(Z3_context c, Z3_sort s) {
156         Z3_TRY;
157         LOG_Z3_get_relation_arity(c, s);
158         RESET_ERROR_CODE();
159         sort * r = to_sort(s);
160         if (Z3_get_sort_kind(c, s) != Z3_RELATION_SORT) {
161             SET_ERROR_CODE(Z3_INVALID_ARG, "sort should be a relation");
162             return 0;
163         }
164         return r->get_num_parameters();
165         Z3_CATCH_RETURN(0);
166     }
167 
Z3_get_relation_column(Z3_context c,Z3_sort s,unsigned col)168     Z3_sort Z3_API Z3_get_relation_column(Z3_context c, Z3_sort s, unsigned col) {
169         Z3_TRY;
170         LOG_Z3_get_relation_column(c, s, col);
171         RESET_ERROR_CODE();
172         sort * r = to_sort(s);
173         if (Z3_get_sort_kind(c, s) != Z3_RELATION_SORT) {
174             SET_ERROR_CODE(Z3_INVALID_ARG, "sort should be a relation");
175             RETURN_Z3(nullptr);
176         }
177         if (col >= r->get_num_parameters()) {
178             SET_ERROR_CODE(Z3_IOB, nullptr);
179             RETURN_Z3(nullptr);
180         }
181         parameter const& p = r->get_parameter(col);
182         if (!p.is_ast() || !is_sort(p.get_ast())) {
183             UNREACHABLE();
184             warning_msg("Sort parameter expected at %d", col);
185             SET_ERROR_CODE(Z3_INTERNAL_FATAL, "sort parameter expected");
186             RETURN_Z3(nullptr);
187         }
188         Z3_sort res = of_sort(to_sort(p.get_ast()));
189         RETURN_Z3(res);
190         Z3_CATCH_RETURN(nullptr);
191     }
192 
Z3_mk_finite_domain_sort(Z3_context c,Z3_symbol name,uint64_t size)193     Z3_sort Z3_API Z3_mk_finite_domain_sort(Z3_context c, Z3_symbol name, uint64_t size) {
194         Z3_TRY;
195         LOG_Z3_mk_finite_domain_sort(c, name, size);
196         RESET_ERROR_CODE();
197         sort* s = mk_c(c)->datalog_util().mk_sort(to_symbol(name), size);
198         mk_c(c)->save_ast_trail(s);
199         RETURN_Z3(of_sort(s));
200         Z3_CATCH_RETURN(nullptr);
201     }
202 
Z3_get_finite_domain_sort_size(Z3_context c,Z3_sort s,uint64_t * out)203     bool Z3_API Z3_get_finite_domain_sort_size(Z3_context c, Z3_sort s, uint64_t * out) {
204         Z3_TRY;
205         if (out) {
206             *out = 0;
207         }
208         if (Z3_get_sort_kind(c, s) != Z3_FINITE_DOMAIN_SORT) {
209             return false;
210         }
211         if (!out) {
212             return false;
213         }
214         // must start logging here, since function uses Z3_get_sort_kind above
215         LOG_Z3_get_finite_domain_sort_size(c, s, out);
216         RESET_ERROR_CODE();
217         VERIFY(mk_c(c)->datalog_util().try_get_size(to_sort(s), *out));
218         return true;
219         Z3_CATCH_RETURN(false);
220     }
221 
Z3_mk_fixedpoint(Z3_context c)222     Z3_fixedpoint Z3_API Z3_mk_fixedpoint(Z3_context c) {
223         Z3_TRY;
224         LOG_Z3_mk_fixedpoint(c);
225         RESET_ERROR_CODE();
226         Z3_fixedpoint_ref * d = alloc(Z3_fixedpoint_ref, *mk_c(c));
227         d->m_datalog = alloc(api::fixedpoint_context, mk_c(c)->m(), mk_c(c)->fparams());
228         mk_c(c)->save_object(d);
229         Z3_fixedpoint r = of_datalog(d);
230         RETURN_Z3(r);
231         Z3_CATCH_RETURN(nullptr);
232     }
233 
Z3_fixedpoint_inc_ref(Z3_context c,Z3_fixedpoint s)234     void Z3_API Z3_fixedpoint_inc_ref(Z3_context c, Z3_fixedpoint s) {
235         Z3_TRY;
236         LOG_Z3_fixedpoint_inc_ref(c, s);
237         RESET_ERROR_CODE();
238         to_fixedpoint(s)->inc_ref();
239         Z3_CATCH;
240     }
241 
Z3_fixedpoint_dec_ref(Z3_context c,Z3_fixedpoint s)242     void Z3_API Z3_fixedpoint_dec_ref(Z3_context c, Z3_fixedpoint s) {
243         Z3_TRY;
244         LOG_Z3_fixedpoint_dec_ref(c, s);
245         RESET_ERROR_CODE();
246         if (s)
247             to_fixedpoint(s)->dec_ref();
248         Z3_CATCH;
249     }
250 
Z3_fixedpoint_assert(Z3_context c,Z3_fixedpoint d,Z3_ast a)251     void Z3_API Z3_fixedpoint_assert(Z3_context c, Z3_fixedpoint d, Z3_ast a) {
252         Z3_TRY;
253         LOG_Z3_fixedpoint_assert(c, d, a);
254         RESET_ERROR_CODE();
255         CHECK_FORMULA(a,);
256         to_fixedpoint_ref(d)->ctx().assert_expr(to_expr(a));
257         Z3_CATCH;
258     }
259 
Z3_fixedpoint_add_rule(Z3_context c,Z3_fixedpoint d,Z3_ast a,Z3_symbol name)260     void Z3_API Z3_fixedpoint_add_rule(Z3_context c, Z3_fixedpoint d, Z3_ast a, Z3_symbol name) {
261         Z3_TRY;
262         LOG_Z3_fixedpoint_add_rule(c, d, a, name);
263         RESET_ERROR_CODE();
264         CHECK_FORMULA(a,);
265         to_fixedpoint_ref(d)->add_rule(to_expr(a), to_symbol(name));
266         Z3_CATCH;
267     }
268 
Z3_fixedpoint_add_fact(Z3_context c,Z3_fixedpoint d,Z3_func_decl r,unsigned num_args,unsigned args[])269     void Z3_API Z3_fixedpoint_add_fact(Z3_context c, Z3_fixedpoint d,
270                                        Z3_func_decl r, unsigned num_args, unsigned args[]) {
271         Z3_TRY;
272         LOG_Z3_fixedpoint_add_fact(c, d, r, num_args, args);
273         RESET_ERROR_CODE();
274         to_fixedpoint_ref(d)->add_table_fact(to_func_decl(r), num_args, args);
275         Z3_CATCH;
276     }
277 
Z3_fixedpoint_query(Z3_context c,Z3_fixedpoint d,Z3_ast q)278     Z3_lbool Z3_API Z3_fixedpoint_query(Z3_context c,Z3_fixedpoint d, Z3_ast q) {
279         Z3_TRY;
280         LOG_Z3_fixedpoint_query(c, d, q);
281         RESET_ERROR_CODE();
282         lbool r = l_undef;
283         unsigned timeout = to_fixedpoint(d)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
284         unsigned rlimit  = to_fixedpoint(d)->m_params.get_uint("rlimit",  mk_c(c)->get_rlimit());
285         bool     use_ctrl_c  = to_fixedpoint(d)->m_params.get_bool("ctrl_c", true);
286         {
287             scoped_rlimit _rlimit(mk_c(c)->m().limit(), rlimit);
288             cancel_eh<reslimit> eh(mk_c(c)->m().limit());
289             api::context::set_interruptable si(*(mk_c(c)), eh);
290             scoped_timer timer(timeout, &eh);
291             scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
292             try {
293                 r = to_fixedpoint_ref(d)->ctx().query(to_expr(q));
294             }
295             catch (z3_exception& ex) {
296                 r = l_undef;
297                 mk_c(c)->handle_exception(ex);
298             }
299             to_fixedpoint_ref(d)->ctx().cleanup();
300         }
301         return of_lbool(r);
302         Z3_CATCH_RETURN(Z3_L_UNDEF);
303     }
304 
Z3_fixedpoint_query_relations(Z3_context c,Z3_fixedpoint d,unsigned num_relations,Z3_func_decl const relations[])305     Z3_lbool Z3_API Z3_fixedpoint_query_relations(
306         Z3_context c,Z3_fixedpoint d,
307         unsigned num_relations, Z3_func_decl const relations[]) {
308         Z3_TRY;
309         LOG_Z3_fixedpoint_query_relations(c, d, num_relations, relations);
310         RESET_ERROR_CODE();
311         lbool r = l_undef;
312         unsigned timeout = to_fixedpoint(d)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
313         cancel_eh<reslimit> eh(mk_c(c)->m().limit());
314         api::context::set_interruptable si(*(mk_c(c)), eh);
315         {
316             scoped_timer timer(timeout, &eh);
317             try {
318                 r = to_fixedpoint_ref(d)->ctx().rel_query(num_relations, to_func_decls(relations));
319             }
320             catch (z3_exception& ex) {
321                 mk_c(c)->handle_exception(ex);
322                 r = l_undef;
323             }
324             to_fixedpoint_ref(d)->ctx().cleanup();
325         }
326         return of_lbool(r);
327         Z3_CATCH_RETURN(Z3_L_UNDEF);
328     }
329 
Z3_fixedpoint_get_answer(Z3_context c,Z3_fixedpoint d)330     Z3_ast Z3_API Z3_fixedpoint_get_answer(Z3_context c, Z3_fixedpoint d) {
331         Z3_TRY;
332         LOG_Z3_fixedpoint_get_answer(c, d);
333         RESET_ERROR_CODE();
334         expr* e = to_fixedpoint_ref(d)->ctx().get_answer_as_formula();
335         mk_c(c)->save_ast_trail(e);
336         RETURN_Z3(of_expr(e));
337         Z3_CATCH_RETURN(nullptr);
338     }
339 
Z3_fixedpoint_get_reason_unknown(Z3_context c,Z3_fixedpoint d)340     Z3_string Z3_API Z3_fixedpoint_get_reason_unknown(Z3_context c,Z3_fixedpoint d) {
341         Z3_TRY;
342         LOG_Z3_fixedpoint_get_reason_unknown(c, d);
343         RESET_ERROR_CODE();
344         return mk_c(c)->mk_external_string(to_fixedpoint_ref(d)->get_last_status());
345         Z3_CATCH_RETURN("");
346     }
347 
Z3_fixedpoint_to_string(Z3_context c,Z3_fixedpoint d,unsigned num_queries,Z3_ast _queries[])348     Z3_string Z3_API Z3_fixedpoint_to_string(
349         Z3_context c,
350         Z3_fixedpoint d,
351         unsigned num_queries,
352         Z3_ast _queries[]) {
353         Z3_TRY;
354         expr*const* queries = to_exprs(num_queries, _queries);
355         LOG_Z3_fixedpoint_to_string(c, d, num_queries, _queries);
356         RESET_ERROR_CODE();
357         return mk_c(c)->mk_external_string(to_fixedpoint_ref(d)->to_string(num_queries, queries));
358         Z3_CATCH_RETURN("");
359     }
360 
Z3_fixedpoint_from_stream(Z3_context c,Z3_fixedpoint d,std::istream & s)361     Z3_ast_vector Z3_fixedpoint_from_stream(
362         Z3_context    c,
363         Z3_fixedpoint d,
364         std::istream& s) {
365         ast_manager& m = mk_c(c)->m();
366         dl_collected_cmds coll(m);
367         cmd_context ctx(false, &m);
368         install_dl_collect_cmds(coll, ctx);
369         ctx.set_ignore_check(true);
370         if (!parse_smt2_commands(ctx, s)) {
371             SET_ERROR_CODE(Z3_PARSER_ERROR, nullptr);
372             return nullptr;
373         }
374 
375         Z3_ast_vector_ref* v = alloc(Z3_ast_vector_ref, *mk_c(c), m);
376         mk_c(c)->save_object(v);
377         for (expr * q : coll.m_queries) {
378             v->m_ast_vector.push_back(q);
379         }
380         for (func_decl * f : coll.m_rels) {
381             to_fixedpoint_ref(d)->ctx().register_predicate(f, true);
382         }
383         for (unsigned i = 0; i < coll.m_rules.size(); ++i) {
384             to_fixedpoint_ref(d)->add_rule(coll.m_rules[i].get(), coll.m_names[i]);
385         }
386         for (expr * e : ctx.assertions()) {
387             to_fixedpoint_ref(d)->ctx().assert_expr(e);
388         }
389 
390         return of_ast_vector(v);
391     }
392 
Z3_fixedpoint_from_string(Z3_context c,Z3_fixedpoint d,Z3_string s)393     Z3_ast_vector Z3_API Z3_fixedpoint_from_string(
394         Z3_context    c,
395         Z3_fixedpoint d,
396         Z3_string     s) {
397         Z3_TRY;
398         LOG_Z3_fixedpoint_from_string(c, d, s);
399         std::string str(s);
400         std::istringstream is(str);
401         RETURN_Z3(Z3_fixedpoint_from_stream(c, d, is));
402         Z3_CATCH_RETURN(nullptr);
403     }
404 
Z3_fixedpoint_from_file(Z3_context c,Z3_fixedpoint d,Z3_string s)405     Z3_ast_vector Z3_API Z3_fixedpoint_from_file(
406         Z3_context    c,
407         Z3_fixedpoint d,
408         Z3_string     s) {
409         Z3_TRY;
410         LOG_Z3_fixedpoint_from_file(c, d, s);
411         std::ifstream is(s);
412         if (!is) {
413             SET_ERROR_CODE(Z3_PARSER_ERROR, nullptr);
414             RETURN_Z3(nullptr);
415         }
416         RETURN_Z3(Z3_fixedpoint_from_stream(c, d, is));
417         Z3_CATCH_RETURN(nullptr);
418     }
419 
420 
Z3_fixedpoint_get_statistics(Z3_context c,Z3_fixedpoint d)421     Z3_stats Z3_API Z3_fixedpoint_get_statistics(Z3_context c,Z3_fixedpoint d) {
422         Z3_TRY;
423         LOG_Z3_fixedpoint_get_statistics(c, d);
424         RESET_ERROR_CODE();
425         Z3_stats_ref * st = alloc(Z3_stats_ref, (*mk_c(c)));
426         to_fixedpoint_ref(d)->ctx().collect_statistics(st->m_stats);
427         mk_c(c)->save_object(st);
428         Z3_stats r = of_stats(st);
429         RETURN_Z3(r);
430         Z3_CATCH_RETURN(nullptr);
431     }
432 
Z3_fixedpoint_register_relation(Z3_context c,Z3_fixedpoint d,Z3_func_decl f)433     void Z3_API Z3_fixedpoint_register_relation(Z3_context c,Z3_fixedpoint d, Z3_func_decl f) {
434         Z3_TRY;
435         LOG_Z3_fixedpoint_register_relation(c, d, f);
436         to_fixedpoint_ref(d)->ctx().register_predicate(to_func_decl(f), true);
437         Z3_CATCH;
438     }
439 
Z3_fixedpoint_set_predicate_representation(Z3_context c,Z3_fixedpoint d,Z3_func_decl f,unsigned num_relations,Z3_symbol const relation_kinds[])440     void Z3_API Z3_fixedpoint_set_predicate_representation(
441         Z3_context c,
442         Z3_fixedpoint d,
443         Z3_func_decl f,
444         unsigned num_relations,
445         Z3_symbol const relation_kinds[]) {
446         Z3_TRY;
447         LOG_Z3_fixedpoint_set_predicate_representation(c, d, f, num_relations, relation_kinds);
448         svector<symbol> kinds;
449         for (unsigned i = 0; i < num_relations; ++i) {
450             kinds.push_back(to_symbol(relation_kinds[i]));
451         }
452         to_fixedpoint_ref(d)->ctx().set_predicate_representation(to_func_decl(f), num_relations, kinds.data());
453         Z3_CATCH;
454     }
455 
456 
Z3_fixedpoint_get_rules(Z3_context c,Z3_fixedpoint d)457     Z3_ast_vector Z3_API Z3_fixedpoint_get_rules(
458         Z3_context c,
459         Z3_fixedpoint d)
460     {
461         Z3_TRY;
462         LOG_Z3_fixedpoint_get_rules(c, d);
463         ast_manager& m = mk_c(c)->m();
464         Z3_ast_vector_ref* v = alloc(Z3_ast_vector_ref, *mk_c(c), m);
465         mk_c(c)->save_object(v);
466         expr_ref_vector rules(m), queries(m);
467         svector<symbol> names;
468 
469         to_fixedpoint_ref(d)->ctx().get_rules_as_formulas(rules, queries, names);
470         for (expr* r : rules) {
471             v->m_ast_vector.push_back(r);
472         }
473         for (expr* q : queries) {
474             v->m_ast_vector.push_back(m.mk_not(q));
475         }
476         RETURN_Z3(of_ast_vector(v));
477         Z3_CATCH_RETURN(nullptr);
478     }
479 
Z3_fixedpoint_get_assertions(Z3_context c,Z3_fixedpoint d)480     Z3_ast_vector Z3_API Z3_fixedpoint_get_assertions(
481         Z3_context c,
482         Z3_fixedpoint d)
483     {
484         Z3_TRY;
485         LOG_Z3_fixedpoint_get_assertions(c, d);
486         ast_manager& m = mk_c(c)->m();
487         Z3_ast_vector_ref* v = alloc(Z3_ast_vector_ref, *mk_c(c), m);
488         mk_c(c)->save_object(v);
489         unsigned num_asserts = to_fixedpoint_ref(d)->ctx().get_num_assertions();
490         for (unsigned i = 0; i < num_asserts; ++i) {
491             v->m_ast_vector.push_back(to_fixedpoint_ref(d)->ctx().get_assertion(i));
492         }
493         RETURN_Z3(of_ast_vector(v));
494         Z3_CATCH_RETURN(nullptr);
495     }
496 
Z3_fixedpoint_set_reduce_assign_callback(Z3_context c,Z3_fixedpoint d,Z3_fixedpoint_reduce_assign_callback_fptr f)497     void Z3_API Z3_fixedpoint_set_reduce_assign_callback(
498         Z3_context c, Z3_fixedpoint d, Z3_fixedpoint_reduce_assign_callback_fptr f) {
499         Z3_TRY;
500         // no logging
501         to_fixedpoint_ref(d)->set_reduce_assign((reduce_assign_callback_fptr)f);
502         Z3_CATCH;
503     }
504 
Z3_fixedpoint_set_reduce_app_callback(Z3_context c,Z3_fixedpoint d,Z3_fixedpoint_reduce_app_callback_fptr f)505     void Z3_API Z3_fixedpoint_set_reduce_app_callback(
506         Z3_context c, Z3_fixedpoint d, Z3_fixedpoint_reduce_app_callback_fptr f) {
507         Z3_TRY;
508         // no logging
509         to_fixedpoint_ref(d)->set_reduce_app((reduce_app_callback_fptr)f);
510         Z3_CATCH;
511     }
512 
Z3_fixedpoint_init(Z3_context c,Z3_fixedpoint d,void * state)513     void Z3_API Z3_fixedpoint_init(Z3_context c,Z3_fixedpoint d, void* state) {
514         Z3_TRY;
515         // not logged
516         to_fixedpoint_ref(d)->set_state(state);
517         Z3_CATCH;
518     }
519 
520 
Z3_fixedpoint_update_rule(Z3_context c,Z3_fixedpoint d,Z3_ast a,Z3_symbol name)521     void Z3_API Z3_fixedpoint_update_rule(Z3_context c, Z3_fixedpoint d, Z3_ast a, Z3_symbol name) {
522         Z3_TRY;
523         LOG_Z3_fixedpoint_update_rule(c, d, a, name);
524         RESET_ERROR_CODE();
525         CHECK_FORMULA(a,);
526         to_fixedpoint_ref(d)->update_rule(to_expr(a), to_symbol(name));
527         Z3_CATCH;
528     }
529 
Z3_fixedpoint_get_num_levels(Z3_context c,Z3_fixedpoint d,Z3_func_decl pred)530     unsigned Z3_API Z3_fixedpoint_get_num_levels(Z3_context c, Z3_fixedpoint d, Z3_func_decl pred) {
531         Z3_TRY;
532         LOG_Z3_fixedpoint_get_num_levels(c, d, pred);
533         RESET_ERROR_CODE();
534         return to_fixedpoint_ref(d)->get_num_levels(to_func_decl(pred));
535         Z3_CATCH_RETURN(0)
536     }
537 
Z3_fixedpoint_get_cover_delta(Z3_context c,Z3_fixedpoint d,int level,Z3_func_decl pred)538     Z3_ast Z3_API Z3_fixedpoint_get_cover_delta(Z3_context c, Z3_fixedpoint d, int level, Z3_func_decl pred) {
539         Z3_TRY;
540         LOG_Z3_fixedpoint_get_cover_delta(c, d, level, pred);
541         RESET_ERROR_CODE();
542         expr_ref r = to_fixedpoint_ref(d)->get_cover_delta(level, to_func_decl(pred));
543         mk_c(c)->save_ast_trail(r);
544         RETURN_Z3(of_expr(r.get()));
545         Z3_CATCH_RETURN(nullptr);
546     }
547 
Z3_fixedpoint_add_cover(Z3_context c,Z3_fixedpoint d,int level,Z3_func_decl pred,Z3_ast property)548     void Z3_API Z3_fixedpoint_add_cover(Z3_context c, Z3_fixedpoint d, int level, Z3_func_decl pred, Z3_ast property) {
549         Z3_TRY;
550         LOG_Z3_fixedpoint_add_cover(c, d, level, pred, property);
551         RESET_ERROR_CODE();
552         to_fixedpoint_ref(d)->add_cover(level, to_func_decl(pred), to_expr(property));
553         Z3_CATCH;
554     }
555 
Z3_fixedpoint_get_help(Z3_context c,Z3_fixedpoint d)556     Z3_string Z3_API Z3_fixedpoint_get_help(Z3_context c, Z3_fixedpoint d) {
557         Z3_TRY;
558         LOG_Z3_fixedpoint_get_help(c, d);
559         RESET_ERROR_CODE();
560         std::ostringstream buffer;
561         param_descrs descrs;
562         to_fixedpoint_ref(d)->collect_param_descrs(descrs);
563         descrs.display(buffer);
564         return mk_c(c)->mk_external_string(buffer.str());
565         Z3_CATCH_RETURN("");
566     }
567 
Z3_fixedpoint_get_param_descrs(Z3_context c,Z3_fixedpoint f)568     Z3_param_descrs Z3_API Z3_fixedpoint_get_param_descrs(Z3_context c, Z3_fixedpoint f) {
569         Z3_TRY;
570         LOG_Z3_fixedpoint_get_param_descrs(c, f);
571         RESET_ERROR_CODE();
572         Z3_param_descrs_ref * d = alloc(Z3_param_descrs_ref, *mk_c(c));
573         mk_c(c)->save_object(d);
574         to_fixedpoint_ref(f)->collect_param_descrs(d->m_descrs);
575         Z3_param_descrs r = of_param_descrs(d);
576         RETURN_Z3(r);
577         Z3_CATCH_RETURN(nullptr);
578     }
579 
Z3_fixedpoint_set_params(Z3_context c,Z3_fixedpoint d,Z3_params p)580     void Z3_API Z3_fixedpoint_set_params(Z3_context c, Z3_fixedpoint d, Z3_params p) {
581         Z3_TRY;
582         LOG_Z3_fixedpoint_set_params(c, d, p);
583         RESET_ERROR_CODE();
584         param_descrs descrs;
585         to_fixedpoint_ref(d)->collect_param_descrs(descrs);
586         to_params(p)->m_params.validate(descrs);
587         to_fixedpoint_ref(d)->updt_params(to_param_ref(p));
588         to_fixedpoint(d)->m_params = to_param_ref(p);
589         Z3_CATCH;
590     }
591 
Z3_fixedpoint_add_callback(Z3_context c,Z3_fixedpoint d,void * state,Z3_fixedpoint_new_lemma_eh new_lemma_eh,Z3_fixedpoint_predecessor_eh predecessor_eh,Z3_fixedpoint_unfold_eh unfold_eh)592     void Z3_API Z3_fixedpoint_add_callback(Z3_context c, Z3_fixedpoint d,
593                                             void *state,
594                                             Z3_fixedpoint_new_lemma_eh new_lemma_eh,
595                                             Z3_fixedpoint_predecessor_eh predecessor_eh,
596                                             Z3_fixedpoint_unfold_eh unfold_eh){
597         Z3_TRY;
598             // not logged
599             to_fixedpoint_ref(d)->ctx().add_callback(state,
600                                                      reinterpret_cast<datalog::t_new_lemma_eh>(new_lemma_eh),
601                                                      reinterpret_cast<datalog::t_predecessor_eh>(predecessor_eh),
602                                                      reinterpret_cast<datalog::t_unfold_eh>(unfold_eh));
603 
604         Z3_CATCH;
605     }
606 
Z3_fixedpoint_add_constraint(Z3_context c,Z3_fixedpoint d,Z3_ast e,unsigned lvl)607     void Z3_API Z3_fixedpoint_add_constraint (Z3_context c, Z3_fixedpoint d, Z3_ast e, unsigned lvl){
608         to_fixedpoint_ref(d)->ctx().add_constraint(to_expr(e), lvl);
609     }
610 
Z3_fixedpoint_query_from_lvl(Z3_context c,Z3_fixedpoint d,Z3_ast q,unsigned lvl)611     Z3_lbool Z3_API Z3_fixedpoint_query_from_lvl (Z3_context c, Z3_fixedpoint d, Z3_ast q, unsigned lvl) {
612         Z3_TRY;
613         LOG_Z3_fixedpoint_query_from_lvl (c, d, q, lvl);
614         RESET_ERROR_CODE();
615         lbool r = l_undef;
616         unsigned timeout = to_fixedpoint(d)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
617         unsigned rlimit  = to_fixedpoint(d)->m_params.get_uint("rlimit", mk_c(c)->get_rlimit());
618         {
619             scoped_rlimit _rlimit(mk_c(c)->m().limit(), rlimit);
620             cancel_eh<reslimit> eh(mk_c(c)->m().limit());
621             api::context::set_interruptable si(*(mk_c(c)), eh);
622             scoped_timer timer(timeout, &eh);
623             try {
624                 r = to_fixedpoint_ref(d)->ctx().query_from_lvl (to_expr(q), lvl);
625             }
626             catch (z3_exception& ex) {
627                 mk_c(c)->handle_exception(ex);
628                 r = l_undef;
629             }
630             to_fixedpoint_ref(d)->ctx().cleanup();
631         }
632         return of_lbool(r);
633         Z3_CATCH_RETURN(Z3_L_UNDEF);
634     }
635 
Z3_fixedpoint_get_ground_sat_answer(Z3_context c,Z3_fixedpoint d)636     Z3_ast Z3_API Z3_fixedpoint_get_ground_sat_answer(Z3_context c, Z3_fixedpoint d) {
637         Z3_TRY;
638         LOG_Z3_fixedpoint_get_ground_sat_answer(c, d);
639         RESET_ERROR_CODE();
640         expr* e = to_fixedpoint_ref(d)->ctx().get_ground_sat_answer();
641         mk_c(c)->save_ast_trail(e);
642         RETURN_Z3(of_expr(e));
643         Z3_CATCH_RETURN(nullptr);
644     }
645 
Z3_fixedpoint_get_rules_along_trace(Z3_context c,Z3_fixedpoint d)646     Z3_ast_vector Z3_API Z3_fixedpoint_get_rules_along_trace(
647         Z3_context c,
648         Z3_fixedpoint d)
649     {
650         Z3_TRY;
651         LOG_Z3_fixedpoint_get_rules_along_trace(c, d);
652         ast_manager& m = mk_c(c)->m();
653         Z3_ast_vector_ref* v = alloc(Z3_ast_vector_ref, *mk_c(c), m);
654         mk_c(c)->save_object(v);
655         expr_ref_vector rules(m);
656         svector<symbol> names;
657 
658         to_fixedpoint_ref(d)->ctx().get_rules_along_trace_as_formulas(rules, names);
659         for (unsigned i = 0; i < rules.size(); ++i) {
660             v->m_ast_vector.push_back(rules[i].get());
661         }
662         RETURN_Z3(of_ast_vector(v));
663         Z3_CATCH_RETURN(nullptr);
664     }
665 
Z3_fixedpoint_get_rule_names_along_trace(Z3_context c,Z3_fixedpoint d)666     Z3_symbol Z3_API Z3_fixedpoint_get_rule_names_along_trace(
667         Z3_context c,
668         Z3_fixedpoint d)
669     {
670         Z3_TRY;
671         LOG_Z3_fixedpoint_get_rule_names_along_trace(c, d);
672         ast_manager& m = mk_c(c)->m();
673         Z3_ast_vector_ref* v = alloc(Z3_ast_vector_ref, *mk_c(c), m);
674         mk_c(c)->save_object(v);
675         expr_ref_vector rules(m);
676         svector<symbol> names;
677         std::stringstream ss;
678 
679         to_fixedpoint_ref(d)->ctx().get_rules_along_trace_as_formulas(rules, names);
680         for (unsigned i = 0; i < names.size(); ++i) {
681             if (i != 0)
682                 ss << ';';
683             ss << names[i].str();
684         }
685         return of_symbol(symbol(ss.str()));
686         Z3_CATCH_RETURN(of_symbol(symbol::null));
687     }
688 
Z3_fixedpoint_add_invariant(Z3_context c,Z3_fixedpoint d,Z3_func_decl pred,Z3_ast property)689     void Z3_API Z3_fixedpoint_add_invariant(Z3_context c, Z3_fixedpoint d, Z3_func_decl pred, Z3_ast property) {
690         Z3_TRY;
691         LOG_Z3_fixedpoint_add_invariant(c, d, pred, property);
692         RESET_ERROR_CODE();
693         to_fixedpoint_ref(d)->ctx ().add_invariant(to_func_decl(pred), to_expr(property));
694         Z3_CATCH;
695     }
696 
Z3_fixedpoint_get_reachable(Z3_context c,Z3_fixedpoint d,Z3_func_decl pred)697     Z3_ast Z3_API Z3_fixedpoint_get_reachable(Z3_context c, Z3_fixedpoint d, Z3_func_decl pred) {
698         Z3_TRY;
699         LOG_Z3_fixedpoint_get_reachable(c, d, pred);
700         RESET_ERROR_CODE();
701         expr_ref r = to_fixedpoint_ref(d)->ctx().get_reachable(to_func_decl(pred));
702         mk_c(c)->save_ast_trail(r);
703         RETURN_Z3(of_expr(r.get()));
704         Z3_CATCH_RETURN(nullptr);
705     }
706 
707 };
708