z3-src 503.2.2

Source distribution of the Z3 SMT solver, for use as a build dependency
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
/*++
Copyright (c) 2011 Microsoft Corporation

Module Name:

    cmd_context.h

Abstract:
    Ultra-light command context.
    It provides a generic command pluging infrastructure.
    A command context also provides names (aka symbols) to Z3 objects.
    These names are used to reference Z3 objects in commands.

Author:

    Leonardo (leonardo) 2011-03-01

Notes:

--*/
#pragma once

#include<sstream>
#include<vector>
#include<functional>
#include "util/stopwatch.h"
#include "util/cmd_context_types.h"
#include "util/event_handler.h"
#include "util/sexpr.h"
#include "util/dictionary.h"
#include "util/scoped_ptr_vector.h"
#include "ast/ast.h"
#include "ast/ast_printer.h"
#include "ast/datatype_decl_plugin.h"
#include "ast/recfun_decl_plugin.h"
#include "ast/rewriter/seq_rewriter.h"
#include "ast/rewriter/var_subst.h"
#include "ast/converters/generic_model_converter.h"
#include "solver/solver.h"
#include "solver/check_logic.h"
#include "solver/progress_callback.h"
#include "solver/simplifier_solver.h"
#include "solver/preferred_value_propagator.h"
#include "cmd_context/pdecl.h"
#include "cmd_context/tactic_manager.h"
#include "params/context_params.h"


class func_decls {
    func_decl * m_decls { nullptr };
    bool signatures_collide(func_decl* f, func_decl* g) const;
    bool signatures_collide(unsigned n, sort*const* domain, sort* range, func_decl* g) const;
public:
    func_decls() = default;
    func_decls(ast_manager & m, func_decl * f);
    void finalize(ast_manager & m);
    bool contains(func_decl * f) const;
    bool contains(unsigned n, sort* const* domain, sort* range) const;
    bool insert(ast_manager & m, func_decl * f);
    void erase(ast_manager & m, func_decl * f);
    bool more_than_one() const;
    bool clash(func_decl * f) const;
    bool empty() const { return m_decls == nullptr; }
    func_decl * first() const;
    func_decl * find(ast_manager & m, unsigned arity, sort * const * domain, sort * range);
    func_decl * find(ast_manager & m, unsigned arity, expr * const * args, sort * range);
    unsigned get_num_entries() const;
    func_decl * get_entry(unsigned inx);
    bool check_signature(ast_manager& m, func_decl* f, unsigned arityh, sort * const* domain, sort * range, bool& coerced) const;
    bool check_poly_signature(ast_manager& m, func_decl* f, unsigned arity, sort* const* domain, sort* range, func_decl*& g);
};

struct macro_decl {
    ptr_vector<sort> m_domain;
    expr*            m_body;

    macro_decl(unsigned arity, sort *const* domain, expr* body):
        m_domain(arity, domain), m_body(body) {}

    void dec_ref(ast_manager& m) { m.dec_ref(m_body); }

};

class macro_decls {
    vector<macro_decl>* m_decls;
public:
    macro_decls() { m_decls = nullptr; }
    void finalize(ast_manager& m);
    bool insert(ast_manager& m, unsigned arity, sort *const* domain, expr* body);
    bool empty() const { return !m_decls || m_decls->empty(); }
    expr* find(unsigned arity, sort *const* domain) const;
    void erase_last(ast_manager& m);
    macro_decl const& last() const { return m_decls->back(); }
    vector<macro_decl>::iterator begin() const { return m_decls->begin(); }
    vector<macro_decl>::iterator end() const { return m_decls->end(); }
};


class proof_cmds {
public:
    virtual ~proof_cmds() = default;
    virtual void add_literal(expr* e) = 0;
    virtual void end_assumption() = 0;
    virtual void end_infer() = 0;
    virtual void end_deleted() = 0;
    virtual void updt_params(params_ref const& p) = 0;
    virtual void register_on_clause(void* ctx, user_propagator::on_clause_eh_t& on_clause) = 0;
};


/**
   \brief Generic wrapper.
*/
class object_ref {
    unsigned m_ref_count = 0;
public:
    virtual ~object_ref() = default;
    virtual void finalize(cmd_context & ctx) = 0;
    void inc_ref(cmd_context & ctx) {
        m_ref_count++;
    }
    void dec_ref(cmd_context & ctx) {
        SASSERT(m_ref_count > 0);
        m_ref_count--;
        if (m_ref_count == 0) {
            finalize(ctx);
            dealloc(this);
        }
    }
    virtual char const * kind() const = 0;
};

