From 52207cd30ad2da120f6d880c32dbade66010a007 Mon Sep 17 00:00:00 2001
From: Michele Alberti <michele.alberti@cea.fr>
Date: Mon, 28 Nov 2022 15:24:23 +0100
Subject: [PATCH] [printer] Add a new printer for VNN-LIB format.

The printer for the SMT-LIB format produces not useful stuff.
---
 config/drivers/discrimination.gen |    1 -
 config/drivers/vnnlib.gen         |   19 +-
 src/dataset.ml                    |   10 +-
 src/printers/smtv2_vnnlib.ml      | 1128 +++++++++++++++++++++++++++++
 src/printers/vnnlib.ml            |  954 ++++--------------------
 5 files changed, 1289 insertions(+), 823 deletions(-)
 create mode 100644 src/printers/smtv2_vnnlib.ml

diff --git a/config/drivers/discrimination.gen b/config/drivers/discrimination.gen
index 519eab6..3c7c30c 100644
--- a/config/drivers/discrimination.gen
+++ b/config/drivers/discrimination.gen
@@ -4,4 +4,3 @@ theory BuiltIn
   meta "select_lsinst_default" "local"
   meta "select_kept_default" "all"
 end
-
diff --git a/config/drivers/vnnlib.gen b/config/drivers/vnnlib.gen
index 8c73915..90d83f1 100644
--- a/config/drivers/vnnlib.gen
+++ b/config/drivers/vnnlib.gen
@@ -24,30 +24,16 @@
 
 prelude ";;; produced by VNN-LIB driver"
 
-printer "smtv2.6_vnnlib"
+printer "vnnlib"
 import "discrimination.gen"
 
 filename "%f-%t-%g.vnnlib"
 
-transformation "inline_trivial"
+transformation "introduce_premises"
 transformation "eliminate_builtin"
-transformation "detect_polymorphism"
-transformation "eliminate_definition_conditionally"
-transformation "eliminate_inductive"
-transformation "eliminate_algebraic_if_poly"
 transformation "eliminate_literal"
-transformation "eliminate_epsilon"
 transformation "simplify_formula"
 
-(* Prepare for counter-example query: get rid of some quantifiers
-   (makes it possible to query model values of the variables in
-   premises) and introduce counter-example projections.  Note: does
-   nothing if meta get_counterexmp is not set *)
-transformation "prepare_for_counterexmp"
-
-transformation "discriminate_if_poly"
-transformation "encoding_smt_if_poly"
-
 theory BuiltIn
   syntax type int   "Int"
   syntax type real  "Real"
@@ -55,7 +41,6 @@ theory BuiltIn
 
   meta "encoding:kept" type int
   meta "encoding:ignore_polymorphism_ls" predicate (=)
-  meta "supports_smt_get_info_unknown_reason" ""
 end
 
 theory int.Int
diff --git a/src/dataset.ml b/src/dataset.ml
index fe30f49..f02efd8 100644
--- a/src/dataset.ml
+++ b/src/dataset.ml
@@ -248,7 +248,7 @@ let add_axioms ?eps ~clip th task input value =
   let ls_ge = Theory.(ns_find_ls th.th_export [ Ident.op_infix ">=" ]) in
   let pr_ge =
     Decl.create_prsymbol
-      (Ident.id_fresh (Fmt.str "axiom_%s_ge" input.Term.ls_name.id_string))
+      (Ident.id_fresh (Fmt.str "axiom_ge_%s" input.Term.ls_name.id_string))
   in
   let t_ge =
     let value = value -. eps in
@@ -261,7 +261,7 @@ let add_axioms ?eps ~clip th task input value =
   let ls_le = Theory.(ns_find_ls th.th_export [ Ident.op_infix "<=" ]) in
   let pr_le =
     Decl.create_prsymbol
-      (Ident.id_fresh (Fmt.str "axiom_%s_le" input.Term.ls_name.id_string))
+      (Ident.id_fresh (Fmt.str "axiom_le_%s" input.Term.ls_name.id_string))
   in
   let t_le =
     let value = value +. eps in
@@ -302,7 +302,7 @@ let add_output_decl ~id predicate_kind ~outputs ~record th task =
   let goal_pr =
     let id =
       Ident.id_fresh
