/*++ Copyright (c) 2007 Microsoft Corporation Module Name: Microsoft.Z3V3.cpp Abstract: Z3 Managed API. Author: Nikolaj Bjorner (nbjorner) Leonardo de Moura (leonardo) 2007-06-8 Notes: --*/ //#include "stdafx.h" #include "Microsoft.Z3V3.h" #include "..\lib\util.h" #include "..\lib\z3_private.h" #include #include #include #include "../lib/rational.h" #include "../lib/z3_private.h" using namespace System::Text; using namespace Microsoft::Z3V3; // ------------------------------- // ref_context ref_context* ref_context::mk(Z3_context ctx, bool owned, bool scoped) { return alloc(ref_context, ctx, owned, scoped); } void ref_context::dec_ref() { --m_count; if (0 == m_count) { if (m_owned) { if (m_dl) { Z3_fixedpoint_dec_ref(m_ctx, m_dl); } Z3_del_context(m_ctx); } dealloc(this); } } void ref_context::inc_ref() { ++m_count; } Z3_fixedpoint ref_context::dl() { if (!m_dl) { m_dl = Z3_mk_fixedpoint(m_ctx); Z3_fixedpoint_inc_ref(m_ctx, m_dl); } return m_dl; } // ------------------------------- // static functions static std::string CreateString( String^ string ) { std::string s; array^ bytes = Encoding::Convert( Encoding::Unicode, Encoding::ASCII, Encoding::Unicode->GetBytes(string) ); for (int i = 0; i < bytes->Length; ++i) { s += bytes[i]; } return s; } bool Z3Log::Open(String^ filename) { m_open = true; return Z3_TRUE == Z3_open_log(CreateString(filename).c_str()); } void Z3Log::Append(String^ s) { Z3_append_log(CreateString(s).c_str()); } void Z3Log::Close() { m_open = false; Z3_close_log(); } template class scoped_array { public: scoped_array(unsigned length) : m_length(length), m_data(new T[length]) { } scoped_array(array^ a) { m_length = a?a->Length:0; m_data = a?(new T[m_length]):0; for (unsigned i = 0; i < m_length; ++i) { m_data[i] = a[i]; } } virtual ~scoped_array() { delete[] m_data; } T* c_ptr() { return m_data; } T const* c_ptr() const { return m_data; } T& operator[](int i) { return m_data[i]; } unsigned size() { return m_length; } protected: unsigned m_length; T* m_data; }; template class scoped_Z3_ast_array : public scoped_array { public: scoped_Z3_ast_array(array^ asts) : scoped_array((!asts)?0:asts->Length) { for (unsigned i = 0; i < m_length; ++i) { c_ptr()[i] = static_cast(asts[i].ToPointer()); } } scoped_Z3_ast_array(int length) : scoped_array(length) {} }; class scoped_Z3_symbol_array : public scoped_array { public: scoped_Z3_symbol_array(array^ symbols) : scoped_array((!symbols)?0:symbols->Length) { for (unsigned i = 0; i < m_length; ++i) { c_ptr()[i] = symbols[i]->get(); } } scoped_Z3_symbol_array(Z3_context ctx, array^ symbols) : scoped_array((!symbols)?0:symbols->Length) { for (unsigned i = 0; i < m_length; ++i) { c_ptr()[i] = Z3_mk_string_symbol(ctx, CreateString(symbols[i]).c_str()); } } scoped_Z3_symbol_array(unsigned n): scoped_array(n) {} }; static void CopyFuncDecl(scoped_Z3_ast_array& src, array^ dst) { SASSERT(dst->Length == src.size()); for (unsigned i = 0; i < src.size(); ++i) { dst[i] = FuncDeclPtr(src[i]); } } static array^ MkArray(unsigned n, Z3_ast const* args) { array^ result = gcnew array(n); for (unsigned i = 0; i < n; ++i) { result[i] = TermPtr(args[i]); } return result; } static SearchFailureExplanation ConvertExplanation(Z3_search_failure f) { switch(f) { case Z3_NO_FAILURE: return SearchFailureExplanation::NoFailure; case Z3_UNKNOWN: return SearchFailureExplanation::Unknown; case Z3_TIMEOUT: return SearchFailureExplanation::TimeOut; case Z3_MEMOUT_WATERMARK: return SearchFailureExplanation::MemOut; case Z3_CANCELED: return SearchFailureExplanation::UserCanceled; case Z3_NUM_CONFLICTS: return SearchFailureExplanation::MaxConflicts; case Z3_THEORY: return SearchFailureExplanation::Theory; case Z3_QUANTIFIERS: return SearchFailureExplanation::Quantifiers; } return SearchFailureExplanation::Unknown; } //---------------------------------------- // Config Config::Config() { m_config = Z3_mk_config(); } Config::~Config() { if (m_config) { Z3_del_config(m_config); m_config = 0; } } Config::!Config() { if (m_config) { if (RawContext::m_error_handler ) { RawContext::m_error_handler->Handler(ErrorCode::NonDisposedConfig); } else { verbose_stream() << "WARNING: configuration was not disposed\n"; } } } void Config::SetParamValue(String^ param_id, String^ param_value) { Z3_set_param_value(m_config, CreateString(param_id).c_str(), CreateString(param_value).c_str()); } //---------------------------------------- // Model RawModel::~RawModel() { Reset(); } RawModel::!RawModel() { if (m_model) { if (RawContext::m_error_handler ) { RawContext::m_error_handler->Handler(ErrorCode::NonDisposedModel); } else { verbose_stream() << "WARNING: model was not disposed\n"; } } } void RawModel::Reset() { if (m_model != 0) { Z3_del_model(m_context(), m_model); m_context.dec_ref(); m_model = 0; } } array^ RawModel::GetModelConstants() { unsigned num_consts = Z3_get_model_num_constants(m_context(), m_model); array^ result = gcnew array(num_consts); for (unsigned i = 0; i < num_consts; ++i) { result[i] = FuncDeclPtr(Z3_get_model_constant(m_context(), m_model, i)); } return result; } String^ RawContext::GetNumeralString(TermPtr v) { return gcnew String(Z3_get_numeral_string(ctx(), get_ast(v))); } int RawContext::GetNumeralInt(TermPtr v) { int result = 0; if (!Z3_get_numeral_int(ctx(), get_ast(v), &result)) { throw gcnew System::ArgumentException("Expecting value of integer type"); } return result; } bool RawContext::TryGetNumeralInt(TermPtr v, int% i) { int result = 0; if (!Z3_get_numeral_int(ctx(), get_ast(v), &result)) { return false; } i = result; return true; } unsigned RawContext::GetNumeralUInt(TermPtr v) { unsigned result = 0; if (!Z3_get_numeral_uint(ctx(), get_ast(v), &result)) { throw gcnew System::ArgumentException("Expecting TermPtr of unsigned integer type"); } return result; } bool RawContext::TryGetNumeralUInt(TermPtr v, unsigned% u) { unsigned result = 0; if (!Z3_get_numeral_uint(ctx(), get_ast(v), &result)) { return false; } u = result; return true; } __int64 RawContext::GetNumeralInt64(TermPtr v) { __int64 result = 0; if (!Z3_get_numeral_int64(ctx(), get_ast(v), &result)) { throw gcnew System::ArgumentException("Expecting value of signed 64 bit integer type"); } return result; } bool RawContext::TryGetNumeralInt64(TermPtr v, __int64% i) { __int64 result = 0; if (!Z3_get_numeral_int64(ctx(), get_ast(v), &result)) { return false; } i = result; return true; } unsigned __int64 RawContext::GetNumeralUInt64(TermPtr v) { unsigned __int64 result = 0; if (!Z3_get_numeral_uint64(ctx(), get_ast(v), &result)) { throw gcnew System::ArgumentException("Expecting value of unsigned 64 bit integer type"); } return result; } bool RawContext::TryGetNumeralUInt64(TermPtr v, unsigned __int64% u) { unsigned __int64 result = 0; if (!Z3_get_numeral_uint64(ctx(), get_ast(v), &result)) { return false; } u = result; return true; } bool RawContext::TryGetNumeral(TermPtr v, [Out] __int64% num, [Out] __int64% den) { __int64 _num, _den; if (!Z3_get_numeral_rational_int64(ctx(), get_ast(v), &_num, &_den)) { return false; } num = _num; den = _den; return true; } void RawContext::GetNumeral(TermPtr v, [Out] System::Numerics::BigInteger% num, [Out] System::Numerics::BigInteger% den) { rational r; if (!Z3_get_numeral_rational(ctx(), get_ast(v), r)) { Z3_error_handler(Z3_INVALID_ARG); return; } rational d = denominator(r); rational n = numerator(r); rational ten(10); bool is_neg = false; SASSERT(!d.is_neg()); if (n.is_neg()) { is_neg = true; n = -n; } num = 0; System::Numerics::BigInteger mul = 1; while (n.is_pos()) { num += mul * mod(n,ten).get_unsigned(); n = div(n,ten); mul *= 10; } if (is_neg) { num = -num; } den = 0; mul = 1; while (d.is_pos()) { den += mul * mod(d,ten).get_unsigned(); d = div(d,ten); mul *= 10; } } LBool RawContext::GetBoolValue(TermPtr a) { switch (Z3_get_bool_value(ctx(), get_ast(a))) { case Z3_L_FALSE: return LBool::False; case Z3_L_UNDEF: return LBool::Undef; case Z3_L_TRUE: return LBool::True; default: UNREACHABLE(); return LBool::Undef; } } bool RawModel::TryGetArrayValue(TermPtr v, RawArrayValue^% av) { unsigned num_entries; if (!Z3_is_array_value(m_context(), m_model, get_ast(v), & num_entries)) { return false; } scoped_Z3_ast_array _indices(num_entries); scoped_Z3_ast_array _values(num_entries); Z3_ast else_value; Z3_get_array_value(m_context(), m_model, get_ast(v), num_entries, _indices.c_ptr(), _values.c_ptr(), &else_value); av = gcnew RawArrayValue(); av->Domain = gcnew array(num_entries); av->Range = gcnew array(num_entries); av->ElseCase = TermPtr(else_value); for (unsigned i = 0; i < num_entries; ++i) { av->Domain[i] = TermPtr(_indices[i]); av->Range[i] = TermPtr(_values[i]); } return true; } TermPtr RawContext::GetAssignments() { return TermPtr(Z3_get_context_assignment(ctx())); } TermPtr RawContext::UpdateTerm(TermPtr t, array^ new_args) { scoped_Z3_ast_array _new_args(new_args); return TermPtr(Z3_update_term(ctx(), get_ast(t), _new_args.size(), _new_args.c_ptr())); } Dictionary^ RawModel::GetFunctionGraphs() { if (m_graphs) { return m_graphs; } SASSERT(m_model); unsigned _num_funs = Z3_get_model_num_funcs(m_context(), m_model); Dictionary^ graphs = gcnew Dictionary(); for (unsigned i = 0; i < _num_funs; ++i) { unsigned num_entries = Z3_get_model_func_num_entries(m_context(), m_model, i); FuncDeclPtr decl = FuncDeclPtr(Z3_get_model_func_decl(m_context(), m_model, i)); RawFunctionGraph^ graph = gcnew RawFunctionGraph(); graphs[decl] = graph; graph->Declaration = decl; graph->Else = TermPtr(Z3_get_model_func_else(m_context(), m_model, i)); graph->Entries = gcnew array(num_entries); for (unsigned j = 0; j < num_entries; ++j) { unsigned num_args = Z3_get_model_func_entry_num_args(m_context(), m_model, i, j); graph->Entries[j] = gcnew RawFunctionEntry(); graph->Entries[j]->Arguments = gcnew array(num_args); for (unsigned k = 0; k < num_args; ++k) { graph->Entries[j]->Arguments[k] = TermPtr(Z3_get_model_func_entry_arg(m_context(), m_model, i, j, k)); } graph->Entries[j]->Result = TermPtr(Z3_get_model_func_entry_value(m_context(), m_model, i, j)); } } m_graphs = graphs; return graphs; } TermPtr RawModel::Eval(TermPtr t) { Z3_ast v = 0; if (!Z3_eval(m_context(), m_model, get_ast(t), &v)) { return IntPtr::Zero; } return TermPtr(v); } TermPtr RawModel::Eval(FuncDeclPtr decl, array^ args) { Z3_ast v = 0; scoped_Z3_ast_array _args(args); if (!Z3_eval_decl(m_context(), m_model, get_func_decl(decl), _args.size(), _args.c_ptr(), &v)) { return IntPtr::Zero; } return TermPtr(v); } String^ RawModel::ToString() { return gcnew String(Z3_model_to_string(m_context(), m_model)); } void RawModel::Display(System::IO::TextWriter^ w) { w->Write(ToString()); } RawTheory^ RawContext::MkTheory(String^ name) { return gcnew RawTheory(*m_context, name); } void RawContext::RegisterRelation(FuncDeclPtr r) { Z3_fixedpoint_register_relation(ctx(), dl(), get_func_decl(r)); } void RawContext::AddRule(TermPtr term, Symbol^ name) { Z3_fixedpoint_add_rule(ctx(), dl(), get_ast(term), name?name->get():0); } LBool RawContext::Query(TermPtr query) { switch(Z3_fixedpoint_query(ctx(), dl(), get_ast(query))) { case Z3_L_FALSE: return LBool::False; case Z3_L_TRUE: return LBool::True; default: return LBool::Undef; } } String^ RawContext::GetQueryStatus() { return gcnew String(Z3_fixedpoint_get_reason_unknown(ctx(),dl())); } TermPtr RawContext::GetQueryAnswer() { return TermPtr(Z3_fixedpoint_get_answer(ctx(),dl())); } static void fixedpoint_assign_callback(void* c, Z3_func_decl f, unsigned n, Z3_ast const* _args, unsigned m, Z3_ast const* outs) { RawContext::fixedpoint_assign_callback(c, f, n, _args, m, outs); } static void fixedpoint_apply_callback(void* c, Z3_func_decl f, unsigned n, Z3_ast const* _args, Z3_ast* out) { RawContext::fixedpoint_apply_callback(c, f, n, _args, out); } void RawContext::init_fixedpoint_callbacks() { if (contexts == nullptr) { contexts = gcnew Dictionary(); } if (m_fixedpoint_gch == IntPtr::Zero) { int id = contexts->Count; GCHandle h = GCHandle::Alloc(id, GCHandleType::Pinned); contexts[h] = this; m_fixedpoint_gch = GCHandle::ToIntPtr(h); Z3_fixedpoint_init(ctx(), dl(), m_fixedpoint_gch.ToPointer()); Z3_fixedpoint_set_reduce_assign_callback(ctx(), dl(), ::fixedpoint_assign_callback); Z3_fixedpoint_set_reduce_app_callback(ctx(), dl(), ::fixedpoint_apply_callback); } } void RawContext::fixedpoint_assign_callback(void* ud, Z3_func_decl f, unsigned n, Z3_ast const* args, unsigned m, Z3_ast const* outs) { RawContext^ ctx = contexts[GCHandle::FromIntPtr(IntPtr(ud))]; if (ctx->m_fixedpoint_assign != nullptr) { array^ _args = MkArray(n, args); array^ _outs = MkArray(m, outs); ctx->m_fixedpoint_assign(TermPtr(f), _args, _outs); } } void RawContext::fixedpoint_apply_callback(void* ud, Z3_func_decl f, unsigned n, Z3_ast const* args, Z3_ast* out) { RawContext^ ctx = contexts[GCHandle::FromIntPtr(IntPtr(ud))]; if (ctx->m_fixedpoint_apply != nullptr) { array^ _args = MkArray(n, args); TermPtr r = ctx->m_fixedpoint_apply(TermPtr(f), _args); if (out) *out = get_ast(r); } } String^ RawContext::FixedpointToString(array^ queries) { scoped_Z3_ast_array _queries(queries); return gcnew String(Z3_fixedpoint_to_string( ctx(), dl(), _queries.size(), _queries.c_ptr())); } array^ RawContext::SimplifyFixedpointRules(array^ rules, array^ output_predicates) { scoped_Z3_ast_array _rules(rules); scoped_Z3_ast_array _outputs(output_predicates); Z3_ast_vector new_rules = Z3_fixedpoint_simplify_rules( ctx(), dl(), _rules.size(), _rules.c_ptr(), _outputs.size(), _outputs.c_ptr()); unsigned num_rules = Z3_ast_vector_size(ctx(), new_rules); Z3_ast_vector_inc_ref(ctx(), new_rules); array^ result = gcnew array(num_rules); for (unsigned i = 0; i < num_rules; ++i) { result[i] = TermPtr(Z3_ast_vector_get(ctx(), new_rules, i)); } Z3_ast_vector_dec_ref(ctx(), new_rules); return result; } //---------------------------------------- // RawContext static void error_handler(Z3_context ctx, Z3_error_code c) { ErrorCode code; switch(c) { case Z3_OK: code = ErrorCode::Ok; break; case Z3_SORT_ERROR: code = ErrorCode::TypeError; break; case Z3_IOB: code = ErrorCode::IndexOutOfBounds; break; case Z3_INVALID_ARG: code = ErrorCode::InvalidArgument; break; case Z3_PARSER_ERROR: code = ErrorCode::ParserError; break; case Z3_NO_PARSER: code = ErrorCode::NoParser; break; case Z3_INVALID_PATTERN: code = ErrorCode::InvalidPattern; break; case Z3_MEMOUT_FAIL: throw gcnew OutOfMemoryException(); case Z3_INTERNAL_FATAL: code = ErrorCode::InternalFatal; break; case Z3_INVALID_USAGE: code = ErrorCode::InvalidUsage; break; case Z3_FILE_ACCESS_ERROR: code = ErrorCode::FileAccessError; break; default: UNREACHABLE(); code = ErrorCode::InvalidArgument; break; } if (RawContext::m_error_handler ) { RawContext::m_error_handler->Handler(code); } // we throw if you don't throw gcnew Z3Error(code); } // ----------------------------- // LabeledLiterals LabeledLiterals::!LabeledLiterals() { if (m_labels) { if (RawContext::m_error_handler ) { RawContext::m_error_handler->Handler(ErrorCode::NonDisposedLiterals); } else { verbose_stream() << "WARNING: labeled literals have not been disposed\n"; } } } // ----------------------------- // RawTheory void RawTheory::static_delete_callback(Z3_theory th) { RawTheory^ theory = GetTheory(th); if (theory->delete_handler) { theory->delete_handler(); } Z3_theory_data td = Z3_theory_get_ext_data(th); theories->Remove(GCHandle::FromIntPtr(IntPtr(td))); GCHandle::FromIntPtr(IntPtr(td)).Free(); } static void static_delete_callback(Z3_theory th) { RawTheory::static_delete_callback(th); } RawTheory::RawTheory(ref_context& ctx, String^ name): m_context(ctx), m_name(name) { if (!theories) theories = gcnew Dictionary(); int id = theories->Count; GCHandle h = GCHandle::Alloc(id, GCHandleType::Pinned); theories[h] = this; IntPtr gch = GCHandle::ToIntPtr(h); m_theory = Z3_mk_theory(ctx(), CreateString(name).c_str(), gch.ToPointer()); m_context.inc_ref(); Z3_set_delete_callback(m_theory, ::static_delete_callback); } RawTheory::~RawTheory() { m_context.dec_ref(); } Z3_bool RawTheory::reduce_eq_callback(Z3_theory th, Z3_ast a, Z3_ast b, Z3_ast* r) { RawTheory^ theory = GetTheory(th); TermPtr res = theory->reduce_eq(TermPtr(a), TermPtr(b)); if (res != TermPtr::Zero) { *r = get_ast(res); } return res != TermPtr::Zero; } static Z3_bool reduce_eq_callback(Z3_theory th, Z3_ast a, Z3_ast b, Z3_ast* r) { return RawTheory::reduce_eq_callback(th, a, b, r); } void RawTheory::set_reduce_eq(Func2^ value) { reduce_eq = value; Z3_set_reduce_eq_callback(m_theory, ::reduce_eq_callback); } Z3_bool RawTheory::reduce_app_callback(Z3_theory th, Z3_func_decl f, unsigned num_args, Z3_ast const args[], Z3_ast* r) { RawTheory^ theory = GetTheory(th); array^ argv = MkArray(num_args, args); TermPtr res = theory->reduce_app(TermPtr(f), argv); if (r && res != TermPtr::Zero) { *r = get_ast(res); } return res != TermPtr::Zero; } static Z3_bool reduce_app_callback(Z3_theory th, Z3_func_decl f, unsigned num_args, Z3_ast const args[], Z3_ast* r) { return RawTheory::reduce_app_callback(th, f, num_args, args, r); } void RawTheory::set_reduce_app(Func2^, TermPtr>^ value) { reduce_app = value; Z3_set_reduce_app_callback(m_theory, ::reduce_app_callback); } Z3_bool RawTheory::reduce_distinct_callback(Z3_theory th, unsigned n, Z3_ast const args[], Z3_ast* r) { RawTheory^ theory = GetTheory(th); TermPtr res = theory->reduce_distinct(MkArray(n, args)); if (r && res != TermPtr::Zero) { *r = get_ast(res); } return res != TermPtr::Zero; } static Z3_bool reduce_distinct_callback(Z3_theory th, unsigned n, Z3_ast const args[], Z3_ast* r) { return RawTheory::reduce_distinct_callback(th, n, args, r); } void RawTheory::set_reduce_distinct(Func1^, TermPtr>^ value) { reduce_distinct = value; Z3_set_reduce_distinct_callback(m_theory, ::reduce_distinct_callback); } static void new_relevant_callback(Z3_theory t, Z3_ast a) { RawTheory::GetTheory(t)->new_relevant(TermPtr(a)); } void RawTheory::set_new_relevant(Action^ value) { new_relevant = value; Z3_set_new_relevant_callback(m_theory, ::new_relevant_callback); } static void new_app_callback(Z3_theory t, Z3_ast a) { RawTheory::GetTheory(t)->new_app(TermPtr(a)); } void RawTheory::set_new_app(Action^ value) { new_app = value; Z3_set_new_app_callback(m_theory, ::new_app_callback); } static void new_elem_callback(Z3_theory t, Z3_ast a) { RawTheory::GetTheory(t)->new_elem(TermPtr(a)); } void RawTheory::set_new_elem(Action^ value) { new_elem = value; Z3_set_new_elem_callback(m_theory, ::new_elem_callback); } static void init_search_callback(Z3_theory t) { RawTheory::GetTheory(t)->init_search(); } void RawTheory::set_init_search(Action0^ value) { init_search = value; Z3_set_init_search_callback(m_theory, ::init_search_callback); } static void push_callback(Z3_theory t) { RawTheory::GetTheory(t)->push(); } void RawTheory::set_push(Action0^ value) { push = value; Z3_set_push_callback(m_theory, ::push_callback); } static void pop_callback(Z3_theory t) { RawTheory::GetTheory(t)->pop(); } void RawTheory::set_pop(Action0^ value) { pop = value; Z3_set_pop_callback(m_theory, ::pop_callback); } static void reset_callback(Z3_theory t) { RawTheory::GetTheory(t)->reset(); } void RawTheory::set_reset(Action0^ value) { reset = value; Z3_set_reset_callback(m_theory, ::reset_callback); } static void restart_callback(Z3_theory t) { RawTheory::GetTheory(t)->restart(); } void RawTheory::set_restart(Action0^ value) { restart = value; Z3_set_restart_callback(m_theory, ::restart_callback); } static Z3_bool final_check_callback(Z3_theory t) { return RawTheory::GetTheory(t)->final_check(); } void RawTheory::set_final_check(Func0^ value) { final_check = value; Z3_set_final_check_callback(m_theory, ::final_check_callback); } static void new_eq_callback(Z3_theory t, Z3_ast a, Z3_ast b) { RawTheory::GetTheory(t)->new_eq(TermPtr(a), TermPtr(b)); } void RawTheory::set_new_eq(Action2^ value) { new_eq = value; Z3_set_new_eq_callback(m_theory, ::new_eq_callback); } static void new_diseq_callback(Z3_theory t, Z3_ast a, Z3_ast b) { RawTheory::GetTheory(t)->new_diseq(TermPtr(a), TermPtr(b)); } void RawTheory::set_new_diseq(Action2^ value) { new_diseq = value; Z3_set_new_diseq_callback(m_theory, ::new_diseq_callback); } static void new_assignment_callback(Z3_theory t, Z3_ast a, Z3_bool b) { RawTheory::GetTheory(t)->new_assignment(TermPtr(a), b?true:false); } void RawTheory::set_new_assignment(Action2^ value) { new_assignment = value; Z3_set_new_assignment_callback(m_theory, ::new_assignment_callback); } FuncDeclPtr RawTheory::MkFuncDecl(Symbol^ n, array^ domain, SortPtr range) { scoped_Z3_ast_array _domain(domain); return FuncDeclPtr(Z3_theory_mk_func_decl(m_context(), m_theory, n->get(), _domain.size(), _domain.c_ptr(), get_sort(range))); } SortPtr RawTheory::MkSort(String^ s) { return SortPtr(Z3_theory_mk_sort(m_context(), m_theory, Z3_mk_string_symbol(m_context(), CreateString(s).c_str()))); } TermPtr RawTheory::MkValue(String^ s, SortPtr srt) { Z3_symbol sym = Z3_mk_string_symbol(m_context(), CreateString(s).c_str()); return TermPtr(Z3_theory_mk_value(m_context(), m_theory, sym, get_sort(srt))); } TermPtr RawTheory::MkConstant(String^ s, SortPtr srt) { Z3_symbol sym = Z3_mk_string_symbol(m_context(), CreateString(s).c_str()); return TermPtr(Z3_theory_mk_constant(m_context(), m_theory, sym, get_sort(srt))); } FuncDeclPtr RawTheory::MkFuncDecl(String^ s, array^ domain, SortPtr range) { Z3_symbol sym = Z3_mk_string_symbol(m_context(), CreateString(s).c_str()); scoped_Z3_ast_array _domain(domain); return FuncDeclPtr(Z3_theory_mk_func_decl(m_context(), m_theory, sym, _domain.size(), _domain.c_ptr(), get_sort(range))); } // ----------------------------- // Constructor Constructor::Constructor( ref_context& context, String^ name, String^ tester, array^ field_names, array^ field_sorts, array^ field_refs ): m_context(context), m_constructor(0), m_name(name), m_tester_name(tester), m_field_names(field_names), m_field_sorts(field_sorts), m_field_refs(field_refs), m_constructor_decl(FuncDeclPtr()), m_tester(FuncDeclPtr()), m_accessors(nullptr) { m_context.inc_ref(); } Z3_constructor Constructor::Get() { if (m_constructor) { return m_constructor; } Z3_symbol _name = Z3_mk_string_symbol(m_context(), CreateString(m_name).c_str()); Z3_symbol _tester = Z3_mk_string_symbol(m_context(), CreateString(m_tester_name).c_str()); unsigned num_fields = (!m_field_names)?0:m_field_names->Length; scoped_Z3_symbol_array _field_names(m_context(), m_field_names); scoped_Z3_ast_array _field_sorts(m_field_sorts); scoped_array _field_refs(m_field_refs); SASSERT(_field_names.size() == _field_sorts.size()); SASSERT(_field_names.size() == _field_refs.size()); m_constructor = Z3_mk_constructor(m_context(), _name, _tester, num_fields, _field_names.c_ptr(), _field_sorts.c_ptr(), _field_refs.c_ptr()); return m_constructor; } Z3_constructor Constructor::Query() { Z3_constructor result = 0; if (!m_accessors) { SASSERT(m_constructor); result = m_constructor; unsigned num_fields = (!m_field_names)?0:m_field_names->Length; m_accessors = gcnew array(num_fields); Z3_func_decl constructor_decl, tester_decl; scoped_array accs(num_fields); Z3_query_constructor(m_context(), m_constructor, num_fields, &constructor_decl, &tester_decl, accs.c_ptr()); m_constructor_decl = FuncDeclPtr(constructor_decl); m_tester = FuncDeclPtr(tester_decl); for (unsigned i = 0; i < num_fields; ++i) { m_accessors[i] = FuncDeclPtr(accs[i]); } m_constructor = 0; } SASSERT(!m_constructor); return result; } Constructor::!Constructor() { SASSERT(!m_constructor); } Constructor::~Constructor() { SASSERT(!m_constructor); m_context.dec_ref(); } FuncDeclPtr Constructor::GetConstructor() { if (!m_constructor && !m_accessors) { throw gcnew Z3Error(ErrorCode::InvalidUsage); } Z3_constructor c = Query(); SASSERT(!c); return FuncDeclPtr(m_constructor_decl); } FuncDeclPtr Constructor::GetTester() { if (!m_constructor && !m_accessors) { throw gcnew Z3Error(ErrorCode::InvalidUsage); } Z3_constructor c = Query(); SASSERT(!c); return FuncDeclPtr(m_tester); } array^ Constructor::GetAccessors() { if (!m_constructor && !m_accessors) { throw gcnew Z3Error(ErrorCode::InvalidUsage); } Z3_constructor c = Query(); SASSERT(!c); return m_accessors; } // ----------------------------- // RawContext void RawContext::Init() { m_disposed = false; s_nonempty = false; if (s_todec == nullptr) { s_todec = gcnew List >(); s_monitor = gcnew IntPtr(0); } Z3_set_error_handler(ctx(), error_handler); } RawContext::RawContext(Config^ config) { m_context = ref_context::mk(Z3_mk_context(config->get()), true, true); Init(); } RawContext::RawContext(Config^ config, ReferenceCounted^ rc) { m_context = ref_context::mk(Z3_mk_context_rc(config->get()), true, false); Init(); } RawContext::RawContext() { m_context = ref_context::mk(Z3_mk_context(0), true, true); Init(); } void RawContext::SetContext(Z3_context ctx) { Reset(); m_context = ref_context::mk(ctx, false, true); } RawContext::!RawContext() { if (!m_disposed) { if (RawContext::m_error_handler ) { RawContext::m_error_handler->Handler(ErrorCode::NonDisposedContext); } else { verbose_stream() << "WARNING: context was not disposed\n"; } } } void RawContext::Reset() { System::Threading::Monitor::Enter(s_monitor); if (!m_disposed) { m_context->dec_ref(); m_disposed = true; } System::Threading::Monitor::Exit(s_monitor); } RawContext::~RawContext() { Reset(); } #include "..\lib\vector.h" #include "..\lib\trace.h" void RawContext::EnableDebugTrace(String^ tag) { static vector pinned; std::string s = CreateString(tag); pinned.push_back(new std::string(s)); enable_trace(pinned.back()->c_str()); } void RawContext::ToggleWarningMessages(bool enabled) { Z3_toggle_warning_messages(enabled); } void RawContext::UpdateParamValue(String^ p, String^ v) { Z3_update_param_value(ctx(), CreateString(p).c_str(), CreateString(v).c_str()); } String^ RawContext::GetParamValue(String^ p) { Z3_string vl = ""; if (!Z3_get_param_value(ctx(), CreateString(p).c_str(), &vl)) { throw gcnew Z3Error(ErrorCode::InvalidArgument); } return gcnew String(vl); } bool RawContext::SetLogic(String^ l) { return Z3_TRUE == Z3_set_logic(ctx(), CreateString(l).c_str()); } Symbol^ RawContext::MkSymbol(String^ s) { return gcnew Symbol(ctx(), Z3_mk_string_symbol(ctx(), CreateString(s).c_str())); } Symbol^ RawContext::MkSymbol(int i) { return gcnew Symbol(ctx(), Z3_mk_int_symbol(ctx(), i)); } SortPtr RawContext::MkSort(Symbol^ s) { return SortPtr(Z3_mk_uninterpreted_sort(ctx(), s->get())); } SortPtr RawContext::MkSort(String^ s) { return SortPtr(Z3_mk_uninterpreted_sort(ctx(), Z3_mk_string_symbol(ctx(), CreateString(s).c_str()))); } SortPtr RawContext::MkSort(int i) { return SortPtr(Z3_mk_uninterpreted_sort(ctx(), Z3_mk_int_symbol(ctx(), i))); } SortPtr RawContext::MkBoolSort() { return SortPtr(Z3_mk_bool_sort(ctx())); } SortPtr RawContext::MkIntSort() { return SortPtr(Z3_mk_int_sort(ctx())); } SortPtr RawContext::MkRealSort() { return SortPtr(Z3_mk_real_sort(ctx())); } SortPtr RawContext::MkBvSort(unsigned sz) { return SortPtr(Z3_mk_bv_sort(ctx(), sz)); } SortPtr RawContext::MkArraySort(SortPtr domain, SortPtr range) { return SortPtr(Z3_mk_array_sort(ctx(), get_sort(domain), get_sort(range))); } SortPtr RawContext::MkFiniteDomainSort(String^ s, unsigned __int64 domain_size) { return SortPtr(Z3_mk_finite_domain_sort(ctx(), Z3_mk_string_symbol(ctx(), CreateString(s).c_str()), domain_size)); } SortPtr RawContext::MkTupleSort( Symbol^ mk_tuple_name, array^ field_names, array^ field_types, FuncDeclPtr% mk_tuple_decl, array^ proj_decls ) { if (!field_names || !field_types || !proj_decls || field_names->Length != field_types->Length || field_names->Length != proj_decls->Length) { throw gcnew Z3Error(ErrorCode::InvalidArgument); } scoped_Z3_symbol_array syms(field_names); scoped_Z3_ast_array types(field_types); scoped_Z3_ast_array projs(field_names->Length); Z3_func_decl decl; Z3_sort ty = Z3_mk_tuple_sort( ctx(), mk_tuple_name->get(), syms.size(), syms.c_ptr(), types.c_ptr(), &decl, projs.c_ptr() ); mk_tuple_decl = FuncDeclPtr(decl); CopyFuncDecl(projs, proj_decls); return SortPtr(ty); } SortPtr RawContext::MkTupleSort( String^ mk_tuple_name, array^ field_names, array^ field_types, FuncDeclPtr% mk_tuple_decl, array^ proj_decls ) { Symbol^ tn = MkSymbol(mk_tuple_name); array^ fields = gcnew array(field_names->Length); for (int i = 0; i < fields->Length; ++i) { fields[i] = MkSymbol(field_names[i]); } return MkTupleSort(tn, fields, field_types, mk_tuple_decl, proj_decls); } SortPtr RawContext::MkEnumerationSort( String^ name, array^ enum_names, array^ enum_consts, array^ enum_testers) { Z3_symbol _name(Z3_mk_string_symbol(ctx(), CreateString(name).c_str())); scoped_Z3_symbol_array _enum_names(ctx(), enum_names); scoped_Z3_ast_array _enum_consts(enum_consts); scoped_Z3_ast_array _enum_testers(enum_testers); unsigned sz = _enum_names.size(); SASSERT(sz == _enum_consts.size()); SASSERT(sz == _enum_testers.size()); Z3_sort s = Z3_mk_enumeration_sort(ctx(), _name, sz, _enum_names.c_ptr(), _enum_consts.c_ptr(), _enum_testers.c_ptr()); CopyFuncDecl(_enum_consts, enum_consts); CopyFuncDecl(_enum_testers, enum_testers); return SortPtr(s); } SortPtr RawContext::MkListSort( String^ name, SortPtr elem_sort, FuncDeclPtr% nil_decl, FuncDeclPtr% is_nil_decl, FuncDeclPtr% cons_decl, FuncDeclPtr% is_cons_decl, FuncDeclPtr% head_decl, FuncDeclPtr% tail_decl ) { Z3_func_decl _nil_decl, _is_nil_decl, _cons_decl, _is_cons_decl, _head_decl, _tail_decl; Z3_symbol _name = Z3_mk_string_symbol(ctx(), CreateString(name).c_str()); Z3_sort _elem_sort = get_sort(elem_sort); Z3_sort s = Z3_mk_list_sort(ctx(), _name, _elem_sort, &_nil_decl, &_is_nil_decl, &_cons_decl, &_is_cons_decl, &_head_decl, &_tail_decl); is_nil_decl = FuncDeclPtr(_is_nil_decl); nil_decl = FuncDeclPtr(_nil_decl); is_cons_decl = FuncDeclPtr(_is_cons_decl); cons_decl = FuncDeclPtr(_cons_decl); head_decl = FuncDeclPtr(_head_decl); tail_decl = FuncDeclPtr(_tail_decl); return SortPtr(s); } Constructor^ RawContext::MkConstructor( String^ name, String^ tester, array^ field_names, array^ field_sorts, array^ field_refs ) { int l1 = (!field_names)?0:field_names->Length; int l2 = (!field_sorts)?0:field_sorts->Length; int l3 = (!field_refs)?0:field_refs->Length; if (l1 != l2 || l1 != l3) { throw gcnew Z3Error(ErrorCode::InvalidArgument); } return gcnew Constructor(*m_context, name, tester, field_names, field_sorts, field_refs); } SortPtr RawContext::MkDataType( String^ name, array^ constructors ) { Z3_symbol _name = Z3_mk_string_symbol(ctx(), CreateString(name).c_str()); scoped_array _cons(constructors->Length); for (int i = 0; i < constructors->Length; ++i) { _cons[i] = constructors[i]->Get(); } Z3_sort s = Z3_mk_datatype(ctx(), _name, _cons.size(), _cons.c_ptr()); for (int i = 0; i < constructors->Length; ++i) { Z3_constructor c = constructors[i]->Query(); Z3_del_constructor(ctx(), c); } return SortPtr(s); } array^ RawContext::MkDataTypes( array^ names, array^>^ constructors_list ) { if (!names || !constructors_list || names->Length != constructors_list->Length) { throw gcnew Z3Error(ErrorCode::InvalidArgument); } unsigned num_sorts = names->Length; scoped_array sort_names(num_sorts); scoped_array clist(num_sorts); scoped_array sort_sorts(num_sorts); array^ result = gcnew array(num_sorts); unsigned num_constructors = 0; for (unsigned j = 0; j < num_sorts; ++j) { num_constructors += constructors_list[j]->Length; } scoped_array constructor_vec(num_constructors); svector constructors_q; unsigned constructor_idx = 0; for (unsigned j = 0; j < num_sorts; ++j) { String^ name = names[j]; array^ constructors = constructors_list[j]; // add sort name Z3_symbol _name = Z3_mk_string_symbol(ctx(), CreateString(name).c_str()); sort_names[j] = _name; // create constructor_list scoped_array _cons(constructors->Length); for (int i = 0; i < constructors->Length; ++i) { _cons[i] = constructors[i]->Get(); constructor_vec[constructor_idx++] = _cons[i]; } Z3_constructor_list cl = Z3_mk_constructor_list(ctx(), _cons.size(), _cons.c_ptr()); clist[j] = cl; } Z3_mk_datatypes(ctx(), num_sorts, sort_names.c_ptr(), sort_sorts.c_ptr(), clist.c_ptr()); for (unsigned j = 0; j < num_sorts; ++j) { Z3_del_constructor_list(ctx(), clist[j]); result[j] = SortPtr(sort_sorts[j]); // populate the constructors array^ constructors = constructors_list[j]; for (int i = 0; i < constructors->Length; ++i) { constructors_q.push_back(constructors[i]->Query()); } } for (unsigned i = 0; i < constructors_q.size(); ++i) { Z3_constructor c = constructors_q[i]; if (c) { Z3_del_constructor(ctx(), c); } } return result; } FuncDeclPtr RawContext::MkFuncDecl(Symbol^ s, array^ domain, SortPtr range) { scoped_Z3_ast_array types(domain); return FuncDeclPtr(Z3_mk_func_decl(ctx(), s->get(), types.size(), types.c_ptr(), get_sort(range))); } FuncDeclPtr RawContext::MkFuncDecl(String^ s, array^ domain, SortPtr range) { scoped_Z3_ast_array types(domain); Z3_symbol sym = Z3_mk_string_symbol(ctx(), CreateString(s).c_str()); return FuncDeclPtr(Z3_mk_func_decl(ctx(), sym, types.size(), types.c_ptr(), get_sort(range))); } FuncDeclPtr RawContext::MkFuncDecl(Symbol^ s, SortPtr domain, SortPtr range) { Z3_sort dom[1] = { get_sort(domain) }; return FuncDeclPtr(Z3_mk_func_decl(ctx(), s->get(), 1, dom, get_sort(range))); } FuncDeclPtr RawContext::MkFuncDecl(Symbol^ s, SortPtr d1, SortPtr d2, SortPtr range) { Z3_sort dom[2] = { get_sort(d1), get_sort(d2) }; return FuncDeclPtr(Z3_mk_func_decl(ctx(), s->get(), 2, dom, get_sort(range))); } FuncDeclPtr RawContext::MkFuncDecl(String^ s, SortPtr domain, SortPtr range) { Z3_sort dom[1] = { get_sort(domain) }; Z3_symbol sym = Z3_mk_string_symbol(ctx(), CreateString(s).c_str()); return FuncDeclPtr(Z3_mk_func_decl(ctx(), sym, 1, dom, get_sort(range))); } FuncDeclPtr RawContext::MkFuncDecl(String^ s, SortPtr d1, SortPtr d2, SortPtr range) { Z3_symbol sym = Z3_mk_string_symbol(ctx(), CreateString(s).c_str()); Z3_sort dom[2] = { get_sort(d1), get_sort(d2) }; return FuncDeclPtr(Z3_mk_func_decl(ctx(), sym, 2, dom, get_sort(range))); } TermPtr RawContext::MkApp(FuncDeclPtr d, array^ args) { scoped_Z3_ast_array z3_args(args); return TermPtr(Z3_mk_app(ctx(), get_func_decl(d), z3_args.size(), z3_args.c_ptr())); } TermPtr RawContext::MkApp(FuncDeclPtr d, TermPtr arg) { Z3_ast args[1] = { get_ast(arg) }; return TermPtr(Z3_mk_app(ctx(), get_func_decl(d), 1, args)); } TermPtr RawContext::MkApp(FuncDeclPtr d, TermPtr arg1, TermPtr arg2) { Z3_ast args[2] = { get_ast(arg1), get_ast(arg2) }; return TermPtr(Z3_mk_app(ctx(), get_func_decl(d), 2, args)); } TermPtr RawContext::MkApp(FuncDeclPtr d, TermPtr arg1, TermPtr arg2, TermPtr arg3) { Z3_ast args[3] = { get_ast(arg1), get_ast(arg2), get_ast(arg3) }; return TermPtr(Z3_mk_app(ctx(), get_func_decl(d), 3, args)); } TermPtr RawContext::MkConst(FuncDeclPtr d) { return TermPtr(Z3_mk_app(ctx(),get_func_decl(d), 0, 0)); } TermPtr RawContext::MkConst(String^ s, SortPtr ty) { Z3_symbol sym = Z3_mk_string_symbol(ctx(),CreateString(s).c_str()); Z3_func_decl d = Z3_mk_func_decl(ctx(), sym, 0, 0, get_sort(ty)); return TermPtr(Z3_mk_app(ctx(), d, 0, 0)); } TermPtr RawContext::MkConst(Symbol^ s, SortPtr ty) { Z3_func_decl d = Z3_mk_func_decl(ctx(), s->get(), 0, 0, get_sort(ty)); return TermPtr(Z3_mk_app(ctx(), d, 0, 0)); } FuncDeclPtr RawContext::MkFreshFuncDecl(String^ prefix, array^ domain, SortPtr range) { scoped_Z3_ast_array types(domain); return FuncDeclPtr(Z3_mk_fresh_func_decl(ctx(), CreateString(prefix).c_str(), types.size(), types.c_ptr(), get_sort(range))); } TermPtr RawContext::MkFreshConst(String^ prefix, SortPtr ty) { return TermPtr(Z3_mk_fresh_const(ctx(), CreateString(prefix).c_str(), get_sort(ty))); } TermPtr RawContext::MkLabel(Symbol^ name, bool pos, TermPtr fml) { return TermPtr(Z3_mk_label(ctx(), name->get(), pos, get_ast(fml))); } TermPtr RawContext::MkEq(TermPtr l, TermPtr r) { return TermPtr(Z3_mk_eq(ctx(), get_ast(l), get_ast(r))); } TermPtr RawContext::MkDistinct(array^ _args) { scoped_Z3_ast_array args(_args); return TermPtr(Z3_mk_distinct(ctx(), args.size(), args.c_ptr())); } TermPtr RawContext::MkNot(TermPtr arg) { return TermPtr(Z3_mk_not(ctx(), get_ast(arg))); } TermPtr RawContext::MkIte(TermPtr t1, TermPtr t2, TermPtr t3) { return TermPtr(Z3_mk_ite(ctx(), get_ast(t1), get_ast(t2), get_ast(t3))); } #define MK_BINARY(fn, t1, t2) return TermPtr(Z3_mk_ ## fn (ctx(), get_ast(t1), get_ast(t2))) #define MK_UNARY(fn, t1) return TermPtr(Z3_mk_ ## fn (ctx(), get_ast(t1))) #define MK_NARY(fn, _args_) { scoped_Z3_ast_array my_args(_args_); return TermPtr(Z3_mk_ ## fn (ctx(), my_args.size(), my_args.c_ptr())); } TermPtr RawContext::MkIff(TermPtr t1, TermPtr t2) { MK_BINARY(iff, t1, t2); } TermPtr RawContext::MkImplies(TermPtr t1, TermPtr t2) { MK_BINARY(implies, t1, t2); } TermPtr RawContext::MkXor(TermPtr t1, TermPtr t2) { MK_BINARY(xor, t1, t2); } TermPtr RawContext::MkAnd(array^ args) { MK_NARY(and, args); } TermPtr RawContext::MkAnd(TermPtr arg1, TermPtr arg2) { Z3_ast args[2] = { get_ast(arg1), get_ast(arg2) }; return TermPtr(Z3_mk_and(ctx(), 2, args)); } TermPtr RawContext::MkOr(array^ args) { MK_NARY(or, args); } TermPtr RawContext::MkOr(TermPtr arg1, TermPtr arg2) { Z3_ast args[2] = { get_ast(arg1), get_ast(arg2) }; return TermPtr(Z3_mk_or(ctx(), 2, args)); } TermPtr RawContext::MkAdd(array^ args) { MK_NARY(add, args); } TermPtr RawContext::MkAdd(TermPtr arg1, TermPtr arg2) { Z3_ast args[2] = { get_ast(arg1), get_ast(arg2) }; return TermPtr(Z3_mk_add(ctx(), 2, args)); } TermPtr RawContext::MkMul(array^ args) { MK_NARY(mul, args); } TermPtr RawContext::MkMul(TermPtr arg1, TermPtr arg2) { Z3_ast args[2] = { get_ast(arg1), get_ast(arg2) }; return TermPtr(Z3_mk_mul(ctx(), 2, args)); } TermPtr RawContext::MkSub(array^ args) { MK_NARY(sub, args); } TermPtr RawContext::MkSub(TermPtr arg1, TermPtr arg2) { Z3_ast args[2] = { get_ast(arg1), get_ast(arg2) }; return TermPtr(Z3_mk_sub(ctx(), 2, args)); } TermPtr RawContext::MkUnaryMinus(TermPtr arg) { MK_UNARY(unary_minus, arg); } TermPtr RawContext::MkDiv(TermPtr arg1, TermPtr arg2) { MK_BINARY(div, arg1, arg2); } TermPtr RawContext::MkMod(TermPtr arg1, TermPtr arg2) { MK_BINARY(mod, arg1, arg2); } TermPtr RawContext::MkRem(TermPtr arg1, TermPtr arg2) { MK_BINARY(rem, arg1, arg2); } TermPtr RawContext::MkToReal(TermPtr arg) { MK_UNARY(int2real, arg); } TermPtr RawContext::MkToInt(TermPtr arg) { MK_UNARY(real2int, arg); } TermPtr RawContext::MkIsInt(TermPtr arg) { MK_UNARY(is_int, arg); } TermPtr RawContext::MkLt(TermPtr arg1, TermPtr arg2) { MK_BINARY(lt, arg1, arg2); } TermPtr RawContext::MkLe(TermPtr arg1, TermPtr arg2) { MK_BINARY(le, arg1, arg2); } TermPtr RawContext::MkGt(TermPtr arg1, TermPtr arg2) { MK_BINARY(gt, arg1, arg2); } TermPtr RawContext::MkGe(TermPtr arg1, TermPtr arg2) { MK_BINARY(ge, arg1, arg2); } TermPtr RawContext::MkBvNot(TermPtr t1) { MK_UNARY(bvnot, t1); } TermPtr RawContext::MkBvReduceAnd(TermPtr t1) { MK_UNARY(bvredand, t1); } TermPtr RawContext::MkBvReduceOr(TermPtr t1) { MK_UNARY(bvredor, t1); } TermPtr RawContext::MkBvAnd(TermPtr t1, TermPtr t2) { MK_BINARY(bvand, t1, t2); } TermPtr RawContext::MkBvOr(TermPtr t1, TermPtr t2) { MK_BINARY(bvor, t1, t2); } TermPtr RawContext::MkBvXor(TermPtr t1, TermPtr t2) { MK_BINARY(bvxor, t1, t2); } TermPtr RawContext::MkBvNand(TermPtr t1, TermPtr t2) { MK_BINARY(bvnand, t1, t2); } TermPtr RawContext::MkBvNor(TermPtr t1, TermPtr t2) { MK_BINARY(bvnor, t1, t2); } TermPtr RawContext::MkBvXnor(TermPtr t1, TermPtr t2) { MK_BINARY(bvxnor, t1, t2); } TermPtr RawContext::MkBvNeg(TermPtr t1) { MK_UNARY(bvneg, t1); } TermPtr RawContext::MkBvAdd(TermPtr t1, TermPtr t2) { MK_BINARY(bvadd, t1, t2); } TermPtr RawContext::MkBvSub(TermPtr t1, TermPtr t2) { MK_BINARY(bvsub, t1, t2); } TermPtr RawContext::MkBvMul(TermPtr t1, TermPtr t2) { MK_BINARY(bvmul, t1, t2); } TermPtr RawContext::MkBvUdiv(TermPtr t1, TermPtr t2) { MK_BINARY(bvudiv, t1, t2); } TermPtr RawContext::MkBvSdiv(TermPtr t1, TermPtr t2) { MK_BINARY(bvsdiv, t1, t2); } TermPtr RawContext::MkBvUrem(TermPtr t1, TermPtr t2) { MK_BINARY(bvurem, t1, t2); } TermPtr RawContext::MkBvSrem(TermPtr t1, TermPtr t2) { MK_BINARY(bvsrem, t1, t2); } TermPtr RawContext::MkBvSmod(TermPtr t1, TermPtr t2) { MK_BINARY(bvsmod, t1, t2); } TermPtr RawContext::MkBvUlt(TermPtr t1, TermPtr t2) { MK_BINARY(bvult, t1, t2); } TermPtr RawContext::MkBvSlt(TermPtr t1, TermPtr t2) { MK_BINARY(bvslt, t1, t2); } TermPtr RawContext::MkBvUle(TermPtr t1, TermPtr t2) { MK_BINARY(bvule, t1, t2); } TermPtr RawContext::MkBvSle(TermPtr t1, TermPtr t2) { MK_BINARY(bvsle, t1, t2); } TermPtr RawContext::MkBvUge(TermPtr t1, TermPtr t2) { MK_BINARY(bvuge, t1, t2); } TermPtr RawContext::MkBvSge(TermPtr t1, TermPtr t2) { MK_BINARY(bvsge, t1, t2); } TermPtr RawContext::MkBvUgt(TermPtr t1, TermPtr t2) { MK_BINARY(bvugt, t1, t2); } TermPtr RawContext::MkBvSgt(TermPtr t1, TermPtr t2) { MK_BINARY(bvsgt, t1, t2); } TermPtr RawContext::MkBvConcat(TermPtr t1, TermPtr t2) { MK_BINARY(concat, t1, t2); } TermPtr RawContext::MkBvExtract(unsigned high, unsigned low, TermPtr t) { return TermPtr(Z3_mk_extract(ctx(), high, low, get_ast(t))); } TermPtr RawContext::MkBvSignExt(unsigned i, TermPtr t) { return TermPtr(Z3_mk_sign_ext(ctx(), i, get_ast(t))); } TermPtr RawContext::MkBvZeroExt(unsigned i, TermPtr t) { return TermPtr(Z3_mk_zero_ext(ctx(), i, get_ast(t))); } TermPtr RawContext::MkBvRepeat(unsigned i, TermPtr t) { return TermPtr(Z3_mk_repeat(ctx(), i, get_ast(t))); } TermPtr RawContext::MkBvShl(TermPtr t1, TermPtr t2) { MK_BINARY(bvshl, t1, t2); } TermPtr RawContext::MkBvLshr(TermPtr t1, TermPtr t2) { MK_BINARY(bvlshr, t1, t2); } TermPtr RawContext::MkBvAshr(TermPtr t1, TermPtr t2) { MK_BINARY(bvashr, t1, t2); } TermPtr RawContext::MkBvRotateLeft(unsigned i, TermPtr t1) { return TermPtr(Z3_mk_rotate_left(ctx(), i, get_ast(t1))); } TermPtr RawContext::MkBvRotateRight(unsigned i, TermPtr t1) { return TermPtr(Z3_mk_rotate_right(ctx(), i, get_ast(t1))); } TermPtr RawContext::MkBvRotateLeft(TermPtr t1, TermPtr t2) { return TermPtr(Z3_mk_ext_rotate_left(ctx(), get_ast(t1), get_ast(t2))); } TermPtr RawContext::MkBvRotateRight(TermPtr t1, TermPtr t2) { return TermPtr(Z3_mk_ext_rotate_right(ctx(), get_ast(t1), get_ast(t2))); } TermPtr RawContext::MkInt2Bv(unsigned i, TermPtr t1) { return TermPtr(Z3_mk_int2bv(ctx(), i, get_ast(t1))); } TermPtr RawContext::MkBv2Int(TermPtr t1, bool is_signed) { return TermPtr(Z3_mk_bv2int(ctx(), get_ast(t1), is_signed)); } TermPtr RawContext::MkBvAddNoOverflow(TermPtr t1, TermPtr t2, bool is_signed) { return TermPtr(Z3_mk_bvadd_no_overflow(ctx(), get_ast(t1), get_ast(t2), is_signed)); } TermPtr RawContext::MkBvAddNoUnderflow(TermPtr t1, TermPtr t2) { return TermPtr(Z3_mk_bvadd_no_underflow(ctx(), get_ast(t1), get_ast(t2))); } TermPtr RawContext::MkBvSubNoOverflow(TermPtr t1, TermPtr t2) { return TermPtr(Z3_mk_bvsub_no_overflow(ctx(), get_ast(t1), get_ast(t2))); } TermPtr RawContext::MkBvSubNoUnderflow(TermPtr t1, TermPtr t2, bool is_signed) { return TermPtr(Z3_mk_bvsub_no_underflow(ctx(), get_ast(t1), get_ast(t2), is_signed)); } TermPtr RawContext::MkBvSDivNoOverflow(TermPtr t1, TermPtr t2) { return TermPtr(Z3_mk_bvsdiv_no_overflow(ctx(), get_ast(t1), get_ast(t2))); } TermPtr RawContext::MkBvNegNoOverflow(TermPtr t1) { return TermPtr(Z3_mk_bvneg_no_overflow(ctx(), get_ast(t1))); } TermPtr RawContext::MkBvMulNoOverflow(TermPtr t1, TermPtr t2, bool is_signed) { return TermPtr(Z3_mk_bvmul_no_overflow(ctx(), get_ast(t1), get_ast(t2), is_signed)); } TermPtr RawContext::MkBvMulNoUnderflow(TermPtr t1, TermPtr t2) { return TermPtr(Z3_mk_bvmul_no_underflow(ctx(), get_ast(t1), get_ast(t2))); } TermPtr RawContext::MkArraySelect(TermPtr a, TermPtr i) { return TermPtr(Z3_mk_select(ctx(), get_ast(a), get_ast(i))); } TermPtr RawContext::MkArrayStore(TermPtr a, TermPtr i, TermPtr v) { return TermPtr(Z3_mk_store(ctx(), get_ast(a), get_ast(i), get_ast(v))); } TermPtr RawContext::MkArrayMap(FuncDeclPtr d, array^ args) { scoped_Z3_ast_array _args(args); return TermPtr(Z3_mk_map(ctx(), get_func_decl(d), _args.size(), _args.c_ptr())); } TermPtr RawContext::MkArrayConst(SortPtr domain, TermPtr v) { return TermPtr(Z3_mk_const_array(ctx(), get_sort(domain), get_ast(v))); } TermPtr RawContext::MkArrayDefault(TermPtr a) { return TermPtr(Z3_mk_array_default(ctx(), get_ast(a))); } TermPtr RawContext::MkSetUnion(array^ sets) { scoped_Z3_ast_array _sets(sets); return TermPtr(Z3_mk_set_union(ctx(), _sets.size(), _sets.c_ptr())); } TermPtr RawContext::MkSetUnion(TermPtr set1, TermPtr set2) { Z3_ast args[2] = { get_ast(set1), get_ast(set2) }; return TermPtr(Z3_mk_set_union(ctx(), 2, args)); } TermPtr RawContext::MkSetIntersect(array^ sets) { scoped_Z3_ast_array _sets(sets); return TermPtr(Z3_mk_set_intersect(ctx(), _sets.size(), _sets.c_ptr())); } TermPtr RawContext::MkSetIntersect(TermPtr set1, TermPtr set2) { Z3_ast args[2] = { get_ast(set1), get_ast(set2) }; return TermPtr(Z3_mk_set_intersect(ctx(), 2, args)); } FuncDeclPtr RawContext::MkInjectiveFunction(String^ name, array^ domain, SortPtr range) { scoped_Z3_ast_array types(domain); Z3_symbol sym = Z3_mk_string_symbol(ctx(), CreateString(name).c_str()); return FuncDeclPtr(Z3_mk_injective_function(ctx(), sym, types.size(), types.c_ptr(), get_sort(range))); } FuncDeclPtr RawContext::MkInjectiveFunction(Symbol^ name, array^ domain, SortPtr range) { scoped_Z3_ast_array types(domain); return FuncDeclPtr(Z3_mk_injective_function(ctx(), name->get(), types.size(), types.c_ptr(), get_sort(range))); } TermPtr RawContext::MkNumeral(String^ numeral, SortPtr ty) { return TermPtr(Z3_mk_numeral(ctx(), CreateString(numeral).c_str(), get_sort(ty))); } TermPtr RawContext::MkNumeral(int n, SortPtr ty) { return TermPtr(Z3_mk_int(ctx(), n, get_sort(ty))); } TermPtr RawContext::MkNumeral(unsigned n, SortPtr ty) { return TermPtr(Z3_mk_unsigned_int(ctx(), n, get_sort(ty))); } TermPtr RawContext::MkNumeral(__int64 n, SortPtr ty) { return TermPtr(Z3_mk_int64(ctx(), n, get_sort(ty))); } TermPtr RawContext::MkNumeral(unsigned __int64 n, SortPtr ty) { return TermPtr(Z3_mk_unsigned_int64(ctx(), n, get_sort(ty))); } PatternPtr RawContext::MkPattern(array^ terms) { scoped_Z3_ast_array args(terms); return PatternPtr(Z3_mk_pattern(ctx(), args.size(), args.c_ptr())); } TermPtr RawContext::MkBound(unsigned index, SortPtr ty) { return TermPtr(Z3_mk_bound(ctx(), index, get_sort(ty))); } TermPtr RawContext::MkForall( unsigned weight, array^ patterns, array^ types, array^ names, TermPtr body ) { scoped_Z3_ast_array _patterns(patterns); scoped_Z3_ast_array _types(types); scoped_Z3_symbol_array _names(names); return TermPtr( Z3_mk_forall( ctx(), weight, _patterns.size(), _patterns.c_ptr(), _types.size(), _types.c_ptr(), _names.c_ptr(), get_ast(body) ) ); } TermPtr RawContext::MkForall( unsigned weight, array^ patterns, array^ types, array^ names, TermPtr body ) { if (!names) { throw gcnew Z3Error(ErrorCode::InvalidArgument); } array^ nameSymbols = gcnew array(names->Length); for (int i = 0; i < nameSymbols->Length; ++i) { nameSymbols[i] = MkSymbol(names[i]); } return MkForall(weight, patterns, types, nameSymbols, body); } TermPtr RawContext::MkForall( unsigned weight, array^ bound, array^ patterns, TermPtr body ) { scoped_Z3_ast_array _bound(bound); scoped_Z3_ast_array _patterns(patterns); return TermPtr( Z3_mk_forall_const( ctx(), weight, _bound.size(), _bound.c_ptr(), _patterns.size(), _patterns.c_ptr(), get_ast(body) )); } TermPtr RawContext::MkExists( unsigned weight, array^ patterns, array^ types, array^ names, TermPtr body ) { scoped_Z3_ast_array _patterns(patterns); scoped_Z3_ast_array _types(types); scoped_Z3_symbol_array _names(names); return TermPtr( Z3_mk_exists( ctx(), weight, _patterns.size(), _patterns.c_ptr(), _types.size(), _types.c_ptr(), _names.c_ptr(), get_ast(body) ) ); } TermPtr RawContext::MkExists( unsigned weight, array^ patterns, array^ types, array^ names, TermPtr body ) { if (!names) { throw gcnew Z3Error(ErrorCode::InvalidArgument); } array^ nameSymbols = gcnew array(names->Length); for (int i = 0; i < nameSymbols->Length; ++i) { nameSymbols[i] = MkSymbol(names[i]); } return MkExists(weight, patterns, types, nameSymbols, body); } TermPtr RawContext::MkExists( unsigned weight, array^ bound, array^ patterns, TermPtr body ) { scoped_Z3_ast_array _bound(bound); scoped_Z3_ast_array _patterns(patterns); return TermPtr( Z3_mk_exists_const( ctx(), weight, _bound.size(), _bound.c_ptr(), _patterns.size(), _patterns.c_ptr(), get_ast(body) )); } TermPtr RawContext::MkQuantifier( bool is_forall, unsigned weight, Symbol^ quantifier_id, Symbol^ skolem_id, array^ patterns, array^ no_patterns, array^ types, array^ names, TermPtr body ) { scoped_Z3_ast_array _patterns(patterns); scoped_Z3_ast_array _no_patterns(no_patterns); scoped_Z3_ast_array _types(types); scoped_Z3_symbol_array _names(names); return TermPtr( Z3_mk_quantifier_ex( ctx(), is_forall, weight, quantifier_id?quantifier_id->get():0, skolem_id?skolem_id->get():0, _patterns.size(), _patterns.c_ptr(), _no_patterns.size(), _no_patterns.c_ptr(), _types.size(), _types.c_ptr(), _names.c_ptr(), get_ast(body) ) ); } TermPtr RawContext::MkQuantifier( bool is_forall, unsigned weight, Symbol^ quantifier_id, Symbol^ skolem_id, array^ patterns, array^ no_patterns, array^ bound, TermPtr body ) { scoped_Z3_ast_array _patterns(patterns); scoped_Z3_ast_array _no_patterns(no_patterns); scoped_Z3_ast_array _bound(bound); return TermPtr( Z3_mk_quantifier_const_ex( ctx(), is_forall, weight, quantifier_id?quantifier_id->get():0, skolem_id?skolem_id->get():0, _bound.size(), _bound.c_ptr(), _patterns.size(), _patterns.c_ptr(), _no_patterns.size(), _no_patterns.c_ptr(), get_ast(body) ) ); } unsigned RawContext::GetTermId(TermPtr t) { return Z3_get_ast_id(ctx(), get_ast(t)); } unsigned RawContext::GetFuncDeclId(FuncDeclPtr t) { return Z3_get_func_decl_id(ctx(), get_func_decl(t)); } unsigned RawContext::GetSortId(SortPtr t) { return Z3_get_sort_id(ctx(), get_sort(t)); } SymbolKind RawContext::GetSymbolKind(Symbol^ s) { switch(Z3_get_symbol_kind(ctx(), s->get())) { case Z3_INT_SYMBOL: return SymbolKind::Int; case Z3_STRING_SYMBOL: return SymbolKind::String; default: UNREACHABLE(); } return SymbolKind::Int; } int RawContext::GetSymbolInt(Symbol^ s) { return Z3_get_symbol_int(ctx(), s->get()); } String^ Symbol::ToString() { return gcnew String(Z3_get_symbol_string(m_ctx, m_symbol)); } String^ RawContext::GetSymbolString(Symbol^ s) { return gcnew String(Z3_get_symbol_string(ctx(), s->get())); } bool RawContext::IsEq(TermPtr t1, TermPtr t2) { return Z3_TRUE == Z3_is_eq_ast(ctx(), get_ast(t1), get_ast(t2)); } bool RawContext::IsWellSorted(TermPtr t) { return Z3_is_well_sorted(ctx(), get_ast(t)) == Z3_TRUE; } TermKind RawContext::GetTermKind(TermPtr a) { switch(Z3_get_ast_kind(ctx(), get_ast(a))) { case Z3_NUMERAL_AST: return TermKind::Numeral; case Z3_APP_AST: return TermKind::App; case Z3_VAR_AST: return TermKind::Var; case Z3_QUANTIFIER_AST: return TermKind::Quantifier; case Z3_UNKNOWN_AST: return TermKind::Unknown; } UNREACHABLE(); return TermKind::Unknown; } DeclKind RawContext::GetDeclKind(FuncDeclPtr d) { switch(Z3_get_decl_kind(ctx(), get_func_decl(d))) { case Z3_OP_TRUE: return DeclKind::True; case Z3_OP_FALSE: return DeclKind::False; case Z3_OP_EQ: return DeclKind::Eq; case Z3_OP_DISTINCT: return DeclKind::Distinct; case Z3_OP_ITE: return DeclKind::Ite; case Z3_OP_AND: return DeclKind::And; case Z3_OP_OR: return DeclKind::Or; case Z3_OP_IFF: return DeclKind::Iff; case Z3_OP_XOR: return DeclKind::Xor; case Z3_OP_NOT: return DeclKind::Not; case Z3_OP_IMPLIES: return DeclKind::Implies; case Z3_OP_ANUM: return DeclKind::ArithNum; case Z3_OP_LE: return DeclKind::Le; case Z3_OP_GE: return DeclKind::Ge; case Z3_OP_LT: return DeclKind::Lt; case Z3_OP_GT: return DeclKind::Gt; case Z3_OP_ADD: return DeclKind::Add; case Z3_OP_SUB: return DeclKind::Sub; case Z3_OP_UMINUS: return DeclKind::Uminus; case Z3_OP_MUL: return DeclKind::Mul; case Z3_OP_DIV: return DeclKind::Div; case Z3_OP_IDIV: return DeclKind::IDiv; case Z3_OP_REM: return DeclKind::Rem; case Z3_OP_MOD: return DeclKind::Mod; case Z3_OP_TO_REAL: return DeclKind::ToReal; case Z3_OP_TO_INT: return DeclKind::ToInt; case Z3_OP_IS_INT: return DeclKind::IsInt; case Z3_OP_STORE: return DeclKind::Store; case Z3_OP_SELECT: return DeclKind::Select; case Z3_OP_CONST_ARRAY: return DeclKind::ConstArray; case Z3_OP_ARRAY_DEFAULT: return DeclKind::DefaultArray; case Z3_OP_ARRAY_MAP: return DeclKind::MapArray; case Z3_OP_SET_UNION: return DeclKind::Union; case Z3_OP_SET_INTERSECT: return DeclKind::Intersect; case Z3_OP_SET_DIFFERENCE: return DeclKind::Difference; case Z3_OP_SET_COMPLEMENT: return DeclKind::Complement; case Z3_OP_SET_SUBSET: return DeclKind::Subset; case Z3_OP_AS_ARRAY: return DeclKind::AsArray; case Z3_OP_BNUM: return DeclKind::BitNum; case Z3_OP_BIT1: return DeclKind::Bit1 ; case Z3_OP_BIT0: return DeclKind::Bit0 ; case Z3_OP_BNEG: return DeclKind::BNeg ; case Z3_OP_BADD: return DeclKind::BAdd ; case Z3_OP_BSUB: return DeclKind::BSub ; case Z3_OP_BMUL: return DeclKind::BMul ; case Z3_OP_BSDIV: return DeclKind::BSDiv ; case Z3_OP_BUDIV: return DeclKind::BUDiv ; case Z3_OP_BSREM: return DeclKind::BSRem ; case Z3_OP_BUREM: return DeclKind::BURem ; case Z3_OP_BSMOD: return DeclKind::BSMod ; // special functions to record the division by 0 cases // these are internal functions case Z3_OP_BSDIV0: return DeclKind::BSDiv0 ; case Z3_OP_BUDIV0: return DeclKind::BUDiv0 ; case Z3_OP_BSREM0: return DeclKind::BSRem0 ; case Z3_OP_BUREM0: return DeclKind::BURem0 ; case Z3_OP_BSMOD0: return DeclKind::BSMod0 ; case Z3_OP_ULEQ: return DeclKind::BULeq ; case Z3_OP_SLEQ: return DeclKind::BSLeq ; case Z3_OP_UGEQ: return DeclKind::BUGeq ; case Z3_OP_SGEQ: return DeclKind::BSGeq ; case Z3_OP_ULT: return DeclKind::BULt ; case Z3_OP_SLT: return DeclKind::BSLt ; case Z3_OP_UGT: return DeclKind::BUGt ; case Z3_OP_SGT: return DeclKind::BSGt ; case Z3_OP_BAND: return DeclKind::BAnd ; case Z3_OP_BOR: return DeclKind::BOr ; case Z3_OP_BNOT: return DeclKind::BNot; case Z3_OP_BXOR: return DeclKind::BXor ; case Z3_OP_BNAND: return DeclKind::BNand ; case Z3_OP_BNOR: return DeclKind::BNor ; case Z3_OP_BXNOR: return DeclKind::BXnor ; case Z3_OP_CONCAT: return DeclKind::BConcat ; case Z3_OP_SIGN_EXT: return DeclKind::BSignExt ; case Z3_OP_ZERO_EXT: return DeclKind::BZeroExt ; case Z3_OP_EXTRACT: return DeclKind::BExtract ; case Z3_OP_REPEAT: return DeclKind::BRepeat ; case Z3_OP_BREDOR: return DeclKind::BRedOr ; case Z3_OP_BREDAND: return DeclKind::BRedAnd ; case Z3_OP_BCOMP: return DeclKind::BComp ; case Z3_OP_BSHL: return DeclKind::BShl ; case Z3_OP_BLSHR: return DeclKind::BLShr ; case Z3_OP_BASHR: return DeclKind::BAShr ; case Z3_OP_ROTATE_LEFT: return DeclKind::BRotateLeft ; case Z3_OP_ROTATE_RIGHT: return DeclKind::BRotateRight ; case Z3_OP_EXT_ROTATE_LEFT: return DeclKind::BExtRotateLeft ; case Z3_OP_EXT_ROTATE_RIGHT: return DeclKind::BExtRotateRight ; case Z3_OP_INT2BV: return DeclKind::BInt2Bv ; case Z3_OP_BV2INT: return DeclKind::BBv2Int ; case Z3_OP_CARRY: return DeclKind::BCarry; case Z3_OP_XOR3: return DeclKind::BXor3; case Z3_OP_PR_ASSERTED: return DeclKind::PrAsserted ; case Z3_OP_PR_GOAL: return DeclKind::PrGoal ; case Z3_OP_PR_MODUS_PONENS: return DeclKind::PrModusPonens ; case Z3_OP_PR_REFLEXIVITY: return DeclKind::PrReflexivity ; case Z3_OP_PR_SYMMETRY: return DeclKind::PrSymmetry ; case Z3_OP_PR_TRANSITIVITY: return DeclKind::PrTransitivity ; case Z3_OP_PR_TRANSITIVITY_STAR: return DeclKind::PrTransitivityStar ; case Z3_OP_PR_MONOTONICITY: return DeclKind::PrMonotonicity ; case Z3_OP_PR_QUANT_INTRO: return DeclKind::PrQuantIntro ; case Z3_OP_PR_DISTRIBUTIVITY: return DeclKind::PrDistributivity ; case Z3_OP_PR_AND_ELIM: return DeclKind::PrAndElim ; case Z3_OP_PR_NOT_OR_ELIM: return DeclKind::PrNotOrElim ; case Z3_OP_PR_REWRITE: return DeclKind::PrRewrite ; case Z3_OP_PR_REWRITE_STAR: return DeclKind::PrRewriteStar ; case Z3_OP_PR_PULL_QUANT: return DeclKind::PrPullQuant ; case Z3_OP_PR_PULL_QUANT_STAR: return DeclKind::PrPullQuantStar ; case Z3_OP_PR_PUSH_QUANT: return DeclKind::PrPushQuant ; case Z3_OP_PR_ELIM_UNUSED_VARS: return DeclKind::PrElimUnusedVars ; case Z3_OP_PR_DER: return DeclKind::PrDer ; case Z3_OP_PR_QUANT_INST: return DeclKind::PrQuantInst ; case Z3_OP_PR_HYPOTHESIS: return DeclKind::PrHypothesis ; case Z3_OP_PR_LEMMA: return DeclKind::PrLemma ; case Z3_OP_PR_UNIT_RESOLUTION: return DeclKind::PrUnitResolution ; case Z3_OP_PR_IFF_TRUE: return DeclKind::PrIffTrue ; case Z3_OP_PR_IFF_FALSE: return DeclKind::PrIffFalse ; case Z3_OP_PR_COMMUTATIVITY: return DeclKind::PrCommutativity ; case Z3_OP_PR_DEF_AXIOM: return DeclKind::PrDefAxiom ; case Z3_OP_PR_DEF_INTRO: return DeclKind::PrDefIntro ; case Z3_OP_PR_APPLY_DEF: return DeclKind::PrApplyDef ; case Z3_OP_PR_IFF_OEQ: return DeclKind::PrIffOeq ; case Z3_OP_PR_NNF_POS: return DeclKind::PrNnfPos ; case Z3_OP_PR_NNF_NEG: return DeclKind::PrNnfNeg ; case Z3_OP_PR_NNF_STAR: return DeclKind::PrNnfStar ; case Z3_OP_PR_SKOLEMIZE: return DeclKind::PrSkolemize ; case Z3_OP_PR_CNF_STAR: return DeclKind::PrCnfStar ; case Z3_OP_PR_MODUS_PONENS_OEQ: return DeclKind::PrModusPonensOeq ; case Z3_OP_PR_TH_LEMMA: return DeclKind::PrThLemma ; case Z3_OP_LABEL: return DeclKind::Label; case Z3_OP_LABEL_LIT: return DeclKind::LabelLit; case Z3_OP_RA_STORE: return DeclKind::RaStore; case Z3_OP_RA_EMPTY: return DeclKind::RaEmpty; case Z3_OP_RA_IS_EMPTY: return DeclKind::RaIsEmpty; case Z3_OP_RA_JOIN: return DeclKind::RaJoin; case Z3_OP_RA_UNION: return DeclKind::RaUnion; case Z3_OP_RA_WIDEN: return DeclKind::RaWiden; case Z3_OP_RA_PROJECT: return DeclKind::RaProject; case Z3_OP_RA_FILTER: return DeclKind::RaFilter; case Z3_OP_RA_NEGATION_FILTER: return DeclKind::RaNegationFilter; case Z3_OP_RA_RENAME: return DeclKind::RaRename; case Z3_OP_RA_COMPLEMENT: return DeclKind::RaComplement; case Z3_OP_RA_SELECT: return DeclKind::RaSelect; case Z3_OP_RA_CLONE: return DeclKind::RaClone; case Z3_OP_UNINTERPRETED: return DeclKind::Uninterpreted; default: UNREACHABLE(); return DeclKind::Uninterpreted; } } array^ RawContext::GetDeclParameters(FuncDeclPtr d) { Z3_func_decl fd = get_func_decl(d); unsigned num_params = Z3_get_decl_num_parameters(ctx(), fd); array^ params = gcnew array(num_params); for (unsigned i = 0; i < num_params; ++i) { switch(Z3_get_decl_parameter_kind(ctx(), fd, i)) { case Z3_PARAMETER_INT: params[i] = gcnew IntParameter(Z3_get_decl_int_parameter(ctx(), fd, i)); break; case Z3_PARAMETER_DOUBLE: params[i] = gcnew DoubleParameter(Z3_get_decl_double_parameter(ctx(), fd, i)); break; case Z3_PARAMETER_RATIONAL: { Z3_string s = Z3_get_decl_rational_parameter(ctx(), fd, i); params[i] = gcnew RationalParameter(gcnew String(s)); break; } case Z3_PARAMETER_SYMBOL: { Z3_symbol s = Z3_get_decl_symbol_parameter(ctx(), fd, i); params[i] = gcnew SymbolParameter(gcnew Symbol(ctx(), s)); break; } case Z3_PARAMETER_SORT: params[i] = gcnew SortPtrParameter(SortPtr(Z3_get_decl_sort_parameter(ctx(), fd, i))); break; case Z3_PARAMETER_AST: params[i] = gcnew TermPtrParameter(TermPtr(Z3_get_decl_ast_parameter(ctx(), fd, i))); break; case Z3_PARAMETER_FUNC_DECL: params[i] = gcnew FuncDeclPtrParameter(FuncDeclPtr(Z3_get_decl_func_decl_parameter(ctx(), fd, i))); break; default: UNREACHABLE(); break; } } return params; } FuncDeclPtr RawContext::GetAppDecl(AppPtr a) { if (GetTermKind(a) != TermKind::App) { throw gcnew Z3Error(ErrorCode::InvalidArgument); } return FuncDeclPtr(Z3_get_app_decl(ctx(), get_const_ast(a))); } array^ RawContext::GetAppArgs(AppPtr a) { if (GetTermKind(a) != TermKind::App) { throw gcnew Z3Error(ErrorCode::InvalidArgument); } unsigned num_args = Z3_get_app_num_args(ctx(), get_const_ast(a)); array^ result = gcnew array(num_args); for (unsigned i = 0; i < num_args; ++i) { result[i] = TermPtr(Z3_get_app_arg(ctx(), get_const_ast(a), i)); } return result; } RawQuantifier^ RawContext::GetQuantifier(TermPtr a) { if (GetTermKind(a) != TermKind::Quantifier) { throw gcnew Z3Error(ErrorCode::InvalidArgument); } RawQuantifier^ t = gcnew RawQuantifier(); Z3_ast ast = get_ast(a); t->IsForall = Z3_TRUE == Z3_is_quantifier_forall(ctx(), ast); t->Weight = Z3_get_quantifier_weight(ctx(), ast); t->Patterns = gcnew array(Z3_get_quantifier_num_patterns(ctx(), ast)); t->NoPatterns = gcnew array(Z3_get_quantifier_num_no_patterns(ctx(), ast)); t->Sorts = gcnew array(Z3_get_quantifier_num_bound(ctx(), ast)); t->Names = gcnew array(Z3_get_quantifier_num_bound(ctx(), ast)); t->Body = TermPtr(Z3_get_quantifier_body(ctx(), ast)); for (int i = 0; i < t->Sorts->Length; ++i) { t->Sorts[i] = SortPtr(Z3_get_quantifier_bound_sort(ctx(), ast, i)); t->Names[i] = gcnew Symbol(ctx(), Z3_get_quantifier_bound_name(ctx(), ast, i)); } for (int i = 0; i < t->Patterns->Length; ++i) { t->Patterns[i] = PatternPtr(Z3_get_quantifier_pattern_ast(ctx(), ast, i)); } for (int i = 0; i < t->NoPatterns->Length; ++i) { t->NoPatterns[i] = TermPtr(Z3_get_quantifier_no_pattern_ast(ctx(), ast, i)); } return t; }; array^ RawContext::GetPatternTerms(PatternPtr p) { unsigned np = Z3_get_pattern_num_terms(ctx(), get_pattern(p)); array^ result = gcnew array(np); for (unsigned i = 0; i < np; ++i) { result[i] = TermPtr(Z3_get_pattern(ctx(), get_pattern(p), i)); } return result; } Symbol^ RawContext::GetDeclName(FuncDeclPtr d) { return gcnew Symbol(ctx(), Z3_get_decl_name(ctx(), get_func_decl(d))); } Symbol^ RawContext::GetSortName(SortPtr ty) { return gcnew Symbol(ctx(), Z3_get_sort_name(ctx(), get_sort(ty))); } SortPtr RawContext::GetSort(TermPtr a) { return SortPtr(Z3_get_sort(ctx(), get_ast(a))); } array^ RawContext::GetDomain(FuncDeclPtr d) { unsigned num_args = Z3_get_domain_size(ctx(), get_func_decl(d)); array^ result = gcnew array(num_args); for (unsigned i = 0; i < num_args; ++i) { result[i] = TermPtr(Z3_get_domain(ctx(), get_func_decl(d), i)); } return result; } SortPtr RawContext::GetRange(FuncDeclPtr d) { return SortPtr(Z3_get_range(ctx(), get_func_decl(d))); } SortKind RawContext::GetSortKind(SortPtr t) { switch(Z3_get_sort_kind(ctx(), get_sort(t))) { case Z3_UNINTERPRETED_SORT: return SortKind::Uninterpreted; case Z3_BOOL_SORT: return SortKind::Bool; case Z3_INT_SORT: return SortKind::Int; case Z3_REAL_SORT: return SortKind::Real; case Z3_BV_SORT: return SortKind::BitVector; case Z3_ARRAY_SORT: return SortKind::Array; case Z3_DATATYPE_SORT: return SortKind::Datatype; case Z3_UNKNOWN_SORT: return SortKind::Unknown; default: UNREACHABLE(); return SortKind::Unknown; } } SearchFailureExplanation RawContext::GetSearchFailureExplanation() { return ConvertExplanation(Z3_get_search_failure(ctx())); } unsigned RawContext::GetBvSortSize(SortPtr t) { return Z3_get_bv_sort_size(ctx(), get_sort(t)); } SortPtr RawContext::GetArraySortDomain(SortPtr t) { return SortPtr(Z3_get_array_sort_domain(ctx(), get_sort(t))); } SortPtr RawContext::GetArraySortRange(SortPtr t) { return SortPtr(Z3_get_array_sort_range(ctx(), get_sort(t))); } FuncDeclPtr RawContext::GetTupleConstructor(SortPtr t) { return FuncDeclPtr(Z3_get_tuple_sort_mk_decl(ctx(), get_sort(t))); } array^ RawContext::GetTupleFields(SortPtr t) { unsigned num_args = Z3_get_tuple_sort_num_fields(ctx(), get_sort(t)); array^ result = gcnew array(num_args); for (unsigned i = 0; i < num_args; ++i) { result[i] = FuncDeclPtr(Z3_get_tuple_sort_field_decl(ctx(), get_sort(t), i)); } return result; } void RawContext::Push() { Z3_push(ctx()); } void RawContext::Pop(unsigned num_scopes) { Z3_pop(ctx(), num_scopes); } unsigned RawContext::GetNumScopes() { return Z3_get_num_scopes(ctx()); } void RawContext::PersistTerm(TermPtr t, unsigned num_scopes) { Z3_persist_ast(ctx(), get_ast(t), num_scopes); } void RawContext::IncRef(IntPtr ast) { Z3_inc_ref(ctx(), get_ast(ast)); // decrement reference counts of whatever is gc'ed. if (s_nonempty) { System::Threading::Monitor::Enter(s_monitor); for (int i = 0; i < s_todec->Count; ++i) { AstPtr a = s_todec[i].Key; RawContext^ c = s_todec[i].Value; SASSERT(c->ref_context().is_ref_counted()); Z3_dec_ref(c->ctx(), get_ast(a)); c->ref_context().dec_ref(); } s_todec->Clear(); s_nonempty = false; System::Threading::Monitor::Exit(s_monitor); } } void RawContext::EnqueueDecRef(IntPtr ast) { System::Threading::Monitor::Enter(s_monitor); s_todec->Add(KeyValuePair(ast, this)); s_nonempty = true; System::Threading::Monitor::Exit(s_monitor); } void RawContext::AssertCnstr(TermPtr a) { Z3_assert_cnstr(ctx(), get_ast(a)); } LBool RawContext::CheckAndGetModel(RawModel^% m) { m = nullptr; Z3_model model = 0; Z3_lbool lb = Z3_check_and_get_model(ctx(), & model); if (model) { m = gcnew RawModel(*m_context, model); } else { m = nullptr; } return ToLBool(lb); } LBool RawContext::Check() { Z3_lbool lb = Z3_check(ctx()); return ToLBool(lb); } LBool RawContext::CheckAssumptions(RawModel^% m, array^ assumptions, TermPtr% proof, array^% core) { scoped_Z3_ast_array _assumptions(assumptions); scoped_Z3_ast_array _core(assumptions); unsigned core_size = 0; Z3_ast _proof = 0; Z3_model model = 0; Z3_lbool lb = Z3_check_assumptions( ctx(), _assumptions.size(), _assumptions.c_ptr(), &model, &_proof, &core_size, _core.c_ptr()); core = gcnew array(core_size); for (unsigned i = 0; i < core_size; ++i) { core[i] = TermPtr(_core[i]); } if(_proof) { proof = TermPtr(_proof); } if (model) { m = gcnew RawModel(*m_context, model); } return ToLBool(lb); } void RawContext::SoftCheckCancel() { Z3_soft_check_cancel(ctx()); } LBool RawContext::GetImpliedEqualities( [In] array^ terms, [Out] array^% class_ids) { scoped_Z3_ast_array _terms(terms); scoped_array _class_ids(_terms.size()); Z3_lbool lb = Z3_get_implied_equalities(ctx(), _terms.size(), _terms.c_ptr(), _class_ids.c_ptr()); class_ids = gcnew array(_terms.size()); for (unsigned i = 0; i < _terms.size(); ++i) { class_ids[i] = _class_ids[i]; } return ToLBool(lb); } LabeledLiterals^ RawContext::GetRelevantLabels() { Z3_literals lbls = Z3_get_relevant_labels(ctx()); return gcnew LabeledLiterals(*m_context, lbls); } LabeledLiterals^ RawContext::GetRelevantLiterals() { Z3_literals lbls = Z3_get_relevant_literals(ctx()); return gcnew LabeledLiterals(*m_context, lbls); } LabeledLiterals^ RawContext::GetGuessedLiterals() { Z3_literals lbls = Z3_get_guessed_literals(ctx()); return gcnew LabeledLiterals(*m_context, lbls); } void RawContext::BlockLiterals(LabeledLiterals^ lbls) { Z3_block_literals(ctx(), lbls->Get()); } TermPtr RawContext::Simplify(TermPtr a) { return TermPtr(Z3_simplify(ctx(), get_ast(a))); } String^ RawContext::ToString() { return gcnew String(Z3_context_to_string(ctx())); } void RawContext::SetPrintMode(PrintMode mode) { Z3_ast_print_mode m = Z3_PRINT_SMTLIB_FULL; switch(mode) { case PrintMode::SmtlibFull: m = Z3_PRINT_SMTLIB_FULL; break; case PrintMode::LowLevel: m = Z3_PRINT_LOW_LEVEL; break; case PrintMode::Smtlib2Compliant: m = Z3_PRINT_SMTLIB2_COMPLIANT; break; case PrintMode::SmtlibCompliant: m = Z3_PRINT_SMTLIB_COMPLIANT; break; default: UNREACHABLE(); break; } Z3_set_ast_print_mode(ctx(), m); } void RawContext::Display(System::IO::TextWriter^ w) { w->Write(ToString()); } String^ RawContext::BenchmarkToSmtlib( String^ name, String^ logic, String^ status, String^ attributes, array^ assumptions, TermPtr formula) { scoped_Z3_ast_array _assumptions(assumptions); return gcnew String(Z3_benchmark_to_smtlib_string( ctx(), (name )?CreateString(name).c_str():0, (logic )?CreateString(logic).c_str():0, (status )?CreateString(status).c_str():0, (attributes )?CreateString(attributes).c_str():0, _assumptions.size(), _assumptions.c_ptr(), get_ast(formula))); } void RawContext::ParseSmtlibString( String^ string, [In] array^ sorts, [In] array^ old_decls, [Out] array^% assumptions, [Out] array^% formulas, [Out] array^% new_decls, [Out] array^% new_sorts, [Out] String^% parser_out ) { scoped_Z3_ast_array _types(sorts); scoped_Z3_ast_array _decls(old_decls); scoped_Z3_symbol_array _sort_names(_types.size()); scoped_Z3_symbol_array _decl_names(_decls.size()); for (unsigned i = 0; i < _sort_names.size(); ++i) { _sort_names[i] = Z3_get_sort_name(ctx(), _types[i]); } for (unsigned i = 0; i < _decl_names.size(); ++i) { _decl_names[i] = Z3_get_decl_name(ctx(), _decls[i]); } try { Z3_parse_smtlib_string( ctx(), CreateString(string).c_str(), _types.size(), _sort_names.c_ptr(), _types.c_ptr(), _decls.size(), _decl_names.c_ptr(), _decls.c_ptr() ); } catch(...) { parser_out = gcnew String(Z3_get_smtlib_error(ctx())); throw; } parser_out = gcnew String(Z3_get_smtlib_error(ctx())); unsigned count = Z3_get_smtlib_num_formulas(ctx()); formulas = gcnew array(count); for (unsigned i = 0; i < count; ++i) { formulas[i] = TermPtr(Z3_get_smtlib_formula(ctx(), i)); } count = Z3_get_smtlib_num_assumptions(ctx()); assumptions = gcnew array(count); for (unsigned i = 0; i < count; ++i) { assumptions[i] = TermPtr(Z3_get_smtlib_assumption(ctx(), i)); } count = Z3_get_smtlib_num_decls(ctx()); new_decls = gcnew array(count); for (unsigned i = 0; i < count; ++i) { new_decls[i] = FuncDeclPtr(Z3_get_smtlib_decl(ctx(), i)); } count = Z3_get_smtlib_num_sorts(ctx()); new_sorts = gcnew array(count); for (unsigned i = 0; i < count; ++i) { new_sorts[i] = SortPtr(Z3_get_smtlib_sort(ctx(), i)); } } void RawContext::ParseSmtlibFile( String^ file, [In] array^ sorts, [In] array^ old_decls, [Out] array^% assumptions, [Out] array^% formulas, [Out] array^% new_decls, [Out] array^% new_sorts, [Out] String^% parser_out ) { scoped_Z3_ast_array _sorts(sorts); scoped_Z3_ast_array _decls(old_decls); scoped_Z3_symbol_array _sort_names(_sorts.size()); scoped_Z3_symbol_array _decl_names(_decls.size()); for (unsigned i = 0; i < _sort_names.size(); ++i) { _sort_names[i] = Z3_get_sort_name(ctx(), _sorts[i]); } for (unsigned i = 0; i < _decl_names.size(); ++i) { _decl_names[i] = Z3_get_decl_name(ctx(), _decls[i]); } try { Z3_parse_smtlib_file( ctx(), CreateString(file).c_str(), _sorts.size(), _sort_names.c_ptr(), _sorts.c_ptr(), _decls.size(), _decl_names.c_ptr(), _decls.c_ptr() ); } catch(...) { parser_out = gcnew String(Z3_get_smtlib_error(ctx())); throw; } parser_out = gcnew String(Z3_get_smtlib_error(ctx())); unsigned count = Z3_get_smtlib_num_formulas(ctx()); formulas = gcnew array(count); for (unsigned i = 0; i < count; ++i) { formulas[i] = TermPtr(Z3_get_smtlib_formula(ctx(), i)); } count = Z3_get_smtlib_num_assumptions(ctx()); assumptions = gcnew array(count); for (unsigned i = 0; i < count; ++i) { assumptions[i] = TermPtr(Z3_get_smtlib_assumption(ctx(), i)); } count = Z3_get_smtlib_num_decls(ctx()); new_decls = gcnew array(count); for (unsigned i = 0; i < count; ++i) { new_decls[i] = FuncDeclPtr(Z3_get_smtlib_decl(ctx(), i)); } count = Z3_get_smtlib_num_sorts(ctx()); new_sorts = gcnew array(count); for (unsigned i = 0; i < count; ++i) { new_sorts[i] = SortPtr(Z3_get_smtlib_sort(ctx(), i)); } } TermPtr RawContext::ParseZ3String(String^ s) { return TermPtr(Z3_parse_z3_string(ctx(), CreateString(s).c_str())); } TermPtr RawContext::ParseZ3File(String^ file) { return TermPtr(Z3_parse_z3_file(ctx(), CreateString(file).c_str())); } #define PROCESS_SMTLIB2(_fn) \ scoped_Z3_ast_array _sorts(sorts); \ scoped_Z3_ast_array _decls(decls); \ scoped_Z3_symbol_array _sort_names(_sorts.size()); \ scoped_Z3_symbol_array _decl_names(_decls.size()); \ for (unsigned i = 0; i < _sort_names.size(); ++i) { \ _sort_names[i] = Z3_get_sort_name(ctx(), _sorts[i]); \ std::cout << Z3_get_symbol_string(ctx(), _sort_names[i]) << "\n"; \ } \ for (unsigned i = 0; i < _decl_names.size(); ++i) { \ _decl_names[i] = Z3_get_decl_name(ctx(), _decls[i]); \ std::cout << Z3_get_symbol_string(ctx(), _decl_names[i]) << "\n"; \ } \ return TermPtr(_fn(ctx(), CreateString(s).c_str(), \ _sorts.size(), _sort_names.c_ptr(), _sorts.c_ptr(), \ _decls.size(), _decl_names.c_ptr(), _decls.c_ptr())); \ TermPtr RawContext::ParseSmtlib2String(String^ s, array^ sorts, array^ decls) { PROCESS_SMTLIB2(Z3_parse_smtlib2_string); } TermPtr RawContext::ParseSmtlib2File(String^ s, array^ sorts, array^ decls) { PROCESS_SMTLIB2(Z3_parse_smtlib2_file); } TermPtr RawContext::ExecSmtlib2String(String^ s, array^ sorts, array^ decls) { PROCESS_SMTLIB2(Z3_exec_smtlib2_string); } TermPtr RawContext::ExecSmtlib2File(String^ s, array^ sorts, array^ decls) { PROCESS_SMTLIB2(Z3_exec_smtlib2_file); } void RawContext::SetErrorHandler(IErrorHandler^ h) { m_error_handler = h; } String^ RawContext::GetErrorMessage(ErrorCode h) { Z3_error_code code; switch(h) { case ErrorCode::Ok: code = Z3_OK; break; case ErrorCode::TypeError: code = Z3_SORT_ERROR; break; case ErrorCode::IndexOutOfBounds: code = Z3_IOB; break; case ErrorCode::InvalidArgument: code = Z3_INVALID_ARG; break; case ErrorCode::ParserError: code = Z3_PARSER_ERROR; break; case ErrorCode::NoParser: code = Z3_NO_PARSER; break; case ErrorCode::InvalidUsage: code = Z3_INVALID_USAGE; break; case ErrorCode::InternalFatal: case ErrorCode::FileAccessError: code = Z3_INVALID_ARG; break; default: UNREACHABLE(); code = Z3_INVALID_ARG; } return gcnew String(Z3_get_error_msg(code)); } void RawContext::ResetMemory() { Z3_reset_memory(); } String^ RawContext::ToString(AstPtr a) { return gcnew String(Z3_ast_to_string(ctx(), get_ast(a))); } void RawContext::Display(System::IO::TextWriter^ w, AstPtr a) { w->Write(ToString(a)); } void RawContext::GetVersion(unsigned% major, unsigned% minor, unsigned% build_number, unsigned% version_number) { unsigned ma, mi, bn, vn; Z3_get_version(&ma,&mi,&bn,&vn); major = ma; minor = mi; build_number = bn; version_number = vn; } // ----------------------------- // Ast Ast::Ast(RawContext^ c, AstPtr a) : m_ast(a), m_ctx(c) { SASSERT(m_ast != IntPtr(0)); if (c->ref_context().is_ref_counted()) { c->IncRef(a); c->ref_context().inc_ref(); } } Ast::!Ast() { if (m_ctx->ref_context().is_ref_counted()) { m_ctx->EnqueueDecRef(m_ast); } } Ast::~Ast() {} bool Ast::Equals(Object^ obj) { if (!obj) { return false; } Ast^ a = dynamic_cast(obj); if (!a) { return false; } return a->GetPtr() == GetPtr(); } int Ast::GetHashCode() { return GetId(); } String^ Ast::ToString() { return m_ctx->ToString(m_ast); } int Ast::CompareTo(Object^ other) { Ast^ a = dynamic_cast(other); if (!a) { return -1; } return GetId() - a->GetId(); } #if 0 bool Ast::operator==(Object^ other) { return this->Equals(other); } bool Ast::operator!=(Object^ other) { return !this->Equals(other); } #endif String^ Sort::GetName() { return m_ctx->GetSymbolString(m_ctx->GetSortName(m_ast)); } String^ FuncDecl::GetDeclName() { return m_ctx->GetSymbolString(m_ctx->GetDeclName(m_ast)); } DeclKind FuncDecl::GetKind() { return m_ctx->GetDeclKind(m_ast); } // ---------------------------- // Term // Assumption: contexts are equal // Note: overloading && and || is possible, // but C# does not seem to perform the // correct type inference when they are used. Term^ Term::operator!(Term^ t) { return gcnew Term(t->m_ctx, t->m_ctx->MkNot(t())); } Term^ Term::operator+(Term^ t1, Term^ t2) { return gcnew Term(t1->m_ctx, t1->m_ctx->MkAdd(t1(), t2())); } Term^ Term::operator^(Term^ t1, Term^ t2) { return gcnew Term(t1->m_ctx, t1->m_ctx->MkXor(t1(), t2())); } Term^ Term::operator&(Term^ t1, Term^ t2) { return gcnew Term(t1->m_ctx, t1->m_ctx->MkAnd(t1(), t2())); } Term^ Term::operator|(Term^ t1, Term^ t2) { return gcnew Term(t1->m_ctx, t1->m_ctx->MkOr(t1(), t2())); } Term^ Term::operator*(Term^ t1, Term^ t2) { return gcnew Term(t1->m_ctx, t1->m_ctx->MkMul(t1(), t2())); } Term^ Term::operator-(Term^ t1, Term^ t2) { return gcnew Term(t1->m_ctx, t1->m_ctx->MkSub(t1(), t2())); } Term^ Term::operator/(Term^ t1, Term^ t2) { return gcnew Term(t1->m_ctx, t1->m_ctx->MkDiv(t1(), t2())); } Term^ Term::operator<(Term^ t1, Term^ t2) { return gcnew Term(t1->m_ctx, t1->m_ctx->MkLt(t1(), t2())); } Term^ Term::operator<=(Term^ t1, Term^ t2) { return gcnew Term(t1->m_ctx, t1->m_ctx->MkLe(t1(), t2())); } Term^ Term::operator>(Term^ t1, Term^ t2) { return gcnew Term(t1->m_ctx, t1->m_ctx->MkGt(t1(), t2())); } Term^ Term::operator>=(Term^ t1, Term^ t2) { return gcnew Term(t1->m_ctx, t1->m_ctx->MkGe(t1(), t2())); } Term^ Term::operator[](Term^ index) { return gcnew Term(m_ctx, m_ctx->MkArraySelect(m_ast, index())); } TermKind Term::GetKind() { return m_ctx->GetTermKind(m_ast); } FuncDecl^ Term::GetAppDecl() { return gcnew FuncDecl(m_ctx, m_ctx->GetAppDecl(m_ast)); } array^ Term::GetAppArgs() { return Context::CopyTermArray(m_ctx, m_ctx->GetAppArgs(m_ast)); } Sort^ Term::GetSort() { return gcnew Sort(m_ctx, m_ctx->GetSort(m_ast)); } String^ Term::GetNumeralString() { return m_ctx->GetNumeralString(m_ast); } unsigned Term::GetVarIndex() { return m_ctx->GetVarIndex(m_ast); } Quantifier^ Term::GetQuantifier() { return Context::GetQuantifier(m_ctx, this); } // ----------------------------- // Context LBool Context::CheckAndGetModel(Model^% m) { RawModel^ md = nullptr; LBool is_sat = m_ctx->CheckAndGetModel(md); if (md ) { m = gcnew Model(md, this); } else { md = nullptr; } return is_sat; } LBool Context::CheckAssumptions( Model^% m, array^ assumptions, Term^% proof, array^% core) { RawModel^ md = nullptr; array^ _core = nullptr; TermPtr _proof; LBool is_sat = m_ctx->CheckAssumptions(md, CopyArray(assumptions), _proof, _core); core = nullptr; proof = nullptr; m = nullptr; if (md ) { m = gcnew Model(md, this); } if (_proof != TermPtr()) { proof = gcnew Term(m_ctx, _proof); } if (_core ) { core = CopyTermArray(_core); } return is_sat; } void Context::SoftCheckCancel() { m_ctx->SoftCheckCancel(); } LBool Context::GetImpliedEqualities( [In] array^ terms, [Out] array^% class_ids) { return m_ctx->GetImpliedEqualities(CopyArray(terms), class_ids); } Quantifier^ Context::GetQuantifier(RawContext^ ctx, Term^ t) { RawQuantifier^ q0 = ctx->GetQuantifier(t()); Quantifier^ q = gcnew Quantifier(); q->IsForall = q0->IsForall; q->Weight = q0->Weight; q->Patterns = gcnew array(q0->Patterns->Length); for (int i = 0; i < q0->Patterns->Length; ++i) { q->Patterns[i] = gcnew Pattern(ctx, q0->Patterns[i]); } q->NoPatterns = gcnew array(q0->NoPatterns->Length); for (int i = 0; i < q0->NoPatterns->Length; ++i) { q->NoPatterns[i] = gcnew Term(ctx, q0->Patterns[i]); } q->Names = q0->Names; q->Body = gcnew Term(ctx, q0->Body); q->Sorts = CopySortArray(ctx, q0->Sorts); return q; } Sort^ Context::MkTupleSort( Symbol^ mk_tuple_name, array^ field_names, array^ field_types, FuncDecl^% mk_tuple_decl, array^ proj_decl ) { array^ ftypes = gcnew array(field_types->Length); for (int i = 0; i < field_types->Length; ++i) { ftypes[i] = field_types[i](); } array^ pdecls = gcnew array(proj_decl->Length); FuncDeclPtr mk_tupled; SortPtr res = m_ctx->MkTupleSort(mk_tuple_name, field_names, ftypes, mk_tupled, pdecls); for (int i = 0; i < pdecls->Length; ++i) { proj_decl[i] = gcnew FuncDecl(m_ctx,pdecls[i]); } mk_tuple_decl = gcnew FuncDecl(m_ctx,mk_tupled); return gcnew Sort(m_ctx,res); } Sort^ Context::MkTupleSort( String^ mk_tuple_name, array^ field_names, array^ field_types, FuncDecl^% mk_tuple_decl, array^ proj_decl ) { array^ ftypes = gcnew array(field_types->Length); for (int i = 0; i < field_types->Length; ++i) { ftypes[i] = field_types[i](); } array^ pdecls = gcnew array(proj_decl->Length); FuncDeclPtr mk_tupled; SortPtr res = m_ctx->MkTupleSort(mk_tuple_name, field_names, ftypes, mk_tupled, pdecls); for (int i = 0; i < pdecls->Length; ++i) { proj_decl[i] = gcnew FuncDecl(m_ctx,pdecls[i]); } mk_tuple_decl = gcnew FuncDecl(m_ctx,mk_tupled); return gcnew Sort(m_ctx,res); } Sort^ Context::MkEnumerationSort( String^ name, array^ enum_names, array^ enum_consts, array^ enum_testers) { array^ _enum_consts = CopyArray(enum_consts); array^ _enum_testers = CopyArray(enum_testers); SortPtr s = m_ctx->MkEnumerationSort(name, enum_names, _enum_consts, _enum_testers); for (int i = 0; i < enum_consts->Length; ++i) { enum_consts[i] = gcnew FuncDecl(m_ctx, _enum_consts[i]); enum_testers[i] = gcnew FuncDecl(m_ctx, _enum_testers[i]); } return gcnew Sort(m_ctx, s); } Sort^ Context::MkListSort( String^ name, Sort^ elem_sort, FuncDecl^% nil_decl, FuncDecl^% is_nil_decl, FuncDecl^% cons_decl, FuncDecl^% is_cons_decl, FuncDecl^% head_decl, FuncDecl^% tail_decl ) { FuncDeclPtr a, b, c, d, e, f; SortPtr s = m_ctx->MkListSort(name, elem_sort(), a, b, c, d, e, f); nil_decl = gcnew FuncDecl(m_ctx, a); is_nil_decl = gcnew FuncDecl(m_ctx, b); cons_decl = gcnew FuncDecl(m_ctx, c); is_cons_decl = gcnew FuncDecl(m_ctx, d); head_decl = gcnew FuncDecl(m_ctx, e); tail_decl = gcnew FuncDecl(m_ctx, f); return gcnew Sort(m_ctx, s); } Constructor^ Context::MkConstructor( String^ name, String^ tester, array^ field_names, array^ field_sorts, array^ field_refs ) { return m_ctx->MkConstructor(name, tester, field_names, CopyArray(field_sorts), field_refs); } FuncDecl^ Context::GetConstructor(Constructor^ c) { return gcnew FuncDecl(m_ctx, m_ctx->GetConstructor(c)); } FuncDecl^ Context::GetTester(Constructor^ c) { return gcnew FuncDecl(m_ctx, m_ctx->GetTester(c)); } array^ Context::GetAccessors(Constructor^ c) { array^ result = m_ctx->GetAccessors(c); return CopyAstArray(result); } bool Model::TryGetArrayValue(Term^ v, ArrayValue^% av) { RawArrayValue^ _av = nullptr; if (m_model->TryGetArrayValue(v(), _av)) { av = gcnew ArrayValue(); av->ElseCase = gcnew Term(m_ctx->GetContext, _av->ElseCase); av->Domain = m_ctx->CopyAstArray(_av->Domain); av->Range = m_ctx->CopyAstArray(_av->Range); return true; } else { return false; } } array^ Context::GetDeclParameters(FuncDecl^ d) { Z3_context ctx = m_ctx->ctx(); Z3_func_decl fd = get_func_decl(d()); unsigned num_params = Z3_get_decl_num_parameters(ctx, fd); array^ params = gcnew array(num_params); for (unsigned i = 0; i < num_params; ++i) { switch(Z3_get_decl_parameter_kind(ctx, fd, i)) { case Z3_PARAMETER_INT: params[i] = gcnew IntParameter(Z3_get_decl_int_parameter(ctx, fd, i)); break; case Z3_PARAMETER_DOUBLE: params[i] = gcnew DoubleParameter(Z3_get_decl_double_parameter(ctx, fd, i)); break; case Z3_PARAMETER_RATIONAL: { Z3_string s = Z3_get_decl_rational_parameter(ctx, fd, i); params[i] = gcnew RationalParameter(gcnew String(s)); break; } case Z3_PARAMETER_SYMBOL: { Z3_symbol s = Z3_get_decl_symbol_parameter(ctx, fd, i); params[i] = gcnew SymbolParameter(gcnew Symbol(ctx, s)); break; } case Z3_PARAMETER_SORT: params[i] = gcnew SortParameter(gcnew Sort(m_ctx,SortPtr(Z3_get_decl_sort_parameter(ctx, fd, i)))); break; case Z3_PARAMETER_AST: params[i] = gcnew TermParameter(gcnew Term(m_ctx,TermPtr(Z3_get_decl_ast_parameter(ctx, fd, i)))); break; case Z3_PARAMETER_FUNC_DECL: params[i] = gcnew FuncDeclParameter(gcnew FuncDecl(m_ctx, FuncDeclPtr(Z3_get_decl_func_decl_parameter(ctx, fd, i)))); break; default: UNREACHABLE(); break; } } return params; } String^ Context::BenchmarkToSmtlib( String^ name, String^ logic, String^ status, String^ attributes, array^ assumptions, Term^ formula) { return m_ctx->BenchmarkToSmtlib(name, logic, status, attributes, CopyArray(assumptions), formula()); } void Context::ParseSmtlibString( String^ string, [In] array^ types, [In] array^ old_decls, [Out] array^% assumptions, [Out] array^% formulas, [Out] array^% new_decls, [Out] array^% new_sorts, [Out] String^% parser_out ) { array^ _assumptions = nullptr; array^ _formulas = nullptr; array^ _new_decls = nullptr; array^ _new_sorts = nullptr; m_ctx->ParseSmtlibString(string, CopyArray(types), CopyArray(old_decls), _assumptions, _formulas, _new_decls, _new_sorts, parser_out); assumptions = CopyTermArray(_assumptions); formulas = CopyTermArray(_formulas); new_decls = CopyAstArray(_new_decls); new_sorts = CopyAstArray(_new_sorts); } void Context::ParseSmtlibFile( String^ file, [In] array^ types, [In] array^ old_decls, [Out] array^% assumptions, [Out] array^% formulas, [Out] array^% new_decls, [Out] array^% new_sorts, [Out] String^% parser_out ) { array^ _assumptions = nullptr; array^ _formulas = nullptr; array^ _new_decls = nullptr; array^ _new_sorts = nullptr; m_ctx->ParseSmtlibFile(file, CopyArray(types), CopyArray(old_decls), _assumptions, _formulas, _new_decls, _new_sorts, parser_out); assumptions = CopyAstArray(_assumptions); formulas = CopyAstArray(_formulas); new_decls = CopyAstArray(_new_decls); new_sorts = CopyAstArray(_new_sorts); } // ----------------------------- // Model ArrayValue^ Model::Mk(RawArrayValue^ av) { ArrayValue^ res = gcnew ArrayValue(); res->Domain = m_ctx->CopyTermArray(av->Domain); res->Range = m_ctx->CopyTermArray(av->Range); res->ElseCase = gcnew Term(m_ctx->GetContext, av->ElseCase); return res; } FunctionEntry^ Model::Mk(RawFunctionEntry^ fe) { FunctionEntry^ res = gcnew FunctionEntry(); res->Arguments = m_ctx->CopyTermArray(fe->Arguments); res->Result = gcnew Term(m_ctx->GetContext, fe->Result); return res; } FunctionGraph^ Model::Mk(RawFunctionGraph^ fg) { FunctionGraph^ res = gcnew FunctionGraph(); res->Declaration = gcnew FuncDecl(m_ctx->GetContext, fg->Declaration); res->Entries = gcnew array(fg->Entries->Length); for (int i = 0; i < fg->Entries->Length; ++i) { res->Entries[i] = Mk(fg->Entries[i]); } res->Else = gcnew Term(m_ctx->GetContext, fg->Else); return res; } Dictionary^ Model::Mk(Dictionary^ fgs) { Dictionary^ res = gcnew Dictionary(); Dictionary::Enumerator e = fgs->GetEnumerator(); while(e.MoveNext()) { KeyValuePair^ kv = e.Current; res->Add(gcnew FuncDecl(m_ctx->GetContext, kv->Key), Mk(kv->Value)); } return res; } Theory^ Context::MkTheory(String^ name) { return gcnew Theory(this, name); }