class ast_object_ref : public object_ref {
    ast * m_ast;
public:
    ast_object_ref(cmd_context & ctx, ast * a);
    void finalize(cmd_context & ctx) override;
    ast * get_ast() const { return m_ast; }
    static char const * cls_kind() { return "AST"; }
    char const * kind() const override { return cls_kind(); }
};

class stream_ref {
    std::string    m_default_name;
    std::ostream & m_default;
    std::string    m_name;
    std::ostream * m_stream;
    bool           m_owner;
public:
    stream_ref(const std::string& n, std::ostream & d):m_default_name(n), m_default(d), m_name(n), m_stream(&d), m_owner(false) {}
    ~stream_ref() { reset(); }
    void set(char const * name);
    void set(std::ostream& strm);
    void reset();
    std::ostream & operator*() { return *m_stream; }
    char const * name() const { return m_name.c_str(); }
};

struct builtin_decl {
    family_id      m_fid = null_family_id;
    decl_kind      m_decl = 0;
    builtin_decl * m_next = nullptr;
    builtin_decl() = default;
    builtin_decl(family_id fid, decl_kind k, builtin_decl * n = nullptr):m_fid(fid), m_decl(k), m_next(n) {}
};

class opt_wrapper : public check_sat_result {
protected:
    preferred_value_propagator *m_preferred = nullptr;

public:
    opt_wrapper(ast_manager& m): check_sat_result(m) {}
    virtual bool empty() = 0;
    virtual void push() = 0;
    virtual void pop(unsigned n) = 0;
    virtual lbool optimize(expr_ref_vector const& asms) = 0;
    virtual void set_hard_constraints(expr_ref_vector const & hard) = 0;
    virtual void display_assignment(std::ostream& out) = 0;
    virtual bool is_pareto() = 0;
    virtual void set_logic(symbol const& s) = 0;
    virtual void get_box_model(model_ref& mdl, unsigned index) = 0;
    virtual void updt_params(params_ref const& p) = 0;
    virtual void initialize_value(expr* var, expr* value) = 0;
    void set_preferred(preferred_value_propagator *p) { m_preferred = p; }
};

class ast_context_params : public context_params { 
    ast_manager* m_manager { nullptr };
public:
    /**
       \brief Create an AST manager using this configuration.
    */
    ast_manager * mk_ast_manager();

    void set_foreign_manager(ast_manager* m) { m_manager = m; }
    bool owns_manager() const { return m_manager != nullptr; }
};


class cmd_context : public progress_callback, public tactic_manager, public ast_printer_context {
public:
    using proof_check_callback = std::function<std::string(proof*, expr_ref_vector const&)>;

    enum status {
        UNSAT, SAT, UNKNOWN
    };

    enum check_sat_state {
        css_unsat, css_sat, css_unknown, css_clear
    };

    typedef std::pair<unsigned, expr*> macro;

    struct scoped_watch {
        cmd_context &   m_ctx;
    public:
        scoped_watch(cmd_context & ctx):m_ctx(ctx) { m_ctx.m_watch.reset(); m_ctx.m_watch.start(); }
        ~scoped_watch() { m_ctx.m_watch.stop(); }
    };

    struct scoped_redirect {
        cmd_context& m_ctx;
        std::ostream& m_verbose;
        std::ostream* m_warning;

        scoped_redirect(cmd_context& ctx): m_ctx(ctx), m_verbose(verbose_stream()), m_warning(warning_stream()) {
            set_warning_stream(&(*m_ctx.m_diagnostic));
            set_verbose_stream(m_ctx.diagnostic_stream());
        }

        ~scoped_redirect() {
            set_verbose_stream(m_verbose);
            set_warning_stream(m_warning);
        }
    };

    

protected:
    ast_context_params           m_params;
    bool                         m_main_ctx;
    symbol                       m_logic;
    bool                         m_interactive_mode = false;
    bool                         m_global_decls = false;
    bool                         m_print_success;
    unsigned                     m_random_seed = 0;
    bool                         m_produce_unsat_cores = false;
    bool                         m_produce_unsat_assumptions = false;
    bool                         m_produce_assignments = false;
    status                       m_status = UNKNOWN;
    bool                         m_numeral_as_real = false;
    bool                         m_ignore_check = false;      // used by the API to disable check-sat() commands when parsing SMT 2.0 files.
    bool                         m_exit_on_error = false;
    bool                         m_allow_duplicate_declarations = false;
    scoped_ptr<proof_cmds>       m_proof_cmds;

