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