-        (Fmt.str "%s_record_%d_Y_%s"
+        (Fmt.str "%s_record%d_y%s"
            (string_of_predicate_kind predicate_kind)
            id label)
     in
@@ -327,11 +327,11 @@ let tasks_of_nn_csv_predicate env
   let task = Task.use_export None th_real in
   (* Add input declarations. *)
   let inputs, task =
-    add_decls ~id:(Fmt.str "X_%d") task predicate.model.Language.nb_inputs
+    add_decls ~id:(Fmt.str "x%d") task predicate.model.Language.nb_inputs
   in
   (* Add output declarations. *)
   let outputs, task =
-    add_decls ~id:(Fmt.str "Y_%d") task predicate.model.Language.nb_outputs
+    add_decls ~id:(Fmt.str "y%d") task predicate.model.Language.nb_outputs
   in
   let tasks =
     List.foldi dataset ~init:[] ~f:(fun id tasks record ->
diff --git a/src/printers/smtv2_vnnlib.ml b/src/printers/smtv2_vnnlib.ml
new file mode 100644
index 0000000..83af6d6
--- /dev/null
+++ b/src/printers/smtv2_vnnlib.ml
@@ -0,0 +1,1128 @@
+(********************************************************************)
+(*                                                                  *)
+(*  The Why3 Verification Platform   /   The Why3 Development Team  *)
+(*  Copyright 2010-2022 --  Inria - CNRS - Paris-Saclay University  *)
+(*                                                                  *)
+(*  This software is distributed under the terms of the GNU Lesser  *)
+(*  General Public License version 2.1, with the special exception  *)
+(*  on linking described in file LICENSE.                           *)
+(*                                                                  *)
+(********************************************************************)
+
+(** SMT v2 printer with some extensions *)
+
+open Format
+open Why3
+
+[@@@warning "-9"]
+
+open Pp
+open Wstdlib
+open Ident
+open Ty
+open Term
+open Decl
+open Printer
+open Cntexmp_printer
+
+let debug =
+  Debug.register_info_flag "smtv2_printer"
+    ~desc:"Print@ debugging@ messages@ about@ printing@ the@ input@ of@ smtv2."
+
+let debug_incremental =
+  Debug.register_info_flag "force_incremental"
+    ~desc:"Force@ incremental@ mode@ for@ smtv2@ provers"
+
+(** SMTLIB tokens taken from CVC4: src/parser/smt2/{Smt2.g,smt2.cpp} *)
+let ident_printer () =
+  let bls =
+    [
+      (* Base SMT-LIB commands, see page 43 *)
+      "assert";
+      "check-sat";
+      "check-sat-assuming";
+      "declare-const";
+      "declare-datatype";
+      "declare-datatypes";
+      "declare-fun";
+      "declare-sort";
+      "define-fun";
+      "define-fun-rec";
+      "define-funs-rec";
+      "define-sort";
+      "echo";
+      "exit";
+      "get-assignment";
+      "get-assertions";
+      "get-info";
+      "get-model";
+      "get-option";
+      "get-proof";
+      "get-unsat-assumptions";
+      "get-unsat-core";
+      "get-value";
+      "pop";
+      "push";
+      "reset";
+      "reset-assertions";
+      "set-info";
+      "set-logic";
+      "set-option";
+      (* Base SMT-LIB tokens, see page 22*)
+      "BINARY";
+      "DECIMAL";
+      "HEXADECIMAL";
+      "NUMERAL";
+      "STRING";
+      "_";
+      "!";
+      "as";
+      "let";
+      "exists";
+      "forall";
+      "match";
+      "par";
+      (* extended commands *)
+      "assert-rewrite";
+      "assert-reduction";
+      "assert-propagation";
+      "declare-sorts";
+      "declare-funs";
+      "declare-preds";
+      "define";
+      "simplify";
+      (* operators, including theory symbols *)
+      "=";
+      "=>";
+      "+";
+      "-";
+      "*";
+      "^";
+      "<";
+      "<=";
+      ">";
+      ">=";
+      "ite";
+      "and";
+      "distinct";
+      "is_int";
+      "not";
+      "or";
+      "select";
+      "store";
+      "to_int";
+      "to_real";
+      "xor";
+      "/";
+      "div";
+      "mod";
+      "rem";
+      "concat";
+      "bvnot";
+      "bvand";
+      "bvor";
+      "bvneg";
+      "bvadd";
+      "bvmul";
+      "bvudiv";
+      "bvurem";
+      "bvshl";
+      "bvlshr";
+      "bvult";
+      "bvnand";
+      "bvnor";
+      "bvxor";
+      "bvxnor";
+      "bvcomp";
+      "bvsub";
+      "bvsdiv";
+      "bvsrem";
+      "bvsmod";
+      "bvashr";
+      "bvule";
+      "bvugt";
+      "bvuge";
+      "bvslt";
+      "bvsle";
+      "bvsgt";
+      "bvsge";
+      "rotate_left";
+      "rotate_right";
+      "bvredor";
+      "bvredand";
+      "bv2nat";
+      "sqrt";
+      "sin";
+      "cos";
+      "tan";
+      "asin";
+      "acos";
+      "atan";
+      "pi";
+      "exp";
+      "csc";
+      "sec";
+      "cot";
+      "arcsin";
+      "arccos";
+      "arctan";
+      "arccsc";
+      "arcsec";
+      "arccot";
+      (* the new floating point theory - updated to the 2014-05-27 standard *)
+      "FloatingPoint";
+      "fp";
+      "Float16";
+      "Float32";
+      "Float64";
+      "Float128";
+      "RoundingMode";
+      "roundNearestTiesToEven";
+      "RNE";
+      "roundNearestTiesToAway";
+      "RNA";
+      "roundTowardPositive";
+      "RTP";
+      "roundTowardNegative";
+      "RTN";
+      "roundTowardZero";
+      "RTZ";
+      "NaN";
+      "+oo";
+      "-oo";
+      "+zero";
+      "-zero";
+      "fp.abs";
+      "fp.neg";
+      "fp.add";
+      "fp.sub";
+      "fp.mul";
+      "fp.div";
+      "fp.fma";
+      "fp.sqrt";
+      "fp.rem";
+      "fp.roundToIntegral";
+      "fp.min";
+      "fp.max";
+      "fp.leq";
+      "fp.lt";
+      "fp.geq";
+      "fp.gt";
+      "fp.eq";
+      "fp.isNormal";
+      "fp.isSubnormal";
+      "fp.isZero";
+      "fp.isInfinite";
+      "fp.isNaN";
+      "fp.isNegative";
+      "fp.isPositive";
+      "to_fp";
+      "to_fp_unsigned";
+      "fp.to_ubv";
+      "fp.to_sbv";
+      "fp.to_real";
+      (* the new proposed string theory *)
+      "String";
+      "str.<";
+      "str.<=";
+      "str.++";
+      "str.len";
+      "str.substr";
+      "str.contains";
+      "str.at";
+      "str.indexof";
+      "str.prefixof";
+      "str.suffixof";
+      "int.to.str";
+      "str.to.int";
+      "u16.to.str";
+      "str.to.u16";
+      "u32.to.str";
+      "str.to.u32";
+      "str.in.re";
+      "str.to.re";
+      "str.replace";
+      "str.tolower";
+      "str.toupper";
+      "str.rev";
+      "str.from_code";
+      "str.is_digit";
+      "str.from_int";
+      "str.to_int";
+      "str.in_re";
+      "str.to_code";
+      "str.replace_all";
+      "int.to.str";
+      "str.to.int";
+      "str.code";
+      "str.replaceall";
+      "re.++";
+      "re.union";
+      "re.inter";
+      "re.*";
+      "re.+";
+      "re.opt";
+      "re.range";
+      "re.loop";
+      "re.comp";
+      "re.diff";
+      (* the new proposed set theory *)
+      "union";
+      "intersection";
+      "setminus";
+      "subset";
+      "member";
+      "singleton";
+      "insert";
+      "card";
+      "complement";
+      "join";
+      "product";
+      "transpose";
+      "tclosure";
+      (* built-in sorts *)
+      "Bool";
+      "Int";
+      "Real";
+      "BitVec";
+      "Array";
+      (* Other stuff that Why3 seems to need *)
+      "unsat";
+      "sat";
+      "true";
+      "false";
+      "const";
+      "abs";
+      "BitVec";
+      "extract";
+      "bv2nat";
+      "nat2bv";
+      (* From Z3 *)
+      "map";
+      "bv";
+      "default";
+      "difference";
+      (* From CVC4 *)
+      "char";
+      "choose";
+      (* Counterexamples specific keywords *)
+      "lambda";
+      "LAMBDA";
+      "model";
+      (* various stuff from "sed -n -e 's/^.*addOperator.*\"\([^\"]*\)\".*/\1/p'
+         src/parser/smt2/smt2.cpp" *)
+      "inst-closure";
+      "dt.size";
+      "sep";
+      "pto";
+      "wand";
+      "emp";
+      "fmf.card";
+      "fmf.card.val";
+    ]
+  in
+  let san = sanitizer char_to_alpha char_to_alnumus in
+  create_ident_printer bls ~sanitizer:san
+
+type version =
+  | V20
+  | V26
+  | V26Par
+
+type info = {
+  info_syn : syntax_map;
+  info_rliteral : syntax_map;
+  mutable info_model : S.t;
+  mutable info_in_goal : bool;
+  info_vc_term : vc_term_info;
+  info_printer : ident_printer;
+  mutable list_projs : Ident.ident Mstr.t;
+  mutable list_field_def : Ident.ident Mstr.t;
+  info_version : version;
+  meta_model_projection : Sls.t;
+  meta_record_def : Sls.t;
+  mutable list_records : field_info list Mstr.t;
+  (* For algebraic type counterexamples: constructors with no arguments can be
+     misunderstood for variables *)
+  mutable noarg_constructors : string list;
+  info_cntexample_need_push : bool;
+  info_cntexample : bool;
+  info_incremental : bool;
+  info_set_incremental : bool;
+  info_supports_reason_unknown : bool;
+  mutable info_labels : Sattr.t Mstr.t;
+  mutable incr_list_axioms : (prsymbol * term) list;
+  mutable incr_list_ldecls : (lsymbol * vsymbol list * term) list;
+}
+
+let debug_print_term message t =
+  let form = Debug.get_debug_formatter () in
+  Debug.dprintf debug message;
+  if Debug.test_flag debug then Pretty.print_term form t;
+  Debug.dprintf debug "@."
+
+let print_ident info fmt id =
+  pp_print_string fmt (id_unique info.info_printer id)
+
+(** type *)
+
+let print_tv info fmt tv =
+  pp_print_string fmt (id_unique info.info_printer tv.tv_name)
+
+(** print `(par ...)` around the given body to print *)
+let print_par info
+  (* body *)
+  (* Format.kdprintf *) print_body fmt tvs =
+  if Ty.Stv.is_empty tvs
+  then print_body fmt
+  else if info.info_version = V26Par
+  then
+    Format.fprintf fmt "(par (%a)@ %t)"
+      (print_iter1 Ty.Stv.iter pp_print_space (print_tv info))
+      tvs print_body
+  else unsupported "smt: polymorphism must be encoded"
+(* body *)
+
+let rec print_type info fmt ty =
+  match ty.ty_node with
+  | Tyvar s -> (
+    match info.info_version with
+    | V20 -> unsupported "smtv2: you must encode type polymorphism"
+    | V26 | V26Par -> print_tv info fmt s)
+  | Tyapp (ts, l) -> (
+    match (query_syntax info.info_syn ts.ts_name, l) with
+    | Some s, _ -> syntax_arguments s (print_type info) fmt l
+    | None, [] -> print_ident info fmt ts.ts_name
+    | None, _ ->
+      fprintf fmt "(%a %a)" (print_ident info) ts.ts_name
+        (print_list space (print_type info))
+        l)
+
+let print_type info fmt ty =
+  try print_type info fmt ty
+  with Unsupported s -> raise (UnsupportedType (ty, s))
+
+let print_type_value info fmt = function
+  | None -> pp_print_string fmt "Bool"
+  | Some ty -> print_type info fmt ty
+
+(** var *)
+let forget_var info v = forget_id info.info_printer v.vs_name
+
+let print_var info fmt { vs_name = id } =
+  let n = id_unique info.info_printer id in
+  pp_print_string fmt n
+
+let print_typed_var info fmt vs =
+  fprintf fmt "(%a %a)" (print_var info) vs (print_type info) vs.vs_ty
+
+let print_var_list info fmt vsl = print_list space (print_var info) fmt vsl
+
+let print_typed_var_list info fmt vsl =
+  print_list space (print_typed_var info) fmt vsl
+
+let collect_model_ls info ls =
+  if Sls.mem ls info.meta_model_projection
+  then
+    info.list_projs <-
+      Mstr.add
+        (sprintf "%a" (print_ident info) ls.ls_name)
+        ls.ls_name info.list_projs;
+  if Sls.mem ls info.meta_record_def
+  then
+    info.list_field_def <-
+      Mstr.add
+        (sprintf "%a" (print_ident info) ls.ls_name)
+        ls.ls_name info.list_field_def;
+  if ls.ls_args = [] && relevant_for_counterexample ls.ls_name
+  then
+    let t = t_app ls [] ls.ls_value in
+    info.info_model <-
+      add_model_element
+        (t_attr_set ?loc:ls.ls_name.id_loc ls.ls_name.id_attrs t)
+        info.info_model
+
+let number_format =
+  {
+    Number.long_int_support = `Default;
+    Number.negative_int_support = `Default;
+    Number.dec_int_support = `Default;
+    Number.hex_int_support = `Unsupported;
+    Number.oct_int_support = `Unsupported;
+    Number.bin_int_support = `Unsupported;
+    Number.negative_real_support = `Default;
+    Number.dec_real_support = `Default;
+    Number.hex_real_support = `Unsupported;
+    Number.frac_real_support =
+      `Custom
+        ( (fun fmt i -> fprintf fmt "%s.0" i),
+          fun fmt i n -> fprintf fmt "(/ %s.0 %s.0)" i n );
+  }
+
+let escape c =
+  match c with
+  | '\\' -> "\\x5C"
+  | '\"' -> "\\x22"
+  | '\032' .. '\126' -> Format.sprintf "%c" c
+  | '\000' .. '\031' | '\127' .. '\255' ->
+    Format.sprintf "\\x%02X" (Char.code c)
+
+(* can the type of a value be derived from the type of the arguments? *)
+let unambig_fs version fs =
+  let rec lookup v ty =
+    match ty.ty_node with
+    | Tyvar u when tv_equal u v -> true
+    | _ -> ty_any (lookup v) ty
+  in
+  let lookup v = List.exists (lookup v) fs.ls_args in
+  let rec inspect ty =
+    match ty.ty_node with
+    | Tyvar u when not (lookup u) -> false
+    | _ -> ty_all inspect ty
+  in
+  match version with
+  | V20 | V26 -> true
+  | V26Par -> inspect (Opt.get fs.ls_value)
+
+(** expr *)
+let rec print_term info fmt t =
+  debug_print_term "Printing term: " t;
+  if check_for_counterexample t
+  then info.info_model <- add_model_element t info.info_model;
+
+  check_enter_vc_term t info.info_in_goal info.info_vc_term;
+
+  let () =
+    match t.t_node with
+    | Tconst c -> (
+      let ts =
+        match t.t_ty with
+        | Some { ty_node = Tyapp (ts, []) } -> ts
+        | _ -> assert false (* impossible *)
+      in
+      (* look for syntax literal ts in driver *)
+      match (query_syntax info.info_rliteral ts.ts_name, c) with
+      | Some st, Constant.ConstInt c -> syntax_range_literal st fmt c
+      | Some st, Constant.ConstReal c ->
+        let fp = match ts.ts_def with Float fp -> fp | _ -> assert false in
+        syntax_float_literal st fp fmt c
+      | _, Constant.ConstStr _ | None, _ ->
+        Constant.print number_format escape fmt c
+      (* TODO/FIXME: we must assert here that the type is either ty_int or
+         ty_real, otherwise it makes no sense to print the literal. Do we ensure
+         that preserved literal types are exactly those that have a dedicated
+         syntax? *))
+    | Tvar v -> print_var info fmt v
+    | Tapp (ls, tl) -> (
+      match query_syntax info.info_syn ls.ls_name with
+      | Some s ->
+        syntax_arguments_typed s (print_term info) (print_type info) t fmt tl
+      | None -> (
+        match tl with
+        (* for cvc3 wich doesn't accept (toto ) *)
+        | [] ->
+          let str_ls = sprintf "%a" (print_ident info) ls.ls_name in
+          let cur_var = info.info_labels in
+          let new_var = update_info_labels str_ls cur_var t ls in
+          let () = info.info_labels <- new_var in
+          let vc_term_info = info.info_vc_term in
+          (if vc_term_info.vc_inside
+          then
+            match vc_term_info.vc_loc with
+            | None -> ()
+            | Some loc ->
+              let attrs =
+                (* match vc_term_info.vc_func_name with | None -> *)
+                ls.ls_name.id_attrs
+                (* | Some _ -> model_trace_for_postcondition
+                   ~attrs:ls.ls_name.id_attrs info.info_vc_term *)
+              in
+              let _t_check_pos = t_attr_set ~loc attrs t in
+              (* TODO: temporarily disable collecting variables inside the term
+                 triggering VC *)
+              (*info.info_model <- add_model_element t_check_pos
+                info.info_model;*)
+              ());
+          if unambig_fs info.info_version ls
+          then fprintf fmt "@[%a@]" (print_ident info) ls.ls_name
+          else
+            fprintf fmt "@[(as %a %a)@]" (print_ident info) ls.ls_name
+              (print_type info) (t_type t)
+        | _ ->
+          if unambig_fs info.info_version ls
+          then
+            fprintf fmt "@[<hv2>(%a@ %a)@]" (print_ident info) ls.ls_name
+              (print_list space (print_term info))
+              tl
+          else
+            fprintf fmt "@[<hv2>((as %a@ %a)@ %a)@]" (print_ident info)
+              ls.ls_name (print_type info) (t_type t)
+              (print_list space (print_term info))
+              tl))
+    | Tlet (t1, tb) ->
+      let v, t2 = t_open_bound tb in
+      fprintf fmt "@[<hv2>(let ((%a %a))@ %a)@]" (print_var info) v
+        (print_term info) t1 (print_term info) t2;
+      forget_var info v
+    | Tif (f1, t1, t2) ->
+      fprintf fmt "@[<hv2>(ite %a@ %a@ %a)@]" (print_fmla info) f1
+        (print_term info) t1 (print_term info) t2
+    | Tcase (t, bl) -> (
+      let ty = t_type t in
+      match ty.ty_node with
+      | Tyapp (ts, _) when ts_equal ts ts_bool ->
+        print_boolean_branches info t print_term fmt bl
+      | _ -> (
+        match t.t_node with
+        | Tvar v -> print_branches info v print_term fmt bl
+        | _ ->
+          let subject = create_vsymbol (id_fresh "subject") (t_type t) in
+          fprintf fmt "@[<hv2>(let ((%a @[%a@]))@ %a)@]" (print_var info)
+            subject (print_term info) t
+            (print_branches info subject print_term)
+            bl;
+          forget_var info subject))
+    | Teps _ -> unsupportedTerm t "smtv2: you must eliminate epsilon"
+    | Tquant _ | Tbinop _ | Tnot _ | Ttrue | Tfalse -> raise (TermExpected t)
+  in
+
+  check_exit_vc_term t info.info_in_goal info.info_vc_term
+
+and print_fmla info fmt f =
+  debug_print_term "Printing formula: " f;
+  if check_for_counterexample f
+  then info.info_model <- add_model_element f info.info_model;
+
+  check_enter_vc_term f info.info_in_goal info.info_vc_term;
+
+  let () =
+    match f.t_node with
+    | Tapp ({ ls_name = id }, []) -> print_ident info fmt id
+    | Tapp (ls, tl) -> (
+      match query_syntax info.info_syn ls.ls_name with
+      | Some s ->
+        syntax_arguments_typed s (print_term info) (print_type info) f fmt tl
+      | None -> (
+        match tl with
+        (* for cvc3 wich doesn't accept (toto ) *)
+        | [] -> print_ident info fmt ls.ls_name
+        | _ ->
+          fprintf fmt "@[<hv2>(%a@ %a)@]" (print_ident info) ls.ls_name
+            (print_list space (print_term info))
+            tl))
+    | Tquant (q, fq) ->
+      let q = match q with Tforall -> "forall" | Texists -> "exists" in
+      let vl, tl, f = t_open_quant fq in
+      (* TODO trigger dépend des capacités du prover : 2 printers?
+         smtwithtriggers/smtstrict *)
+      if tl = []
+      then
+        fprintf fmt "@[<hv2>(%s @[<h>(%a)@]@ %a)@]" q
+          (print_typed_var_list info)
+          vl (print_fmla info) f
+      else
+        fprintf fmt "@[<hv2>(%s @[<h>(%a)@]@ (! %a %a))@]" q
+          (print_typed_var_list info)
+          vl (print_fmla info) f (print_triggers info) tl;
+      List.iter (forget_var info) vl
+    | Tbinop (Tand, f1, f2) ->
+      fprintf fmt "@[<hv2>(and@ %a@ %a)@]" (print_fmla info) f1
+        (print_fmla info) f2
+    | Tbinop (Tor, f1, f2) ->
+      fprintf fmt "@[<hv2>(or@ %a@ %a)@]" (print_fmla info) f1 (print_fmla info)
+        f2
+    | Tbinop (Timplies, f1, f2) ->
+      fprintf fmt "@[<hv2>(=>@ %a@ %a)@]" (print_fmla info) f1 (print_fmla info)
+        f2
+    | Tbinop (Tiff, f1, f2) ->
+      fprintf fmt "@[<hv2>(=@ %a@ %a)@]" (print_fmla info) f1 (print_fmla info)
+        f2
+    | Tnot f -> fprintf fmt "@[<hv2>(not@ %a)@]" (print_fmla info) f
+    | Ttrue -> pp_print_string fmt "true"
+    | Tfalse -> pp_print_string fmt "false"
+    | Tif (f1, f2, f3) ->
+      fprintf fmt "@[<hv2>(ite %a@ %a@ %a)@]" (print_fmla info) f1
+        (print_fmla info) f2 (print_fmla info) f3
+    | Tlet (t1, tb) ->
+      let v, f2 = t_open_bound tb in
+      fprintf fmt "@[<hv2>(let ((%a %a))@ %a)@]" (print_var info) v
+        (print_term info) t1 (print_fmla info) f2;
+      forget_var info v
+    | Tcase (t, bl) -> (
+      let ty = t_type t in
+      match ty.ty_node with
+      | Tyapp (ts, _) when ts_equal ts ts_bool ->
+        print_boolean_branches info t print_fmla fmt bl
+      | _ -> (
+        match t.t_node with
+        | Tvar v -> print_branches info v print_fmla fmt bl
+        | _ ->
+          let subject = create_vsymbol (id_fresh "subject") (t_type t) in
+          fprintf fmt "@[<hv2>(let ((%a @[%a@]))@ %a)@]" (print_var info)
+            subject (print_term info) t
+            (print_branches info subject print_fmla)
+            bl;
+          forget_var info subject))
+    | Tvar _ | Tconst _ | Teps _ -> raise (FmlaExpected f)
+  in
+
+  check_exit_vc_term f info.info_in_goal info.info_vc_term
+
+and print_boolean_branches info subject pr fmt bl =
+  let error () =
+    unsupportedTerm subject
+      "smtv2: bad pattern-matching on Boolean (compile_match missing?)"
+  in
+  match bl with
+  | [ br1; br2 ] -> (
+    let p1, t1 = t_open_branch br1 in
+    let _p2, t2 = t_open_branch br2 in
+    match p1.pat_node with
+    | Papp (cs, _) ->
+      let csname = if ls_equal cs fs_bool_true then "true" else "false" in
+      fprintf fmt "@[<hv2>(ite (= %a %s) %a %a)@]" (print_term info) subject
+        csname (pr info) t1 (pr info) t2
+    | _ -> error ())
+  | _ -> error ()
+
+and print_branches info subject pr fmt bl =
+  match bl with
+  | [] -> assert false
+  | br :: bl -> (
+    let p, t = t_open_branch br in
+    let error () =
+      unsupportedPattern p "smtv2: you must compile nested pattern-matching"
+    in
+    match p.pat_node with
+    | Pwild -> pr info fmt t
+    | Papp (cs, args) ->
+      let args =
+        List.map (function { pat_node = Pvar v } -> v | _ -> error ()) args
+      in
+      if bl = []
+      then print_branch info subject pr fmt (cs, args, t)
+      else
+        (match info.info_version with
+        | V20 | V26 (* It should be the same than V26Par but it was different *)
+          ->
+          fprintf fmt "@[<hv2>(ite (is-%a %a) %a %a)@]"
+        | V26Par -> fprintf fmt "@[<hv2>(ite ((_ is %a) %a) %a %a)@]")
+          (print_ident info) cs.ls_name (print_var info) subject
+          (print_branch info subject pr)
+          (cs, args, t)
+          (print_branches info subject pr)
+          bl
+    | _ -> error ())
+
+and print_branch info subject pr fmt (cs, vars, t) =
+  if vars = []
+  then pr info fmt t
+  else
+    let tvs = t_freevars Mvs.empty t in
+    if List.for_all (fun v -> not (Mvs.mem v tvs)) vars
+    then pr info fmt t
+    else
+      let i = ref 0 in
+      let pr_proj fmt v =
+        incr i;
+        if Mvs.mem v tvs
+        then
+          fprintf fmt "(%a (%a_proj_%d %a))" (print_var info) v
+            (print_ident info) cs.ls_name !i (print_var info) subject
+      in
+      fprintf fmt "@[<hv2>(let (%a) %a)@]" (print_list space pr_proj) vars
+        (pr info) t
+
+and print_expr info fmt =
+  TermTF.t_select (print_term info fmt) (print_fmla info fmt)
+
+and print_trigger info fmt e = print_expr info fmt e
+
+and print_triggers info fmt = function
+  | [] -> ()
+  | a :: l ->
+    fprintf fmt ":pattern (%a) %a"
+      (print_list space (print_trigger info))
+      a (print_triggers info) l
+
+let print_type_decl info fmt ts =
+  if is_alias_type_def ts.ts_def
+  then ()
+  else if Mid.mem ts.ts_name info.info_syn
+  then ()
+  else
+    fprintf fmt "(declare-sort %a %i)@\n@\n" (print_ident info) ts.ts_name
+      (List.length ts.ts_args)
+
+let print_param_decl info fmt ls =
+  if Mid.mem ls.ls_name info.info_syn
+  then ()
+  else
+    match ls.ls_args with
+    (* only in SMTLIB 2.5 | [] -> fprintf fmt "@[<hov 2>(declare-const %a
+       %a)@]@\n@\n" (print_ident info) ls.ls_name (print_type_value info)
+       ls.ls_value *)
+    | _ ->
+      let tvs = Term.ls_ty_freevars ls in
+      fprintf fmt ";; %s@\n@[<v2>(declare-fun %a %a)@]@\n@\n"
+        ls.ls_name.id_string (print_ident info) ls.ls_name
+        (print_par info (fun fmt ->
+           Format.fprintf fmt "(%a) %a"
+             (print_list space (print_type info))
+             ls.ls_args (print_type_value info) ls.ls_value))
+        tvs
+
+let rec has_quantification f =
+  match f.t_node with
+  | Tquant _ | Teps _ -> true
+  | _ -> Term.t_any has_quantification f
+
+let print_logic_decl_aux flag info fmt (ls, def) =
+  if not (Mid.mem ls.ls_name info.info_syn)
+  then (
+    collect_model_ls info ls;
+    let vsl, expr = Decl.open_ls_defn def in
+    if info.info_incremental && has_quantification expr
+    then (
+      fprintf fmt ";; %s@\n@[<hov2>(declare-fun %a (%a) %a)@]@\n@\n"
+        ls.ls_name.id_string (print_ident info) ls.ls_name
+        (print_list space (print_type info))
+        (List.map (fun vs -> vs.vs_ty) vsl)
+        (print_type_value info) ls.ls_value;
+      info.incr_list_ldecls <- (ls, vsl, expr) :: info.incr_list_ldecls)
+    else
+      let tvs = Term.ls_ty_freevars ls in
+      fprintf fmt ";; %s@\n@[<v2>(define-fun%s %a %a)@]@\n@\n"
+        ls.ls_name.id_string flag (print_ident info) ls.ls_name
+        (print_par info (fun fmt ->
+           Format.fprintf fmt "@[<h>(%a) %a@]@ %a"
+             (print_typed_var_list info)
+             vsl (print_type_value info) ls.ls_value (print_expr info) expr))
+        tvs;
+      List.iter (forget_var info) vsl)
+
+let print_logic_decl = print_logic_decl_aux ""
+
+let print_rec_logic_decl info fmt = function
+  | [] -> ()
+  | [ ld ] -> print_logic_decl_aux "-rec" info fmt ld
+  | l ->
+    let l =
+      List.map
+        (fun (ls, def) ->
+          let vsl, expr = Decl.open_ls_defn def in
+          (ls, vsl, expr))
+        l
+    in
+    let print_decl fmt (ls, vsl, _) =
+      if Mid.mem ls.ls_name info.info_syn
+      then ()
+      else (
+        collect_model_ls info ls;
+        let tvs = Term.ls_ty_freevars ls in
+        fprintf fmt "@[<hov 2>(%a %a)@]@\n@\n" (print_ident info) ls.ls_name
+          (print_par info (fun fmt ->
+             Format.fprintf fmt "(%a) %a"
+               (print_typed_var_list info)
+               vsl (print_type_value info) ls.ls_value))
+          tvs)
+    in
+    let print_term fmt (ls, _, expr) =
+      if Mid.mem ls.ls_name info.info_syn
+      then ()
+      else fprintf fmt "@[<hov 2>%a@]" (print_expr info) expr
+    in
+    fprintf fmt "@[<hov 2>(define-funs-rec (%a) (%a))@]@\n@\n"
+      (print_list nothing print_decl)
+      l
+      (print_list nothing print_term)
+      l;
+    List.iter (fun (_, vsl, _) -> List.iter (forget_var info) vsl) l
+
+let print_info_model info =
+  (* Prints the content of info.info_model *)
+  let info_model = info.info_model in
+  if (not (S.is_empty info_model)) && info.info_cntexample
+  then (
+    let model_map =
+      S.fold
+        (fun f acc ->
+          let s = asprintf "%a" (print_fmla info) f in
+          Mstr.add s f acc)
+        info_model Mstr.empty
+    in
+
+    (* Printing model has modification of info.info_model as undesirable
+       side-effect. Revert it back. *)
+    info.info_model <- info_model;
+    model_map)
+  else Mstr.empty
+
+(* TODO factor out print_prop ? *)
+let print_prop info fmt (pr, f) =
+  let tvs = Term.t_ty_freevars Ty.Stv.empty f in
+  fprintf fmt ";; %s@\n@[<hov 2>(assert@ %a)@]@\n@\n"
+    pr.pr_name.id_string (* FIXME? collisions *)
+    (print_par info (fun fmt -> print_fmla info fmt f))
+    tvs
+
+let add_check_sat info fmt =
+  if info.info_cntexample && info.info_cntexample_need_push
+  then fprintf fmt "@[(push)@]@\n";
+  fprintf fmt "@[(check-sat)@]@\n";
+  if info.info_supports_reason_unknown
+  then fprintf fmt "@[(get-info :reason-unknown)@]@\n";
+  if info.info_cntexample then fprintf fmt "@[(get-model)@]@\n@\n"
+
+let print_ldecl_axiom info fmt (ls, vls, t) =
+  fprintf fmt ";; %s@\n" ls.ls_name.id_string;
+  fprintf fmt
+    "@[<hv2>(assert@ @[<hv2>(forall @[(%a)@]@ @[<hv2>(= @[<h>(%a %a)@]@ \
+     %a)@])@])@]@\n\
+     @\n"
+    (print_typed_var_list info)
+    vls (print_ident info) ls.ls_name (print_var_list info) vls
+    (print_expr info) t
+
+(* TODO if the property doesnt begin with quantifier, then we print it first.
+   Else, we print it afterwards. *)
+let print_incremental_axiom info fmt =
+  List.iter (print_prop info fmt) info.incr_list_axioms;
+  List.iter (print_ldecl_axiom info fmt) info.incr_list_ldecls;
+  add_check_sat info fmt
+
+let print_prop_decl vc_loc vc_attrs printing_info info fmt k pr f =
+  match k with
+  | Paxiom ->
+    if info.info_incremental && has_quantification f
+    then info.incr_list_axioms <- (pr, f) :: info.incr_list_axioms
+    else print_prop info fmt (pr, f)
+  | Pgoal ->
+    let tvs = Term.t_ty_freevars Ty.Stv.empty f in
+    if not (Ty.Stv.is_empty tvs)
+    then unsupported "smt: monomorphise goal must be applied";
+    fprintf fmt ";; Goal %s@\n" pr.pr_name.id_string;
+    (match pr.pr_name.id_loc with
+    | None -> ()
+    | Some loc -> fprintf fmt ";; %a@\n" Loc.gen_report_position loc);
+    info.info_in_goal <- true;
+    fprintf fmt "@[(assert@\n";
+    fprintf fmt "  @[(not@ %a))@]@\n@\n" (print_fmla info) f;
+    info.info_in_goal <- false;
+    add_check_sat info fmt;
+
+    (* If in incremental mode, we empty the list of axioms we stored *)
+    if info.info_incremental then print_incremental_axiom info fmt;
+
+    let model_list = print_info_model info in
+
+    printing_info :=
+      Some
+        {
+          vc_term_loc = vc_loc;
+          vc_term_attrs = vc_attrs;
+          queried_terms = model_list;
+          list_projections = info.list_projs;
+          list_fields = info.list_field_def;
+          Printer.list_records = info.list_records;
+          noarg_constructors = info.noarg_constructors;
+          set_str = info.info_labels;
+        }
+  | Plemma -> assert false
+
+let print_constructor_decl info fmt (ls, args) =
+  let field_names =
+    match args with
+    | [] ->
+      fprintf fmt "(%a)" (print_ident info) ls.ls_name;
+      let cons_name = sprintf "%a" (print_ident info) ls.ls_name in
+      info.noarg_constructors <- cons_name :: info.noarg_constructors;
+      []
+    | _ ->
+      fprintf fmt "@[(%a@ " (print_ident info) ls.ls_name;
+      let field_names, _ =
+        List.fold_left2
+          (fun (acc, i) ty pr ->
+            let field_name =
+              match pr with
+              | Some pr ->
+                let field_name = sprintf "%a" (print_ident info) pr.ls_name in
+                fprintf fmt "(%s" field_name;
+                let field_trace =
+                  try
+                    let attr =
+                      Sattr.choose
+                        (Sattr.filter
+                           (fun l ->
+                             Strings.has_prefix "model_trace:" l.attr_string)
+                           pr.ls_name.id_attrs)
+                    in
+                    Strings.remove_prefix "model_trace:" attr.attr_string
+                  with Not_found -> ""
+                in
+                { field_name; field_trace; field_ident = Some pr.ls_name }
+              | None ->
+                let field_name =
+                  sprintf "%a_proj_%d" (print_ident info) ls.ls_name i
+                in
+                (* FIXME: is it possible to generate 2 same value with _proj_
+                   inside it ? Need sanitizing and uniquifying ? *)
+                fprintf fmt "(%s" field_name;
+                { field_name; field_trace = ""; field_ident = None }
+            in
+            fprintf fmt " %a)" (print_type info) ty;
+            (field_name :: acc, succ i))
+          ([], 1) ls.ls_args args
+      in
+      fprintf fmt ")@]";
+      List.rev field_names
+  in
+
+  if Strings.has_suffix "'mk" ls.ls_name.id_string
+  then
+    info.list_records <-
+      Mstr.add
+        (sprintf "%a" (print_ident info) ls.ls_name)
+        field_names info.list_records
+
+let print_data_decl info fmt (ts, cl) =
+  fprintf fmt "@[(%a@ %a)@]" (print_ident info) ts.ts_name
+    (print_list space (print_constructor_decl info))
+    cl
+
+let print_data_def info fmt (ts, cl) =
+  if ts.ts_args <> []
+  then
+    let args = List.map (fun arg -> arg.tv_name) ts.ts_args in
+    fprintf fmt "@[(par (%a) (%a))@]"
+      (print_list space (print_ident info))
+      args
+      (print_list space (print_constructor_decl info))
+      cl
+  else
+    fprintf fmt "@[(%a)@]" (print_list space (print_constructor_decl info)) cl
+
+let print_sort_decl info fmt (ts, _) =
+  fprintf fmt "@[(%a %d)@]" (print_ident info) ts.ts_name
+    (List.length ts.ts_args)
+
+let print_decl vc_loc vc_attrs printing_info info fmt d =
+  match d.d_node with
+  | Dtype ts -> print_type_decl info fmt ts
+  | Ddata [ (ts, _) ] when query_syntax info.info_syn ts.ts_name <> None -> ()
+  | Ddata dl -> (
+    match info.info_version with
+    | V20 ->
+      fprintf fmt "@[<v2>(declare-datatypes ()@ (%a))@]@\n@\n"
+        (print_list space (print_data_decl info))
+        dl
+    | V26 | V26Par ->
+      fprintf fmt "@[<v2>(declare-datatypes (%a)@ (%a))@]@\n@\n"
+        (print_list space (print_sort_decl info))
+        dl
+        (print_list space (print_data_def info))
+        dl)
+  | Dparam ls ->
+    collect_model_ls info ls;
+    print_param_decl info fmt ls
+  | Dlogic dl -> (
+    match info.info_version with
+    | V20 | V26 -> print_list nothing (print_logic_decl info) fmt dl
+    | V26Par -> (
+      match dl with
+      | [ ((s, _) as dl) ] when not (Sid.mem s.ls_name (get_decl_syms d)) ->
+        print_logic_decl info fmt dl
+      | dl -> print_rec_logic_decl info fmt dl))
+  | Dind _ -> unsupportedDecl d "smtv2: inductive definitions are not supported"
+  | Dprop (k, pr, f) ->
+    if Mid.mem pr.pr_name info.info_syn
+    then ()
+    else print_prop_decl vc_loc vc_attrs printing_info info fmt k pr f
+
+let set_produce_models fmt info =
+  if info.info_cntexample
+  then fprintf fmt "(set-option :produce-models true)@\n"
+
+let set_incremental fmt info =
+  if info.info_set_incremental
+  then fprintf fmt "(set-option :incremental true)@\n"
+
+let meta_counterexmp_need_push =
+  Theory.register_meta_excl "counterexample_need_smtlib_push"
+    [ Theory.MTstring ] ~desc:"Internal@ use@ only"
+
+let meta_incremental =
+  Theory.register_meta_excl "meta_incremental" [ Theory.MTstring ]
+    ~desc:"Internal@ use@ only"
+
+let meta_supports_reason_unknown =
+  Theory.register_meta_excl "supports_smt_get_info_unknown_reason"
+    [ Theory.MTstring ] ~desc:"Internal@ use@ only"
+
+let print_task version args ?old:_ fmt task =
+  let cntexample = Driver.get_counterexmp task in
+  let incremental =
+    let incr_meta = Task.find_meta_tds task meta_incremental in
+    not (Theory.Stdecl.is_empty incr_meta.Task.tds_set)
+  in
+  let incremental = Debug.test_flag debug_incremental || incremental in
+  let need_push =
+    let need_push_meta = Task.find_meta_tds task meta_counterexmp_need_push in
+    not (Theory.Stdecl.is_empty need_push_meta.Task.tds_set)
+  in
+  let supports_reason_unknown =
+    let m = Task.find_meta_tds task meta_supports_reason_unknown in
+    not (Theory.Stdecl.is_empty m.Task.tds_set)
+  in
+  let vc_loc = Intro_vc_vars_counterexmp.get_location_of_vc task in
+  let vc_attrs = (Task.task_goal_fmla task).t_attrs in
+  let vc_info = { vc_inside = false; vc_loc = None; vc_func_name = None } in
+  let info =
+    {
+      info_syn = Discriminate.get_syntax_map task;
+      info_rliteral = Printer.get_rliteral_map task;
+      info_model = S.empty;
+      info_in_goal = false;
+      info_vc_term = vc_info;
+      info_printer = ident_printer ();
+      list_projs = Mstr.empty;
+      list_field_def = Mstr.empty;
+      info_version = version;
+      meta_model_projection = Task.on_tagged_ls Theory.meta_projection task;
+      meta_record_def = Task.on_tagged_ls Theory.meta_record task;
+      list_records = Mstr.empty;
+      noarg_constructors = [];
+      info_cntexample_need_push = need_push;
+      info_cntexample = cntexample;
+      info_incremental = incremental;
+      info_labels = Mstr.empty;
+      (* info_set_incremental add the incremental option to the header. It is
+         not needed for some provers *)
+      info_set_incremental = (not need_push) && incremental;
+      info_supports_reason_unknown = supports_reason_unknown;
+      incr_list_axioms = [];
+      incr_list_ldecls = [];
+    }
+  in
+  print_prelude fmt args.prelude;
+  set_produce_models fmt info;
+  set_incremental fmt info;
+  print_th_prelude task fmt args.th_prelude;
+  let rec print_decls = function
+    | Some t -> (
+      print_decls t.Task.task_prev;
+      match t.Task.task_decl.Theory.td_node with
+      | Theory.Decl d -> (
+        try print_decl vc_loc vc_attrs args.printing_info info fmt d
+        with Unsupported s -> raise (UnsupportedDecl (d, s)))
+      | _ -> ())
+    | None -> ()
+  in
+  print_decls task;
+  pp_print_flush fmt ()
+
+let init () =
+  register_printer "smtv2_vnnlib" (print_task V20)
+    ~desc:"Printer@ for@ the@ SMTlib@ version@ 2@ format.";
+  register_printer "smtv2.6_vnnlib" (print_task V26)
+    ~desc:"Printer@ for@ the@ SMTlib@ version@ 2.6@ format."
diff --git a/src/printers/vnnlib.ml b/src/printers/vnnlib.ml
index 83af6d6..6329d4b 100644
--- a/src/printers/vnnlib.ml
+++ b/src/printers/vnnlib.ml
@@ -1,38 +1,27 @@
-(********************************************************************)
-(*                                                                  *)
-(*  The Why3 Verification Platform   /   The Why3 Development Team  *)
-(*  Copyright 2010-2022 --  Inria - CNRS - Paris-Saclay University  *)
-(*                                                                  *)
-(*  This software is distributed under the terms of the GNU Lesser  *)
-(*  General Public License version 2.1, with the special exception  *)
-(*  on linking described in file LICENSE.                           *)
-(*                                                                  *)
-(********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of CAISAR.                                          *)
+(*                                                                        *)
+(*  Copyright (C) 2022                                                    *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  You can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the          *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
+(*                                                                        *)
+(**************************************************************************)
 
-(** SMT v2 printer with some extensions *)
-
-open Format
 open Why3
 
-[@@@warning "-9"]
-
-open Pp
-open Wstdlib
-open Ident
-open Ty
-open Term
-open Decl
-open Printer
-open Cntexmp_printer
-
-let debug =
-  Debug.register_info_flag "smtv2_printer"
-    ~desc:"Print@ debugging@ messages@ about@ printing@ the@ input@ of@ smtv2."
-
-let debug_incremental =
-  Debug.register_info_flag "force_incremental"
-    ~desc:"Force@ incremental@ mode@ for@ smtv2@ provers"
-
 (** SMTLIB tokens taken from CVC4: src/parser/smt2/{Smt2.g,smt2.cpp} *)
 let ident_printer () =
   let bls =
@@ -321,127 +310,23 @@ let ident_printer () =
       "fmf.card.val";
     ]
   in
-  let san = sanitizer char_to_alpha char_to_alnumus in
-  create_ident_printer bls ~sanitizer:san
-
-type version =
-  | V20
-  | V26
-  | V26Par
+  let sanitizer = Ident.(sanitizer char_to_alpha char_to_alnumus) in
+  Ident.create_ident_printer bls ~sanitizer
+
+type relops = {
+  le : Term.lsymbol;
+  ge : Term.lsymbol;
+  lt : Term.lsymbol;
+  gt : Term.lsymbol;
+}
 
 type info = {
-  info_syn : syntax_map;
-  info_rliteral : syntax_map;
-  mutable info_model : S.t;
-  mutable info_in_goal : bool;
-  info_vc_term : vc_term_info;
-  info_printer : ident_printer;
-  mutable list_projs : Ident.ident Mstr.t;
-  mutable list_field_def : Ident.ident Mstr.t;
-  info_version : version;
-  meta_model_projection : Sls.t;
-  meta_record_def : Sls.t;
-  mutable list_records : field_info list Mstr.t;
-  (* For algebraic type counterexamples: constructors with no arguments can be
-     misunderstood for variables *)
-  mutable noarg_constructors : string list;
-  info_cntexample_need_push : bool;
-  info_cntexample : bool;
-  info_incremental : bool;
-  info_set_incremental : bool;
-  info_supports_reason_unknown : bool;
-  mutable info_labels : Sattr.t Mstr.t;
-  mutable incr_list_axioms : (prsymbol * term) list;
-  mutable incr_list_ldecls : (lsymbol * vsymbol list * term) list;
+  ls_rel_real : relops;
+  info_printer : Ident.ident_printer;
+  info_syn : Printer.syntax_map;
+  variables : string Term.Hls.t;
 }
 
-let debug_print_term message t =
-  let form = Debug.get_debug_formatter () in
-  Debug.dprintf debug message;
-  if Debug.test_flag debug then Pretty.print_term form t;
-  Debug.dprintf debug "@."
-
-let print_ident info fmt id =
-  pp_print_string fmt (id_unique info.info_printer id)
-
-(** type *)
-
-let print_tv info fmt tv =
-  pp_print_string fmt (id_unique info.info_printer tv.tv_name)
-
-(** print `(par ...)` around the given body to print *)
-let print_par info
-  (* body *)
-  (* Format.kdprintf *) print_body fmt tvs =
-  if Ty.Stv.is_empty tvs
-  then print_body fmt
-  else if info.info_version = V26Par
-  then
-    Format.fprintf fmt "(par (%a)@ %t)"
-      (print_iter1 Ty.Stv.iter pp_print_space (print_tv info))
-      tvs print_body
-  else unsupported "smt: polymorphism must be encoded"
-(* body *)
-
-let rec print_type info fmt ty =
-  match ty.ty_node with
-  | Tyvar s -> (
-    match info.info_version with
-    | V20 -> unsupported "smtv2: you must encode type polymorphism"
-    | V26 | V26Par -> print_tv info fmt s)
-  | Tyapp (ts, l) -> (
-    match (query_syntax info.info_syn ts.ts_name, l) with
-    | Some s, _ -> syntax_arguments s (print_type info) fmt l
-    | None, [] -> print_ident info fmt ts.ts_name
-    | None, _ ->
-      fprintf fmt "(%a %a)" (print_ident info) ts.ts_name
-        (print_list space (print_type info))
-        l)
-
-let print_type info fmt ty =
-  try print_type info fmt ty
-  with Unsupported s -> raise (UnsupportedType (ty, s))
-
-let print_type_value info fmt = function
-  | None -> pp_print_string fmt "Bool"
-  | Some ty -> print_type info fmt ty
-
-(** var *)
-let forget_var info v = forget_id info.info_printer v.vs_name
-
-let print_var info fmt { vs_name = id } =
-  let n = id_unique info.info_printer id in
-  pp_print_string fmt n
-
-let print_typed_var info fmt vs =
-  fprintf fmt "(%a %a)" (print_var info) vs (print_type info) vs.vs_ty
-
-let print_var_list info fmt vsl = print_list space (print_var info) fmt vsl
-
-let print_typed_var_list info fmt vsl =
-  print_list space (print_typed_var info) fmt vsl
-
-let collect_model_ls info ls =
-  if Sls.mem ls info.meta_model_projection
-  then
-    info.list_projs <-
-      Mstr.add
-        (sprintf "%a" (print_ident info) ls.ls_name)
-        ls.ls_name info.list_projs;
-  if Sls.mem ls info.meta_record_def
-  then
-    info.list_field_def <-
-      Mstr.add
-        (sprintf "%a" (print_ident info) ls.ls_name)
-        ls.ls_name info.list_field_def;
-  if ls.ls_args = [] && relevant_for_counterexample ls.ls_name
-  then
-    let t = t_app ls [] ls.ls_value in
-    info.info_model <-
-      add_model_element
-        (t_attr_set ?loc:ls.ls_name.id_loc ls.ls_name.id_attrs t)
-        info.info_model
-
 let number_format =
   {
     Number.long_int_support = `Default;
@@ -455,674 +340,143 @@ let number_format =
     Number.hex_real_support = `Unsupported;
     Number.frac_real_support =
       `Custom
-        ( (fun fmt i -> fprintf fmt "%s.0" i),
-          fun fmt i n -> fprintf fmt "(/ %s.0 %s.0)" i n );
+        ( (fun fmt i -> Fmt.pf fmt "%s.0" i),
+          fun fmt i n -> Fmt.pf fmt "(/ %s.0 %s.0)" i n );
   }
 
-let escape c =
-  match c with
-  | '\\' -> "\\x5C"
-  | '\"' -> "\\x22"
-  | '\032' .. '\126' -> Format.sprintf "%c" c
-  | '\000' .. '\031' | '\127' .. '\255' ->
-    Format.sprintf "\\x%02X" (Char.code c)
-
-(* can the type of a value be derived from the type of the arguments? *)
-let unambig_fs version fs =
-  let rec lookup v ty =
-    match ty.ty_node with
-    | Tyvar u when tv_equal u v -> true
-    | _ -> ty_any (lookup v) ty
-  in
-  let lookup v = List.exists (lookup v) fs.ls_args in
-  let rec inspect ty =
-    match ty.ty_node with
-    | Tyvar u when not (lookup u) -> false
-    | _ -> ty_all inspect ty
-  in
-  match version with
-  | V20 | V26 -> true
-  | V26Par -> inspect (Opt.get fs.ls_value)
-
-(** expr *)
-let rec print_term info fmt t =
-  debug_print_term "Printing term: " t;
-  if check_for_counterexample t
-  then info.info_model <- add_model_element t info.info_model;
-
-  check_enter_vc_term t info.info_in_goal info.info_vc_term;
-
-  let () =
-    match t.t_node with
-    | Tconst c -> (
-      let ts =
-        match t.t_ty with
-        | Some { ty_node = Tyapp (ts, []) } -> ts
-        | _ -> assert false (* impossible *)
-      in
-      (* look for syntax literal ts in driver *)
-      match (query_syntax info.info_rliteral ts.ts_name, c) with
-      | Some st, Constant.ConstInt c -> syntax_range_literal st fmt c
-      | Some st, Constant.ConstReal c ->
-        let fp = match ts.ts_def with Float fp -> fp | _ -> assert false in
-        syntax_float_literal st fp fmt c
-      | _, Constant.ConstStr _ | None, _ ->
-        Constant.print number_format escape fmt c
-      (* TODO/FIXME: we must assert here that the type is either ty_int or
-         ty_real, otherwise it makes no sense to print the literal. Do we ensure
-         that preserved literal types are exactly those that have a dedicated
-         syntax? *))
-    | Tvar v -> print_var info fmt v
-    | Tapp (ls, tl) -> (
-      match query_syntax info.info_syn ls.ls_name with
-      | Some s ->
-        syntax_arguments_typed s (print_term info) (print_type info) t fmt tl
-      | None -> (
-        match tl with
-        (* for cvc3 wich doesn't accept (toto ) *)
-        | [] ->
-          let str_ls = sprintf "%a" (print_ident info) ls.ls_name in
-          let cur_var = info.info_labels in
-          let new_var = update_info_labels str_ls cur_var t ls in
-          let () = info.info_labels <- new_var in
-          let vc_term_info = info.info_vc_term in
-          (if vc_term_info.vc_inside
-          then
-            match vc_term_info.vc_loc with
-            | None -> ()
-            | Some loc ->
-              let attrs =
-                (* match vc_term_info.vc_func_name with | None -> *)
-                ls.ls_name.id_attrs
-                (* | Some _ -> model_trace_for_postcondition
-                   ~attrs:ls.ls_name.id_attrs info.info_vc_term *)
-              in
-              let _t_check_pos = t_attr_set ~loc attrs t in
-              (* TODO: temporarily disable collecting variables inside the term
-                 triggering VC *)
-              (*info.info_model <- add_model_element t_check_pos
-                info.info_model;*)
-              ());
-          if unambig_fs info.info_version ls
-          then fprintf fmt "@[%a@]" (print_ident info) ls.ls_name
-          else
-            fprintf fmt "@[(as %a %a)@]" (print_ident info) ls.ls_name
-              (print_type info) (t_type t)
-        | _ ->
-          if unambig_fs info.info_version ls
-          then
-            fprintf fmt "@[<hv2>(%a@ %a)@]" (print_ident info) ls.ls_name
-              (print_list space (print_term info))
-              tl
-          else
-            fprintf fmt "@[<hv2>((as %a@ %a)@ %a)@]" (print_ident info)
-              ls.ls_name (print_type info) (t_type t)
-              (print_list space (print_term info))
-              tl))
-    | Tlet (t1, tb) ->
-      let v, t2 = t_open_bound tb in
-      fprintf fmt "@[<hv2>(let ((%a %a))@ %a)@]" (print_var info) v
-        (print_term info) t1 (print_term info) t2;
-      forget_var info v
-    | Tif (f1, t1, t2) ->
-      fprintf fmt "@[<hv2>(ite %a@ %a@ %a)@]" (print_fmla info) f1
-        (print_term info) t1 (print_term info) t2
-    | Tcase (t, bl) -> (
-      let ty = t_type t in
-      match ty.ty_node with
-      | Tyapp (ts, _) when ts_equal ts ts_bool ->
-        print_boolean_branches info t print_term fmt bl
-      | _ -> (
-        match t.t_node with
-        | Tvar v -> print_branches info v print_term fmt bl
-        | _ ->
-          let subject = create_vsymbol (id_fresh "subject") (t_type t) in
-          fprintf fmt "@[<hv2>(let ((%a @[%a@]))@ %a)@]" (print_var info)
-            subject (print_term info) t
-            (print_branches info subject print_term)
-            bl;
-          forget_var info subject))
-    | Teps _ -> unsupportedTerm t "smtv2: you must eliminate epsilon"
-    | Tquant _ | Tbinop _ | Tnot _ | Ttrue | Tfalse -> raise (TermExpected t)
-  in
-
-  check_exit_vc_term t info.info_in_goal info.info_vc_term
-
-and print_fmla info fmt f =
-  debug_print_term "Printing formula: " f;
-  if check_for_counterexample f
-  then info.info_model <- add_model_element f info.info_model;
-
-  check_enter_vc_term f info.info_in_goal info.info_vc_term;
-
-  let () =
-    match f.t_node with
-    | Tapp ({ ls_name = id }, []) -> print_ident info fmt id
-    | Tapp (ls, tl) -> (
-      match query_syntax info.info_syn ls.ls_name with
-      | Some s ->
-        syntax_arguments_typed s (print_term info) (print_type info) f fmt tl
-      | None -> (
-        match tl with
-        (* for cvc3 wich doesn't accept (toto ) *)
-        | [] -> print_ident info fmt ls.ls_name
-        | _ ->
-          fprintf fmt "@[<hv2>(%a@ %a)@]" (print_ident info) ls.ls_name
-            (print_list space (print_term info))
-            tl))
-    | Tquant (q, fq) ->
-      let q = match q with Tforall -> "forall" | Texists -> "exists" in
-      let vl, tl, f = t_open_quant fq in
-      (* TODO trigger dépend des capacités du prover : 2 printers?
-         smtwithtriggers/smtstrict *)
-      if tl = []
-      then
-        fprintf fmt "@[<hv2>(%s @[<h>(%a)@]@ %a)@]" q
-          (print_typed_var_list info)
-          vl (print_fmla info) f
-      else
-        fprintf fmt "@[<hv2>(%s @[<h>(%a)@]@ (! %a %a))@]" q
-          (print_typed_var_list info)
-          vl (print_fmla info) f (print_triggers info) tl;
-      List.iter (forget_var info) vl
-    | Tbinop (Tand, f1, f2) ->
-      fprintf fmt "@[<hv2>(and@ %a@ %a)@]" (print_fmla info) f1
-        (print_fmla info) f2
-    | Tbinop (Tor, f1, f2) ->
-      fprintf fmt "@[<hv2>(or@ %a@ %a)@]" (print_fmla info) f1 (print_fmla info)
-        f2
-    | Tbinop (Timplies, f1, f2) ->
-      fprintf fmt "@[<hv2>(=>@ %a@ %a)@]" (print_fmla info) f1 (print_fmla info)
-        f2
-    | Tbinop (Tiff, f1, f2) ->
-      fprintf fmt "@[<hv2>(=@ %a@ %a)@]" (print_fmla info) f1 (print_fmla info)
-        f2
-    | Tnot f -> fprintf fmt "@[<hv2>(not@ %a)@]" (print_fmla info) f
-    | Ttrue -> pp_print_string fmt "true"
-    | Tfalse -> pp_print_string fmt "false"
-    | Tif (f1, f2, f3) ->
-      fprintf fmt "@[<hv2>(ite %a@ %a@ %a)@]" (print_fmla info) f1
-        (print_fmla info) f2 (print_fmla info) f3
-    | Tlet (t1, tb) ->
-      let v, f2 = t_open_bound tb in
-      fprintf fmt "@[<hv2>(let ((%a %a))@ %a)@]" (print_var info) v
-        (print_term info) t1 (print_fmla info) f2;
-      forget_var info v
-    | Tcase (t, bl) -> (
-      let ty = t_type t in
-      match ty.ty_node with
-      | Tyapp (ts, _) when ts_equal ts ts_bool ->
-        print_boolean_branches info t print_fmla fmt bl
-      | _ -> (
-        match t.t_node with
-        | Tvar v -> print_branches info v print_fmla fmt bl
-        | _ ->
-          let subject = create_vsymbol (id_fresh "subject") (t_type t) in
-          fprintf fmt "@[<hv2>(let ((%a @[%a@]))@ %a)@]" (print_var info)
-            subject (print_term info) t
-            (print_branches info subject print_fmla)
-            bl;
-          forget_var info subject))
-    | Tvar _ | Tconst _ | Teps _ -> raise (FmlaExpected f)
-  in
+let print_ident info fmt id =
+  Fmt.string fmt (Ident.id_unique info.info_printer id)
 
-  check_exit_vc_term f info.info_in_goal info.info_vc_term
+let rec print_type info fmt ty =
+  match ty.Ty.ty_node with
+  | Tyvar _ -> Printer.unsupportedType ty "Unknown type variable"
+  | Tyapp (ts, tyl) -> (
+    match (Printer.query_syntax info.info_syn ts.ts_name, tyl) with
+    | Some s, _ -> Printer.syntax_arguments s (print_type info) fmt tyl
+    | None, [] -> print_ident info fmt ts.ts_name
+    | None, _ ->
+      Fmt.pf fmt "(%a %a)" (print_ident info) ts.ts_name
+        (Pp.print_list Pp.space (print_type info))
+        tyl)
 
-and print_boolean_branches info subject pr fmt bl =
-  let error () =
-    unsupportedTerm subject
-      "smtv2: bad pattern-matching on Boolean (compile_match missing?)"
-  in
-  match bl with
-  | [ br1; br2 ] -> (
-    let p1, t1 = t_open_branch br1 in
-    let _p2, t2 = t_open_branch br2 in
-    match p1.pat_node with
-    | Papp (cs, _) ->
-      let csname = if ls_equal cs fs_bool_true then "true" else "false" in
-      fprintf fmt "@[<hv2>(ite (= %a %s) %a %a)@]" (print_term info) subject
-        csname (pr info) t1 (pr info) t2
-    | _ -> error ())
-  | _ -> error ()
+let print_type_value info fmt = function
+  | None -> Fmt.string fmt "Bool"
+  | Some ty -> print_type info fmt ty
 
-and print_branches info subject pr fmt bl =
-  match bl with
-  | [] -> assert false
-  | br :: bl -> (
-    let p, t = t_open_branch br in
-    let error () =
-      unsupportedPattern p "smtv2: you must compile nested pattern-matching"
+let rec print_term info fmt t =
+  match t.Term.t_node with
+  | Tconst c -> Constant.(print number_format unsupported_escape) fmt c
+  | Tbinop (Tand, t1, t2) ->
+    Fmt.pf fmt "@[<hv2>(and@ %a@ %a)@]" (print_term info) t1 (print_term info)
+      t2
+  | Tbinop (Tor, t1, t2) ->
+    Fmt.pf fmt "@[<hv2>(or@ %a@ %a)@]" (print_term info) t1 (print_term info) t2
+  | Tapp ({ ls_name = id; _ }, []) -> print_ident info fmt id
+  | Tapp (ls, tl) -> (
+    match Printer.query_syntax info.info_syn ls.ls_name with
+    | Some s -> Printer.syntax_arguments s (print_term info) fmt tl
+    | None -> Printer.unsupportedTerm t "Unknown logic symbol(s)")
+  | _ -> ()
+
+let print_axiom info fmt (pr, t) =
+  Fmt.pf fmt ";; %s@\n" pr.Decl.pr_name.id_string;
+  Fmt.pf fmt "@[(assert %a)@]@\n@\n" (print_term info) t
+
+let print_goal info fmt (pr, t) =
+  Fmt.pf fmt ";; Goal %s@\n" pr.Decl.pr_name.id_string;
+  Fmt.pf fmt "@[<hov 2>(assert@ %a)@]@\n" (print_term info) t
+
+let rec negate_term info t =
+  match t.Term.t_node with
+  | Tbinop (Tand, t1, t2) ->
+    Term.t_or (negate_term info t1) (negate_term info t2)
+  | Tbinop (Tor, t1, t2) ->
+    Term.t_and (negate_term info t1) (negate_term info t2)
+  | Tapp (ls, [ t1; t2 ]) ->
+    let tt = [ t1; t2 ] in
+    (* Negate real relational symbols. *)
+    let ls_neg =
+      if Term.ls_equal ls info.ls_rel_real.le
+      then info.ls_rel_real.gt
+      else if Term.ls_equal ls info.ls_rel_real.ge
+      then info.ls_rel_real.lt
+      else if Term.ls_equal ls info.ls_rel_real.lt
+      then info.ls_rel_real.ge
+      else if Term.ls_equal ls info.ls_rel_real.gt
+      then info.ls_rel_real.le
+      else ls
     in
-    match p.pat_node with
-    | Pwild -> pr info fmt t
-    | Papp (cs, args) ->
-      let args =
-        List.map (function { pat_node = Pvar v } -> v | _ -> error ()) args
-      in
-      if bl = []
-      then print_branch info subject pr fmt (cs, args, t)
-      else
-        (match info.info_version with
-        | V20 | V26 (* It should be the same than V26Par but it was different *)
-          ->
-          fprintf fmt "@[<hv2>(ite (is-%a %a) %a %a)@]"
-        | V26Par -> fprintf fmt "@[<hv2>(ite ((_ is %a) %a) %a %a)@]")
-          (print_ident info) cs.ls_name (print_var info) subject
-          (print_branch info subject pr)
-          (cs, args, t)
-          (print_branches info subject pr)
-          bl
-    | _ -> error ())
-
-and print_branch info subject pr fmt (cs, vars, t) =
-  if vars = []
-  then pr info fmt t
-  else
-    let tvs = t_freevars Mvs.empty t in
-    if List.for_all (fun v -> not (Mvs.mem v tvs)) vars
-    then pr info fmt t
-    else
-      let i = ref 0 in
-      let pr_proj fmt v =
-        incr i;
-        if Mvs.mem v tvs
-        then
-          fprintf fmt "(%a (%a_proj_%d %a))" (print_var info) v
-            (print_ident info) cs.ls_name !i (print_var info) subject
-      in
-      fprintf fmt "@[<hv2>(let (%a) %a)@]" (print_list space pr_proj) vars
-        (pr info) t
-
-and print_expr info fmt =
-  TermTF.t_select (print_term info fmt) (print_fmla info fmt)
-
-and print_trigger info fmt e = print_expr info fmt e
-
-and print_triggers info fmt = function
-  | [] -> ()
-  | a :: l ->
-    fprintf fmt ":pattern (%a) %a"
-      (print_list space (print_trigger info))
-      a (print_triggers info) l
-
-let print_type_decl info fmt ts =
-  if is_alias_type_def ts.ts_def
-  then ()
-  else if Mid.mem ts.ts_name info.info_syn
-  then ()
-  else
-    fprintf fmt "(declare-sort %a %i)@\n@\n" (print_ident info) ts.ts_name
-      (List.length ts.ts_args)
+    if Term.ls_equal ls_neg ls
+    then Printer.unsupportedTerm t "Cannot negate such term"
+    else Term.ps_app ls_neg tt
+  | _ -> Printer.unsupportedTerm t "Cannot negate such term"
+
+let print_prop_decl info fmt prop_kind pr t =
+  match prop_kind with
+  | Decl.Plemma -> assert false
+  | Decl.Paxiom -> print_axiom info fmt (pr, t)
+  | Decl.Pgoal ->
+    let negated_term = negate_term info t in
+    print_goal info fmt (pr, negated_term)
 
 let print_param_decl info fmt ls =
-  if Mid.mem ls.ls_name info.info_syn
+  if Ident.Mid.mem ls.Term.ls_name info.info_syn
   then ()
   else
     match ls.ls_args with
-    (* only in SMTLIB 2.5 | [] -> fprintf fmt "@[<hov 2>(declare-const %a
-       %a)@]@\n@\n" (print_ident info) ls.ls_name (print_type_value info)
-       ls.ls_value *)
-    | _ ->
-      let tvs = Term.ls_ty_freevars ls in
-      fprintf fmt ";; %s@\n@[<v2>(declare-fun %a %a)@]@\n@\n"
-        ls.ls_name.id_string (print_ident info) ls.ls_name
-        (print_par info (fun fmt ->
-           Format.fprintf fmt "(%a) %a"
-             (print_list space (print_type info))
-             ls.ls_args (print_type_value info) ls.ls_value))
-        tvs
-
-let rec has_quantification f =
-  match f.t_node with
-  | Tquant _ | Teps _ -> true
-  | _ -> Term.t_any has_quantification f
-
-let print_logic_decl_aux flag info fmt (ls, def) =
-  if not (Mid.mem ls.ls_name info.info_syn)
-  then (
-    collect_model_ls info ls;
-    let vsl, expr = Decl.open_ls_defn def in
-    if info.info_incremental && has_quantification expr
-    then (
-      fprintf fmt ";; %s@\n@[<hov2>(declare-fun %a (%a) %a)@]@\n@\n"
-        ls.ls_name.id_string (print_ident info) ls.ls_name
-        (print_list space (print_type info))
-        (List.map (fun vs -> vs.vs_ty) vsl)
-        (print_type_value info) ls.ls_value;
-      info.incr_list_ldecls <- (ls, vsl, expr) :: info.incr_list_ldecls)
-    else
-      let tvs = Term.ls_ty_freevars ls in
-      fprintf fmt ";; %s@\n@[<v2>(define-fun%s %a %a)@]@\n@\n"
-        ls.ls_name.id_string flag (print_ident info) ls.ls_name
-        (print_par info (fun fmt ->
-           Format.fprintf fmt "@[<h>(%a) %a@]@ %a"
-             (print_typed_var_list info)
-             vsl (print_type_value info) ls.ls_value (print_expr info) expr))
-        tvs;
-      List.iter (forget_var info) vsl)
-
-let print_logic_decl = print_logic_decl_aux ""
-
-let print_rec_logic_decl info fmt = function
-  | [] -> ()
-  | [ ld ] -> print_logic_decl_aux "-rec" info fmt ld
-  | l ->
-    let l =
-      List.map
-        (fun (ls, def) ->
-          let vsl, expr = Decl.open_ls_defn def in
-          (ls, vsl, expr))
-        l
-    in
-    let print_decl fmt (ls, vsl, _) =
-      if Mid.mem ls.ls_name info.info_syn
-      then ()
-      else (
-        collect_model_ls info ls;
-        let tvs = Term.ls_ty_freevars ls in
-        fprintf fmt "@[<hov 2>(%a %a)@]@\n@\n" (print_ident info) ls.ls_name
-          (print_par info (fun fmt ->
-             Format.fprintf fmt "(%a) %a"
-               (print_typed_var_list info)
-               vsl (print_type_value info) ls.ls_value))
-          tvs)
-    in
-    let print_term fmt (ls, _, expr) =
-      if Mid.mem ls.ls_name info.info_syn
-      then ()
-      else fprintf fmt "@[<hov 2>%a@]" (print_expr info) expr
-    in
-    fprintf fmt "@[<hov 2>(define-funs-rec (%a) (%a))@]@\n@\n"
-      (print_list nothing print_decl)
-      l
-      (print_list nothing print_term)
-      l;
-    List.iter (fun (_, vsl, _) -> List.iter (forget_var info) vsl) l
-
-let print_info_model info =
-  (* Prints the content of info.info_model *)
-  let info_model = info.info_model in
-  if (not (S.is_empty info_model)) && info.info_cntexample
-  then (
-    let model_map =
-      S.fold
-        (fun f acc ->
-          let s = asprintf "%a" (print_fmla info) f in
-          Mstr.add s f acc)
-        info_model Mstr.empty
-    in
-
-    (* Printing model has modification of info.info_model as undesirable
-       side-effect. Revert it back. *)
-    info.info_model <- info_model;
-    model_map)
-  else Mstr.empty
-
-(* TODO factor out print_prop ? *)
-let print_prop info fmt (pr, f) =
-  let tvs = Term.t_ty_freevars Ty.Stv.empty f in
-  fprintf fmt ";; %s@\n@[<hov 2>(assert@ %a)@]@\n@\n"
-    pr.pr_name.id_string (* FIXME? collisions *)
-    (print_par info (fun fmt -> print_fmla info fmt f))
-    tvs
-
-let add_check_sat info fmt =
-  if info.info_cntexample && info.info_cntexample_need_push
-  then fprintf fmt "@[(push)@]@\n";
-  fprintf fmt "@[(check-sat)@]@\n";
-  if info.info_supports_reason_unknown
-  then fprintf fmt "@[(get-info :reason-unknown)@]@\n";
-  if info.info_cntexample then fprintf fmt "@[(get-model)@]@\n@\n"
-
-let print_ldecl_axiom info fmt (ls, vls, t) =
-  fprintf fmt ";; %s@\n" ls.ls_name.id_string;
-  fprintf fmt
-    "@[<hv2>(assert@ @[<hv2>(forall @[(%a)@]@ @[<hv2>(= @[<h>(%a %a)@]@ \
-     %a)@])@])@]@\n\
-     @\n"
-    (print_typed_var_list info)
-    vls (print_ident info) ls.ls_name (print_var_list info) vls
-    (print_expr info) t
-
-(* TODO if the property doesnt begin with quantifier, then we print it first.
-   Else, we print it afterwards. *)
-let print_incremental_axiom info fmt =
-  List.iter (print_prop info fmt) info.incr_list_axioms;
-  List.iter (print_ldecl_axiom info fmt) info.incr_list_ldecls;
-  add_check_sat info fmt
-
-let print_prop_decl vc_loc vc_attrs printing_info info fmt k pr f =
-  match k with
-  | Paxiom ->
-    if info.info_incremental && has_quantification f
-    then info.incr_list_axioms <- (pr, f) :: info.incr_list_axioms
-    else print_prop info fmt (pr, f)
-  | Pgoal ->
-    let tvs = Term.t_ty_freevars Ty.Stv.empty f in
-    if not (Ty.Stv.is_empty tvs)
-    then unsupported "smt: monomorphise goal must be applied";
-    fprintf fmt ";; Goal %s@\n" pr.pr_name.id_string;
-    (match pr.pr_name.id_loc with
-    | None -> ()
-    | Some loc -> fprintf fmt ";; %a@\n" Loc.gen_report_position loc);
-    info.info_in_goal <- true;
-    fprintf fmt "@[(assert@\n";
-    fprintf fmt "  @[(not@ %a))@]@\n@\n" (print_fmla info) f;
-    info.info_in_goal <- false;
-    add_check_sat info fmt;
-
-    (* If in incremental mode, we empty the list of axioms we stored *)
-    if info.info_incremental then print_incremental_axiom info fmt;
-
-    let model_list = print_info_model info in
-
-    printing_info :=
-      Some
-        {
-          vc_term_loc = vc_loc;
-          vc_term_attrs = vc_attrs;
-          queried_terms = model_list;
-          list_projections = info.list_projs;
-          list_fields = info.list_field_def;
-          Printer.list_records = info.list_records;
-          noarg_constructors = info.noarg_constructors;
-          set_str = info.info_labels;
-        }
-  | Plemma -> assert false
-
-let print_constructor_decl info fmt (ls, args) =
-  let field_names =
-    match args with
     | [] ->
-      fprintf fmt "(%a)" (print_ident info) ls.ls_name;
-      let cons_name = sprintf "%a" (print_ident info) ls.ls_name in
-      info.noarg_constructors <- cons_name :: info.noarg_constructors;
-      []
-    | _ ->
-      fprintf fmt "@[(%a@ " (print_ident info) ls.ls_name;
-      let field_names, _ =
-        List.fold_left2
-          (fun (acc, i) ty pr ->
-            let field_name =
-              match pr with
-              | Some pr ->
-                let field_name = sprintf "%a" (print_ident info) pr.ls_name in
-                fprintf fmt "(%s" field_name;
-                let field_trace =
-                  try
-                    let attr =
-                      Sattr.choose
-                        (Sattr.filter
-                           (fun l ->
-                             Strings.has_prefix "model_trace:" l.attr_string)
-                           pr.ls_name.id_attrs)
-                    in
-                    Strings.remove_prefix "model_trace:" attr.attr_string
-                  with Not_found -> ""
-                in
-                { field_name; field_trace; field_ident = Some pr.ls_name }
-              | None ->
-                let field_name =
-                  sprintf "%a_proj_%d" (print_ident info) ls.ls_name i
-                in
-                (* FIXME: is it possible to generate 2 same value with _proj_
-                   inside it ? Need sanitizing and uniquifying ? *)
-                fprintf fmt "(%s" field_name;
-                { field_name; field_trace = ""; field_ident = None }
-            in
-            fprintf fmt " %a)" (print_type info) ty;
-            (field_name :: acc, succ i))
-          ([], 1) ls.ls_args args
-      in
-      fprintf fmt ")@]";
-      List.rev field_names
+      Fmt.pf fmt ";; %s@\n" ls.ls_name.id_string;
+      Fmt.pf fmt "@[(declare-const %a %a)@]@\n@\n" (print_ident info) ls.ls_name
+        (print_type_value info) ls.ls_value
+    | _ -> Printer.unsupported "Function declaration"
+
+let print_decl info fmt d =
+  match d.Decl.d_node with
+  | Dtype _ -> ()
+  | Ddata _ -> ()
+  | Dlogic _ -> ()
+  | Dind _ -> ()
+  | Dparam ls -> print_param_decl info fmt ls
+  | Dprop (k, pr, f) -> print_prop_decl info fmt k pr f
+
+let rec print_tdecl info fmt task =
+  match task with
+  | None -> ()
+  | Some { Task.task_prev; task_decl; _ } -> (
+    print_tdecl info fmt task_prev;
+    match task_decl.Theory.td_node with
+    | Use _ | Clone _ -> ()
+    | Meta (meta, l) when Theory.meta_equal meta Utils.meta_input -> (
+      match l with
+      | [ MAls ls; MAint i ] -> Term.Hls.add info.variables ls (Fmt.str "x%i" i)
+      | _ -> assert false)
+    | Meta (meta, l) when Theory.meta_equal meta Utils.meta_output -> (
+      match l with
+      | [ MAls ls; MAint i ] -> Term.Hls.add info.variables ls (Fmt.str "y%i" i)
+      | _ -> assert false)
+    | Meta _ -> ()
+    | Decl d -> print_decl info fmt d)
+
+let print_task args ?old:_ fmt task =
+  let ls_rel_real =
+    let th = Env.read_theory args.Printer.env [ "real" ] "Real" in
+    let le = Theory.ns_find_ls th.th_export [ Ident.op_infix "<=" ] in
+    let lt = Theory.ns_find_ls th.th_export [ Ident.op_infix "<" ] in
+    let ge = Theory.ns_find_ls th.th_export [ Ident.op_infix ">=" ] in
+    let gt = Theory.ns_find_ls th.th_export [ Ident.op_infix ">" ] in
+    { le; ge; lt; gt }
   in
-
-  if Strings.has_suffix "'mk" ls.ls_name.id_string
-  then
-    info.list_records <-
-      Mstr.add
-        (sprintf "%a" (print_ident info) ls.ls_name)
-        field_names info.list_records
-
-let print_data_decl info fmt (ts, cl) =
-  fprintf fmt "@[(%a@ %a)@]" (print_ident info) ts.ts_name
-    (print_list space (print_constructor_decl info))
-    cl
-
-let print_data_def info fmt (ts, cl) =
-  if ts.ts_args <> []
-  then
-    let args = List.map (fun arg -> arg.tv_name) ts.ts_args in
-    fprintf fmt "@[(par (%a) (%a))@]"
-      (print_list space (print_ident info))
-      args
-      (print_list space (print_constructor_decl info))
-      cl
-  else
-    fprintf fmt "@[(%a)@]" (print_list space (print_constructor_decl info)) cl
-
-let print_sort_decl info fmt (ts, _) =
-  fprintf fmt "@[(%a %d)@]" (print_ident info) ts.ts_name
-    (List.length ts.ts_args)
-
-let print_decl vc_loc vc_attrs printing_info info fmt d =
-  match d.d_node with
-  | Dtype ts -> print_type_decl info fmt ts
-  | Ddata [ (ts, _) ] when query_syntax info.info_syn ts.ts_name <> None -> ()
-  | Ddata dl -> (
-    match info.info_version with
-    | V20 ->
-      fprintf fmt "@[<v2>(declare-datatypes ()@ (%a))@]@\n@\n"
-        (print_list space (print_data_decl info))
-        dl
-    | V26 | V26Par ->
-      fprintf fmt "@[<v2>(declare-datatypes (%a)@ (%a))@]@\n@\n"
-        (print_list space (print_sort_decl info))
-        dl
-        (print_list space (print_data_def info))
-        dl)
-  | Dparam ls ->
-    collect_model_ls info ls;
-    print_param_decl info fmt ls
-  | Dlogic dl -> (
-    match info.info_version with
-    | V20 | V26 -> print_list nothing (print_logic_decl info) fmt dl
-    | V26Par -> (
-      match dl with
-      | [ ((s, _) as dl) ] when not (Sid.mem s.ls_name (get_decl_syms d)) ->
-        print_logic_decl info fmt dl
-      | dl -> print_rec_logic_decl info fmt dl))
-  | Dind _ -> unsupportedDecl d "smtv2: inductive definitions are not supported"
-  | Dprop (k, pr, f) ->
-    if Mid.mem pr.pr_name info.info_syn
-    then ()
-    else print_prop_decl vc_loc vc_attrs printing_info info fmt k pr f
-
-let set_produce_models fmt info =
-  if info.info_cntexample
-  then fprintf fmt "(set-option :produce-models true)@\n"
-
-let set_incremental fmt info =
-  if info.info_set_incremental
-  then fprintf fmt "(set-option :incremental true)@\n"
-
-let meta_counterexmp_need_push =
-  Theory.register_meta_excl "counterexample_need_smtlib_push"
-    [ Theory.MTstring ] ~desc:"Internal@ use@ only"
-
-let meta_incremental =
-  Theory.register_meta_excl "meta_incremental" [ Theory.MTstring ]
-    ~desc:"Internal@ use@ only"
-
-let meta_supports_reason_unknown =
-  Theory.register_meta_excl "supports_smt_get_info_unknown_reason"
-    [ Theory.MTstring ] ~desc:"Internal@ use@ only"
-
-let print_task version args ?old:_ fmt task =
-  let cntexample = Driver.get_counterexmp task in
-  let incremental =
-    let incr_meta = Task.find_meta_tds task meta_incremental in
-    not (Theory.Stdecl.is_empty incr_meta.Task.tds_set)
-  in
-  let incremental = Debug.test_flag debug_incremental || incremental in
-  let need_push =
-    let need_push_meta = Task.find_meta_tds task meta_counterexmp_need_push in
-    not (Theory.Stdecl.is_empty need_push_meta.Task.tds_set)
-  in
-  let supports_reason_unknown =
-    let m = Task.find_meta_tds task meta_supports_reason_unknown in
-    not (Theory.Stdecl.is_empty m.Task.tds_set)
-  in
-  let vc_loc = Intro_vc_vars_counterexmp.get_location_of_vc task in
-  let vc_attrs = (Task.task_goal_fmla task).t_attrs in
-  let vc_info = { vc_inside = false; vc_loc = None; vc_func_name = None } in
   let info =
     {
-      info_syn = Discriminate.get_syntax_map task;
-      info_rliteral = Printer.get_rliteral_map task;
-      info_model = S.empty;
-      info_in_goal = false;
-      info_vc_term = vc_info;
+      ls_rel_real;
       info_printer = ident_printer ();
-      list_projs = Mstr.empty;
-      list_field_def = Mstr.empty;
-      info_version = version;
-      meta_model_projection = Task.on_tagged_ls Theory.meta_projection task;
-      meta_record_def = Task.on_tagged_ls Theory.meta_record task;
-      list_records = Mstr.empty;
-      noarg_constructors = [];
-      info_cntexample_need_push = need_push;
-      info_cntexample = cntexample;
-      info_incremental = incremental;
-      info_labels = Mstr.empty;
-      (* info_set_incremental add the incremental option to the header. It is
-         not needed for some provers *)
-      info_set_incremental = (not need_push) && incremental;
-      info_supports_reason_unknown = supports_reason_unknown;
-      incr_list_axioms = [];
-      incr_list_ldecls = [];
+      info_syn = Discriminate.get_syntax_map task;
+      variables = Term.Hls.create 10;
     }
   in
-  print_prelude fmt args.prelude;
-  set_produce_models fmt info;
-  set_incremental fmt info;
-  print_th_prelude task fmt args.th_prelude;
-  let rec print_decls = function
-    | Some t -> (
-      print_decls t.Task.task_prev;
-      match t.Task.task_decl.Theory.td_node with
-      | Theory.Decl d -> (
-        try print_decl vc_loc vc_attrs args.printing_info info fmt d
-        with Unsupported s -> raise (UnsupportedDecl (d, s)))
-      | _ -> ())
-    | None -> ()
-  in
-  print_decls task;
-  pp_print_flush fmt ()
+  Printer.print_prelude fmt args.Printer.prelude;
+  print_tdecl info fmt task
 
 let init () =
-  register_printer "smtv2_vnnlib" (print_task V20)
-    ~desc:"Printer@ for@ the@ SMTlib@ version@ 2@ format.";
-  register_printer "smtv2.6_vnnlib" (print_task V26)
-    ~desc:"Printer@ for@ the@ SMTlib@ version@ 2.6@ format."
+  Printer.register_printer ~desc:"Printer@ for@ the@ VNN-LIB@ format." "vnnlib"
+    print_task
-- 
GitLab