    static std::ostringstream    g_error_stream;

    generic_model_converter* mc0() { return m_mcs.back(); }
    sref_vector<generic_model_converter> m_mcs;
    ast_manager *                m_manager;
    bool                         m_own_manager;
    bool                         m_manager_initialized = false;
    pdecl_manager *              m_pmanager = nullptr;
    sexpr_manager *              m_sexpr_manager = nullptr;
    check_logic                  m_check_logic;
    stream_ref                   m_regular;
    stream_ref                   m_diagnostic;
    dictionary<cmd*>             m_cmds;
    dictionary<builtin_decl>     m_builtin_decls;
    scoped_ptr_vector<builtin_decl> m_extra_builtin_decls; // make sure that dynamically allocated builtin_decls are deleted
    dictionary<object_ref*>      m_object_refs; // anything that can be named.
    dictionary<sexpr*>           m_user_tactic_decls;
    vector<std::pair<expr_ref, expr_ref>> m_var2values;
    scoped_ptr<preferred_value_propagator> m_preferred;

    dictionary<func_decls>       m_func_decls;
    obj_map<func_decl, symbol>   m_func_decl2alias;
    dictionary<psort_decl*>      m_psort_decls;
    dictionary<macro_decls>      m_macros;
    // the following fields m_func_decls_stack, m_psort_decls_stack and m_exprs_stack are used when m_global_decls == false
    typedef std::pair<symbol, func_decl *> sf_pair;
    svector<sf_pair>             m_func_decls_stack;
    svector<symbol>              m_psort_decls_stack;
    svector<symbol>              m_macros_stack;
    ptr_vector<pdecl>            m_psort_inst_stack;

    //
    ptr_vector<pdecl>            m_aux_pdecls;
    ptr_vector<expr>             m_assertions;
    std::vector<std::string>     m_assertion_strings;
    ptr_vector<expr>             m_assertion_names; // named assertions are represented using boolean variables.
    scoped_ptr<var_subst>        m_std_subst, m_rev_subst;
    simplifier_factory           m_simplifier_factory;

    struct scope {
        unsigned m_func_decls_stack_lim;
        unsigned m_psort_decls_stack_lim;
        unsigned m_macros_stack_lim;
        unsigned m_aux_pdecls_lim;
        unsigned m_psort_inst_stack_lim;
        // Declaration limits are ignored when m_global_decls = true.
        unsigned m_assertions_lim;
        unsigned m_rlimit;
    };

    svector<scope>               m_scopes;
    scoped_ptr<solver_factory>   m_solver_factory;
    ref<solver>                  m_solver;
    ref<check_sat_result>        m_check_sat_result;
    proof_check_callback        m_proof_check_callback;
    ref<opt_wrapper>             m_opt;

    stopwatch                    m_watch;

    class dt_eh : public new_datatype_eh {
        cmd_context &             m_owner;
        datatype_util             m_dt_util;
    public:
        void reset() { m_dt_util.reset(); }
        dt_eh(cmd_context & owner);
        void operator()(sort * dt, pdecl* pd) override;
    };

    friend class dt_eh;
    scoped_ptr<dt_eh>             m_dt_eh;

    class pp_env;
    friend class pp_env;

    scoped_ptr<pp_env>            m_pp_env;
    pp_env & get_pp_env() const;

    var_subst& std_subst() { if (!m_std_subst) m_std_subst = alloc(var_subst, m(), true); return *m_std_subst; }
    var_subst& rev_subst() { if (!m_rev_subst) m_rev_subst = alloc(var_subst, m(), false); return *m_rev_subst; }

    void register_builtin_sorts(decl_plugin * p);
    void restrict_builtin_sorts();
    void register_builtin_ops(decl_plugin * p);
    void load_plugin(symbol const & name, bool install_names, svector<family_id>& fids);
    void init_manager_core(bool new_manager);

    void init_external_manager();
    void reset_cmds();
    void finalize_cmds();
    void add_declared_functions(model& mdl);

    void restore_func_decls(unsigned old_sz);
    void restore_psort_decls(unsigned old_sz);
    void restore_macros(unsigned old_sz);
    void restore_aux_pdecls(unsigned old_sz);
    void restore_assertions(unsigned old_sz);
    void restore_psort_inst(unsigned old_sz);

