2 * Copyright (C) 2025 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
24 fn z3_mk_world : z3_world;
25 fn z3_mk_context(w : z3_world) : (z3_world, z3_context);
27 fn z3_eval_smtlib2_string(w : z3_world, ctx : z3_context, str : bytes) : (z3_world, bytes);
28 fn z3_eval_smtlib2_string_noret(w : z3_world, ctx : z3_context, str : bytes) : z3_world;
35 type z3_world := world;
38 destr : ffi_destructor;
40 z3_set_error : ffi_function;
41 z3_get_error_code : ffi_function;
42 z3_get_error_msg : ffi_function;
43 z3_eval_smtlib2_string : ffi_function;
46 fn z3_mk_world := ffi_unsafe_get_world;
48 fn z3_mk_context(implicit w : z3_world) : (z3_world, z3_context)
50 var ctx := z3_context.[ ];
52 ctx.destr := ffi_destructor_new();
53 ctx.z3_set_error := ffi_create_function("libz3.so.4", "Z3_set_error", ffi_error.e_none, 2, ffi_type.t_void, [ ffi_type.t_pointer, ffi_type.t_uint ]);
54 ctx.z3_get_error_code := ffi_create_function("libz3.so.4", "Z3_get_error_code", ffi_error.e_none, 1, ffi_type.t_uint, [ ffi_type.t_pointer ]);
55 ctx.z3_get_error_msg := ffi_create_function("libz3.so.4", "Z3_get_error_msg", ffi_error.e_none, 2, ffi_type.t_pointer, [ ffi_type.t_pointer, ffi_type.t_uint ]);
56 ctx.z3_eval_smtlib2_string := ffi_create_function("libz3.so.4", "Z3_eval_smtlib2_string", ffi_error.e_none, 3, ffi_type.t_pointer, [ ffi_type.t_pointer, ffi_type.t_pointer ]);
57 var z3_mk_context := ffi_create_function("libz3.so.4", "Z3_mk_context", ffi_error.e_none, 1, ffi_type.t_pointer, [ ffi_type.t_pointer ]);
58 var z3_del_context := ffi_create_function("libz3.so.4", "Z3_del_context", ffi_error.e_none, 1, ffi_type.t_void, [ ffi_type.t_pointer ]);
59 var z3_set_error_handler := ffi_create_function("libz3.so.4", "Z3_set_error_handler", ffi_error.e_none, 1, ffi_type.t_void, [ ffi_type.t_pointer, ffi_type.t_pointer ]);
62 ctx.ptr_z3_context, e := ffi_call_function(z3_mk_context, [ 0 ]);
63 ffi_destructor_call(ctx.destr, z3_del_context, [ ctx.ptr_z3_context ]);
66 v, e := ffi_call_function(z3_set_error_handler, [ ctx.ptr_z3_context, 0 ]);
70 fn z3_eval_smtlib2_string(implicit w : z3_world, ctx : z3_context, str : bytes) : (z3_world, bytes)
72 //if not is_exception w then eval debug("Z3: " + str);
74 r, e := ffi_call_function(ctx.z3_set_error, [ ctx.ptr_z3_context, 0 ]);
75 var mem_str := ffi_poke_zstring(ctx.destr, str);
76 r, e := ffi_call_function(ctx.z3_eval_smtlib2_string, [ ctx.ptr_z3_context, mem_str ]);
77 ffi_destructor_free(ctx.destr, mem_str);
78 ec, e := ffi_call_function(ctx.z3_get_error_code, [ ctx.ptr_z3_context ]);
80 es, e := ffi_call_function(ctx.z3_get_error_msg, [ ctx.ptr_z3_context, ec ]);
81 var b := ffi_peek_zstring(es);
82 b := list_join(list_break_to_lines(b), "");
83 xeval ffi_destructor_destroy(ctx.destr);
84 abort exception_make_str(z3_world, ec_library, error_invalid_operation, ec, true, b);
86 var b := ffi_peek_zstring(r);
87 xeval ffi_destructor_destroy(ctx.destr);
91 fn z3_eval_smtlib2_string_noret(implicit w : z3_world, ctx : z3_context, str : bytes) : z3_world
93 var b := z3_eval_smtlib2_string(ctx, str);