    void erase_func_decl_core(symbol const & s, func_decl * f);
    void erase_psort_decl_core(symbol const & s);

    bool logic_has_arith() const;
    bool logic_has_bv() const;
    bool logic_has_pb() const;
    bool logic_has_seq() const;
    bool logic_has_array() const;
    bool logic_has_datatype() const;
    bool logic_has_fpa() const;
    bool logic_has_recfun() const;

    void print_unsupported_msg() { regular_stream() << "unsupported" << std::endl; }
    void print_unsupported_info(symbol const& s, int line, int pos) { if (s != symbol::null) diagnostic_stream() << "; " << s << " line: " << line << " position: " << pos << std::endl;}

    void mk_solver();

    bool contains_func_decl(symbol const& s, unsigned n, sort* const* domain, sort* range) const;
    bool builtin_signature_collides(symbol const& s, unsigned arity, sort* const* domain) const;
    bool is_transcendental_shadow_decl(symbol const& s, unsigned arity, sort* const* domain) const;

    bool contains_macro(symbol const& s) const;
    bool contains_macro(symbol const& s, func_decl* f) const;
    bool contains_macro(symbol const& s, unsigned arity, sort *const* domain) const;
    void insert_macro(symbol const& s, unsigned arity, sort*const* domain, expr* t);
    void erase_macro(symbol const& s);
    bool macros_find(symbol const& s, unsigned n, expr*const* args, expr_ref_vector& coerced_args, expr_ref& t);

    recfun::decl::plugin& get_recfun_plugin();

public:
    cmd_context(bool main_ctx = true, ast_manager * m = nullptr, symbol const & l = symbol::null);
    ~cmd_context() override;
    void set_cancel(bool f);
    void register_plist();
    context_params  & params() { return m_params; }
    solver_factory &get_solver_factory() { return *m_solver_factory; }
    opt_wrapper*  get_opt();
    void          set_opt(opt_wrapper* o);
    void global_params_updated(); // this method should be invoked when global (and module) params are updated.
    bool set_logic(symbol const & s);
    bool has_logic() const { return m_logic != symbol::null; }
    symbol const & get_logic() const { return m_logic; }
    bool is_logic(char const * l_name) const { return has_logic() && strcmp(m_logic.bare_str(), l_name) == 0; }
    bool numeral_as_real() const { return m_numeral_as_real; }
    void set_numeral_as_real(bool f) { m_numeral_as_real = f; }
    void set_interactive_mode(bool flag) { m_interactive_mode = flag; }
    void set_ignore_check(bool flag) { m_ignore_check = flag; }
    bool ignore_check() const { return m_ignore_check; }
    void set_exit_on_error(bool flag) { m_exit_on_error = flag; }
    bool exit_on_error() const { return m_exit_on_error; }
    bool interactive_mode() const { return m_interactive_mode; }
    void set_print_success(bool flag) { m_print_success = flag; }
    bool print_success_enabled() const { return m_print_success; }
    void print_success() { if (print_success_enabled())  regular_stream() << "success" << std::endl; }
    void print_unsupported(symbol const & s, int line, int pos) { print_unsupported_msg(); print_unsupported_info(s, line, pos); }
    bool global_decls() const { return m_global_decls; }
    void set_global_decls(bool flag) { SASSERT(!has_manager()); m_global_decls = flag; }
    unsigned random_seed() const { return m_random_seed; }
    void set_random_seed(unsigned s) { m_random_seed = s; }
    bool produce_models() const;
    bool produce_proofs() const;
    bool produce_unsat_cores() const;
    bool well_sorted_check_enabled() const;
    bool validate_model_enabled() const;
    bool has_assertions() const { return !m_assertions.empty(); }
    void set_produce_models(bool flag);
    void set_produce_unsat_cores(bool flag);
    void set_produce_proofs(bool flag);
    void set_produce_unsat_assumptions(bool flag) { m_produce_unsat_assumptions = flag; }
    void set_allow_duplicate_declarations() { m_allow_duplicate_declarations = true; }
    bool produce_assignments() const { return m_produce_assignments; }
    bool produce_unsat_assumptions() const { return m_produce_unsat_assumptions; }
    void set_produce_assignments(bool flag) { m_produce_assignments = flag; }
    void set_status(status st) { m_status = st; }
    status get_status() const { return m_status; }
    std::string reason_unknown() const;

    bool has_manager() const { return m_manager != nullptr; }
    ast_manager & m() const { const_cast<cmd_context*>(this)->init_manager(); return *m_manager; }
    ast_manager & get_ast_manager() override { return m(); }
    pdecl_manager & pm() const { if (!m_pmanager) const_cast<cmd_context*>(this)->init_manager(); return *m_pmanager; }
    sexpr_manager & sm() const { if (!m_sexpr_manager) const_cast<cmd_context*>(this)->m_sexpr_manager = alloc(sexpr_manager); return *m_sexpr_manager; }

    proof_cmds* get_proof_cmds() { return m_proof_cmds.get(); }
    void init_manager();
    solver* get_solver() { return m_solver.get(); }
    void set_solver(solver* s) { m_solver = s; }
    void set_proof_cmds(proof_cmds* pc) { m_proof_cmds = pc; }
    void set_initial_value(expr* var, expr* value);
    void set_preferred(expr *fmla);
    void reset_preferred();

    void set_solver_factory(solver_factory * s);
    void set_simplifier_factory(simplifier_factory& sf) { m_simplifier_factory = sf; }
    void set_check_sat_result(check_sat_result * r) { m_check_sat_result = r; }
    check_sat_result * get_check_sat_result() const { return m_check_sat_result.get(); }
    check_sat_state cs_state() const;
    void complete_model(model_ref& mdl) const;
    void validate_model();
    void analyze_failure(expr_mark& seen, model_evaluator& ev, expr* e, bool expected_value);
    void display_detailed_analysis(std::ostream& out, model_evaluator& ev, expr* e);
    void display_model(model_ref& mdl);

    void register_plugin(symbol const & name, decl_plugin * p, bool install_names);
    bool is_func_decl(symbol const & s) const;
    bool is_sort_decl(symbol const& s) const { return m_psort_decls.contains(s); }
    void insert(cmd * c);
    void insert(symbol const & s, func_decl * f);
    void insert(func_decl * f) { insert(f->get_name(), f); }
    void insert(symbol const & s, psort_decl * p);
    void insert(psort_decl * p) { insert(p->get_name(), p); }
    void insert(symbol const & s, unsigned arity, sort *const* domain, expr * t);
    void insert(symbol const & s, object_ref *);
    void insert(tactic_cmd * c) { tactic_manager::insert(c); }
    void insert(probe_info * p) { tactic_manager::insert(p); }
    void insert_user_tactic(symbol const & s, sexpr * d);
    void insert_aux_pdecl(pdecl * p);
    void model_add(symbol const & s, unsigned arity, sort *const* domain, expr * t);
    void model_del(func_decl* f);
    void register_fun(symbol const& s, func_decl* f);
    void insert_rec_fun(func_decl* f, expr_ref_vector const& binding, svector<symbol> const& ids, expr* e);
    func_decl * find_func_decl(symbol const & s) const;
    func_decl * find_func_decl(symbol const & s, unsigned num_indices, unsigned const * indices,
                               unsigned arity, sort * const * domain, sort * range);
    recfun::promise_def decl_rec_fun(const symbol &name, unsigned int arity, sort *const *domain, sort *range);
    psort_decl * find_psort_decl(symbol const & s) const;
    cmd * find_cmd(symbol const & s) const;
    sexpr * find_user_tactic(symbol const & s) const;
    object_ref * find_object_ref(symbol const & s) const;
    void mk_const(symbol const & s, expr_ref & result);
    void mk_app(symbol const & s, unsigned num_args, expr * const * args, unsigned num_indices, parameter const * indices, sort * range,
                expr_ref & r);
    bool try_mk_macro_app(symbol const & s, unsigned num_args, expr * const * args, unsigned num_indices, parameter const * indices, sort * range,
                expr_ref & r);
    bool try_mk_builtin_app(symbol const & s, unsigned num_args, expr * const * args, unsigned num_indices, parameter const * indices, sort * range,
                expr_ref & r) const;
    bool try_mk_declared_app(symbol const & s, unsigned num_args, expr * const * args, 
                             unsigned num_indices, parameter const * indices, sort * range,
                             expr_ref & result);
    bool try_mk_pdecl_app(symbol const & s, unsigned num_args, expr * const * args, unsigned num_indices, parameter const * indices, expr_ref & r) const;
    void erase_cmd(symbol const & s);
    void erase_func_decl(symbol const & s);
    void erase_func_decl(symbol const & s, func_decl * f);
    void erase_func_decl(func_decl * f) { erase_func_decl(f->get_name(), f); }
    void erase_psort_decl(symbol const & s);
    void erase_object_ref(symbol const & s);
    void erase_user_tactic(symbol const & s);
    void reset_func_decls();
    void reset_psort_decls();
    void reset_macros();
    void reset_object_refs();
    void reset_user_tactics();
    void set_regular_stream(char const * name) { m_regular.set(name); }
    void set_regular_stream(std::ostream& out) { m_regular.set(out); }
    void set_diagnostic_stream(std::ostream& out) { m_diagnostic.set(out); }
    void set_diagnostic_stream(char const * name);
    std::ostream & regular_stream() override { return *m_regular; }
    std::ostream & diagnostic_stream() override { return *m_diagnostic; }
    char const * get_regular_stream_name() const { return m_regular.name(); }
    char const * get_diagnostic_stream_name() const { return m_diagnostic.name(); }
    typedef dictionary<cmd*>::iterator cmd_iterator;
    cmd_iterator begin_cmds() const { return m_cmds.begin(); }
    cmd_iterator end_cmds() const { return m_cmds.end(); }

    typedef dictionary<sexpr*>::iterator user_tactic_iterator;
    user_tactic_iterator begin_user_tactics() const { return m_user_tactic_decls.begin(); }
    user_tactic_iterator end_user_tactics() const { return m_user_tactic_decls.end(); }

    void display_assertions();
    void display_statistics(bool show_total_time = false, double total_time = 0.0);
    void display_dimacs();
    void display_parameters(std::ostream& out);
    void reset(bool finalize = false);
    void assert_expr(expr * t);
    void assert_expr(symbol const & name, expr * t);
    void push_assert_string(std::string const & s) { SASSERT(m_interactive_mode); m_assertion_strings.push_back(s); }
    void push();
    void push(unsigned n);
    void pop(unsigned n);
    void check_sat(unsigned num_assumptions, expr * const * assumptions);
    void set_proof_check_callback(proof_check_callback callback) { m_proof_check_callback = std::move(callback); }
    void check_proof(unsigned num_assumptions = 0, expr* const* assumptions = nullptr);
    void get_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars, expr_ref_vector & conseq);
    void reset_assertions();
    // display the result produced by a check-sat or check-sat-using commands in the regular stream
    void display_sat_result(lbool r);
    // check if result produced by check-sat or check-sat-using matches the known status
    void validate_check_sat_result(lbool r);
    unsigned num_scopes() const { return m_scopes.size(); }

    dictionary<macro_decls> const & get_macros() const { return m_macros; }

    model_converter* get_model_converter() { return mc0(); }

    bool is_model_available(model_ref& md) const;

    double get_seconds() const { return m_watch.get_seconds(); }

    ptr_vector<expr> const& assertions() const { return m_assertions; }
    ptr_vector<expr> const& assertion_names() const { return m_assertion_names; }
    vector<std::pair<expr*,expr*>> tracked_assertions();
    void reset_tracked_assertions();

    /**
       \brief Hack: consume assertions if there are no scopes.
       This method is useful for reducing memory consumption in huge benchmarks were incrementality is not an issue.
    */
    bool consume_assertions() {
        if (num_scopes() > 0)
            return false;
        restore_assertions(0);
        return true;
    }

    format_ns::format * pp(sort * s) const;
    format_ns::format* try_pp(sort* s) const;
    void pp(sort * s, format_ns::format_ref & r) const override { r = pp(s); }
    void pp(func_decl * f, format_ns::format_ref & r) const override;
    void pp(expr * n, unsigned num_vars, char const * var_prefix, format_ns::format_ref & r, sbuffer<symbol> & var_names) const override;
    void pp(expr * n, format_ns::format_ref & r) const override;
    void display(std::ostream & out, sort * s, unsigned indent = 0) const override;
    void display(std::ostream & out, expr * n, unsigned indent, unsigned num_vars, char const * var_prefix, sbuffer<symbol> & var_names) const override;
    void display(std::ostream & out, expr * n, unsigned indent = 0) const override;
    void display(std::ostream & out, func_decl * f, unsigned indent = 0) const override;

    // dump assertions in out using the pretty printer.
    void dump_assertions(std::ostream & out) const;

    // display assertions as a SMT2 benchmark.
    void display_smt2_benchmark(std::ostream & out, unsigned num, expr * const * assertions, symbol const & logic = symbol::null) const;


    void slow_progress_sample() override;
    void fast_progress_sample() override;
};

std::ostream & operator<<(std::ostream & out, cmd_context::status st);