Rename namespace CVC5 to cvc5. (#6258)
[cvc5.git] / src / api / cvc4cpp.cpp
index 10f39cb383a34ba3ff7f539e6f0cc14fb2b3451b..9e55cdaf03c5f3a3aeb8a4ec257baffd058e21d6 100644 (file)
@@ -4,7 +4,7 @@
  ** Top contributors (to current version):
  **   Aina Niemetz, Andrew Reynolds, Andres Noetzli
  ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
  ** in the top-level source directory and their institutional affiliations.
  ** All rights reserved.  See the file COPYING in the top-level source
  ** directory for licensing information.\endverbatim
 #include <cstring>
 #include <sstream>
 
+#include "api/checks.h"
 #include "base/check.h"
 #include "base/configuration.h"
 #include "expr/dtype.h"
-#include "expr/expr.h"
-#include "expr/expr_manager.h"
-#include "expr/expr_manager_scope.h"
+#include "expr/dtype_cons.h"
+#include "expr/dtype_selector.h"
 #include "expr/kind.h"
 #include "expr/metakind.h"
 #include "expr/node.h"
+#include "expr/node_algorithm.h"
 #include "expr/node_manager.h"
 #include "expr/sequence.h"
-#include "expr/type.h"
 #include "expr/type_node.h"
 #include "options/main_options.h"
 #include "options/options.h"
 #include "theory/theory_model.h"
 #include "util/random.h"
 #include "util/result.h"
+#include "util/statistics_registry.h"
+#include "util/stats_histogram.h"
 #include "util/utility.h"
 
-namespace CVC4 {
+namespace cvc5 {
 namespace api {
 
+/* -------------------------------------------------------------------------- */
+/* Statistics                                                                 */
+/* -------------------------------------------------------------------------- */
+
+struct Statistics
+{
+  Statistics()
+      : d_consts("api::CONSTANT"), d_vars("api::VARIABLE"), d_terms("api::TERM")
+  {
+  }
+  IntegralHistogramStat<TypeConstant> d_consts;
+  IntegralHistogramStat<TypeConstant> d_vars;
+  IntegralHistogramStat<Kind> d_terms;
+};
+
 /* -------------------------------------------------------------------------- */
 /* Kind                                                                       */
 /* -------------------------------------------------------------------------- */
 
 /* Mapping from external (API) kind to internal kind. */
-const static std::unordered_map<Kind, CVC4::Kind, KindHashFunction> s_kinds{
-    {INTERNAL_KIND, CVC4::Kind::UNDEFINED_KIND},
-    {UNDEFINED_KIND, CVC4::Kind::UNDEFINED_KIND},
-    {NULL_EXPR, CVC4::Kind::NULL_EXPR},
+const static std::unordered_map<Kind, cvc5::Kind, KindHashFunction> s_kinds{
+    {INTERNAL_KIND, cvc5::Kind::UNDEFINED_KIND},
+    {UNDEFINED_KIND, cvc5::Kind::UNDEFINED_KIND},
+    {NULL_EXPR, cvc5::Kind::NULL_EXPR},
     /* Builtin ------------------------------------------------------------- */
-    {UNINTERPRETED_CONSTANT, CVC4::Kind::UNINTERPRETED_CONSTANT},
-    {ABSTRACT_VALUE, CVC4::Kind::ABSTRACT_VALUE},
-    {EQUAL, CVC4::Kind::EQUAL},
-    {DISTINCT, CVC4::Kind::DISTINCT},
-    {CONSTANT, CVC4::Kind::VARIABLE},
-    {VARIABLE, CVC4::Kind::BOUND_VARIABLE},
-    {SEXPR, CVC4::Kind::SEXPR},
-    {LAMBDA, CVC4::Kind::LAMBDA},
-    {WITNESS, CVC4::Kind::WITNESS},
+    {UNINTERPRETED_CONSTANT, cvc5::Kind::UNINTERPRETED_CONSTANT},
+    {ABSTRACT_VALUE, cvc5::Kind::ABSTRACT_VALUE},
+    {EQUAL, cvc5::Kind::EQUAL},
+    {DISTINCT, cvc5::Kind::DISTINCT},
+    {CONSTANT, cvc5::Kind::VARIABLE},
+    {VARIABLE, cvc5::Kind::BOUND_VARIABLE},
+    {SEXPR, cvc5::Kind::SEXPR},
+    {LAMBDA, cvc5::Kind::LAMBDA},
+    {WITNESS, cvc5::Kind::WITNESS},
     /* Boolean ------------------------------------------------------------- */
-    {CONST_BOOLEAN, CVC4::Kind::CONST_BOOLEAN},
-    {NOT, CVC4::Kind::NOT},
-    {AND, CVC4::Kind::AND},
-    {IMPLIES, CVC4::Kind::IMPLIES},
-    {OR, CVC4::Kind::OR},
-    {XOR, CVC4::Kind::XOR},
-    {ITE, CVC4::Kind::ITE},
-    {MATCH, CVC4::Kind::MATCH},
-    {MATCH_CASE, CVC4::Kind::MATCH_CASE},
-    {MATCH_BIND_CASE, CVC4::Kind::MATCH_BIND_CASE},
+    {CONST_BOOLEAN, cvc5::Kind::CONST_BOOLEAN},
+    {NOT, cvc5::Kind::NOT},
+    {AND, cvc5::Kind::AND},
+    {IMPLIES, cvc5::Kind::IMPLIES},
+    {OR, cvc5::Kind::OR},
+    {XOR, cvc5::Kind::XOR},
+    {ITE, cvc5::Kind::ITE},
+    {MATCH, cvc5::Kind::MATCH},
+    {MATCH_CASE, cvc5::Kind::MATCH_CASE},
+    {MATCH_BIND_CASE, cvc5::Kind::MATCH_BIND_CASE},
     /* UF ------------------------------------------------------------------ */
-    {APPLY_UF, CVC4::Kind::APPLY_UF},
-    {CARDINALITY_CONSTRAINT, CVC4::Kind::CARDINALITY_CONSTRAINT},
-    {CARDINALITY_VALUE, CVC4::Kind::CARDINALITY_VALUE},
-    {HO_APPLY, CVC4::Kind::HO_APPLY},
+    {APPLY_UF, cvc5::Kind::APPLY_UF},
+    {CARDINALITY_CONSTRAINT, cvc5::Kind::CARDINALITY_CONSTRAINT},
+    {CARDINALITY_VALUE, cvc5::Kind::CARDINALITY_VALUE},
+    {HO_APPLY, cvc5::Kind::HO_APPLY},
     /* Arithmetic ---------------------------------------------------------- */
-    {PLUS, CVC4::Kind::PLUS},
-    {MULT, CVC4::Kind::MULT},
-    {IAND, CVC4::Kind::IAND},
-    {MINUS, CVC4::Kind::MINUS},
-    {UMINUS, CVC4::Kind::UMINUS},
-    {DIVISION, CVC4::Kind::DIVISION},
-    {INTS_DIVISION, CVC4::Kind::INTS_DIVISION},
-    {INTS_MODULUS, CVC4::Kind::INTS_MODULUS},
-    {ABS, CVC4::Kind::ABS},
-    {DIVISIBLE, CVC4::Kind::DIVISIBLE},
-    {POW, CVC4::Kind::POW},
-    {EXPONENTIAL, CVC4::Kind::EXPONENTIAL},
-    {SINE, CVC4::Kind::SINE},
-    {COSINE, CVC4::Kind::COSINE},
-    {TANGENT, CVC4::Kind::TANGENT},
-    {COSECANT, CVC4::Kind::COSECANT},
-    {SECANT, CVC4::Kind::SECANT},
-    {COTANGENT, CVC4::Kind::COTANGENT},
-    {ARCSINE, CVC4::Kind::ARCSINE},
-    {ARCCOSINE, CVC4::Kind::ARCCOSINE},
-    {ARCTANGENT, CVC4::Kind::ARCTANGENT},
-    {ARCCOSECANT, CVC4::Kind::ARCCOSECANT},
-    {ARCSECANT, CVC4::Kind::ARCSECANT},
-    {ARCCOTANGENT, CVC4::Kind::ARCCOTANGENT},
-    {SQRT, CVC4::Kind::SQRT},
-    {CONST_RATIONAL, CVC4::Kind::CONST_RATIONAL},
-    {LT, CVC4::Kind::LT},
-    {LEQ, CVC4::Kind::LEQ},
-    {GT, CVC4::Kind::GT},
-    {GEQ, CVC4::Kind::GEQ},
-    {IS_INTEGER, CVC4::Kind::IS_INTEGER},
-    {TO_INTEGER, CVC4::Kind::TO_INTEGER},
-    {TO_REAL, CVC4::Kind::TO_REAL},
-    {PI, CVC4::Kind::PI},
+    {PLUS, cvc5::Kind::PLUS},
+    {MULT, cvc5::Kind::MULT},
+    {IAND, cvc5::Kind::IAND},
+    {MINUS, cvc5::Kind::MINUS},
+    {UMINUS, cvc5::Kind::UMINUS},
+    {DIVISION, cvc5::Kind::DIVISION},
+    {INTS_DIVISION, cvc5::Kind::INTS_DIVISION},
+    {INTS_MODULUS, cvc5::Kind::INTS_MODULUS},
+    {ABS, cvc5::Kind::ABS},
+    {DIVISIBLE, cvc5::Kind::DIVISIBLE},
+    {POW, cvc5::Kind::POW},
+    {EXPONENTIAL, cvc5::Kind::EXPONENTIAL},
+    {SINE, cvc5::Kind::SINE},
+    {COSINE, cvc5::Kind::COSINE},
+    {TANGENT, cvc5::Kind::TANGENT},
+    {COSECANT, cvc5::Kind::COSECANT},
+    {SECANT, cvc5::Kind::SECANT},
+    {COTANGENT, cvc5::Kind::COTANGENT},
+    {ARCSINE, cvc5::Kind::ARCSINE},
+    {ARCCOSINE, cvc5::Kind::ARCCOSINE},
+    {ARCTANGENT, cvc5::Kind::ARCTANGENT},
+    {ARCCOSECANT, cvc5::Kind::ARCCOSECANT},
+    {ARCSECANT, cvc5::Kind::ARCSECANT},
+    {ARCCOTANGENT, cvc5::Kind::ARCCOTANGENT},
+    {SQRT, cvc5::Kind::SQRT},
+    {CONST_RATIONAL, cvc5::Kind::CONST_RATIONAL},
+    {LT, cvc5::Kind::LT},
+    {LEQ, cvc5::Kind::LEQ},
+    {GT, cvc5::Kind::GT},
+    {GEQ, cvc5::Kind::GEQ},
+    {IS_INTEGER, cvc5::Kind::IS_INTEGER},
+    {TO_INTEGER, cvc5::Kind::TO_INTEGER},
+    {TO_REAL, cvc5::Kind::TO_REAL},
+    {PI, cvc5::Kind::PI},
     /* BV ------------------------------------------------------------------ */
-    {CONST_BITVECTOR, CVC4::Kind::CONST_BITVECTOR},
-    {BITVECTOR_CONCAT, CVC4::Kind::BITVECTOR_CONCAT},
-    {BITVECTOR_AND, CVC4::Kind::BITVECTOR_AND},
-    {BITVECTOR_OR, CVC4::Kind::BITVECTOR_OR},
-    {BITVECTOR_XOR, CVC4::Kind::BITVECTOR_XOR},
-    {BITVECTOR_NOT, CVC4::Kind::BITVECTOR_NOT},
-    {BITVECTOR_NAND, CVC4::Kind::BITVECTOR_NAND},
-    {BITVECTOR_NOR, CVC4::Kind::BITVECTOR_NOR},
-    {BITVECTOR_XNOR, CVC4::Kind::BITVECTOR_XNOR},
-    {BITVECTOR_COMP, CVC4::Kind::BITVECTOR_COMP},
-    {BITVECTOR_MULT, CVC4::Kind::BITVECTOR_MULT},
-    {BITVECTOR_PLUS, CVC4::Kind::BITVECTOR_PLUS},
-    {BITVECTOR_SUB, CVC4::Kind::BITVECTOR_SUB},
-    {BITVECTOR_NEG, CVC4::Kind::BITVECTOR_NEG},
-    {BITVECTOR_UDIV, CVC4::Kind::BITVECTOR_UDIV},
-    {BITVECTOR_UREM, CVC4::Kind::BITVECTOR_UREM},
-    {BITVECTOR_SDIV, CVC4::Kind::BITVECTOR_SDIV},
-    {BITVECTOR_SREM, CVC4::Kind::BITVECTOR_SREM},
-    {BITVECTOR_SMOD, CVC4::Kind::BITVECTOR_SMOD},
-    {BITVECTOR_SHL, CVC4::Kind::BITVECTOR_SHL},
-    {BITVECTOR_LSHR, CVC4::Kind::BITVECTOR_LSHR},
-    {BITVECTOR_ASHR, CVC4::Kind::BITVECTOR_ASHR},
-    {BITVECTOR_ULT, CVC4::Kind::BITVECTOR_ULT},
-    {BITVECTOR_ULE, CVC4::Kind::BITVECTOR_ULE},
-    {BITVECTOR_UGT, CVC4::Kind::BITVECTOR_UGT},
-    {BITVECTOR_UGE, CVC4::Kind::BITVECTOR_UGE},
-    {BITVECTOR_SLT, CVC4::Kind::BITVECTOR_SLT},
-    {BITVECTOR_SLE, CVC4::Kind::BITVECTOR_SLE},
-    {BITVECTOR_SGT, CVC4::Kind::BITVECTOR_SGT},
-    {BITVECTOR_SGE, CVC4::Kind::BITVECTOR_SGE},
-    {BITVECTOR_ULTBV, CVC4::Kind::BITVECTOR_ULTBV},
-    {BITVECTOR_SLTBV, CVC4::Kind::BITVECTOR_SLTBV},
-    {BITVECTOR_ITE, CVC4::Kind::BITVECTOR_ITE},
-    {BITVECTOR_REDOR, CVC4::Kind::BITVECTOR_REDOR},
-    {BITVECTOR_REDAND, CVC4::Kind::BITVECTOR_REDAND},
-    {BITVECTOR_EXTRACT, CVC4::Kind::BITVECTOR_EXTRACT},
-    {BITVECTOR_REPEAT, CVC4::Kind::BITVECTOR_REPEAT},
-    {BITVECTOR_ZERO_EXTEND, CVC4::Kind::BITVECTOR_ZERO_EXTEND},
-    {BITVECTOR_SIGN_EXTEND, CVC4::Kind::BITVECTOR_SIGN_EXTEND},
-    {BITVECTOR_ROTATE_LEFT, CVC4::Kind::BITVECTOR_ROTATE_LEFT},
-    {BITVECTOR_ROTATE_RIGHT, CVC4::Kind::BITVECTOR_ROTATE_RIGHT},
-    {INT_TO_BITVECTOR, CVC4::Kind::INT_TO_BITVECTOR},
-    {BITVECTOR_TO_NAT, CVC4::Kind::BITVECTOR_TO_NAT},
+    {CONST_BITVECTOR, cvc5::Kind::CONST_BITVECTOR},
+    {BITVECTOR_CONCAT, cvc5::Kind::BITVECTOR_CONCAT},
+    {BITVECTOR_AND, cvc5::Kind::BITVECTOR_AND},
+    {BITVECTOR_OR, cvc5::Kind::BITVECTOR_OR},
+    {BITVECTOR_XOR, cvc5::Kind::BITVECTOR_XOR},
+    {BITVECTOR_NOT, cvc5::Kind::BITVECTOR_NOT},
+    {BITVECTOR_NAND, cvc5::Kind::BITVECTOR_NAND},
+    {BITVECTOR_NOR, cvc5::Kind::BITVECTOR_NOR},
+    {BITVECTOR_XNOR, cvc5::Kind::BITVECTOR_XNOR},
+    {BITVECTOR_COMP, cvc5::Kind::BITVECTOR_COMP},
+    {BITVECTOR_MULT, cvc5::Kind::BITVECTOR_MULT},
+    {BITVECTOR_PLUS, cvc5::Kind::BITVECTOR_PLUS},
+    {BITVECTOR_SUB, cvc5::Kind::BITVECTOR_SUB},
+    {BITVECTOR_NEG, cvc5::Kind::BITVECTOR_NEG},
+    {BITVECTOR_UDIV, cvc5::Kind::BITVECTOR_UDIV},
+    {BITVECTOR_UREM, cvc5::Kind::BITVECTOR_UREM},
+    {BITVECTOR_SDIV, cvc5::Kind::BITVECTOR_SDIV},
+    {BITVECTOR_SREM, cvc5::Kind::BITVECTOR_SREM},
+    {BITVECTOR_SMOD, cvc5::Kind::BITVECTOR_SMOD},
+    {BITVECTOR_SHL, cvc5::Kind::BITVECTOR_SHL},
+    {BITVECTOR_LSHR, cvc5::Kind::BITVECTOR_LSHR},
+    {BITVECTOR_ASHR, cvc5::Kind::BITVECTOR_ASHR},
+    {BITVECTOR_ULT, cvc5::Kind::BITVECTOR_ULT},
+    {BITVECTOR_ULE, cvc5::Kind::BITVECTOR_ULE},
+    {BITVECTOR_UGT, cvc5::Kind::BITVECTOR_UGT},
+    {BITVECTOR_UGE, cvc5::Kind::BITVECTOR_UGE},
+    {BITVECTOR_SLT, cvc5::Kind::BITVECTOR_SLT},
+    {BITVECTOR_SLE, cvc5::Kind::BITVECTOR_SLE},
+    {BITVECTOR_SGT, cvc5::Kind::BITVECTOR_SGT},
+    {BITVECTOR_SGE, cvc5::Kind::BITVECTOR_SGE},
+    {BITVECTOR_ULTBV, cvc5::Kind::BITVECTOR_ULTBV},
+    {BITVECTOR_SLTBV, cvc5::Kind::BITVECTOR_SLTBV},
+    {BITVECTOR_ITE, cvc5::Kind::BITVECTOR_ITE},
+    {BITVECTOR_REDOR, cvc5::Kind::BITVECTOR_REDOR},
+    {BITVECTOR_REDAND, cvc5::Kind::BITVECTOR_REDAND},
+    {BITVECTOR_EXTRACT, cvc5::Kind::BITVECTOR_EXTRACT},
+    {BITVECTOR_REPEAT, cvc5::Kind::BITVECTOR_REPEAT},
+    {BITVECTOR_ZERO_EXTEND, cvc5::Kind::BITVECTOR_ZERO_EXTEND},
+    {BITVECTOR_SIGN_EXTEND, cvc5::Kind::BITVECTOR_SIGN_EXTEND},
+    {BITVECTOR_ROTATE_LEFT, cvc5::Kind::BITVECTOR_ROTATE_LEFT},
+    {BITVECTOR_ROTATE_RIGHT, cvc5::Kind::BITVECTOR_ROTATE_RIGHT},
+    {INT_TO_BITVECTOR, cvc5::Kind::INT_TO_BITVECTOR},
+    {BITVECTOR_TO_NAT, cvc5::Kind::BITVECTOR_TO_NAT},
     /* FP ------------------------------------------------------------------ */
-    {CONST_FLOATINGPOINT, CVC4::Kind::CONST_FLOATINGPOINT},
-    {CONST_ROUNDINGMODE, CVC4::Kind::CONST_ROUNDINGMODE},
-    {FLOATINGPOINT_FP, CVC4::Kind::FLOATINGPOINT_FP},
-    {FLOATINGPOINT_EQ, CVC4::Kind::FLOATINGPOINT_EQ},
-    {FLOATINGPOINT_ABS, CVC4::Kind::FLOATINGPOINT_ABS},
-    {FLOATINGPOINT_NEG, CVC4::Kind::FLOATINGPOINT_NEG},
-    {FLOATINGPOINT_PLUS, CVC4::Kind::FLOATINGPOINT_PLUS},
-    {FLOATINGPOINT_SUB, CVC4::Kind::FLOATINGPOINT_SUB},
-    {FLOATINGPOINT_MULT, CVC4::Kind::FLOATINGPOINT_MULT},
-    {FLOATINGPOINT_DIV, CVC4::Kind::FLOATINGPOINT_DIV},
-    {FLOATINGPOINT_FMA, CVC4::Kind::FLOATINGPOINT_FMA},
-    {FLOATINGPOINT_SQRT, CVC4::Kind::FLOATINGPOINT_SQRT},
-    {FLOATINGPOINT_REM, CVC4::Kind::FLOATINGPOINT_REM},
-    {FLOATINGPOINT_RTI, CVC4::Kind::FLOATINGPOINT_RTI},
-    {FLOATINGPOINT_MIN, CVC4::Kind::FLOATINGPOINT_MIN},
-    {FLOATINGPOINT_MAX, CVC4::Kind::FLOATINGPOINT_MAX},
-    {FLOATINGPOINT_LEQ, CVC4::Kind::FLOATINGPOINT_LEQ},
-    {FLOATINGPOINT_LT, CVC4::Kind::FLOATINGPOINT_LT},
-    {FLOATINGPOINT_GEQ, CVC4::Kind::FLOATINGPOINT_GEQ},
-    {FLOATINGPOINT_GT, CVC4::Kind::FLOATINGPOINT_GT},
-    {FLOATINGPOINT_ISN, CVC4::Kind::FLOATINGPOINT_ISN},
-    {FLOATINGPOINT_ISSN, CVC4::Kind::FLOATINGPOINT_ISSN},
-    {FLOATINGPOINT_ISZ, CVC4::Kind::FLOATINGPOINT_ISZ},
-    {FLOATINGPOINT_ISINF, CVC4::Kind::FLOATINGPOINT_ISINF},
-    {FLOATINGPOINT_ISNAN, CVC4::Kind::FLOATINGPOINT_ISNAN},
-    {FLOATINGPOINT_ISNEG, CVC4::Kind::FLOATINGPOINT_ISNEG},
-    {FLOATINGPOINT_ISPOS, CVC4::Kind::FLOATINGPOINT_ISPOS},
+    {CONST_FLOATINGPOINT, cvc5::Kind::CONST_FLOATINGPOINT},
+    {CONST_ROUNDINGMODE, cvc5::Kind::CONST_ROUNDINGMODE},
+    {FLOATINGPOINT_FP, cvc5::Kind::FLOATINGPOINT_FP},
+    {FLOATINGPOINT_EQ, cvc5::Kind::FLOATINGPOINT_EQ},
+    {FLOATINGPOINT_ABS, cvc5::Kind::FLOATINGPOINT_ABS},
+    {FLOATINGPOINT_NEG, cvc5::Kind::FLOATINGPOINT_NEG},
+    {FLOATINGPOINT_PLUS, cvc5::Kind::FLOATINGPOINT_PLUS},
+    {FLOATINGPOINT_SUB, cvc5::Kind::FLOATINGPOINT_SUB},
+    {FLOATINGPOINT_MULT, cvc5::Kind::FLOATINGPOINT_MULT},
+    {FLOATINGPOINT_DIV, cvc5::Kind::FLOATINGPOINT_DIV},
+    {FLOATINGPOINT_FMA, cvc5::Kind::FLOATINGPOINT_FMA},
+    {FLOATINGPOINT_SQRT, cvc5::Kind::FLOATINGPOINT_SQRT},
+    {FLOATINGPOINT_REM, cvc5::Kind::FLOATINGPOINT_REM},
+    {FLOATINGPOINT_RTI, cvc5::Kind::FLOATINGPOINT_RTI},
+    {FLOATINGPOINT_MIN, cvc5::Kind::FLOATINGPOINT_MIN},
+    {FLOATINGPOINT_MAX, cvc5::Kind::FLOATINGPOINT_MAX},
+    {FLOATINGPOINT_LEQ, cvc5::Kind::FLOATINGPOINT_LEQ},
+    {FLOATINGPOINT_LT, cvc5::Kind::FLOATINGPOINT_LT},
+    {FLOATINGPOINT_GEQ, cvc5::Kind::FLOATINGPOINT_GEQ},
+    {FLOATINGPOINT_GT, cvc5::Kind::FLOATINGPOINT_GT},
+    {FLOATINGPOINT_ISN, cvc5::Kind::FLOATINGPOINT_ISN},
+    {FLOATINGPOINT_ISSN, cvc5::Kind::FLOATINGPOINT_ISSN},
+    {FLOATINGPOINT_ISZ, cvc5::Kind::FLOATINGPOINT_ISZ},
+    {FLOATINGPOINT_ISINF, cvc5::Kind::FLOATINGPOINT_ISINF},
+    {FLOATINGPOINT_ISNAN, cvc5::Kind::FLOATINGPOINT_ISNAN},
+    {FLOATINGPOINT_ISNEG, cvc5::Kind::FLOATINGPOINT_ISNEG},
+    {FLOATINGPOINT_ISPOS, cvc5::Kind::FLOATINGPOINT_ISPOS},
     {FLOATINGPOINT_TO_FP_FLOATINGPOINT,
-     CVC4::Kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT},
-    {FLOATINGPOINT_TO_FP_REAL, CVC4::Kind::FLOATINGPOINT_TO_FP_REAL},
+     cvc5::Kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT},
+    {FLOATINGPOINT_TO_FP_REAL, cvc5::Kind::FLOATINGPOINT_TO_FP_REAL},
     {FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR,
-     CVC4::Kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR},
+     cvc5::Kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR},
     {FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR,
-     CVC4::Kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR},
-    {FLOATINGPOINT_TO_FP_GENERIC, CVC4::Kind::FLOATINGPOINT_TO_FP_GENERIC},
-    {FLOATINGPOINT_TO_UBV, CVC4::Kind::FLOATINGPOINT_TO_UBV},
-    {FLOATINGPOINT_TO_SBV, CVC4::Kind::FLOATINGPOINT_TO_SBV},
-    {FLOATINGPOINT_TO_REAL, CVC4::Kind::FLOATINGPOINT_TO_REAL},
+     cvc5::Kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR},
+    {FLOATINGPOINT_TO_FP_GENERIC, cvc5::Kind::FLOATINGPOINT_TO_FP_GENERIC},
+    {FLOATINGPOINT_TO_UBV, cvc5::Kind::FLOATINGPOINT_TO_UBV},
+    {FLOATINGPOINT_TO_SBV, cvc5::Kind::FLOATINGPOINT_TO_SBV},
+    {FLOATINGPOINT_TO_REAL, cvc5::Kind::FLOATINGPOINT_TO_REAL},
     /* Arrays -------------------------------------------------------------- */
-    {SELECT, CVC4::Kind::SELECT},
-    {STORE, CVC4::Kind::STORE},
-    {CONST_ARRAY, CVC4::Kind::STORE_ALL},
-    {EQ_RANGE, CVC4::Kind::EQ_RANGE},
+    {SELECT, cvc5::Kind::SELECT},
+    {STORE, cvc5::Kind::STORE},
+    {CONST_ARRAY, cvc5::Kind::STORE_ALL},
+    {EQ_RANGE, cvc5::Kind::EQ_RANGE},
     /* Datatypes ----------------------------------------------------------- */
-    {APPLY_SELECTOR, CVC4::Kind::APPLY_SELECTOR},
-    {APPLY_CONSTRUCTOR, CVC4::Kind::APPLY_CONSTRUCTOR},
-    {APPLY_TESTER, CVC4::Kind::APPLY_TESTER},
-    {TUPLE_UPDATE, CVC4::Kind::TUPLE_UPDATE},
-    {RECORD_UPDATE, CVC4::Kind::RECORD_UPDATE},
-    {DT_SIZE, CVC4::Kind::DT_SIZE},
+    {APPLY_SELECTOR, cvc5::Kind::APPLY_SELECTOR},
+    {APPLY_CONSTRUCTOR, cvc5::Kind::APPLY_CONSTRUCTOR},
+    {APPLY_TESTER, cvc5::Kind::APPLY_TESTER},
+    {TUPLE_UPDATE, cvc5::Kind::TUPLE_UPDATE},
+    {RECORD_UPDATE, cvc5::Kind::RECORD_UPDATE},
+    {DT_SIZE, cvc5::Kind::DT_SIZE},
+    {TUPLE_PROJECT, cvc5::Kind::TUPLE_PROJECT},
     /* Separation Logic ---------------------------------------------------- */
-    {SEP_NIL, CVC4::Kind::SEP_NIL},
-    {SEP_EMP, CVC4::Kind::SEP_EMP},
-    {SEP_PTO, CVC4::Kind::SEP_PTO},
-    {SEP_STAR, CVC4::Kind::SEP_STAR},
-    {SEP_WAND, CVC4::Kind::SEP_WAND},
+    {SEP_NIL, cvc5::Kind::SEP_NIL},
+    {SEP_EMP, cvc5::Kind::SEP_EMP},
+    {SEP_PTO, cvc5::Kind::SEP_PTO},
+    {SEP_STAR, cvc5::Kind::SEP_STAR},
+    {SEP_WAND, cvc5::Kind::SEP_WAND},
     /* Sets ---------------------------------------------------------------- */
-    {EMPTYSET, CVC4::Kind::EMPTYSET},
-    {UNION, CVC4::Kind::UNION},
-    {INTERSECTION, CVC4::Kind::INTERSECTION},
-    {SETMINUS, CVC4::Kind::SETMINUS},
-    {SUBSET, CVC4::Kind::SUBSET},
-    {MEMBER, CVC4::Kind::MEMBER},
-    {SINGLETON, CVC4::Kind::SINGLETON},
-    {INSERT, CVC4::Kind::INSERT},
-    {CARD, CVC4::Kind::CARD},
-    {COMPLEMENT, CVC4::Kind::COMPLEMENT},
-    {UNIVERSE_SET, CVC4::Kind::UNIVERSE_SET},
-    {JOIN, CVC4::Kind::JOIN},
-    {PRODUCT, CVC4::Kind::PRODUCT},
-    {TRANSPOSE, CVC4::Kind::TRANSPOSE},
-    {TCLOSURE, CVC4::Kind::TCLOSURE},
-    {JOIN_IMAGE, CVC4::Kind::JOIN_IMAGE},
-    {IDEN, CVC4::Kind::IDEN},
-    {COMPREHENSION, CVC4::Kind::COMPREHENSION},
-    {CHOOSE, CVC4::Kind::CHOOSE},
-    {IS_SINGLETON, CVC4::Kind::IS_SINGLETON},
+    {EMPTYSET, cvc5::Kind::EMPTYSET},
+    {UNION, cvc5::Kind::UNION},
+    {INTERSECTION, cvc5::Kind::INTERSECTION},
+    {SETMINUS, cvc5::Kind::SETMINUS},
+    {SUBSET, cvc5::Kind::SUBSET},
+    {MEMBER, cvc5::Kind::MEMBER},
+    {SINGLETON, cvc5::Kind::SINGLETON},
+    {INSERT, cvc5::Kind::INSERT},
+    {CARD, cvc5::Kind::CARD},
+    {COMPLEMENT, cvc5::Kind::COMPLEMENT},
+    {UNIVERSE_SET, cvc5::Kind::UNIVERSE_SET},
+    {JOIN, cvc5::Kind::JOIN},
+    {PRODUCT, cvc5::Kind::PRODUCT},
+    {TRANSPOSE, cvc5::Kind::TRANSPOSE},
+    {TCLOSURE, cvc5::Kind::TCLOSURE},
+    {JOIN_IMAGE, cvc5::Kind::JOIN_IMAGE},
+    {IDEN, cvc5::Kind::IDEN},
+    {COMPREHENSION, cvc5::Kind::COMPREHENSION},
+    {CHOOSE, cvc5::Kind::CHOOSE},
+    {IS_SINGLETON, cvc5::Kind::IS_SINGLETON},
     /* Bags ---------------------------------------------------------------- */
-    {UNION_MAX, CVC4::Kind::UNION_MAX},
-    {UNION_DISJOINT, CVC4::Kind::UNION_DISJOINT},
-    {INTERSECTION_MIN, CVC4::Kind::INTERSECTION_MIN},
-    {DIFFERENCE_SUBTRACT, CVC4::Kind::DIFFERENCE_SUBTRACT},
-    {DIFFERENCE_REMOVE, CVC4::Kind::DIFFERENCE_REMOVE},
-    {SUBBAG, CVC4::Kind::SUBBAG},
-    {BAG_COUNT, CVC4::Kind::BAG_COUNT},
-    {DUPLICATE_REMOVAL, CVC4::Kind::DUPLICATE_REMOVAL},
-    {MK_BAG, CVC4::Kind::MK_BAG},
-    {EMPTYBAG, CVC4::Kind::EMPTYBAG},
-    {BAG_CARD, CVC4::Kind::BAG_CARD},
-    {BAG_CHOOSE, CVC4::Kind::BAG_CHOOSE},
-    {BAG_IS_SINGLETON, CVC4::Kind::BAG_IS_SINGLETON},
-    {BAG_FROM_SET, CVC4::Kind::BAG_FROM_SET},
-    {BAG_TO_SET, CVC4::Kind::BAG_TO_SET},
+    {UNION_MAX, cvc5::Kind::UNION_MAX},
+    {UNION_DISJOINT, cvc5::Kind::UNION_DISJOINT},
+    {INTERSECTION_MIN, cvc5::Kind::INTERSECTION_MIN},
+    {DIFFERENCE_SUBTRACT, cvc5::Kind::DIFFERENCE_SUBTRACT},
+    {DIFFERENCE_REMOVE, cvc5::Kind::DIFFERENCE_REMOVE},
+    {SUBBAG, cvc5::Kind::SUBBAG},
+    {BAG_COUNT, cvc5::Kind::BAG_COUNT},
+    {DUPLICATE_REMOVAL, cvc5::Kind::DUPLICATE_REMOVAL},
+    {MK_BAG, cvc5::Kind::MK_BAG},
+    {EMPTYBAG, cvc5::Kind::EMPTYBAG},
+    {BAG_CARD, cvc5::Kind::BAG_CARD},
+    {BAG_CHOOSE, cvc5::Kind::BAG_CHOOSE},
+    {BAG_IS_SINGLETON, cvc5::Kind::BAG_IS_SINGLETON},
+    {BAG_FROM_SET, cvc5::Kind::BAG_FROM_SET},
+    {BAG_TO_SET, cvc5::Kind::BAG_TO_SET},
     /* Strings ------------------------------------------------------------- */
-    {STRING_CONCAT, CVC4::Kind::STRING_CONCAT},
-    {STRING_IN_REGEXP, CVC4::Kind::STRING_IN_REGEXP},
-    {STRING_LENGTH, CVC4::Kind::STRING_LENGTH},
-    {STRING_SUBSTR, CVC4::Kind::STRING_SUBSTR},
-    {STRING_UPDATE, CVC4::Kind::STRING_UPDATE},
-    {STRING_CHARAT, CVC4::Kind::STRING_CHARAT},
-    {STRING_CONTAINS, CVC4::Kind::STRING_STRCTN},
-    {STRING_INDEXOF, CVC4::Kind::STRING_STRIDOF},
-    {STRING_REPLACE, CVC4::Kind::STRING_STRREPL},
-    {STRING_REPLACE_ALL, CVC4::Kind::STRING_STRREPLALL},
-    {STRING_REPLACE_RE, CVC4::Kind::STRING_REPLACE_RE},
-    {STRING_REPLACE_RE_ALL, CVC4::Kind::STRING_REPLACE_RE_ALL},
-    {STRING_TOLOWER, CVC4::Kind::STRING_TOLOWER},
-    {STRING_TOUPPER, CVC4::Kind::STRING_TOUPPER},
-    {STRING_REV, CVC4::Kind::STRING_REV},
-    {STRING_FROM_CODE, CVC4::Kind::STRING_FROM_CODE},
-    {STRING_TO_CODE, CVC4::Kind::STRING_TO_CODE},
-    {STRING_LT, CVC4::Kind::STRING_LT},
-    {STRING_LEQ, CVC4::Kind::STRING_LEQ},
-    {STRING_PREFIX, CVC4::Kind::STRING_PREFIX},
-    {STRING_SUFFIX, CVC4::Kind::STRING_SUFFIX},
-    {STRING_IS_DIGIT, CVC4::Kind::STRING_IS_DIGIT},
-    {STRING_FROM_INT, CVC4::Kind::STRING_ITOS},
-    {STRING_TO_INT, CVC4::Kind::STRING_STOI},
-    {CONST_STRING, CVC4::Kind::CONST_STRING},
-    {STRING_TO_REGEXP, CVC4::Kind::STRING_TO_REGEXP},
-    {REGEXP_CONCAT, CVC4::Kind::REGEXP_CONCAT},
-    {REGEXP_UNION, CVC4::Kind::REGEXP_UNION},
-    {REGEXP_INTER, CVC4::Kind::REGEXP_INTER},
-    {REGEXP_DIFF, CVC4::Kind::REGEXP_DIFF},
-    {REGEXP_STAR, CVC4::Kind::REGEXP_STAR},
-    {REGEXP_PLUS, CVC4::Kind::REGEXP_PLUS},
-    {REGEXP_OPT, CVC4::Kind::REGEXP_OPT},
-    {REGEXP_RANGE, CVC4::Kind::REGEXP_RANGE},
-    {REGEXP_REPEAT, CVC4::Kind::REGEXP_REPEAT},
-    {REGEXP_LOOP, CVC4::Kind::REGEXP_LOOP},
-    {REGEXP_EMPTY, CVC4::Kind::REGEXP_EMPTY},
-    {REGEXP_SIGMA, CVC4::Kind::REGEXP_SIGMA},
-    {REGEXP_COMPLEMENT, CVC4::Kind::REGEXP_COMPLEMENT},
+    {STRING_CONCAT, cvc5::Kind::STRING_CONCAT},
+    {STRING_IN_REGEXP, cvc5::Kind::STRING_IN_REGEXP},
+    {STRING_LENGTH, cvc5::Kind::STRING_LENGTH},
+    {STRING_SUBSTR, cvc5::Kind::STRING_SUBSTR},
+    {STRING_UPDATE, cvc5::Kind::STRING_UPDATE},
+    {STRING_CHARAT, cvc5::Kind::STRING_CHARAT},
+    {STRING_CONTAINS, cvc5::Kind::STRING_STRCTN},
+    {STRING_INDEXOF, cvc5::Kind::STRING_STRIDOF},
+    {STRING_REPLACE, cvc5::Kind::STRING_STRREPL},
+    {STRING_REPLACE_ALL, cvc5::Kind::STRING_STRREPLALL},
+    {STRING_REPLACE_RE, cvc5::Kind::STRING_REPLACE_RE},
+    {STRING_REPLACE_RE_ALL, cvc5::Kind::STRING_REPLACE_RE_ALL},
+    {STRING_TOLOWER, cvc5::Kind::STRING_TOLOWER},
+    {STRING_TOUPPER, cvc5::Kind::STRING_TOUPPER},
+    {STRING_REV, cvc5::Kind::STRING_REV},
+    {STRING_FROM_CODE, cvc5::Kind::STRING_FROM_CODE},
+    {STRING_TO_CODE, cvc5::Kind::STRING_TO_CODE},
+    {STRING_LT, cvc5::Kind::STRING_LT},
+    {STRING_LEQ, cvc5::Kind::STRING_LEQ},
+    {STRING_PREFIX, cvc5::Kind::STRING_PREFIX},
+    {STRING_SUFFIX, cvc5::Kind::STRING_SUFFIX},
+    {STRING_IS_DIGIT, cvc5::Kind::STRING_IS_DIGIT},
+    {STRING_FROM_INT, cvc5::Kind::STRING_ITOS},
+    {STRING_TO_INT, cvc5::Kind::STRING_STOI},
+    {CONST_STRING, cvc5::Kind::CONST_STRING},
+    {STRING_TO_REGEXP, cvc5::Kind::STRING_TO_REGEXP},
+    {REGEXP_CONCAT, cvc5::Kind::REGEXP_CONCAT},
+    {REGEXP_UNION, cvc5::Kind::REGEXP_UNION},
+    {REGEXP_INTER, cvc5::Kind::REGEXP_INTER},
+    {REGEXP_DIFF, cvc5::Kind::REGEXP_DIFF},
+    {REGEXP_STAR, cvc5::Kind::REGEXP_STAR},
+    {REGEXP_PLUS, cvc5::Kind::REGEXP_PLUS},
+    {REGEXP_OPT, cvc5::Kind::REGEXP_OPT},
+    {REGEXP_RANGE, cvc5::Kind::REGEXP_RANGE},
+    {REGEXP_REPEAT, cvc5::Kind::REGEXP_REPEAT},
+    {REGEXP_LOOP, cvc5::Kind::REGEXP_LOOP},
+    {REGEXP_EMPTY, cvc5::Kind::REGEXP_EMPTY},
+    {REGEXP_SIGMA, cvc5::Kind::REGEXP_SIGMA},
+    {REGEXP_COMPLEMENT, cvc5::Kind::REGEXP_COMPLEMENT},
     // maps to the same kind as the string versions
-    {SEQ_CONCAT, CVC4::Kind::STRING_CONCAT},
-    {SEQ_LENGTH, CVC4::Kind::STRING_LENGTH},
-    {SEQ_EXTRACT, CVC4::Kind::STRING_SUBSTR},
-    {SEQ_UPDATE, CVC4::Kind::STRING_UPDATE},
-    {SEQ_AT, CVC4::Kind::STRING_CHARAT},
-    {SEQ_CONTAINS, CVC4::Kind::STRING_STRCTN},
-    {SEQ_INDEXOF, CVC4::Kind::STRING_STRIDOF},
-    {SEQ_REPLACE, CVC4::Kind::STRING_STRREPL},
-    {SEQ_REPLACE_ALL, CVC4::Kind::STRING_STRREPLALL},
-    {SEQ_REV, CVC4::Kind::STRING_REV},
-    {SEQ_PREFIX, CVC4::Kind::STRING_PREFIX},
-    {SEQ_SUFFIX, CVC4::Kind::STRING_SUFFIX},
-    {CONST_SEQUENCE, CVC4::Kind::CONST_SEQUENCE},
-    {SEQ_UNIT, CVC4::Kind::SEQ_UNIT},
-    {SEQ_NTH, CVC4::Kind::SEQ_NTH},
+    {SEQ_CONCAT, cvc5::Kind::STRING_CONCAT},
+    {SEQ_LENGTH, cvc5::Kind::STRING_LENGTH},
+    {SEQ_EXTRACT, cvc5::Kind::STRING_SUBSTR},
+    {SEQ_UPDATE, cvc5::Kind::STRING_UPDATE},
+    {SEQ_AT, cvc5::Kind::STRING_CHARAT},
+    {SEQ_CONTAINS, cvc5::Kind::STRING_STRCTN},
+    {SEQ_INDEXOF, cvc5::Kind::STRING_STRIDOF},
+    {SEQ_REPLACE, cvc5::Kind::STRING_STRREPL},
+    {SEQ_REPLACE_ALL, cvc5::Kind::STRING_STRREPLALL},
+    {SEQ_REV, cvc5::Kind::STRING_REV},
+    {SEQ_PREFIX, cvc5::Kind::STRING_PREFIX},
+    {SEQ_SUFFIX, cvc5::Kind::STRING_SUFFIX},
+    {CONST_SEQUENCE, cvc5::Kind::CONST_SEQUENCE},
+    {SEQ_UNIT, cvc5::Kind::SEQ_UNIT},
+    {SEQ_NTH, cvc5::Kind::SEQ_NTH},
     /* Quantifiers --------------------------------------------------------- */
-    {FORALL, CVC4::Kind::FORALL},
-    {EXISTS, CVC4::Kind::EXISTS},
-    {BOUND_VAR_LIST, CVC4::Kind::BOUND_VAR_LIST},
-    {INST_PATTERN, CVC4::Kind::INST_PATTERN},
-    {INST_NO_PATTERN, CVC4::Kind::INST_NO_PATTERN},
-    {INST_ATTRIBUTE, CVC4::Kind::INST_ATTRIBUTE},
-    {INST_PATTERN_LIST, CVC4::Kind::INST_PATTERN_LIST},
-    {LAST_KIND, CVC4::Kind::LAST_KIND},
+    {FORALL, cvc5::Kind::FORALL},
+    {EXISTS, cvc5::Kind::EXISTS},
+    {BOUND_VAR_LIST, cvc5::Kind::BOUND_VAR_LIST},
+    {INST_PATTERN, cvc5::Kind::INST_PATTERN},
+    {INST_NO_PATTERN, cvc5::Kind::INST_NO_PATTERN},
+    {INST_ATTRIBUTE, cvc5::Kind::INST_ATTRIBUTE},
+    {INST_PATTERN_LIST, cvc5::Kind::INST_PATTERN_LIST},
+    {LAST_KIND, cvc5::Kind::LAST_KIND},
 };
 
 /* Mapping from internal kind to external (API) kind. */
-const static std::unordered_map<CVC4::Kind, Kind, CVC4::kind::KindHashFunction>
+const static std::unordered_map<cvc5::Kind, Kind, cvc5::kind::KindHashFunction>
     s_kinds_internal{
-        {CVC4::Kind::UNDEFINED_KIND, UNDEFINED_KIND},
-        {CVC4::Kind::NULL_EXPR, NULL_EXPR},
+        {cvc5::Kind::UNDEFINED_KIND, UNDEFINED_KIND},
+        {cvc5::Kind::NULL_EXPR, NULL_EXPR},
         /* Builtin --------------------------------------------------------- */
-        {CVC4::Kind::UNINTERPRETED_CONSTANT, UNINTERPRETED_CONSTANT},
-        {CVC4::Kind::ABSTRACT_VALUE, ABSTRACT_VALUE},
-        {CVC4::Kind::EQUAL, EQUAL},
-        {CVC4::Kind::DISTINCT, DISTINCT},
-        {CVC4::Kind::VARIABLE, CONSTANT},
-        {CVC4::Kind::BOUND_VARIABLE, VARIABLE},
-        {CVC4::Kind::SEXPR, SEXPR},
-        {CVC4::Kind::LAMBDA, LAMBDA},
-        {CVC4::Kind::WITNESS, WITNESS},
+        {cvc5::Kind::UNINTERPRETED_CONSTANT, UNINTERPRETED_CONSTANT},
+        {cvc5::Kind::ABSTRACT_VALUE, ABSTRACT_VALUE},
+        {cvc5::Kind::EQUAL, EQUAL},
+        {cvc5::Kind::DISTINCT, DISTINCT},
+        {cvc5::Kind::VARIABLE, CONSTANT},
+        {cvc5::Kind::BOUND_VARIABLE, VARIABLE},
+        {cvc5::Kind::SEXPR, SEXPR},
+        {cvc5::Kind::LAMBDA, LAMBDA},
+        {cvc5::Kind::WITNESS, WITNESS},
         /* Boolean --------------------------------------------------------- */
-        {CVC4::Kind::CONST_BOOLEAN, CONST_BOOLEAN},
-        {CVC4::Kind::NOT, NOT},
-        {CVC4::Kind::AND, AND},
-        {CVC4::Kind::IMPLIES, IMPLIES},
-        {CVC4::Kind::OR, OR},
-        {CVC4::Kind::XOR, XOR},
-        {CVC4::Kind::ITE, ITE},
-        {CVC4::Kind::MATCH, MATCH},
-        {CVC4::Kind::MATCH_CASE, MATCH_CASE},
-        {CVC4::Kind::MATCH_BIND_CASE, MATCH_BIND_CASE},
+        {cvc5::Kind::CONST_BOOLEAN, CONST_BOOLEAN},
+        {cvc5::Kind::NOT, NOT},
+        {cvc5::Kind::AND, AND},
+        {cvc5::Kind::IMPLIES, IMPLIES},
+        {cvc5::Kind::OR, OR},
+        {cvc5::Kind::XOR, XOR},
+        {cvc5::Kind::ITE, ITE},
+        {cvc5::Kind::MATCH, MATCH},
+        {cvc5::Kind::MATCH_CASE, MATCH_CASE},
+        {cvc5::Kind::MATCH_BIND_CASE, MATCH_BIND_CASE},
         /* UF -------------------------------------------------------------- */
-        {CVC4::Kind::APPLY_UF, APPLY_UF},
-        {CVC4::Kind::CARDINALITY_CONSTRAINT, CARDINALITY_CONSTRAINT},
-        {CVC4::Kind::CARDINALITY_VALUE, CARDINALITY_VALUE},
-        {CVC4::Kind::HO_APPLY, HO_APPLY},
+        {cvc5::Kind::APPLY_UF, APPLY_UF},
+        {cvc5::Kind::CARDINALITY_CONSTRAINT, CARDINALITY_CONSTRAINT},
+        {cvc5::Kind::CARDINALITY_VALUE, CARDINALITY_VALUE},
+        {cvc5::Kind::HO_APPLY, HO_APPLY},
         /* Arithmetic ------------------------------------------------------ */
-        {CVC4::Kind::PLUS, PLUS},
-        {CVC4::Kind::MULT, MULT},
-        {CVC4::Kind::IAND, IAND},
-        {CVC4::Kind::MINUS, MINUS},
-        {CVC4::Kind::UMINUS, UMINUS},
-        {CVC4::Kind::DIVISION, DIVISION},
-        {CVC4::Kind::DIVISION_TOTAL, INTERNAL_KIND},
-        {CVC4::Kind::INTS_DIVISION, INTS_DIVISION},
-        {CVC4::Kind::INTS_DIVISION_TOTAL, INTERNAL_KIND},
-        {CVC4::Kind::INTS_MODULUS, INTS_MODULUS},
-        {CVC4::Kind::INTS_MODULUS_TOTAL, INTERNAL_KIND},
-        {CVC4::Kind::ABS, ABS},
-        {CVC4::Kind::DIVISIBLE, DIVISIBLE},
-        {CVC4::Kind::POW, POW},
-        {CVC4::Kind::EXPONENTIAL, EXPONENTIAL},
-        {CVC4::Kind::SINE, SINE},
-        {CVC4::Kind::COSINE, COSINE},
-        {CVC4::Kind::TANGENT, TANGENT},
-        {CVC4::Kind::COSECANT, COSECANT},
-        {CVC4::Kind::SECANT, SECANT},
-        {CVC4::Kind::COTANGENT, COTANGENT},
-        {CVC4::Kind::ARCSINE, ARCSINE},
-        {CVC4::Kind::ARCCOSINE, ARCCOSINE},
-        {CVC4::Kind::ARCTANGENT, ARCTANGENT},
-        {CVC4::Kind::ARCCOSECANT, ARCCOSECANT},
-        {CVC4::Kind::ARCSECANT, ARCSECANT},
-        {CVC4::Kind::ARCCOTANGENT, ARCCOTANGENT},
-        {CVC4::Kind::SQRT, SQRT},
-        {CVC4::Kind::DIVISIBLE_OP, DIVISIBLE},
-        {CVC4::Kind::CONST_RATIONAL, CONST_RATIONAL},
-        {CVC4::Kind::LT, LT},
-        {CVC4::Kind::LEQ, LEQ},
-        {CVC4::Kind::GT, GT},
-        {CVC4::Kind::GEQ, GEQ},
-        {CVC4::Kind::IS_INTEGER, IS_INTEGER},
-        {CVC4::Kind::TO_INTEGER, TO_INTEGER},
-        {CVC4::Kind::TO_REAL, TO_REAL},
-        {CVC4::Kind::PI, PI},
+        {cvc5::Kind::PLUS, PLUS},
+        {cvc5::Kind::MULT, MULT},
+        {cvc5::Kind::IAND, IAND},
+        {cvc5::Kind::MINUS, MINUS},
+        {cvc5::Kind::UMINUS, UMINUS},
+        {cvc5::Kind::DIVISION, DIVISION},
+        {cvc5::Kind::DIVISION_TOTAL, INTERNAL_KIND},
+        {cvc5::Kind::INTS_DIVISION, INTS_DIVISION},
+        {cvc5::Kind::INTS_DIVISION_TOTAL, INTERNAL_KIND},
+        {cvc5::Kind::INTS_MODULUS, INTS_MODULUS},
+        {cvc5::Kind::INTS_MODULUS_TOTAL, INTERNAL_KIND},
+        {cvc5::Kind::ABS, ABS},
+        {cvc5::Kind::DIVISIBLE, DIVISIBLE},
+        {cvc5::Kind::POW, POW},
+        {cvc5::Kind::EXPONENTIAL, EXPONENTIAL},
+        {cvc5::Kind::SINE, SINE},
+        {cvc5::Kind::COSINE, COSINE},
+        {cvc5::Kind::TANGENT, TANGENT},
+        {cvc5::Kind::COSECANT, COSECANT},
+        {cvc5::Kind::SECANT, SECANT},
+        {cvc5::Kind::COTANGENT, COTANGENT},
+        {cvc5::Kind::ARCSINE, ARCSINE},
+        {cvc5::Kind::ARCCOSINE, ARCCOSINE},
+        {cvc5::Kind::ARCTANGENT, ARCTANGENT},
+        {cvc5::Kind::ARCCOSECANT, ARCCOSECANT},
+        {cvc5::Kind::ARCSECANT, ARCSECANT},
+        {cvc5::Kind::ARCCOTANGENT, ARCCOTANGENT},
+        {cvc5::Kind::SQRT, SQRT},
+        {cvc5::Kind::DIVISIBLE_OP, DIVISIBLE},
+        {cvc5::Kind::CONST_RATIONAL, CONST_RATIONAL},
+        {cvc5::Kind::LT, LT},
+        {cvc5::Kind::LEQ, LEQ},
+        {cvc5::Kind::GT, GT},
+        {cvc5::Kind::GEQ, GEQ},
+        {cvc5::Kind::IS_INTEGER, IS_INTEGER},
+        {cvc5::Kind::TO_INTEGER, TO_INTEGER},
+        {cvc5::Kind::TO_REAL, TO_REAL},
+        {cvc5::Kind::PI, PI},
         /* BV -------------------------------------------------------------- */
-        {CVC4::Kind::CONST_BITVECTOR, CONST_BITVECTOR},
-        {CVC4::Kind::BITVECTOR_CONCAT, BITVECTOR_CONCAT},
-        {CVC4::Kind::BITVECTOR_AND, BITVECTOR_AND},
-        {CVC4::Kind::BITVECTOR_OR, BITVECTOR_OR},
-        {CVC4::Kind::BITVECTOR_XOR, BITVECTOR_XOR},
-        {CVC4::Kind::BITVECTOR_NOT, BITVECTOR_NOT},
-        {CVC4::Kind::BITVECTOR_NAND, BITVECTOR_NAND},
-        {CVC4::Kind::BITVECTOR_NOR, BITVECTOR_NOR},
-        {CVC4::Kind::BITVECTOR_XNOR, BITVECTOR_XNOR},
-        {CVC4::Kind::BITVECTOR_COMP, BITVECTOR_COMP},
-        {CVC4::Kind::BITVECTOR_MULT, BITVECTOR_MULT},
-        {CVC4::Kind::BITVECTOR_PLUS, BITVECTOR_PLUS},
-        {CVC4::Kind::BITVECTOR_SUB, BITVECTOR_SUB},
-        {CVC4::Kind::BITVECTOR_NEG, BITVECTOR_NEG},
-        {CVC4::Kind::BITVECTOR_UDIV, BITVECTOR_UDIV},
-        {CVC4::Kind::BITVECTOR_UREM, BITVECTOR_UREM},
-        {CVC4::Kind::BITVECTOR_SDIV, BITVECTOR_SDIV},
-        {CVC4::Kind::BITVECTOR_SREM, BITVECTOR_SREM},
-        {CVC4::Kind::BITVECTOR_SMOD, BITVECTOR_SMOD},
-        {CVC4::Kind::BITVECTOR_UDIV_TOTAL, INTERNAL_KIND},
-        {CVC4::Kind::BITVECTOR_UREM_TOTAL, INTERNAL_KIND},
-        {CVC4::Kind::BITVECTOR_SHL, BITVECTOR_SHL},
-        {CVC4::Kind::BITVECTOR_LSHR, BITVECTOR_LSHR},
-        {CVC4::Kind::BITVECTOR_ASHR, BITVECTOR_ASHR},
-        {CVC4::Kind::BITVECTOR_ULT, BITVECTOR_ULT},
-        {CVC4::Kind::BITVECTOR_ULE, BITVECTOR_ULE},
-        {CVC4::Kind::BITVECTOR_UGT, BITVECTOR_UGT},
-        {CVC4::Kind::BITVECTOR_UGE, BITVECTOR_UGE},
-        {CVC4::Kind::BITVECTOR_SLT, BITVECTOR_SLT},
-        {CVC4::Kind::BITVECTOR_SLE, BITVECTOR_SLE},
-        {CVC4::Kind::BITVECTOR_SGT, BITVECTOR_SGT},
-        {CVC4::Kind::BITVECTOR_SGE, BITVECTOR_SGE},
-        {CVC4::Kind::BITVECTOR_ULTBV, BITVECTOR_ULTBV},
-        {CVC4::Kind::BITVECTOR_SLTBV, BITVECTOR_SLTBV},
-        {CVC4::Kind::BITVECTOR_ITE, BITVECTOR_ITE},
-        {CVC4::Kind::BITVECTOR_REDOR, BITVECTOR_REDOR},
-        {CVC4::Kind::BITVECTOR_REDAND, BITVECTOR_REDAND},
-        {CVC4::Kind::BITVECTOR_EXTRACT_OP, BITVECTOR_EXTRACT},
-        {CVC4::Kind::BITVECTOR_REPEAT_OP, BITVECTOR_REPEAT},
-        {CVC4::Kind::BITVECTOR_ZERO_EXTEND_OP, BITVECTOR_ZERO_EXTEND},
-        {CVC4::Kind::BITVECTOR_SIGN_EXTEND_OP, BITVECTOR_SIGN_EXTEND},
-        {CVC4::Kind::BITVECTOR_ROTATE_LEFT_OP, BITVECTOR_ROTATE_LEFT},
-        {CVC4::Kind::BITVECTOR_ROTATE_RIGHT_OP, BITVECTOR_ROTATE_RIGHT},
-        {CVC4::Kind::BITVECTOR_EXTRACT, BITVECTOR_EXTRACT},
-        {CVC4::Kind::BITVECTOR_REPEAT, BITVECTOR_REPEAT},
-        {CVC4::Kind::BITVECTOR_ZERO_EXTEND, BITVECTOR_ZERO_EXTEND},
-        {CVC4::Kind::BITVECTOR_SIGN_EXTEND, BITVECTOR_SIGN_EXTEND},
-        {CVC4::Kind::BITVECTOR_ROTATE_LEFT, BITVECTOR_ROTATE_LEFT},
-        {CVC4::Kind::BITVECTOR_ROTATE_RIGHT, BITVECTOR_ROTATE_RIGHT},
-        {CVC4::Kind::INT_TO_BITVECTOR_OP, INT_TO_BITVECTOR},
-        {CVC4::Kind::INT_TO_BITVECTOR, INT_TO_BITVECTOR},
-        {CVC4::Kind::BITVECTOR_TO_NAT, BITVECTOR_TO_NAT},
+        {cvc5::Kind::CONST_BITVECTOR, CONST_BITVECTOR},
+        {cvc5::Kind::BITVECTOR_CONCAT, BITVECTOR_CONCAT},
+        {cvc5::Kind::BITVECTOR_AND, BITVECTOR_AND},
+        {cvc5::Kind::BITVECTOR_OR, BITVECTOR_OR},
+        {cvc5::Kind::BITVECTOR_XOR, BITVECTOR_XOR},
+        {cvc5::Kind::BITVECTOR_NOT, BITVECTOR_NOT},
+        {cvc5::Kind::BITVECTOR_NAND, BITVECTOR_NAND},
+        {cvc5::Kind::BITVECTOR_NOR, BITVECTOR_NOR},
+        {cvc5::Kind::BITVECTOR_XNOR, BITVECTOR_XNOR},
+        {cvc5::Kind::BITVECTOR_COMP, BITVECTOR_COMP},
+        {cvc5::Kind::BITVECTOR_MULT, BITVECTOR_MULT},
+        {cvc5::Kind::BITVECTOR_PLUS, BITVECTOR_PLUS},
+        {cvc5::Kind::BITVECTOR_SUB, BITVECTOR_SUB},
+        {cvc5::Kind::BITVECTOR_NEG, BITVECTOR_NEG},
+        {cvc5::Kind::BITVECTOR_UDIV, BITVECTOR_UDIV},
+        {cvc5::Kind::BITVECTOR_UREM, BITVECTOR_UREM},
+        {cvc5::Kind::BITVECTOR_SDIV, BITVECTOR_SDIV},
+        {cvc5::Kind::BITVECTOR_SREM, BITVECTOR_SREM},
+        {cvc5::Kind::BITVECTOR_SMOD, BITVECTOR_SMOD},
+        {cvc5::Kind::BITVECTOR_SHL, BITVECTOR_SHL},
+        {cvc5::Kind::BITVECTOR_LSHR, BITVECTOR_LSHR},
+        {cvc5::Kind::BITVECTOR_ASHR, BITVECTOR_ASHR},
+        {cvc5::Kind::BITVECTOR_ULT, BITVECTOR_ULT},
+        {cvc5::Kind::BITVECTOR_ULE, BITVECTOR_ULE},
+        {cvc5::Kind::BITVECTOR_UGT, BITVECTOR_UGT},
+        {cvc5::Kind::BITVECTOR_UGE, BITVECTOR_UGE},
+        {cvc5::Kind::BITVECTOR_SLT, BITVECTOR_SLT},
+        {cvc5::Kind::BITVECTOR_SLE, BITVECTOR_SLE},
+        {cvc5::Kind::BITVECTOR_SGT, BITVECTOR_SGT},
+        {cvc5::Kind::BITVECTOR_SGE, BITVECTOR_SGE},
+        {cvc5::Kind::BITVECTOR_ULTBV, BITVECTOR_ULTBV},
+        {cvc5::Kind::BITVECTOR_SLTBV, BITVECTOR_SLTBV},
+        {cvc5::Kind::BITVECTOR_ITE, BITVECTOR_ITE},
+        {cvc5::Kind::BITVECTOR_REDOR, BITVECTOR_REDOR},
+        {cvc5::Kind::BITVECTOR_REDAND, BITVECTOR_REDAND},
+        {cvc5::Kind::BITVECTOR_EXTRACT_OP, BITVECTOR_EXTRACT},
+        {cvc5::Kind::BITVECTOR_REPEAT_OP, BITVECTOR_REPEAT},
+        {cvc5::Kind::BITVECTOR_ZERO_EXTEND_OP, BITVECTOR_ZERO_EXTEND},
+        {cvc5::Kind::BITVECTOR_SIGN_EXTEND_OP, BITVECTOR_SIGN_EXTEND},
+        {cvc5::Kind::BITVECTOR_ROTATE_LEFT_OP, BITVECTOR_ROTATE_LEFT},
+        {cvc5::Kind::BITVECTOR_ROTATE_RIGHT_OP, BITVECTOR_ROTATE_RIGHT},
+        {cvc5::Kind::BITVECTOR_EXTRACT, BITVECTOR_EXTRACT},
+        {cvc5::Kind::BITVECTOR_REPEAT, BITVECTOR_REPEAT},
+        {cvc5::Kind::BITVECTOR_ZERO_EXTEND, BITVECTOR_ZERO_EXTEND},
+        {cvc5::Kind::BITVECTOR_SIGN_EXTEND, BITVECTOR_SIGN_EXTEND},
+        {cvc5::Kind::BITVECTOR_ROTATE_LEFT, BITVECTOR_ROTATE_LEFT},
+        {cvc5::Kind::BITVECTOR_ROTATE_RIGHT, BITVECTOR_ROTATE_RIGHT},
+        {cvc5::Kind::INT_TO_BITVECTOR_OP, INT_TO_BITVECTOR},
+        {cvc5::Kind::INT_TO_BITVECTOR, INT_TO_BITVECTOR},
+        {cvc5::Kind::BITVECTOR_TO_NAT, BITVECTOR_TO_NAT},
         /* FP -------------------------------------------------------------- */
-        {CVC4::Kind::CONST_FLOATINGPOINT, CONST_FLOATINGPOINT},
-        {CVC4::Kind::CONST_ROUNDINGMODE, CONST_ROUNDINGMODE},
-        {CVC4::Kind::FLOATINGPOINT_FP, FLOATINGPOINT_FP},
-        {CVC4::Kind::FLOATINGPOINT_EQ, FLOATINGPOINT_EQ},
-        {CVC4::Kind::FLOATINGPOINT_ABS, FLOATINGPOINT_ABS},
-        {CVC4::Kind::FLOATINGPOINT_NEG, FLOATINGPOINT_NEG},
-        {CVC4::Kind::FLOATINGPOINT_PLUS, FLOATINGPOINT_PLUS},
-        {CVC4::Kind::FLOATINGPOINT_SUB, FLOATINGPOINT_SUB},
-        {CVC4::Kind::FLOATINGPOINT_MULT, FLOATINGPOINT_MULT},
-        {CVC4::Kind::FLOATINGPOINT_DIV, FLOATINGPOINT_DIV},
-        {CVC4::Kind::FLOATINGPOINT_FMA, FLOATINGPOINT_FMA},
-        {CVC4::Kind::FLOATINGPOINT_SQRT, FLOATINGPOINT_SQRT},
-        {CVC4::Kind::FLOATINGPOINT_REM, FLOATINGPOINT_REM},
-        {CVC4::Kind::FLOATINGPOINT_RTI, FLOATINGPOINT_RTI},
-        {CVC4::Kind::FLOATINGPOINT_MIN, FLOATINGPOINT_MIN},
-        {CVC4::Kind::FLOATINGPOINT_MAX, FLOATINGPOINT_MAX},
-        {CVC4::Kind::FLOATINGPOINT_LEQ, FLOATINGPOINT_LEQ},
-        {CVC4::Kind::FLOATINGPOINT_LT, FLOATINGPOINT_LT},
-        {CVC4::Kind::FLOATINGPOINT_GEQ, FLOATINGPOINT_GEQ},
-        {CVC4::Kind::FLOATINGPOINT_GT, FLOATINGPOINT_GT},
-        {CVC4::Kind::FLOATINGPOINT_ISN, FLOATINGPOINT_ISN},
-        {CVC4::Kind::FLOATINGPOINT_ISSN, FLOATINGPOINT_ISSN},
-        {CVC4::Kind::FLOATINGPOINT_ISZ, FLOATINGPOINT_ISZ},
-        {CVC4::Kind::FLOATINGPOINT_ISINF, FLOATINGPOINT_ISINF},
-        {CVC4::Kind::FLOATINGPOINT_ISNAN, FLOATINGPOINT_ISNAN},
-        {CVC4::Kind::FLOATINGPOINT_ISNEG, FLOATINGPOINT_ISNEG},
-        {CVC4::Kind::FLOATINGPOINT_ISPOS, FLOATINGPOINT_ISPOS},
-        {CVC4::Kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR_OP,
+        {cvc5::Kind::CONST_FLOATINGPOINT, CONST_FLOATINGPOINT},
+        {cvc5::Kind::CONST_ROUNDINGMODE, CONST_ROUNDINGMODE},
+        {cvc5::Kind::FLOATINGPOINT_FP, FLOATINGPOINT_FP},
+        {cvc5::Kind::FLOATINGPOINT_EQ, FLOATINGPOINT_EQ},
+        {cvc5::Kind::FLOATINGPOINT_ABS, FLOATINGPOINT_ABS},
+        {cvc5::Kind::FLOATINGPOINT_NEG, FLOATINGPOINT_NEG},
+        {cvc5::Kind::FLOATINGPOINT_PLUS, FLOATINGPOINT_PLUS},
+        {cvc5::Kind::FLOATINGPOINT_SUB, FLOATINGPOINT_SUB},
+        {cvc5::Kind::FLOATINGPOINT_MULT, FLOATINGPOINT_MULT},
+        {cvc5::Kind::FLOATINGPOINT_DIV, FLOATINGPOINT_DIV},
+        {cvc5::Kind::FLOATINGPOINT_FMA, FLOATINGPOINT_FMA},
+        {cvc5::Kind::FLOATINGPOINT_SQRT, FLOATINGPOINT_SQRT},
+        {cvc5::Kind::FLOATINGPOINT_REM, FLOATINGPOINT_REM},
+        {cvc5::Kind::FLOATINGPOINT_RTI, FLOATINGPOINT_RTI},
+        {cvc5::Kind::FLOATINGPOINT_MIN, FLOATINGPOINT_MIN},
+        {cvc5::Kind::FLOATINGPOINT_MAX, FLOATINGPOINT_MAX},
+        {cvc5::Kind::FLOATINGPOINT_LEQ, FLOATINGPOINT_LEQ},
+        {cvc5::Kind::FLOATINGPOINT_LT, FLOATINGPOINT_LT},
+        {cvc5::Kind::FLOATINGPOINT_GEQ, FLOATINGPOINT_GEQ},
+        {cvc5::Kind::FLOATINGPOINT_GT, FLOATINGPOINT_GT},
+        {cvc5::Kind::FLOATINGPOINT_ISN, FLOATINGPOINT_ISN},
+        {cvc5::Kind::FLOATINGPOINT_ISSN, FLOATINGPOINT_ISSN},
+        {cvc5::Kind::FLOATINGPOINT_ISZ, FLOATINGPOINT_ISZ},
+        {cvc5::Kind::FLOATINGPOINT_ISINF, FLOATINGPOINT_ISINF},
+        {cvc5::Kind::FLOATINGPOINT_ISNAN, FLOATINGPOINT_ISNAN},
+        {cvc5::Kind::FLOATINGPOINT_ISNEG, FLOATINGPOINT_ISNEG},
+        {cvc5::Kind::FLOATINGPOINT_ISPOS, FLOATINGPOINT_ISPOS},
+        {cvc5::Kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR_OP,
          FLOATINGPOINT_TO_FP_IEEE_BITVECTOR},
-        {CVC4::Kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR,
+        {cvc5::Kind::FLOATINGPOINT_TO_FP_IEEE_BITVECTOR,
          FLOATINGPOINT_TO_FP_IEEE_BITVECTOR},
-        {CVC4::Kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT_OP,
+        {cvc5::Kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT_OP,
          FLOATINGPOINT_TO_FP_FLOATINGPOINT},
-        {CVC4::Kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT,
+        {cvc5::Kind::FLOATINGPOINT_TO_FP_FLOATINGPOINT,
          FLOATINGPOINT_TO_FP_FLOATINGPOINT},
-        {CVC4::Kind::FLOATINGPOINT_TO_FP_REAL_OP, FLOATINGPOINT_TO_FP_REAL},
-        {CVC4::Kind::FLOATINGPOINT_TO_FP_REAL, FLOATINGPOINT_TO_FP_REAL},
-        {CVC4::Kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR_OP,
+        {cvc5::Kind::FLOATINGPOINT_TO_FP_REAL_OP, FLOATINGPOINT_TO_FP_REAL},
+        {cvc5::Kind::FLOATINGPOINT_TO_FP_REAL, FLOATINGPOINT_TO_FP_REAL},
+        {cvc5::Kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR_OP,
          FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR},
-        {CVC4::Kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR,
+        {cvc5::Kind::FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR,
          FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR},
-        {CVC4::Kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR_OP,
+        {cvc5::Kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR_OP,
          FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR},
-        {CVC4::Kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR,
+        {cvc5::Kind::FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR,
          FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR},
-        {CVC4::Kind::FLOATINGPOINT_TO_FP_GENERIC_OP,
+        {cvc5::Kind::FLOATINGPOINT_TO_FP_GENERIC_OP,
          FLOATINGPOINT_TO_FP_GENERIC},
-        {CVC4::Kind::FLOATINGPOINT_TO_FP_GENERIC, FLOATINGPOINT_TO_FP_GENERIC},
-        {CVC4::Kind::FLOATINGPOINT_TO_UBV_OP, FLOATINGPOINT_TO_UBV},
-        {CVC4::Kind::FLOATINGPOINT_TO_UBV, FLOATINGPOINT_TO_UBV},
-        {CVC4::Kind::FLOATINGPOINT_TO_UBV_TOTAL_OP, INTERNAL_KIND},
-        {CVC4::Kind::FLOATINGPOINT_TO_UBV_TOTAL, INTERNAL_KIND},
-        {CVC4::Kind::FLOATINGPOINT_TO_SBV_OP, FLOATINGPOINT_TO_SBV},
-        {CVC4::Kind::FLOATINGPOINT_TO_SBV, FLOATINGPOINT_TO_SBV},
-        {CVC4::Kind::FLOATINGPOINT_TO_SBV_TOTAL_OP, INTERNAL_KIND},
-        {CVC4::Kind::FLOATINGPOINT_TO_SBV_TOTAL, INTERNAL_KIND},
-        {CVC4::Kind::FLOATINGPOINT_TO_REAL, FLOATINGPOINT_TO_REAL},
-        {CVC4::Kind::FLOATINGPOINT_TO_REAL_TOTAL, INTERNAL_KIND},
+        {cvc5::Kind::FLOATINGPOINT_TO_FP_GENERIC, FLOATINGPOINT_TO_FP_GENERIC},
+        {cvc5::Kind::FLOATINGPOINT_TO_UBV_OP, FLOATINGPOINT_TO_UBV},
+        {cvc5::Kind::FLOATINGPOINT_TO_UBV, FLOATINGPOINT_TO_UBV},
+        {cvc5::Kind::FLOATINGPOINT_TO_UBV_TOTAL_OP, INTERNAL_KIND},
+        {cvc5::Kind::FLOATINGPOINT_TO_UBV_TOTAL, INTERNAL_KIND},
+        {cvc5::Kind::FLOATINGPOINT_TO_SBV_OP, FLOATINGPOINT_TO_SBV},
+        {cvc5::Kind::FLOATINGPOINT_TO_SBV, FLOATINGPOINT_TO_SBV},
+        {cvc5::Kind::FLOATINGPOINT_TO_SBV_TOTAL_OP, INTERNAL_KIND},
+        {cvc5::Kind::FLOATINGPOINT_TO_SBV_TOTAL, INTERNAL_KIND},
+        {cvc5::Kind::FLOATINGPOINT_TO_REAL, FLOATINGPOINT_TO_REAL},
+        {cvc5::Kind::FLOATINGPOINT_TO_REAL_TOTAL, INTERNAL_KIND},
         /* Arrays ---------------------------------------------------------- */
-        {CVC4::Kind::SELECT, SELECT},
-        {CVC4::Kind::STORE, STORE},
-        {CVC4::Kind::STORE_ALL, CONST_ARRAY},
+        {cvc5::Kind::SELECT, SELECT},
+        {cvc5::Kind::STORE, STORE},
+        {cvc5::Kind::STORE_ALL, CONST_ARRAY},
         /* Datatypes ------------------------------------------------------- */
-        {CVC4::Kind::APPLY_SELECTOR, APPLY_SELECTOR},
-        {CVC4::Kind::APPLY_CONSTRUCTOR, APPLY_CONSTRUCTOR},
-        {CVC4::Kind::APPLY_SELECTOR_TOTAL, INTERNAL_KIND},
-        {CVC4::Kind::APPLY_TESTER, APPLY_TESTER},
-        {CVC4::Kind::TUPLE_UPDATE_OP, TUPLE_UPDATE},
-        {CVC4::Kind::TUPLE_UPDATE, TUPLE_UPDATE},
-        {CVC4::Kind::RECORD_UPDATE_OP, RECORD_UPDATE},
-        {CVC4::Kind::RECORD_UPDATE, RECORD_UPDATE},
-        {CVC4::Kind::DT_SIZE, DT_SIZE},
+        {cvc5::Kind::APPLY_SELECTOR, APPLY_SELECTOR},
+        {cvc5::Kind::APPLY_CONSTRUCTOR, APPLY_CONSTRUCTOR},
+        {cvc5::Kind::APPLY_SELECTOR_TOTAL, INTERNAL_KIND},
+        {cvc5::Kind::APPLY_TESTER, APPLY_TESTER},
+        {cvc5::Kind::TUPLE_UPDATE_OP, TUPLE_UPDATE},
+        {cvc5::Kind::TUPLE_UPDATE, TUPLE_UPDATE},
+        {cvc5::Kind::RECORD_UPDATE_OP, RECORD_UPDATE},
+        {cvc5::Kind::RECORD_UPDATE, RECORD_UPDATE},
+        {cvc5::Kind::DT_SIZE, DT_SIZE},
+        {cvc5::Kind::TUPLE_PROJECT, TUPLE_PROJECT},
         /* Separation Logic ------------------------------------------------ */
-        {CVC4::Kind::SEP_NIL, SEP_NIL},
-        {CVC4::Kind::SEP_EMP, SEP_EMP},
-        {CVC4::Kind::SEP_PTO, SEP_PTO},
-        {CVC4::Kind::SEP_STAR, SEP_STAR},
-        {CVC4::Kind::SEP_WAND, SEP_WAND},
+        {cvc5::Kind::SEP_NIL, SEP_NIL},
+        {cvc5::Kind::SEP_EMP, SEP_EMP},
+        {cvc5::Kind::SEP_PTO, SEP_PTO},
+        {cvc5::Kind::SEP_STAR, SEP_STAR},
+        {cvc5::Kind::SEP_WAND, SEP_WAND},
         /* Sets ------------------------------------------------------------ */
-        {CVC4::Kind::EMPTYSET, EMPTYSET},
-        {CVC4::Kind::UNION, UNION},
-        {CVC4::Kind::INTERSECTION, INTERSECTION},
-        {CVC4::Kind::SETMINUS, SETMINUS},
-        {CVC4::Kind::SUBSET, SUBSET},
-        {CVC4::Kind::MEMBER, MEMBER},
-        {CVC4::Kind::SINGLETON, SINGLETON},
-        {CVC4::Kind::INSERT, INSERT},
-        {CVC4::Kind::CARD, CARD},
-        {CVC4::Kind::COMPLEMENT, COMPLEMENT},
-        {CVC4::Kind::UNIVERSE_SET, UNIVERSE_SET},
-        {CVC4::Kind::JOIN, JOIN},
-        {CVC4::Kind::PRODUCT, PRODUCT},
-        {CVC4::Kind::TRANSPOSE, TRANSPOSE},
-        {CVC4::Kind::TCLOSURE, TCLOSURE},
-        {CVC4::Kind::JOIN_IMAGE, JOIN_IMAGE},
-        {CVC4::Kind::IDEN, IDEN},
-        {CVC4::Kind::COMPREHENSION, COMPREHENSION},
-        {CVC4::Kind::CHOOSE, CHOOSE},
-        {CVC4::Kind::IS_SINGLETON, IS_SINGLETON},
+        {cvc5::Kind::EMPTYSET, EMPTYSET},
+        {cvc5::Kind::UNION, UNION},
+        {cvc5::Kind::INTERSECTION, INTERSECTION},
+        {cvc5::Kind::SETMINUS, SETMINUS},
+        {cvc5::Kind::SUBSET, SUBSET},
+        {cvc5::Kind::MEMBER, MEMBER},
+        {cvc5::Kind::SINGLETON, SINGLETON},
+        {cvc5::Kind::INSERT, INSERT},
+        {cvc5::Kind::CARD, CARD},
+        {cvc5::Kind::COMPLEMENT, COMPLEMENT},
+        {cvc5::Kind::UNIVERSE_SET, UNIVERSE_SET},
+        {cvc5::Kind::JOIN, JOIN},
+        {cvc5::Kind::PRODUCT, PRODUCT},
+        {cvc5::Kind::TRANSPOSE, TRANSPOSE},
+        {cvc5::Kind::TCLOSURE, TCLOSURE},
+        {cvc5::Kind::JOIN_IMAGE, JOIN_IMAGE},
+        {cvc5::Kind::IDEN, IDEN},
+        {cvc5::Kind::COMPREHENSION, COMPREHENSION},
+        {cvc5::Kind::CHOOSE, CHOOSE},
+        {cvc5::Kind::IS_SINGLETON, IS_SINGLETON},
         /* Bags ------------------------------------------------------------ */
-        {CVC4::Kind::UNION_MAX, UNION_MAX},
-        {CVC4::Kind::UNION_DISJOINT, UNION_DISJOINT},
-        {CVC4::Kind::INTERSECTION_MIN, INTERSECTION_MIN},
-        {CVC4::Kind::DIFFERENCE_SUBTRACT, DIFFERENCE_SUBTRACT},
-        {CVC4::Kind::DIFFERENCE_REMOVE, DIFFERENCE_REMOVE},
-        {CVC4::Kind::SUBBAG, SUBBAG},
-        {CVC4::Kind::BAG_COUNT, BAG_COUNT},
-        {CVC4::Kind::DUPLICATE_REMOVAL, DUPLICATE_REMOVAL},
-        {CVC4::Kind::MK_BAG, MK_BAG},
-        {CVC4::Kind::EMPTYBAG, EMPTYBAG},
-        {CVC4::Kind::BAG_CARD, BAG_CARD},
-        {CVC4::Kind::BAG_CHOOSE, BAG_CHOOSE},
-        {CVC4::Kind::BAG_IS_SINGLETON, BAG_IS_SINGLETON},
-        {CVC4::Kind::BAG_FROM_SET, BAG_FROM_SET},
-        {CVC4::Kind::BAG_TO_SET, BAG_TO_SET},
+        {cvc5::Kind::UNION_MAX, UNION_MAX},
+        {cvc5::Kind::UNION_DISJOINT, UNION_DISJOINT},
+        {cvc5::Kind::INTERSECTION_MIN, INTERSECTION_MIN},
+        {cvc5::Kind::DIFFERENCE_SUBTRACT, DIFFERENCE_SUBTRACT},
+        {cvc5::Kind::DIFFERENCE_REMOVE, DIFFERENCE_REMOVE},
+        {cvc5::Kind::SUBBAG, SUBBAG},
+        {cvc5::Kind::BAG_COUNT, BAG_COUNT},
+        {cvc5::Kind::DUPLICATE_REMOVAL, DUPLICATE_REMOVAL},
+        {cvc5::Kind::MK_BAG, MK_BAG},
+        {cvc5::Kind::EMPTYBAG, EMPTYBAG},
+        {cvc5::Kind::BAG_CARD, BAG_CARD},
+        {cvc5::Kind::BAG_CHOOSE, BAG_CHOOSE},
+        {cvc5::Kind::BAG_IS_SINGLETON, BAG_IS_SINGLETON},
+        {cvc5::Kind::BAG_FROM_SET, BAG_FROM_SET},
+        {cvc5::Kind::BAG_TO_SET, BAG_TO_SET},
         /* Strings --------------------------------------------------------- */
-        {CVC4::Kind::STRING_CONCAT, STRING_CONCAT},
-        {CVC4::Kind::STRING_IN_REGEXP, STRING_IN_REGEXP},
-        {CVC4::Kind::STRING_LENGTH, STRING_LENGTH},
-        {CVC4::Kind::STRING_SUBSTR, STRING_SUBSTR},
-        {CVC4::Kind::STRING_UPDATE, STRING_UPDATE},
-        {CVC4::Kind::STRING_CHARAT, STRING_CHARAT},
-        {CVC4::Kind::STRING_STRCTN, STRING_CONTAINS},
-        {CVC4::Kind::STRING_STRIDOF, STRING_INDEXOF},
-        {CVC4::Kind::STRING_STRREPL, STRING_REPLACE},
-        {CVC4::Kind::STRING_STRREPLALL, STRING_REPLACE_ALL},
-        {CVC4::Kind::STRING_REPLACE_RE, STRING_REPLACE_RE},
-        {CVC4::Kind::STRING_REPLACE_RE_ALL, STRING_REPLACE_RE_ALL},
-        {CVC4::Kind::STRING_TOLOWER, STRING_TOLOWER},
-        {CVC4::Kind::STRING_TOUPPER, STRING_TOUPPER},
-        {CVC4::Kind::STRING_REV, STRING_REV},
-        {CVC4::Kind::STRING_FROM_CODE, STRING_FROM_CODE},
-        {CVC4::Kind::STRING_TO_CODE, STRING_TO_CODE},
-        {CVC4::Kind::STRING_LT, STRING_LT},
-        {CVC4::Kind::STRING_LEQ, STRING_LEQ},
-        {CVC4::Kind::STRING_PREFIX, STRING_PREFIX},
-        {CVC4::Kind::STRING_SUFFIX, STRING_SUFFIX},
-        {CVC4::Kind::STRING_IS_DIGIT, STRING_IS_DIGIT},
-        {CVC4::Kind::STRING_ITOS, STRING_FROM_INT},
-        {CVC4::Kind::STRING_STOI, STRING_TO_INT},
-        {CVC4::Kind::CONST_STRING, CONST_STRING},
-        {CVC4::Kind::STRING_TO_REGEXP, STRING_TO_REGEXP},
-        {CVC4::Kind::REGEXP_CONCAT, REGEXP_CONCAT},
-        {CVC4::Kind::REGEXP_UNION, REGEXP_UNION},
-        {CVC4::Kind::REGEXP_INTER, REGEXP_INTER},
-        {CVC4::Kind::REGEXP_DIFF, REGEXP_DIFF},
-        {CVC4::Kind::REGEXP_STAR, REGEXP_STAR},
-        {CVC4::Kind::REGEXP_PLUS, REGEXP_PLUS},
-        {CVC4::Kind::REGEXP_OPT, REGEXP_OPT},
-        {CVC4::Kind::REGEXP_RANGE, REGEXP_RANGE},
-        {CVC4::Kind::REGEXP_REPEAT, REGEXP_REPEAT},
-        {CVC4::Kind::REGEXP_REPEAT_OP, REGEXP_REPEAT},
-        {CVC4::Kind::REGEXP_LOOP, REGEXP_LOOP},
-        {CVC4::Kind::REGEXP_LOOP_OP, REGEXP_LOOP},
-        {CVC4::Kind::REGEXP_EMPTY, REGEXP_EMPTY},
-        {CVC4::Kind::REGEXP_SIGMA, REGEXP_SIGMA},
-        {CVC4::Kind::REGEXP_COMPLEMENT, REGEXP_COMPLEMENT},
-        {CVC4::Kind::CONST_SEQUENCE, CONST_SEQUENCE},
-        {CVC4::Kind::SEQ_UNIT, SEQ_UNIT},
-        {CVC4::Kind::SEQ_NTH, SEQ_NTH},
+        {cvc5::Kind::STRING_CONCAT, STRING_CONCAT},
+        {cvc5::Kind::STRING_IN_REGEXP, STRING_IN_REGEXP},
+        {cvc5::Kind::STRING_LENGTH, STRING_LENGTH},
+        {cvc5::Kind::STRING_SUBSTR, STRING_SUBSTR},
+        {cvc5::Kind::STRING_UPDATE, STRING_UPDATE},
+        {cvc5::Kind::STRING_CHARAT, STRING_CHARAT},
+        {cvc5::Kind::STRING_STRCTN, STRING_CONTAINS},
+        {cvc5::Kind::STRING_STRIDOF, STRING_INDEXOF},
+        {cvc5::Kind::STRING_STRREPL, STRING_REPLACE},
+        {cvc5::Kind::STRING_STRREPLALL, STRING_REPLACE_ALL},
+        {cvc5::Kind::STRING_REPLACE_RE, STRING_REPLACE_RE},
+        {cvc5::Kind::STRING_REPLACE_RE_ALL, STRING_REPLACE_RE_ALL},
+        {cvc5::Kind::STRING_TOLOWER, STRING_TOLOWER},
+        {cvc5::Kind::STRING_TOUPPER, STRING_TOUPPER},
+        {cvc5::Kind::STRING_REV, STRING_REV},
+        {cvc5::Kind::STRING_FROM_CODE, STRING_FROM_CODE},
+        {cvc5::Kind::STRING_TO_CODE, STRING_TO_CODE},
+        {cvc5::Kind::STRING_LT, STRING_LT},
+        {cvc5::Kind::STRING_LEQ, STRING_LEQ},
+        {cvc5::Kind::STRING_PREFIX, STRING_PREFIX},
+        {cvc5::Kind::STRING_SUFFIX, STRING_SUFFIX},
+        {cvc5::Kind::STRING_IS_DIGIT, STRING_IS_DIGIT},
+        {cvc5::Kind::STRING_ITOS, STRING_FROM_INT},
+        {cvc5::Kind::STRING_STOI, STRING_TO_INT},
+        {cvc5::Kind::CONST_STRING, CONST_STRING},
+        {cvc5::Kind::STRING_TO_REGEXP, STRING_TO_REGEXP},
+        {cvc5::Kind::REGEXP_CONCAT, REGEXP_CONCAT},
+        {cvc5::Kind::REGEXP_UNION, REGEXP_UNION},
+        {cvc5::Kind::REGEXP_INTER, REGEXP_INTER},
+        {cvc5::Kind::REGEXP_DIFF, REGEXP_DIFF},
+        {cvc5::Kind::REGEXP_STAR, REGEXP_STAR},
+        {cvc5::Kind::REGEXP_PLUS, REGEXP_PLUS},
+        {cvc5::Kind::REGEXP_OPT, REGEXP_OPT},
+        {cvc5::Kind::REGEXP_RANGE, REGEXP_RANGE},
+        {cvc5::Kind::REGEXP_REPEAT, REGEXP_REPEAT},
+        {cvc5::Kind::REGEXP_REPEAT_OP, REGEXP_REPEAT},
+        {cvc5::Kind::REGEXP_LOOP, REGEXP_LOOP},
+        {cvc5::Kind::REGEXP_LOOP_OP, REGEXP_LOOP},
+        {cvc5::Kind::REGEXP_EMPTY, REGEXP_EMPTY},
+        {cvc5::Kind::REGEXP_SIGMA, REGEXP_SIGMA},
+        {cvc5::Kind::REGEXP_COMPLEMENT, REGEXP_COMPLEMENT},
+        {cvc5::Kind::CONST_SEQUENCE, CONST_SEQUENCE},
+        {cvc5::Kind::SEQ_UNIT, SEQ_UNIT},
+        {cvc5::Kind::SEQ_NTH, SEQ_NTH},
         /* Quantifiers ----------------------------------------------------- */
-        {CVC4::Kind::FORALL, FORALL},
-        {CVC4::Kind::EXISTS, EXISTS},
-        {CVC4::Kind::BOUND_VAR_LIST, BOUND_VAR_LIST},
-        {CVC4::Kind::INST_PATTERN, INST_PATTERN},
-        {CVC4::Kind::INST_NO_PATTERN, INST_NO_PATTERN},
-        {CVC4::Kind::INST_ATTRIBUTE, INST_ATTRIBUTE},
-        {CVC4::Kind::INST_PATTERN_LIST, INST_PATTERN_LIST},
+        {cvc5::Kind::FORALL, FORALL},
+        {cvc5::Kind::EXISTS, EXISTS},
+        {cvc5::Kind::BOUND_VAR_LIST, BOUND_VAR_LIST},
+        {cvc5::Kind::INST_PATTERN, INST_PATTERN},
+        {cvc5::Kind::INST_NO_PATTERN, INST_NO_PATTERN},
+        {cvc5::Kind::INST_ATTRIBUTE, INST_ATTRIBUTE},
+        {cvc5::Kind::INST_PATTERN_LIST, INST_PATTERN_LIST},
         /* ----------------------------------------------------------------- */
-        {CVC4::Kind::LAST_KIND, LAST_KIND},
+        {cvc5::Kind::LAST_KIND, LAST_KIND},
     };
 
 /* Set of kinds for indexed operators */
@@ -660,32 +677,58 @@ const static std::unordered_set<Kind, KindHashFunction> s_indexed_kinds(
 
 namespace {
 
+/** Convert a cvc5::Kind (internal) to a cvc5::api::Kind (external). */
+cvc5::api::Kind intToExtKind(cvc5::Kind k)
+{
+  auto it = api::s_kinds_internal.find(k);
+  if (it == api::s_kinds_internal.end())
+  {
+    return api::INTERNAL_KIND;
+  }
+  return it->second;
+}
+
+/** Convert a cvc5::api::Kind (external) to a cvc5::Kind (internal). */
+cvc5::Kind extToIntKind(cvc5::api::Kind k)
+{
+  auto it = api::s_kinds.find(k);
+  if (it == api::s_kinds.end())
+  {
+    return cvc5::Kind::UNDEFINED_KIND;
+  }
+  return it->second;
+}
+
+/** Return true if given kind is a defined external kind. */
 bool isDefinedKind(Kind k) { return k > UNDEFINED_KIND && k < LAST_KIND; }
 
-/** Returns true if the internal kind is one where the API term structure
- *  differs from internal structure. This happens for APPLY_* kinds.
- *  The API takes a "higher-order" perspective and treats functions as well
- *  as datatype constructors/selectors/testers as terms
- *  but interally they are not
+/**
+ * Return true if the internal kind is one where the API term structure
+ * differs from internal structure. This happens for APPLY_* kinds.
+ * The API takes a "higher-order" perspective and treats functions as well
+ * as datatype constructors/selectors/testers as terms
+ * but interally they are not
  */
-bool isApplyKind(CVC4::Kind k)
+bool isApplyKind(cvc5::Kind k)
 {
-  return (k == CVC4::Kind::APPLY_UF || k == CVC4::Kind::APPLY_CONSTRUCTOR
-          || k == CVC4::Kind::APPLY_SELECTOR || k == CVC4::Kind::APPLY_TESTER);
+  return (k == cvc5::Kind::APPLY_UF || k == cvc5::Kind::APPLY_CONSTRUCTOR
+          || k == cvc5::Kind::APPLY_SELECTOR || k == cvc5::Kind::APPLY_TESTER);
 }
 
 #ifdef CVC4_ASSERTIONS
-bool isDefinedIntKind(CVC4::Kind k)
+/** Return true if given kind is a defined internal kind. */
+bool isDefinedIntKind(cvc5::Kind k)
 {
-  return k != CVC4::Kind::UNDEFINED_KIND && k != CVC4::Kind::LAST_KIND;
+  return k != cvc5::Kind::UNDEFINED_KIND && k != cvc5::Kind::LAST_KIND;
 }
 #endif
 
+/** Return the minimum arity of given kind. */
 uint32_t minArity(Kind k)
 {
   Assert(isDefinedKind(k));
   Assert(isDefinedIntKind(extToIntKind(k)));
-  uint32_t min = CVC4::ExprManager::minArity(extToIntKind(k));
+  uint32_t min = cvc5::kind::metakind::getMinArityForKind(extToIntKind(k));
 
   // At the API level, we treat functions/constructors/selectors/testers as
   // normal terms instead of making them part of the operator
@@ -696,11 +739,12 @@ uint32_t minArity(Kind k)
   return min;
 }
 
+/** Return the maximum arity of given kind. */
 uint32_t maxArity(Kind k)
 {
   Assert(isDefinedKind(k));
   Assert(isDefinedIntKind(extToIntKind(k)));
-  uint32_t max = CVC4::ExprManager::maxArity(extToIntKind(k));
+  uint32_t max = cvc5::kind::metakind::getMaxArityForKind(extToIntKind(k));
 
   // At the API level, we treat functions/constructors/selectors/testers as
   // normal terms instead of making them part of the operator
@@ -718,7 +762,7 @@ uint32_t maxArity(Kind k)
 std::string kindToString(Kind k)
 {
   return k == INTERNAL_KIND ? "INTERNAL_KIND"
-                            : CVC4::kind::kindToString(extToIntKind(k));
+                            : cvc5::kind::kindToString(extToIntKind(k));
 }
 
 std::ostream& operator<<(std::ostream& out, Kind k)
@@ -748,7 +792,7 @@ class CVC4ApiExceptionStream
    * default to noexcept(true) (else this triggers a call to std::terminate). */
   ~CVC4ApiExceptionStream() noexcept(false)
   {
-    if (!std::uncaught_exception())
+    if (std::uncaught_exceptions() == 0)
     {
       throw CVC4ApiException(d_stream.str());
     }
@@ -769,7 +813,7 @@ class CVC4ApiRecoverableExceptionStream
    * default to noexcept(true) (else this triggers a call to std::terminate). */
   ~CVC4ApiRecoverableExceptionStream() noexcept(false)
   {
-    if (!std::uncaught_exception())
+    if (std::uncaught_exceptions() == 0)
     {
       throw CVC4ApiRecoverableException(d_stream.str());
     }
@@ -781,145 +825,71 @@ class CVC4ApiRecoverableExceptionStream
   std::stringstream d_stream;
 };
 
-#define CVC4_API_CHECK(cond) \
-  CVC4_PREDICT_TRUE(cond)    \
-  ? (void)0 : OstreamVoider() & CVC4ApiExceptionStream().ostream()
-
-#define CVC4_API_RECOVERABLE_CHECK(cond) \
-  CVC4_PREDICT_TRUE(cond)                \
-  ? (void)0 : OstreamVoider() & CVC4ApiRecoverableExceptionStream().ostream()
-
-#define CVC4_API_CHECK_NOT_NULL                     \
-  CVC4_API_CHECK(!isNullHelper())                   \
-      << "Invalid call to '" << __PRETTY_FUNCTION__ \
-      << "', expected non-null object";
-
-#define CVC4_API_ARG_CHECK_NOT_NULL(arg) \
-  CVC4_API_CHECK(!arg.isNull()) << "Invalid null argument for '" << #arg << "'";
-
-#define CVC4_API_ARG_CHECK_NOT_NULLPTR(arg) \
-  CVC4_API_CHECK(arg != nullptr)            \
-      << "Invalid null argument for '" << #arg << "'";
-
-#define CVC4_API_KIND_CHECK(kind)     \
-  CVC4_API_CHECK(isDefinedKind(kind)) \
-      << "Invalid kind '" << kindToString(kind) << "'";
-
-#define CVC4_API_KIND_CHECK_EXPECTED(cond, kind) \
-  CVC4_PREDICT_TRUE(cond)                        \
-  ? (void)0                                      \
-  : OstreamVoider()                              \
-          & CVC4ApiExceptionStream().ostream()   \
-                << "Invalid kind '" << kindToString(kind) << "', expected "
-
-#define CVC4_API_ARG_CHECK_EXPECTED(cond, arg)                      \
-  CVC4_PREDICT_TRUE(cond)                                           \
-  ? (void)0                                                         \
-  : OstreamVoider()                                                 \
-          & CVC4ApiExceptionStream().ostream()                      \
-                << "Invalid argument '" << arg << "' for '" << #arg \
-                << "', expected "
-
-#define CVC4_API_RECOVERABLE_ARG_CHECK_EXPECTED(cond, arg)          \
-  CVC4_PREDICT_TRUE(cond)                                           \
-  ? (void)0                                                         \
-  : OstreamVoider()                                                 \
-          & CVC4ApiRecoverableExceptionStream().ostream()           \
-                << "Invalid argument '" << arg << "' for '" << #arg \
-                << "', expected "
-
-#define CVC4_API_ARG_SIZE_CHECK_EXPECTED(cond, arg) \
-  CVC4_PREDICT_TRUE(cond)                           \
-  ? (void)0                                         \
-  : OstreamVoider()                                 \
-          & CVC4ApiExceptionStream().ostream()      \
-                << "Invalid size of argument '" << #arg << "', expected "
-
-#define CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(cond, what, arg, idx)           \
-  CVC4_PREDICT_TRUE(cond)                                                    \
-  ? (void)0                                                                  \
-  : OstreamVoider()                                                          \
-          & CVC4ApiExceptionStream().ostream()                               \
-                << "Invalid " << what << " '" << arg << "' at index " << idx \
-                << ", expected "
-
-#define CVC4_API_SOLVER_TRY_CATCH_BEGIN \
-  try                                   \
-  {
-#define CVC4_API_SOLVER_TRY_CATCH_END                                          \
+#define CVC4_API_TRY_CATCH_BEGIN \
+  try                            \
+  {
+#define CVC4_API_TRY_CATCH_END                                                 \
   }                                                                            \
   catch (const UnrecognizedOptionException& e)                                 \
   {                                                                            \
     throw CVC4ApiRecoverableException(e.getMessage());                         \
   }                                                                            \
-  catch (const CVC4::RecoverableModalException& e)                             \
+  catch (const cvc5::RecoverableModalException& e)                             \
   {                                                                            \
     throw CVC4ApiRecoverableException(e.getMessage());                         \
   }                                                                            \
-  catch (const CVC4::Exception& e) { throw CVC4ApiException(e.getMessage()); } \
+  catch (const cvc5::Exception& e) { throw CVC4ApiException(e.getMessage()); } \
   catch (const std::invalid_argument& e) { throw CVC4ApiException(e.what()); }
 
-#define CVC4_API_SOLVER_CHECK_SORT(sort) \
-  CVC4_API_CHECK(this == sort.d_solver)  \
-      << "Given sort is not associated with this solver";
-
-#define CVC4_API_SOLVER_CHECK_TERM(term) \
-  CVC4_API_CHECK(this == term.d_solver)  \
-      << "Given term is not associated with this solver";
-
-#define CVC4_API_SOLVER_CHECK_OP(op)  \
-  CVC4_API_CHECK(this == op.d_solver) \
-      << "Given operator is not associated with this solver";
-
 }  // namespace
 
 /* -------------------------------------------------------------------------- */
 /* Result                                                                     */
 /* -------------------------------------------------------------------------- */
 
-Result::Result(const CVC4::Result& r) : d_result(new CVC4::Result(r)) {}
+Result::Result(const cvc5::Result& r) : d_result(new cvc5::Result(r)) {}
 
-Result::Result() : d_result(new CVC4::Result()) {}
+Result::Result() : d_result(new cvc5::Result()) {}
 
 bool Result::isNull() const
 {
-  return d_result->getType() == CVC4::Result::TYPE_NONE;
+  return d_result->getType() == cvc5::Result::TYPE_NONE;
 }
 
 bool Result::isSat(void) const
 {
-  return d_result->getType() == CVC4::Result::TYPE_SAT
-         && d_result->isSat() == CVC4::Result::SAT;
+  return d_result->getType() == cvc5::Result::TYPE_SAT
+         && d_result->isSat() == cvc5::Result::SAT;
 }
 
 bool Result::isUnsat(void) const
 {
-  return d_result->getType() == CVC4::Result::TYPE_SAT
-         && d_result->isSat() == CVC4::Result::UNSAT;
+  return d_result->getType() == cvc5::Result::TYPE_SAT
+         && d_result->isSat() == cvc5::Result::UNSAT;
 }
 
 bool Result::isSatUnknown(void) const
 {
-  return d_result->getType() == CVC4::Result::TYPE_SAT
-         && d_result->isSat() == CVC4::Result::SAT_UNKNOWN;
+  return d_result->getType() == cvc5::Result::TYPE_SAT
+         && d_result->isSat() == cvc5::Result::SAT_UNKNOWN;
 }
 
 bool Result::isEntailed(void) const
 {
-  return d_result->getType() == CVC4::Result::TYPE_ENTAILMENT
-         && d_result->isEntailed() == CVC4::Result::ENTAILED;
+  return d_result->getType() == cvc5::Result::TYPE_ENTAILMENT
+         && d_result->isEntailed() == cvc5::Result::ENTAILED;
 }
 
 bool Result::isNotEntailed(void) const
 {
-  return d_result->getType() == CVC4::Result::TYPE_ENTAILMENT
-         && d_result->isEntailed() == CVC4::Result::NOT_ENTAILED;
+  return d_result->getType() == cvc5::Result::TYPE_ENTAILMENT
+         && d_result->isEntailed() == cvc5::Result::NOT_ENTAILED;
 }
 
 bool Result::isEntailmentUnknown(void) const
 {
-  return d_result->getType() == CVC4::Result::TYPE_ENTAILMENT
-         && d_result->isEntailed() == CVC4::Result::ENTAILMENT_UNKNOWN;
+  return d_result->getType() == cvc5::Result::TYPE_ENTAILMENT
+         && d_result->isEntailed() == cvc5::Result::ENTAILMENT_UNKNOWN;
 }
 
 bool Result::operator==(const Result& r) const
@@ -932,39 +902,62 @@ bool Result::operator!=(const Result& r) const
   return *d_result != *r.d_result;
 }
 
-std::string Result::getUnknownExplanation(void) const
+Result::UnknownExplanation Result::getUnknownExplanation(void) const
 {
-  std::stringstream ss;
-  ss << d_result->whyUnknown();
-  return ss.str();
+  cvc5::Result::UnknownExplanation expl = d_result->whyUnknown();
+  switch (expl)
+  {
+    case cvc5::Result::REQUIRES_FULL_CHECK: return REQUIRES_FULL_CHECK;
+    case cvc5::Result::INCOMPLETE: return INCOMPLETE;
+    case cvc5::Result::TIMEOUT: return TIMEOUT;
+    case cvc5::Result::RESOURCEOUT: return RESOURCEOUT;
+    case cvc5::Result::MEMOUT: return MEMOUT;
+    case cvc5::Result::INTERRUPTED: return INTERRUPTED;
+    case cvc5::Result::NO_STATUS: return NO_STATUS;
+    case cvc5::Result::UNSUPPORTED: return UNSUPPORTED;
+    case cvc5::Result::OTHER: return OTHER;
+    default: return UNKNOWN_REASON;
+  }
+  return UNKNOWN_REASON;
 }
 
 std::string Result::toString(void) const { return d_result->toString(); }
 
-// !!! This is only temporarily available until the parser is fully migrated
-// to the new API. !!!
-CVC4::Result Result::getResult(void) const { return *d_result; }
-
 std::ostream& operator<<(std::ostream& out, const Result& r)
 {
   out << r.toString();
   return out;
 }
 
+std::ostream& operator<<(std::ostream& out, enum Result::UnknownExplanation e)
+{
+  switch (e)
+  {
+    case Result::REQUIRES_FULL_CHECK: out << "REQUIRES_FULL_CHECK"; break;
+    case Result::INCOMPLETE: out << "INCOMPLETE"; break;
+    case Result::TIMEOUT: out << "TIMEOUT"; break;
+    case Result::RESOURCEOUT: out << "RESOURCEOUT"; break;
+    case Result::MEMOUT: out << "MEMOUT"; break;
+    case Result::INTERRUPTED: out << "INTERRUPTED"; break;
+    case Result::NO_STATUS: out << "NO_STATUS"; break;
+    case Result::UNSUPPORTED: out << "UNSUPPORTED"; break;
+    case Result::OTHER: out << "OTHER"; break;
+    case Result::UNKNOWN_REASON: out << "UNKNOWN_REASON"; break;
+    default: Unhandled() << e;
+  }
+  return out;
+}
+
 /* -------------------------------------------------------------------------- */
 /* Sort                                                                       */
 /* -------------------------------------------------------------------------- */
 
-Sort::Sort(const Solver* slv, const CVC4::Type& t)
-    : d_solver(slv), d_type(new CVC4::TypeNode(TypeNode::fromType(t)))
-{
-}
-Sort::Sort(const Solver* slv, const CVC4::TypeNode& t)
-    : d_solver(slv), d_type(new CVC4::TypeNode(t))
+Sort::Sort(const Solver* slv, const cvc5::TypeNode& t)
+    : d_solver(slv), d_type(new cvc5::TypeNode(t))
 {
 }
 
-Sort::Sort() : d_solver(nullptr), d_type(new CVC4::TypeNode()) {}
+Sort::Sort() : d_solver(nullptr), d_type(new cvc5::TypeNode()) {}
 
 Sort::~Sort()
 {
@@ -977,351 +970,766 @@ Sort::~Sort()
   }
 }
 
-/* Helpers                                                                    */
-/* -------------------------------------------------------------------------- */
+std::set<TypeNode> Sort::sortSetToTypeNodes(const std::set<Sort>& sorts)
+{
+  std::set<TypeNode> types;
+  for (const Sort& s : sorts)
+  {
+    types.insert(s.getTypeNode());
+  }
+  return types;
+}
 
-/* Split out to avoid nested API calls (problematic with API tracing).        */
-/* .......................................................................... */
+std::vector<TypeNode> Sort::sortVectorToTypeNodes(
+    const std::vector<Sort>& sorts)
+{
+  std::vector<TypeNode> typeNodes;
+  for (const Sort& sort : sorts)
+  {
+    typeNodes.push_back(sort.getTypeNode());
+  }
+  return typeNodes;
+}
 
-bool Sort::isNullHelper() const { return d_type->isNull(); }
+std::vector<Sort> Sort::typeNodeVectorToSorts(
+    const Solver* slv, const std::vector<TypeNode>& types)
+{
+  std::vector<Sort> sorts;
+  for (size_t i = 0, tsize = types.size(); i < tsize; i++)
+  {
+    sorts.push_back(Sort(slv, types[i]));
+  }
+  return sorts;
+}
 
-bool Sort::operator==(const Sort& s) const { return *d_type == *s.d_type; }
+bool Sort::operator==(const Sort& s) const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return *d_type == *s.d_type;
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::operator!=(const Sort& s) const { return *d_type != *s.d_type; }
+bool Sort::operator!=(const Sort& s) const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return *d_type != *s.d_type;
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::operator<(const Sort& s) const { return *d_type < *s.d_type; }
+bool Sort::operator<(const Sort& s) const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return *d_type < *s.d_type;
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::operator>(const Sort& s) const { return *d_type > *s.d_type; }
+bool Sort::operator>(const Sort& s) const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return *d_type > *s.d_type;
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::operator<=(const Sort& s) const { return *d_type <= *s.d_type; }
+bool Sort::operator<=(const Sort& s) const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return *d_type <= *s.d_type;
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::operator>=(const Sort& s) const { return *d_type >= *s.d_type; }
+bool Sort::operator>=(const Sort& s) const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return *d_type >= *s.d_type;
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isNull() const { return isNullHelper(); }
+bool Sort::isNull() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return isNullHelper();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isBoolean() const { return d_type->isBoolean(); }
+bool Sort::isBoolean() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isBoolean();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isInteger() const { return d_type->isInteger(); }
+bool Sort::isInteger() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isInteger();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isReal() const { return d_type->isReal(); }
+bool Sort::isReal() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isReal();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isString() const { return d_type->isString(); }
+bool Sort::isString() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isString();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isRegExp() const { return d_type->isRegExp(); }
+bool Sort::isRegExp() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isRegExp();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isRoundingMode() const { return d_type->isRoundingMode(); }
+bool Sort::isRoundingMode() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isRoundingMode();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isBitVector() const { return d_type->isBitVector(); }
+bool Sort::isBitVector() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isBitVector();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isFloatingPoint() const { return d_type->isFloatingPoint(); }
+bool Sort::isFloatingPoint() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isFloatingPoint();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isDatatype() const { return d_type->isDatatype(); }
+bool Sort::isDatatype() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isDatatype();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
 bool Sort::isParametricDatatype() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   if (!d_type->isDatatype()) return false;
   return d_type->isParametricDatatype();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-bool Sort::isConstructor() const { return d_type->isConstructor(); }
-bool Sort::isSelector() const { return d_type->isSelector(); }
-bool Sort::isTester() const { return d_type->isTester(); }
+bool Sort::isConstructor() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isConstructor();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
+
+bool Sort::isSelector() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isSelector();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
+
+bool Sort::isTester() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isTester();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isFunction() const { return d_type->isFunction(); }
+bool Sort::isFunction() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isFunction();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isPredicate() const { return d_type->isPredicate(); }
+bool Sort::isPredicate() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isPredicate();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isTuple() const { return d_type->isTuple(); }
+bool Sort::isTuple() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isTuple();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isRecord() const { return d_type->isRecord(); }
+bool Sort::isRecord() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isRecord();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isArray() const { return d_type->isArray(); }
+bool Sort::isArray() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isArray();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isSet() const { return d_type->isSet(); }
+bool Sort::isSet() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isSet();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isBag() const { return d_type->isBag(); }
+bool Sort::isBag() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isBag();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isSequence() const { return d_type->isSequence(); }
+bool Sort::isSequence() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isSequence();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isUninterpretedSort() const { return d_type->isSort(); }
+bool Sort::isUninterpretedSort() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isSort();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isSortConstructor() const { return d_type->isSortConstructor(); }
+bool Sort::isSortConstructor() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isSortConstructor();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isFirstClass() const { return d_type->isFirstClass(); }
+bool Sort::isFirstClass() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isFirstClass();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isFunctionLike() const { return d_type->isFunctionLike(); }
+bool Sort::isFunctionLike() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return d_type->isFunctionLike();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isSubsortOf(Sort s) const { return d_type->isSubtypeOf(*s.d_type); }
+bool Sort::isSubsortOf(const Sort& s) const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_ARG_CHECK_SOLVER("sort", s);
+  //////// all checks before this line
+  return d_type->isSubtypeOf(*s.d_type);
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Sort::isComparableTo(Sort s) const
+bool Sort::isComparableTo(const Sort& s) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_ARG_CHECK_SOLVER("sort", s);
+  //////// all checks before this line
   return d_type->isComparableTo(*s.d_type);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Datatype Sort::getDatatype() const
 {
   NodeManagerScope scope(d_solver->getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isDatatype()) << "Expected datatype sort.";
+  //////// all checks before this line
   return Datatype(d_solver, d_type->getDType());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Sort::instantiate(const std::vector<Sort>& params) const
 {
   NodeManagerScope scope(d_solver->getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  CVC4_API_CHECK_SORTS(params);
   CVC4_API_CHECK(isParametricDatatype() || isSortConstructor())
       << "Expected parametric datatype or sort constructor sort.";
-  std::vector<CVC4::TypeNode> tparams = sortVectorToTypeNodes(params);
+  //////// all checks before this line
+  std::vector<cvc5::TypeNode> tparams = sortVectorToTypeNodes(params);
   if (d_type->isDatatype())
   {
     return Sort(d_solver, d_type->instantiateParametricDatatype(tparams));
   }
   Assert(d_type->isSortConstructor());
   return Sort(d_solver, d_solver->getNodeManager()->mkSort(*d_type, tparams));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Sort::substitute(const Sort& sort, const Sort& replacement) const
 {
   NodeManagerScope scope(d_solver->getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  CVC4_API_CHECK_SORT(sort);
+  CVC4_API_CHECK_SORT(replacement);
+  //////// all checks before this line
   return Sort(
       d_solver,
       d_type->substitute(sort.getTypeNode(), replacement.getTypeNode()));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Sort::substitute(const std::vector<Sort>& sorts,
                       const std::vector<Sort>& replacements) const
 {
   NodeManagerScope scope(d_solver->getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  CVC4_API_CHECK_SORTS(sorts);
+  CVC4_API_CHECK_SORTS(replacements);
+  //////// all checks before this line
 
-  std::vector<CVC4::TypeNode> tSorts = sortVectorToTypeNodes(sorts),
+  std::vector<cvc5::TypeNode> tSorts = sortVectorToTypeNodes(sorts),
                               tReplacements =
                                   sortVectorToTypeNodes(replacements);
-
   return Sort(d_solver,
               d_type->substitute(tSorts.begin(),
                                  tSorts.end(),
                                  tReplacements.begin(),
                                  tReplacements.end()));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::string Sort::toString() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   if (d_solver != nullptr)
   {
     NodeManagerScope scope(d_solver->getNodeManager());
     return d_type->toString();
   }
   return d_type->toString();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-// !!! This is only temporarily available until the parser is fully migrated
-// to the new API. !!!
-CVC4::Type Sort::getType(void) const
-{
-  if (d_type->isNull()) return Type();
-  NodeManagerScope scope(d_solver->getNodeManager());
-  return d_type->toType();
-}
-const CVC4::TypeNode& Sort::getTypeNode(void) const { return *d_type; }
+const cvc5::TypeNode& Sort::getTypeNode(void) const { return *d_type; }
 
 /* Constructor sort ------------------------------------------------------- */
 
 size_t Sort::getConstructorArity() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isConstructor()) << "Not a constructor sort: " << (*this);
+  //////// all checks before this line
   return d_type->getNumChildren() - 1;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::vector<Sort> Sort::getConstructorDomainSorts() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isConstructor()) << "Not a constructor sort: " << (*this);
+  //////// all checks before this line
   return typeNodeVectorToSorts(d_solver, d_type->getArgTypes());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Sort::getConstructorCodomainSort() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isConstructor()) << "Not a constructor sort: " << (*this);
+  //////// all checks before this line
   return Sort(d_solver, d_type->getConstructorRangeType());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Selector sort ------------------------------------------------------- */
 
 Sort Sort::getSelectorDomainSort() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isSelector()) << "Not a selector sort: " << (*this);
+  //////// all checks before this line
   return Sort(d_solver, d_type->getSelectorDomainType());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Sort::getSelectorCodomainSort() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isSelector()) << "Not a selector sort: " << (*this);
+  //////// all checks before this line
   return Sort(d_solver, d_type->getSelectorRangeType());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Tester sort ------------------------------------------------------- */
 
 Sort Sort::getTesterDomainSort() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isTester()) << "Not a tester sort: " << (*this);
+  //////// all checks before this line
   return Sort(d_solver, d_type->getTesterDomainType());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Sort::getTesterCodomainSort() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isTester()) << "Not a tester sort: " << (*this);
+  //////// all checks before this line
   return d_solver->getBooleanSort();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Function sort ------------------------------------------------------- */
 
 size_t Sort::getFunctionArity() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isFunction()) << "Not a function sort: " << (*this);
+  //////// all checks before this line
   return d_type->getNumChildren() - 1;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::vector<Sort> Sort::getFunctionDomainSorts() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isFunction()) << "Not a function sort: " << (*this);
+  //////// all checks before this line
   return typeNodeVectorToSorts(d_solver, d_type->getArgTypes());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Sort::getFunctionCodomainSort() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isFunction()) << "Not a function sort" << (*this);
+  //////// all checks before this line
   return Sort(d_solver, d_type->getRangeType());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Array sort ---------------------------------------------------------- */
 
 Sort Sort::getArrayIndexSort() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isArray()) << "Not an array sort.";
+  //////// all checks before this line
   return Sort(d_solver, d_type->getArrayIndexType());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Sort::getArrayElementSort() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isArray()) << "Not an array sort.";
+  //////// all checks before this line
   return Sort(d_solver, d_type->getArrayConstituentType());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Set sort ------------------------------------------------------------ */
 
 Sort Sort::getSetElementSort() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isSet()) << "Not a set sort.";
+  //////// all checks before this line
   return Sort(d_solver, d_type->getSetElementType());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Bag sort ------------------------------------------------------------ */
 
 Sort Sort::getBagElementSort() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isBag()) << "Not a bag sort.";
+  //////// all checks before this line
   return Sort(d_solver, d_type->getBagElementType());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Sequence sort ------------------------------------------------------- */
 
 Sort Sort::getSequenceElementSort() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isSequence()) << "Not a sequence sort.";
+  //////// all checks before this line
   return Sort(d_solver, d_type->getSequenceElementType());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Uninterpreted sort -------------------------------------------------- */
 
 std::string Sort::getUninterpretedSortName() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isUninterpretedSort()) << "Not an uninterpreted sort.";
+  //////// all checks before this line
   return d_type->getName();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 bool Sort::isUninterpretedSortParameterized() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isUninterpretedSort()) << "Not an uninterpreted sort.";
-  // This method is not implemented in the NodeManager, since whether a
-  // uninterpreted sort is parametrized is irrelevant for solving.
+  //////// all checks before this line
+
+  /* This method is not implemented in the NodeManager, since whether a
+   * uninterpreted sort is parameterized is irrelevant for solving. */
   return d_type->getNumChildren() > 0;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::vector<Sort> Sort::getUninterpretedSortParamSorts() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isUninterpretedSort()) << "Not an uninterpreted sort.";
-  // This method is not implemented in the NodeManager, since whether a
-  // uninterpreted sort is parametrized is irrelevant for solving.
+  //////// all checks before this line
+
+  /* This method is not implemented in the NodeManager, since whether a
+   * uninterpreted sort is parameterized is irrelevant for solving. */
   std::vector<TypeNode> params;
   for (size_t i = 0, nchildren = d_type->getNumChildren(); i < nchildren; i++)
   {
     params.push_back((*d_type)[i]);
   }
   return typeNodeVectorToSorts(d_solver, params);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Sort constructor sort ----------------------------------------------- */
 
 std::string Sort::getSortConstructorName() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isSortConstructor()) << "Not a sort constructor sort.";
+  //////// all checks before this line
   return d_type->getName();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 size_t Sort::getSortConstructorArity() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isSortConstructor()) << "Not a sort constructor sort.";
+  //////// all checks before this line
   return d_type->getSortConstructorArity();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Bit-vector sort ----------------------------------------------------- */
 
 uint32_t Sort::getBVSize() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isBitVector()) << "Not a bit-vector sort.";
+  //////// all checks before this line
   return d_type->getBitVectorSize();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Floating-point sort ------------------------------------------------- */
 
 uint32_t Sort::getFPExponentSize() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isFloatingPoint()) << "Not a floating-point sort.";
+  //////// all checks before this line
   return d_type->getFloatingPointExponentSize();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 uint32_t Sort::getFPSignificandSize() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isFloatingPoint()) << "Not a floating-point sort.";
+  //////// all checks before this line
   return d_type->getFloatingPointSignificandSize();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Datatype sort ------------------------------------------------------- */
 
 std::vector<Sort> Sort::getDatatypeParamSorts() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isParametricDatatype()) << "Not a parametric datatype sort.";
-  std::vector<CVC4::TypeNode> typeNodes = d_type->getParamTypes();
-  return typeNodeVectorToSorts(d_solver, typeNodes);
+  //////// all checks before this line
+  return typeNodeVectorToSorts(d_solver, d_type->getParamTypes());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 size_t Sort::getDatatypeArity() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isDatatype()) << "Not a datatype sort.";
+  //////// all checks before this line
   return d_type->getNumChildren() - 1;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Tuple sort ---------------------------------------------------------- */
 
 size_t Sort::getTupleLength() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isTuple()) << "Not a tuple sort.";
+  //////// all checks before this line
   return d_type->getTupleLength();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::vector<Sort> Sort::getTupleSorts() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(isTuple()) << "Not a tuple sort.";
-  std::vector<CVC4::TypeNode> typeNodes = d_type->getTupleTypes();
-  return typeNodeVectorToSorts(d_solver, typeNodes);
+  //////// all checks before this line
+  return typeNodeVectorToSorts(d_solver, d_type->getTupleTypes());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* --------------------------------------------------------------------- */
@@ -1337,24 +1745,27 @@ size_t SortHashFunction::operator()(const Sort& s) const
   return TypeNodeHashFunction()(*s.d_type);
 }
 
+/* Helpers                                                                    */
+/* -------------------------------------------------------------------------- */
+
+/* Split out to avoid nested API calls (problematic with API tracing).        */
+/* .......................................................................... */
+
+bool Sort::isNullHelper() const { return d_type->isNull(); }
+
 /* -------------------------------------------------------------------------- */
 /* Op                                                                     */
 /* -------------------------------------------------------------------------- */
 
-Op::Op() : d_solver(nullptr), d_kind(NULL_EXPR), d_node(new CVC4::Node()) {}
+Op::Op() : d_solver(nullptr), d_kind(NULL_EXPR), d_node(new cvc5::Node()) {}
 
 Op::Op(const Solver* slv, const Kind k)
-    : d_solver(slv), d_kind(k), d_node(new CVC4::Node())
-{
-}
-
-Op::Op(const Solver* slv, const Kind k, const CVC4::Expr& e)
-    : d_solver(slv), d_kind(k), d_node(new CVC4::Node(Node::fromExpr(e)))
+    : d_solver(slv), d_kind(k), d_node(new cvc5::Node())
 {
 }
 
-Op::Op(const Solver* slv, const Kind k, const CVC4::Node& n)
-    : d_solver(slv), d_kind(k), d_node(new CVC4::Node(n))
+Op::Op(const Solver* slv, const Kind k, const cvc5::Node& n)
+    : d_solver(slv), d_kind(k), d_node(new cvc5::Node(n))
 {
 }
 
@@ -1369,22 +1780,11 @@ Op::~Op()
   }
 }
 
-/* Helpers                                                                    */
-/* -------------------------------------------------------------------------- */
-
-/* Split out to avoid nested API calls (problematic with API tracing).        */
-/* .......................................................................... */
-
-bool Op::isNullHelper() const
-{
-  return (d_node->isNull() && (d_kind == NULL_EXPR));
-}
-
-bool Op::isIndexedHelper() const { return !d_node->isNull(); }
-
 /* Public methods                                                             */
 bool Op::operator==(const Op& t) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   if (d_node->isNull() && t.d_node->isNull())
   {
     return (d_kind == t.d_kind);
@@ -1394,56 +1794,70 @@ bool Op::operator==(const Op& t) const
     return false;
   }
   return (d_kind == t.d_kind) && (*d_node == *t.d_node);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-bool Op::operator!=(const Op& t) const { return !(*this == t); }
+bool Op::operator!=(const Op& t) const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return !(*this == t);
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
 Kind Op::getKind() const
 {
   CVC4_API_CHECK(d_kind != NULL_EXPR) << "Expecting a non-null Kind";
+  //////// all checks before this line
   return d_kind;
 }
 
-bool Op::isNull() const { return isNullHelper(); }
+bool Op::isNull() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return isNullHelper();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Op::isIndexed() const { return isIndexedHelper(); }
+bool Op::isIndexed() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return isIndexedHelper();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
 template <>
 std::string Op::getIndices() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(!d_node->isNull())
       << "Expecting a non-null internal expression. This Op is not indexed.";
-
-  std::string i;
   Kind k = intToExtKind(d_node->getKind());
-
-  if (k == DIVISIBLE)
-  {
-    // DIVISIBLE returns a string index to support
-    // arbitrary precision integers
-    CVC4::Integer _int = d_node->getConst<Divisible>().k;
-    i = _int.toString();
-  }
-  else if (k == RECORD_UPDATE)
-  {
-    i = d_node->getConst<RecordUpdate>().getField();
-  }
-  else
-  {
-    CVC4_API_CHECK(false) << "Can't get string index from"
-                          << " kind " << kindToString(k);
-  }
-
-  return i;
+  CVC4_API_CHECK(k == DIVISIBLE || k == RECORD_UPDATE)
+      << "Can't get string index from"
+      << " kind " << kindToString(k);
+  //////// all checks before this line
+  return k == DIVISIBLE ? d_node->getConst<Divisible>().k.toString()
+                        : d_node->getConst<RecordUpdate>().getField();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 template <>
 uint32_t Op::getIndices() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(!d_node->isNull())
       << "Expecting a non-null internal expression. This Op is not indexed.";
+  //////// all checks before this line
 
   uint32_t i = 0;
   Kind k = intToExtKind(d_node->getKind());
@@ -1477,18 +1891,22 @@ uint32_t Op::getIndices() const
       i = d_node->getConst<RegExpRepeat>().d_repeatAmount;
       break;
     default:
-      CVC4ApiExceptionStream().ostream() << "Can't get uint32_t index from"
-                                         << " kind " << kindToString(k);
+      CVC4_API_CHECK(false) << "Can't get uint32_t index from"
+                            << " kind " << kindToString(k);
   }
   return i;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 template <>
 std::pair<uint32_t, uint32_t> Op::getIndices() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(!d_node->isNull())
       << "Expecting a non-null internal expression. This Op is not indexed.";
+  //////// all checks before this line
 
   std::pair<uint32_t, uint32_t> indices;
   Kind k = intToExtKind(d_node->getKind());
@@ -1496,53 +1914,53 @@ std::pair<uint32_t, uint32_t> Op::getIndices() const
   // using if/else instead of case statement because want local variables
   if (k == BITVECTOR_EXTRACT)
   {
-    CVC4::BitVectorExtract ext = d_node->getConst<BitVectorExtract>();
+    cvc5::BitVectorExtract ext = d_node->getConst<BitVectorExtract>();
     indices = std::make_pair(ext.d_high, ext.d_low);
   }
   else if (k == FLOATINGPOINT_TO_FP_IEEE_BITVECTOR)
   {
-    CVC4::FloatingPointToFPIEEEBitVector ext =
+    cvc5::FloatingPointToFPIEEEBitVector ext =
         d_node->getConst<FloatingPointToFPIEEEBitVector>();
-    indices = std::make_pair(ext.d_fp_size.exponentWidth(),
-                             ext.d_fp_size.significandWidth());
+    indices = std::make_pair(ext.getSize().exponentWidth(),
+                             ext.getSize().significandWidth());
   }
   else if (k == FLOATINGPOINT_TO_FP_FLOATINGPOINT)
   {
-    CVC4::FloatingPointToFPFloatingPoint ext =
+    cvc5::FloatingPointToFPFloatingPoint ext =
         d_node->getConst<FloatingPointToFPFloatingPoint>();
-    indices = std::make_pair(ext.d_fp_size.exponentWidth(),
-                             ext.d_fp_size.significandWidth());
+    indices = std::make_pair(ext.getSize().exponentWidth(),
+                             ext.getSize().significandWidth());
   }
   else if (k == FLOATINGPOINT_TO_FP_REAL)
   {
-    CVC4::FloatingPointToFPReal ext = d_node->getConst<FloatingPointToFPReal>();
-    indices = std::make_pair(ext.d_fp_size.exponentWidth(),
-                             ext.d_fp_size.significandWidth());
+    cvc5::FloatingPointToFPReal ext = d_node->getConst<FloatingPointToFPReal>();
+    indices = std::make_pair(ext.getSize().exponentWidth(),
+                             ext.getSize().significandWidth());
   }
   else if (k == FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR)
   {
-    CVC4::FloatingPointToFPSignedBitVector ext =
+    cvc5::FloatingPointToFPSignedBitVector ext =
         d_node->getConst<FloatingPointToFPSignedBitVector>();
-    indices = std::make_pair(ext.d_fp_size.exponentWidth(),
-                             ext.d_fp_size.significandWidth());
+    indices = std::make_pair(ext.getSize().exponentWidth(),
+                             ext.getSize().significandWidth());
   }
   else if (k == FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR)
   {
-    CVC4::FloatingPointToFPUnsignedBitVector ext =
+    cvc5::FloatingPointToFPUnsignedBitVector ext =
         d_node->getConst<FloatingPointToFPUnsignedBitVector>();
-    indices = std::make_pair(ext.d_fp_size.exponentWidth(),
-                             ext.d_fp_size.significandWidth());
+    indices = std::make_pair(ext.getSize().exponentWidth(),
+                             ext.getSize().significandWidth());
   }
   else if (k == FLOATINGPOINT_TO_FP_GENERIC)
   {
-    CVC4::FloatingPointToFPGeneric ext =
+    cvc5::FloatingPointToFPGeneric ext =
         d_node->getConst<FloatingPointToFPGeneric>();
-    indices = std::make_pair(ext.d_fp_size.exponentWidth(),
-                             ext.d_fp_size.significandWidth());
+    indices = std::make_pair(ext.getSize().exponentWidth(),
+                             ext.getSize().significandWidth());
   }
   else if (k == REGEXP_LOOP)
   {
-    CVC4::RegExpLoop ext = d_node->getConst<RegExpLoop>();
+    cvc5::RegExpLoop ext = d_node->getConst<RegExpLoop>();
     indices = std::make_pair(ext.d_loopMinOcc, ext.d_loopMaxOcc);
   }
   else
@@ -1551,11 +1969,14 @@ std::pair<uint32_t, uint32_t> Op::getIndices() const
                           << " kind " << kindToString(k);
   }
   return indices;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::string Op::toString() const
 {
-  CVC4_API_CHECK_NOT_NULL;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   if (d_node->isNull())
   {
     return kindToString(d_kind);
@@ -1571,15 +1992,8 @@ std::string Op::toString() const
     }
     return d_node->toString();
   }
-}
-
-// !!! This is only temporarily available until the parser is fully migrated
-// to the new API. !!!
-CVC4::Expr Op::getExpr(void) const
-{
-  if (d_node->isNull()) return Expr();
-  NodeManagerScope scope(d_solver->getNodeManager());
-  return d_node->toExpr();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::ostream& operator<<(std::ostream& out, const Op& t)
@@ -1592,7 +2006,7 @@ size_t OpHashFunction::operator()(const Op& t) const
 {
   if (t.isIndexedHelper())
   {
-    return ExprHashFunction()(t.d_node->toExpr());
+    return NodeHashFunction()(*t.d_node);
   }
   else
   {
@@ -1600,24 +2014,30 @@ size_t OpHashFunction::operator()(const Op& t) const
   }
 }
 
-/* -------------------------------------------------------------------------- */
-/* Term                                                                       */
+/* Helpers                                                                    */
 /* -------------------------------------------------------------------------- */
 
-Term::Term() : d_solver(nullptr), d_node(new CVC4::Node()) {}
+/* Split out to avoid nested API calls (problematic with API tracing).        */
+/* .......................................................................... */
 
-Term::Term(const Solver* slv, const CVC4::Expr& e) : d_solver(slv)
+bool Op::isNullHelper() const
 {
-  // Ensure that we create the node in the correct node manager.
-  NodeManagerScope scope(d_solver->getNodeManager());
-  d_node.reset(new CVC4::Node(e));
+  return (d_node->isNull() && (d_kind == NULL_EXPR));
 }
 
-Term::Term(const Solver* slv, const CVC4::Node& n) : d_solver(slv)
+bool Op::isIndexedHelper() const { return !d_node->isNull(); }
+
+/* -------------------------------------------------------------------------- */
+/* Term                                                                       */
+/* -------------------------------------------------------------------------- */
+
+Term::Term() : d_solver(nullptr), d_node(new cvc5::Node()) {}
+
+Term::Term(const Solver* slv, const cvc5::Node& n) : d_solver(slv)
 {
   // Ensure that we create the node in the correct node manager.
   NodeManagerScope scope(d_solver->getNodeManager());
-  d_node.reset(new CVC4::Node(n));
+  d_node.reset(new cvc5::Node(n));
 }
 
 Term::~Term()
@@ -1631,72 +2051,66 @@ Term::~Term()
   }
 }
 
-bool Term::isNullHelper() const
+bool Term::operator==(const Term& t) const
 {
-  /* Split out to avoid nested API calls (problematic with API tracing). */
-  return d_node->isNull();
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return *d_node == *t.d_node;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Kind Term::getKindHelper() const
+bool Term::operator!=(const Term& t) const
 {
-  // Sequence kinds do not exist internally, so we must convert their internal
-  // (string) versions back to sequence. All operators where this is
-  // necessary are such that their first child is of sequence type, which
-  // we check here.
-  if (d_node->getNumChildren() > 0 && (*d_node)[0].getType().isSequence())
-  {
-    switch (d_node->getKind())
-    {
-      case CVC4::Kind::STRING_CONCAT: return SEQ_CONCAT;
-      case CVC4::Kind::STRING_LENGTH: return SEQ_LENGTH;
-      case CVC4::Kind::STRING_SUBSTR: return SEQ_EXTRACT;
-      case CVC4::Kind::STRING_UPDATE: return SEQ_UPDATE;
-      case CVC4::Kind::STRING_CHARAT: return SEQ_AT;
-      case CVC4::Kind::STRING_STRCTN: return SEQ_CONTAINS;
-      case CVC4::Kind::STRING_STRIDOF: return SEQ_INDEXOF;
-      case CVC4::Kind::STRING_STRREPL: return SEQ_REPLACE;
-      case CVC4::Kind::STRING_STRREPLALL: return SEQ_REPLACE_ALL;
-      case CVC4::Kind::STRING_REV: return SEQ_REV;
-      case CVC4::Kind::STRING_PREFIX: return SEQ_PREFIX;
-      case CVC4::Kind::STRING_SUFFIX: return SEQ_SUFFIX;
-      default:
-        // fall through to conversion below
-        break;
-    }
-  }
-  // Notice that kinds like APPLY_TYPE_ASCRIPTION will be converted to
-  // INTERNAL_KIND.
-  if(isCastedReal())
-  {
-    return CONST_RATIONAL;
-  }
-  return intToExtKind(d_node->getKind());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return *d_node != *t.d_node;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-bool Term::isCastedReal() const
+bool Term::operator<(const Term& t) const
 {
-  if(d_node->getKind() == kind::CAST_TO_REAL)
-  {
-    return (*d_node)[0].isConst() && (*d_node)[0].getType().isInteger();
-  }
-  return false;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return *d_node < *t.d_node;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-bool Term::operator==(const Term& t) const { return *d_node == *t.d_node; }
-
-bool Term::operator!=(const Term& t) const { return *d_node != *t.d_node; }
-
-bool Term::operator<(const Term& t) const { return *d_node < *t.d_node; }
-
-bool Term::operator>(const Term& t) const { return *d_node > *t.d_node; }
+bool Term::operator>(const Term& t) const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return *d_node > *t.d_node;
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Term::operator<=(const Term& t) const { return *d_node <= *t.d_node; }
+bool Term::operator<=(const Term& t) const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return *d_node <= *t.d_node;
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Term::operator>=(const Term& t) const { return *d_node >= *t.d_node; }
+bool Term::operator>=(const Term& t) const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return *d_node >= *t.d_node;
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
 size_t Term::getNumChildren() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+
   // special case for apply kinds
   if (isApplyKind(d_node->getKind()))
   {
@@ -1707,99 +2121,122 @@ size_t Term::getNumChildren() const
     return 0;
   }
   return d_node->getNumChildren();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Term::operator[](size_t index) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
-
-  // check the index within the number of children
   CVC4_API_CHECK(index < getNumChildren()) << "index out of bound";
+  CVC4_API_CHECK(!isApplyKind(d_node->getKind()) || d_node->hasOperator())
+      << "Expected apply kind to have operator when accessing child of Term";
+  //////// all checks before this line
 
   // special cases for apply kinds
   if (isApplyKind(d_node->getKind()))
   {
-    CVC4_API_CHECK(d_node->hasOperator())
-        << "Expected apply kind to have operator when accessing child of Term";
     if (index == 0)
     {
       // return the operator
-      return Term(d_solver, d_node->getOperator().toExpr());
+      return Term(d_solver, d_node->getOperator());
+    }
+    else
+    {
+      index -= 1;
     }
-    // otherwise we are looking up child at (index-1)
-    index--;
   }
-  return Term(d_solver, (*d_node)[index].toExpr());
+  // otherwise we are looking up child at (index-1)
+  return Term(d_solver, (*d_node)[index]);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 uint64_t Term::getId() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return d_node->getId();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Kind Term::getKind() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return getKindHelper();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Term::getSort() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
   NodeManagerScope scope(d_solver->getNodeManager());
+  //////// all checks before this line
   return Sort(d_solver, d_node->getType());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Term::substitute(Term e, Term replacement) const
+Term Term::substitute(const Term& term, const Term& replacement) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
-  CVC4_API_CHECK(!e.isNull())
-      << "Expected non-null term to replace in substitute";
-  CVC4_API_CHECK(!replacement.isNull())
-      << "Expected non-null term as replacement in substitute";
-  CVC4_API_CHECK(e.getSort().isComparableTo(replacement.getSort()))
+  CVC4_API_CHECK_TERM(term);
+  CVC4_API_CHECK_TERM(replacement);
+  CVC4_API_CHECK(term.getSort().isComparableTo(replacement.getSort()))
       << "Expecting terms of comparable sort in substitute";
-  return Term(d_solver,
-              d_node->substitute(TNode(*e.d_node), TNode(*replacement.d_node)));
+  //////// all checks before this line
+  return Term(
+      d_solver,
+      d_node->substitute(TNode(*term.d_node), TNode(*replacement.d_node)));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Term::substitute(const std::vector<Term> es,
+Term Term::substitute(const std::vector<Term>& terms,
                       const std::vector<Term>& replacements) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
-  CVC4_API_CHECK(es.size() == replacements.size())
+  CVC4_API_CHECK(terms.size() == replacements.size())
       << "Expecting vectors of the same arity in substitute";
-  for (unsigned i = 0, nterms = es.size(); i < nterms; i++)
-  {
-    CVC4_API_CHECK(!es[i].isNull())
-        << "Expected non-null term to replace in substitute";
-    CVC4_API_CHECK(!replacements[i].isNull())
-        << "Expected non-null term as replacement in substitute";
-    CVC4_API_CHECK(es[i].getSort().isComparableTo(replacements[i].getSort()))
-        << "Expecting terms of comparable sort in substitute";
-  }
-
-  std::vector<Node> nodes = termVectorToNodes(es);
-  std::vector<Node> nodeReplacements = termVectorToNodes(replacements);
+  CVC4_API_TERM_CHECK_TERMS_WITH_TERMS_COMPARABLE_TO(terms, replacements);
+  //////// all checks before this line
+  std::vector<Node> nodes = Term::termVectorToNodes(terms);
+  std::vector<Node> nodeReplacements = Term::termVectorToNodes(replacements);
   return Term(d_solver,
               d_node->substitute(nodes.begin(),
                                  nodes.end(),
                                  nodeReplacements.begin(),
                                  nodeReplacements.end()));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 bool Term::hasOp() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return d_node->hasOperator();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Op Term::getOp() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(d_node->hasOperator())
       << "Expecting Term to have an Op when calling getOp()";
+  //////// all checks before this line
 
   // special cases for parameterized operators that are not indexed operators
   // the API level differs from the internal structure
@@ -1814,32 +2251,47 @@ Op Term::getOp() const
   {
     // it's an indexed operator
     // so we should return the indexed op
-    CVC4::Node op = d_node->getOperator();
+    cvc5::Node op = d_node->getOperator();
     return Op(d_solver, intToExtKind(d_node->getKind()), op);
   }
   // Notice this is the only case where getKindHelper is used, since the
   // cases above do not have special cases for intToExtKind.
   return Op(d_solver, getKindHelper());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-bool Term::isNull() const { return isNullHelper(); }
+bool Term::isNull() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return isNullHelper();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
 Term Term::getConstArrayBase() const
 {
-  CVC4::ExprManagerScope exmgrs(*(d_solver->getExprManager()));
+  NodeManagerScope scope(d_solver->getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
   // CONST_ARRAY kind maps to STORE_ALL internal kind
-  CVC4_API_CHECK(d_node->getKind() == CVC4::Kind::STORE_ALL)
+  CVC4_API_CHECK(d_node->getKind() == cvc5::Kind::STORE_ALL)
       << "Expecting a CONST_ARRAY Term when calling getConstArrayBase()";
+  //////// all checks before this line
   return Term(d_solver, d_node->getConst<ArrayStoreAll>().getValue());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::vector<Term> Term::getConstSequenceElements() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
-  CVC4_API_CHECK(d_node->getKind() == CVC4::Kind::CONST_SEQUENCE)
+  CVC4_API_CHECK(d_node->getKind() == cvc5::Kind::CONST_SEQUENCE)
       << "Expecting a CONST_SEQUENCE Term when calling "
          "getConstSequenceElements()";
+  //////// all checks before this line
   const std::vector<Node>& elems = d_node->getConst<Sequence>().getVec();
   std::vector<Term> terms;
   for (const Node& t : elems)
@@ -1847,128 +2299,113 @@ std::vector<Term> Term::getConstSequenceElements() const
     terms.push_back(Term(d_solver, t));
   }
   return terms;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Term::notTerm() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
-  try
-  {
-    Node res = d_node->notNode();
-    (void)res.getType(true); /* kick off type checking */
-    return Term(d_solver, res);
-  }
-  catch (const CVC4::TypeCheckingExceptionPrivate& e)
-  {
-    throw CVC4ApiException(e.getMessage());
-  }
+  //////// all checks before this line
+  Node res = d_node->notNode();
+  (void)res.getType(true); /* kick off type checking */
+  return Term(d_solver, res);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Term::andTerm(const Term& t) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
-  CVC4_API_ARG_CHECK_NOT_NULL(t);
-  try
-  {
-    Node res = d_node->andNode(*t.d_node);
-    (void)res.getType(true); /* kick off type checking */
-    return Term(d_solver, res);
-  }
-  catch (const CVC4::TypeCheckingExceptionPrivate& e)
-  {
-    throw CVC4ApiException(e.getMessage());
-  }
+  CVC4_API_CHECK_TERM(t);
+  //////// all checks before this line
+  Node res = d_node->andNode(*t.d_node);
+  (void)res.getType(true); /* kick off type checking */
+  return Term(d_solver, res);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Term::orTerm(const Term& t) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
-  CVC4_API_ARG_CHECK_NOT_NULL(t);
-  try
-  {
-    Node res = d_node->orNode(*t.d_node);
-    (void)res.getType(true); /* kick off type checking */
-    return Term(d_solver, res);
-  }
-  catch (const CVC4::TypeCheckingExceptionPrivate& e)
-  {
-    throw CVC4ApiException(e.getMessage());
-  }
+  CVC4_API_CHECK_TERM(t);
+  //////// all checks before this line
+  Node res = d_node->orNode(*t.d_node);
+  (void)res.getType(true); /* kick off type checking */
+  return Term(d_solver, res);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Term::xorTerm(const Term& t) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
-  CVC4_API_ARG_CHECK_NOT_NULL(t);
-  try
-  {
-    Node res = d_node->xorNode(*t.d_node);
-    (void)res.getType(true); /* kick off type checking */
-    return Term(d_solver, res);
-  }
-  catch (const CVC4::TypeCheckingExceptionPrivate& e)
-  {
-    throw CVC4ApiException(e.getMessage());
-  }
+  CVC4_API_CHECK_TERM(t);
+  //////// all checks before this line
+  Node res = d_node->xorNode(*t.d_node);
+  (void)res.getType(true); /* kick off type checking */
+  return Term(d_solver, res);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Term::eqTerm(const Term& t) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
-  CVC4_API_ARG_CHECK_NOT_NULL(t);
-  try
-  {
-    Node res = d_node->eqNode(*t.d_node);
-    (void)res.getType(true); /* kick off type checking */
-    return Term(d_solver, res);
-  }
-  catch (const CVC4::TypeCheckingExceptionPrivate& e)
-  {
-    throw CVC4ApiException(e.getMessage());
-  }
+  CVC4_API_CHECK_TERM(t);
+  //////// all checks before this line
+  Node res = d_node->eqNode(*t.d_node);
+  (void)res.getType(true); /* kick off type checking */
+  return Term(d_solver, res);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Term::impTerm(const Term& t) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
-  CVC4_API_ARG_CHECK_NOT_NULL(t);
-  try
-  {
-    Node res = d_node->impNode(*t.d_node);
-    (void)res.getType(true); /* kick off type checking */
-    return Term(d_solver, res);
-  }
-  catch (const CVC4::TypeCheckingExceptionPrivate& e)
-  {
-    throw CVC4ApiException(e.getMessage());
-  }
+  CVC4_API_CHECK_TERM(t);
+  //////// all checks before this line
+  Node res = d_node->impNode(*t.d_node);
+  (void)res.getType(true); /* kick off type checking */
+  return Term(d_solver, res);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Term::iteTerm(const Term& then_t, const Term& else_t) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
-  CVC4_API_ARG_CHECK_NOT_NULL(then_t);
-  CVC4_API_ARG_CHECK_NOT_NULL(else_t);
-  try
-  {
-    Node res = d_node->iteNode(*then_t.d_node, *else_t.d_node);
-    (void)res.getType(true); /* kick off type checking */
-    return Term(d_solver, res);
-  }
-  catch (const CVC4::TypeCheckingExceptionPrivate& e)
-  {
-    throw CVC4ApiException(e.getMessage());
-  }
+  CVC4_API_CHECK_TERM(then_t);
+  CVC4_API_CHECK_TERM(else_t);
+  //////// all checks before this line
+  Node res = d_node->iteNode(*then_t.d_node, *else_t.d_node);
+  (void)res.getType(true); /* kick off type checking */
+  return Term(d_solver, res);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::string Term::toString() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   if (d_solver != nullptr)
   {
     NodeManagerScope scope(d_solver->getNodeManager());
     return d_node->toString();
   }
   return d_node->toString();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term::const_iterator::const_iterator()
@@ -1977,7 +2414,7 @@ Term::const_iterator::const_iterator()
 }
 
 Term::const_iterator::const_iterator(const Solver* slv,
-                                     const std::shared_ptr<CVC4::Node>& n,
+                                     const std::shared_ptr<cvc5::Node>& n,
                                      uint32_t p)
     : d_solver(slv), d_origNode(n), d_pos(p)
 {
@@ -2078,28 +2515,14 @@ Term::const_iterator Term::end() const
   return Term::const_iterator(d_solver, d_node, endpos);
 }
 
-// !!! This is only temporarily available until the parser is fully migrated
-// to the new API. !!!
-CVC4::Expr Term::getExpr(void) const
-{
-  if (d_node->isNull())
-  {
-    return Expr();
-  }
-  NodeManagerScope scope(d_solver->getNodeManager());
-  return d_node->toExpr();
-}
-
-// !!! This is only temporarily available until the parser is fully migrated
-// to the new API. !!!
-const CVC4::Node& Term::getNode(void) const { return *d_node; }
+const cvc5::Node& Term::getNode(void) const { return *d_node; }
 
 namespace detail {
-const Rational& getRational(const CVC4::Node& node)
+const Rational& getRational(const cvc5::Node& node)
 {
   return node.getConst<Rational>();
 }
-Integer getInteger(const CVC4::Node& node)
+Integer getInteger(const cvc5::Node& node)
 {
   return node.getConst<Rational>().getNumerator();
 }
@@ -2122,7 +2545,7 @@ bool checkReal64Bounds(const Rational& r)
 
 bool isInteger(const Node& node)
 {
-  return node.getKind() == CVC4::Kind::CONST_RATIONAL
+  return node.getKind() == cvc5::Kind::CONST_RATIONAL
          && node.getConst<Rational>().isIntegral();
 }
 bool isInt32(const Node& node)
@@ -2147,51 +2570,119 @@ bool isUInt64(const Node& node)
 }
 }  // namespace detail
 
-bool Term::isInt32() const { return detail::isInt32(*d_node); }
+bool Term::isInt32() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return detail::isInt32(*d_node);
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
+
 std::int32_t Term::getInt32() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(detail::isInt32(*d_node))
       << "Term should be a Int32 when calling getInt32()";
+  //////// all checks before this line
   return detail::getInteger(*d_node).getSignedInt();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
+
 bool Term::isUInt32() const { return detail::isUInt32(*d_node); }
 std::uint32_t Term::getUInt32() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(detail::isUInt32(*d_node))
       << "Term should be a UInt32 when calling getUInt32()";
+  //////// all checks before this line
   return detail::getInteger(*d_node).getUnsignedInt();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
+
 bool Term::isInt64() const { return detail::isInt64(*d_node); }
 std::int64_t Term::getInt64() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(detail::isInt64(*d_node))
       << "Term should be a Int64 when calling getInt64()";
+  //////// all checks before this line
   return detail::getInteger(*d_node).getLong();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
-bool Term::isUInt64() const { return detail::isUInt64(*d_node); }
+
+bool Term::isUInt64() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return detail::isUInt64(*d_node);
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
+
 std::uint64_t Term::getUInt64() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(detail::isUInt64(*d_node))
       << "Term should be a UInt64 when calling getUInt64()";
+  //////// all checks before this line
   return detail::getInteger(*d_node).getUnsignedLong();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
+
 bool Term::isInteger() const { return detail::isInteger(*d_node); }
 std::string Term::getInteger() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(detail::isInteger(*d_node))
       << "Term should be an Int when calling getIntString()";
+  //////// all checks before this line
   return detail::getInteger(*d_node).toString();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 bool Term::isString() const
 {
-  return d_node->getKind() == CVC4::Kind::CONST_STRING;
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return d_node->getKind() == cvc5::Kind::CONST_STRING;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
+
 std::wstring Term::getString() const
 {
-  CVC4_API_CHECK(d_node->getKind() == CVC4::Kind::CONST_STRING)
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  CVC4_API_CHECK(d_node->getKind() == cvc5::Kind::CONST_STRING)
       << "Term should be a String when calling getString()";
-  return d_node->getConst<CVC4::String>().toWString();
+  //////// all checks before this line
+  return d_node->getConst<cvc5::String>().toWString();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
+
+std::vector<Node> Term::termVectorToNodes(const std::vector<Term>& terms)
+{
+  std::vector<Node> res;
+  for (const Term& t : terms)
+  {
+    res.push_back(t.getNode());
+  }
+  return res;
 }
 
 std::ostream& operator<<(std::ostream& out, const Term& t)
@@ -2241,6 +2732,63 @@ size_t TermHashFunction::operator()(const Term& t) const
   return NodeHashFunction()(*t.d_node);
 }
 
+/* Helpers                                                                    */
+/* -------------------------------------------------------------------------- */
+
+/* Split out to avoid nested API calls (problematic with API tracing).        */
+/* .......................................................................... */
+
+bool Term::isNullHelper() const
+{
+  /* Split out to avoid nested API calls (problematic with API tracing). */
+  return d_node->isNull();
+}
+
+Kind Term::getKindHelper() const
+{
+  /* Sequence kinds do not exist internally, so we must convert their internal
+   * (string) versions back to sequence. All operators where this is
+   * necessary are such that their first child is of sequence type, which
+   * we check here. */
+  if (d_node->getNumChildren() > 0 && (*d_node)[0].getType().isSequence())
+  {
+    switch (d_node->getKind())
+    {
+      case cvc5::Kind::STRING_CONCAT: return SEQ_CONCAT;
+      case cvc5::Kind::STRING_LENGTH: return SEQ_LENGTH;
+      case cvc5::Kind::STRING_SUBSTR: return SEQ_EXTRACT;
+      case cvc5::Kind::STRING_UPDATE: return SEQ_UPDATE;
+      case cvc5::Kind::STRING_CHARAT: return SEQ_AT;
+      case cvc5::Kind::STRING_STRCTN: return SEQ_CONTAINS;
+      case cvc5::Kind::STRING_STRIDOF: return SEQ_INDEXOF;
+      case cvc5::Kind::STRING_STRREPL: return SEQ_REPLACE;
+      case cvc5::Kind::STRING_STRREPLALL: return SEQ_REPLACE_ALL;
+      case cvc5::Kind::STRING_REV: return SEQ_REV;
+      case cvc5::Kind::STRING_PREFIX: return SEQ_PREFIX;
+      case cvc5::Kind::STRING_SUFFIX: return SEQ_SUFFIX;
+      default:
+        // fall through to conversion below
+        break;
+    }
+  }
+  // Notice that kinds like APPLY_TYPE_ASCRIPTION will be converted to
+  // INTERNAL_KIND.
+  if (isCastedReal())
+  {
+    return CONST_RATIONAL;
+  }
+  return intToExtKind(d_node->getKind());
+}
+
+bool Term::isCastedReal() const
+{
+  if (d_node->getKind() == kind::CAST_TO_REAL)
+  {
+    return (*d_node)[0].isConst() && (*d_node)[0].getType().isInteger();
+  }
+  return false;
+}
+
 /* -------------------------------------------------------------------------- */
 /* Datatypes                                                                  */
 /* -------------------------------------------------------------------------- */
@@ -2254,7 +2802,7 @@ DatatypeConstructorDecl::DatatypeConstructorDecl()
 
 DatatypeConstructorDecl::DatatypeConstructorDecl(const Solver* slv,
                                                  const std::string& name)
-    : d_solver(slv), d_ctor(new CVC4::DTypeConstructor(name))
+    : d_solver(slv), d_ctor(new cvc5::DTypeConstructor(name))
 {
 }
 DatatypeConstructorDecl::~DatatypeConstructorDecl()
@@ -2267,33 +2815,50 @@ DatatypeConstructorDecl::~DatatypeConstructorDecl()
   }
 }
 
-void DatatypeConstructorDecl::addSelector(const std::string& name, Sort sort)
+void DatatypeConstructorDecl::addSelector(const std::string& name,
+                                          const Sort& sort)
 {
   NodeManagerScope scope(d_solver->getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  CVC4_API_CHECK_SORT(sort);
   CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort)
       << "non-null range sort for selector";
+  //////// all checks before this line
   d_ctor->addArg(name, *sort.d_type);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 void DatatypeConstructorDecl::addSelectorSelf(const std::string& name)
 {
   NodeManagerScope scope(d_solver->getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   d_ctor->addArgSelf(name);
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
+
+bool DatatypeConstructorDecl::isNull() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return isNullHelper();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::string DatatypeConstructorDecl::toString() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   std::stringstream ss;
   ss << *d_ctor;
   return ss.str();
-}
-
-// !!! This is only temporarily available until the parser is fully migrated
-// to the new API. !!!
-const CVC4::DTypeConstructor& DatatypeConstructorDecl::getDatatypeConstructor(
-    void) const
-{
-  return *d_ctor;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::ostream& operator<<(std::ostream& out,
@@ -2310,6 +2875,8 @@ std::ostream& operator<<(std::ostream& out,
   return out;
 }
 
+bool DatatypeConstructorDecl::isNullHelper() const { return d_ctor == nullptr; }
+
 /* DatatypeDecl ------------------------------------------------------------- */
 
 DatatypeDecl::DatatypeDecl() : d_solver(nullptr), d_dtype(nullptr) {}
@@ -2317,16 +2884,16 @@ DatatypeDecl::DatatypeDecl() : d_solver(nullptr), d_dtype(nullptr) {}
 DatatypeDecl::DatatypeDecl(const Solver* slv,
                            const std::string& name,
                            bool isCoDatatype)
-    : d_solver(slv), d_dtype(new CVC4::DType(name, isCoDatatype))
+    : d_solver(slv), d_dtype(new cvc5::DType(name, isCoDatatype))
 {
 }
 
 DatatypeDecl::DatatypeDecl(const Solver* slv,
                            const std::string& name,
-                           Sort param,
+                           const Sort& param,
                            bool isCoDatatype)
     : d_solver(slv),
-      d_dtype(new CVC4::DType(
+      d_dtype(new cvc5::DType(
           name, std::vector<TypeNode>{*param.d_type}, isCoDatatype))
 {
 }
@@ -2337,9 +2904,9 @@ DatatypeDecl::DatatypeDecl(const Solver* slv,
                            bool isCoDatatype)
     : d_solver(slv)
 {
-  std::vector<TypeNode> tparams = sortVectorToTypeNodes(params);
-  d_dtype = std::shared_ptr<CVC4::DType>(
-      new CVC4::DType(name, tparams, isCoDatatype));
+  std::vector<TypeNode> tparams = Sort::sortVectorToTypeNodes(params);
+  d_dtype = std::shared_ptr<cvc5::DType>(
+      new cvc5::DType(name, tparams, isCoDatatype));
 }
 
 bool DatatypeDecl::isNullHelper() const { return !d_dtype; }
@@ -2357,41 +2924,66 @@ DatatypeDecl::~DatatypeDecl()
 void DatatypeDecl::addConstructor(const DatatypeConstructorDecl& ctor)
 {
   NodeManagerScope scope(d_solver->getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
+  CVC4_API_ARG_CHECK_NOT_NULL(ctor);
+  CVC4_API_ARG_CHECK_SOLVER("datatype constructor declaration", ctor);
+  //////// all checks before this line
   d_dtype->addConstructor(ctor.d_ctor);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 size_t DatatypeDecl::getNumConstructors() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return d_dtype->getNumConstructors();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 bool DatatypeDecl::isParametric() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return d_dtype->isParametric();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::string DatatypeDecl::toString() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   std::stringstream ss;
   ss << *d_dtype;
   return ss.str();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::string DatatypeDecl::getName() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return d_dtype->getName();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-bool DatatypeDecl::isNull() const { return isNullHelper(); }
-
-// !!! This is only temporarily available until the parser is fully migrated
-// to the new API. !!!
-CVC4::DType& DatatypeDecl::getDatatype(void) const { return *d_dtype; }
+bool DatatypeDecl::isNull() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return isNullHelper();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
 std::ostream& operator<<(std::ostream& out, const DatatypeDecl& dtdecl)
 {
@@ -2399,13 +2991,15 @@ std::ostream& operator<<(std::ostream& out, const DatatypeDecl& dtdecl)
   return out;
 }
 
+cvc5::DType& DatatypeDecl::getDatatype(void) const { return *d_dtype; }
+
 /* DatatypeSelector --------------------------------------------------------- */
 
 DatatypeSelector::DatatypeSelector() : d_solver(nullptr), d_stor(nullptr) {}
 
 DatatypeSelector::DatatypeSelector(const Solver* slv,
-                                   const CVC4::DTypeSelector& stor)
-    : d_solver(slv), d_stor(new CVC4::DTypeSelector(stor))
+                                   const cvc5::DTypeSelector& stor)
+    : d_solver(slv), d_stor(new cvc5::DTypeSelector(stor))
 {
   CVC4_API_CHECK(d_stor->isResolved()) << "Expected resolved datatype selector";
 }
@@ -2420,31 +3014,54 @@ DatatypeSelector::~DatatypeSelector()
   }
 }
 
-std::string DatatypeSelector::getName() const { return d_stor->getName(); }
+std::string DatatypeSelector::getName() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return d_stor->getName();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
 Term DatatypeSelector::getSelectorTerm() const
 {
-  Term sel = Term(d_solver, d_stor->getSelector());
-  return sel;
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return Term(d_solver, d_stor->getSelector());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort DatatypeSelector::getRangeSort() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return Sort(d_solver, d_stor->getRangeType());
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
+
+bool DatatypeSelector::isNull() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return isNullHelper();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::string DatatypeSelector::toString() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   std::stringstream ss;
   ss << *d_stor;
   return ss.str();
-}
-
-// !!! This is only temporarily available until the parser is fully migrated
-// to the new API. !!!
-CVC4::DTypeSelector DatatypeSelector::getDatatypeConstructorArg(void) const
-{
-  return *d_stor;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::ostream& operator<<(std::ostream& out, const DatatypeSelector& stor)
@@ -2453,6 +3070,8 @@ std::ostream& operator<<(std::ostream& out, const DatatypeSelector& stor)
   return out;
 }
 
+bool DatatypeSelector::isNullHelper() const { return d_stor == nullptr; }
+
 /* DatatypeConstructor ------------------------------------------------------ */
 
 DatatypeConstructor::DatatypeConstructor() : d_solver(nullptr), d_ctor(nullptr)
@@ -2460,8 +3079,8 @@ DatatypeConstructor::DatatypeConstructor() : d_solver(nullptr), d_ctor(nullptr)
 }
 
 DatatypeConstructor::DatatypeConstructor(const Solver* slv,
-                                         const CVC4::DTypeConstructor& ctor)
-    : d_solver(slv), d_ctor(new CVC4::DTypeConstructor(ctor))
+                                         const cvc5::DTypeConstructor& ctor)
+    : d_solver(slv), d_ctor(new cvc5::DTypeConstructor(ctor))
 {
   CVC4_API_CHECK(d_ctor->isResolved())
       << "Expected resolved datatype constructor";
@@ -2477,23 +3096,38 @@ DatatypeConstructor::~DatatypeConstructor()
   }
 }
 
-std::string DatatypeConstructor::getName() const { return d_ctor->getName(); }
+std::string DatatypeConstructor::getName() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return d_ctor->getName();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
 Term DatatypeConstructor::getConstructorTerm() const
 {
-  Term ctor = Term(d_solver, d_ctor->getConstructor());
-  return ctor;
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return Term(d_solver, d_ctor->getConstructor());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term DatatypeConstructor::getSpecializedConstructorTerm(Sort retSort) const
+Term DatatypeConstructor::getSpecializedConstructorTerm(
+    const Sort& retSort) const
 {
   NodeManagerScope scope(d_solver->getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(d_ctor->isResolved())
       << "Expected resolved datatype constructor";
   CVC4_API_CHECK(retSort.isDatatype())
       << "Cannot get specialized constructor type for non-datatype type "
       << retSort;
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  //////// all checks before this line
 
   NodeManager* nm = d_solver->getNodeManager();
   Node ret =
@@ -2505,40 +3139,68 @@ Term DatatypeConstructor::getSpecializedConstructorTerm(Sort retSort) const
   // apply type ascription to the operator
   Term sctor = api::Term(d_solver, ret);
   return sctor;
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term DatatypeConstructor::getTesterTerm() const
 {
-  Term tst = Term(d_solver, d_ctor->getTester());
-  return tst;
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return Term(d_solver, d_ctor->getTester());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 size_t DatatypeConstructor::getNumSelectors() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return d_ctor->getNumArgs();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 DatatypeSelector DatatypeConstructor::operator[](size_t index) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return DatatypeSelector(d_solver, (*d_ctor)[index]);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 DatatypeSelector DatatypeConstructor::operator[](const std::string& name) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return getSelectorForName(name);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 DatatypeSelector DatatypeConstructor::getSelector(const std::string& name) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return getSelectorForName(name);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term DatatypeConstructor::getSelectorTerm(const std::string& name) const
 {
-  DatatypeSelector sel = getSelector(name);
-  return sel.getSelectorTerm();
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return getSelector(name).getSelectorTerm();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 DatatypeConstructor::const_iterator DatatypeConstructor::begin() const
@@ -2552,14 +3214,14 @@ DatatypeConstructor::const_iterator DatatypeConstructor::end() const
 }
 
 DatatypeConstructor::const_iterator::const_iterator(
-    const Solver* slv, const CVC4::DTypeConstructor& ctor, bool begin)
+    const Solver* slv, const cvc5::DTypeConstructor& ctor, bool begin)
 {
   d_solver = slv;
   d_int_stors = &ctor.getArgs();
 
-  const std::vector<std::shared_ptr<CVC4::DTypeSelector>>& sels =
+  const std::vector<std::shared_ptr<cvc5::DTypeSelector>>& sels =
       ctor.getArgs();
-  for (const std::shared_ptr<CVC4::DTypeSelector>& s : sels)
+  for (const std::shared_ptr<cvc5::DTypeSelector>& s : sels)
   {
     /* Can not use emplace_back here since constructor is private. */
     d_stors.push_back(DatatypeSelector(d_solver, *s.get()));
@@ -2620,20 +3282,27 @@ bool DatatypeConstructor::const_iterator::operator!=(
   return d_int_stors != other.d_int_stors || d_idx != other.d_idx;
 }
 
+bool DatatypeConstructor::isNull() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return isNullHelper();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
+
 std::string DatatypeConstructor::toString() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   std::stringstream ss;
   ss << *d_ctor;
   return ss.str();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-// !!! This is only temporarily available until the parser is fully migrated
-// to the new API. !!!
-const CVC4::DTypeConstructor& DatatypeConstructor::getDatatypeConstructor(
-    void) const
-{
-  return *d_ctor;
-}
+bool DatatypeConstructor::isNullHelper() const { return d_ctor == nullptr; }
 
 DatatypeSelector DatatypeConstructor::getSelectorForName(
     const std::string& name) const
@@ -2672,8 +3341,8 @@ std::ostream& operator<<(std::ostream& out, const DatatypeConstructor& ctor)
 
 /* Datatype ----------------------------------------------------------------- */
 
-Datatype::Datatype(const Solver* slv, const CVC4::DType& dtype)
-    : d_solver(slv), d_dtype(new CVC4::DType(dtype))
+Datatype::Datatype(const Solver* slv, const cvc5::DType& dtype)
+    : d_solver(slv), d_dtype(new cvc5::DType(dtype))
 {
   CVC4_API_CHECK(d_dtype->isResolved()) << "Expected resolved datatype";
 }
@@ -2692,48 +3361,153 @@ Datatype::~Datatype()
 
 DatatypeConstructor Datatype::operator[](size_t idx) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
   CVC4_API_CHECK(idx < getNumConstructors()) << "Index out of bounds.";
+  //////// all checks before this line
   return DatatypeConstructor(d_solver, (*d_dtype)[idx]);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 DatatypeConstructor Datatype::operator[](const std::string& name) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return getConstructorForName(name);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 DatatypeConstructor Datatype::getConstructor(const std::string& name) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return getConstructorForName(name);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Datatype::getConstructorTerm(const std::string& name) const
 {
-  DatatypeConstructor ctor = getConstructor(name);
-  return ctor.getConstructorTerm();
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return getConstructor(name).getConstructorTerm();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-std::string Datatype::getName() const { return d_dtype->getName(); }
+std::string Datatype::getName() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return d_dtype->getName();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
 size_t Datatype::getNumConstructors() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return d_dtype->getNumConstructors();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
+
+bool Datatype::isParametric() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return d_dtype->isParametric();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
+
+bool Datatype::isCodatatype() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return d_dtype->isCodatatype();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-bool Datatype::isParametric() const { return d_dtype->isParametric(); }
-bool Datatype::isCodatatype() const { return d_dtype->isCodatatype(); }
+bool Datatype::isTuple() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return d_dtype->isTuple();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Datatype::isTuple() const { return d_dtype->isTuple(); }
+bool Datatype::isRecord() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return d_dtype->isRecord();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Datatype::isRecord() const { return d_dtype->isRecord(); }
+bool Datatype::isFinite() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return d_dtype->isFinite();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-bool Datatype::isFinite() const { return d_dtype->isFinite(); }
-bool Datatype::isWellFounded() const { return d_dtype->isWellFounded(); }
+bool Datatype::isWellFounded() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return d_dtype->isWellFounded();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 bool Datatype::hasNestedRecursion() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
   return d_dtype->hasNestedRecursion();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
+
+bool Datatype::isNull() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return isNullHelper();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-std::string Datatype::toString() const { return d_dtype->getName(); }
+std::string Datatype::toString() const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_NOT_NULL;
+  //////// all checks before this line
+  return d_dtype->getName();
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
 Datatype::const_iterator Datatype::begin() const
 {
@@ -2745,10 +3519,6 @@ Datatype::const_iterator Datatype::end() const
   return Datatype::const_iterator(d_solver, *d_dtype, false);
 }
 
-// !!! This is only temporarily available until the parser is fully migrated
-// to the new API. !!!
-const CVC4::DType& Datatype::getDatatype(void) const { return *d_dtype; }
-
 DatatypeConstructor Datatype::getConstructorForName(
     const std::string& name) const
 {
@@ -2779,7 +3549,7 @@ DatatypeConstructor Datatype::getConstructorForName(
 }
 
 Datatype::const_iterator::const_iterator(const Solver* slv,
-                                         const CVC4::DType& dtype,
+                                         const cvc5::DType& dtype,
                                          bool begin)
     : d_solver(slv), d_int_ctors(&dtype.getConstructors())
 {
@@ -2843,6 +3613,8 @@ bool Datatype::const_iterator::operator!=(
   return d_int_ctors != other.d_int_ctors || d_idx != other.d_idx;
 }
 
+bool Datatype::isNullHelper() const { return d_dtype == nullptr; }
+
 /* -------------------------------------------------------------------------- */
 /* Grammar                                                                    */
 /* -------------------------------------------------------------------------- */
@@ -2875,70 +3647,83 @@ Grammar::Grammar(const Solver* slv,
   }
 }
 
-void Grammar::addRule(Term ntSymbol, Term rule)
+void Grammar::addRule(const Term& ntSymbol, const Term& rule)
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(!d_isResolved) << "Grammar cannot be modified after passing "
                                    "it as an argument to synthFun/synthInv";
-  CVC4_API_ARG_CHECK_NOT_NULL(ntSymbol);
-  CVC4_API_ARG_CHECK_NOT_NULL(rule);
+  CVC4_API_CHECK_TERM(ntSymbol);
+  CVC4_API_CHECK_TERM(rule);
   CVC4_API_ARG_CHECK_EXPECTED(
       d_ntsToTerms.find(ntSymbol) != d_ntsToTerms.cend(), ntSymbol)
       << "ntSymbol to be one of the non-terminal symbols given in the "
          "predeclaration";
   CVC4_API_CHECK(ntSymbol.d_node->getType() == rule.d_node->getType())
       << "Expected ntSymbol and rule to have the same sort";
-
+  CVC4_API_ARG_CHECK_EXPECTED(!containsFreeVariables(rule), rule)
+      << "a term whose free variables are limited to synthFun/synthInv "
+         "parameters and non-terminal symbols of the grammar";
+  //////// all checks before this line
   d_ntsToTerms[ntSymbol].push_back(rule);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-void Grammar::addRules(Term ntSymbol, std::vector<Term> rules)
+void Grammar::addRules(const Term& ntSymbol, const std::vector<Term>& rules)
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(!d_isResolved) << "Grammar cannot be modified after passing "
                                    "it as an argument to synthFun/synthInv";
-  CVC4_API_ARG_CHECK_NOT_NULL(ntSymbol);
+  CVC4_API_CHECK_TERM(ntSymbol);
+  CVC4_API_CHECK_TERMS_WITH_SORT(rules, ntSymbol.getSort());
   CVC4_API_ARG_CHECK_EXPECTED(
       d_ntsToTerms.find(ntSymbol) != d_ntsToTerms.cend(), ntSymbol)
       << "ntSymbol to be one of the non-terminal symbols given in the "
          "predeclaration";
-
   for (size_t i = 0, n = rules.size(); i < n; ++i)
   {
     CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        !rules[i].isNull(), "parameter rule", rules[i], i)
-        << "non-null term";
-    CVC4_API_CHECK(ntSymbol.d_node->getType() == rules[i].d_node->getType())
-        << "Expected ntSymbol and rule at index " << i
-        << " to have the same sort";
+        !containsFreeVariables(rules[i]), rules[i], rules, i)
+        << "a term whose free variables are limited to synthFun/synthInv "
+           "parameters and non-terminal symbols of the grammar";
   }
-
+  //////// all checks before this line
   d_ntsToTerms[ntSymbol].insert(
       d_ntsToTerms[ntSymbol].cend(), rules.cbegin(), rules.cend());
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-void Grammar::addAnyConstant(Term ntSymbol)
+void Grammar::addAnyConstant(const Term& ntSymbol)
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(!d_isResolved) << "Grammar cannot be modified after passing "
                                    "it as an argument to synthFun/synthInv";
-  CVC4_API_ARG_CHECK_NOT_NULL(ntSymbol);
+  CVC4_API_CHECK_TERM(ntSymbol);
   CVC4_API_ARG_CHECK_EXPECTED(
       d_ntsToTerms.find(ntSymbol) != d_ntsToTerms.cend(), ntSymbol)
       << "ntSymbol to be one of the non-terminal symbols given in the "
          "predeclaration";
-
+  //////// all checks before this line
   d_allowConst.insert(ntSymbol);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-void Grammar::addAnyVariable(Term ntSymbol)
+void Grammar::addAnyVariable(const Term& ntSymbol)
 {
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(!d_isResolved) << "Grammar cannot be modified after passing "
                                    "it as an argument to synthFun/synthInv";
-  CVC4_API_ARG_CHECK_NOT_NULL(ntSymbol);
+  CVC4_API_CHECK_TERM(ntSymbol);
   CVC4_API_ARG_CHECK_EXPECTED(
       d_ntsToTerms.find(ntSymbol) != d_ntsToTerms.cend(), ntSymbol)
       << "ntSymbol to be one of the non-terminal symbols given in the "
          "predeclaration";
-
+  //////// all checks before this line
   d_allowVars.insert(ntSymbol);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -2973,6 +3758,8 @@ std::string join(Iterator first, Iterator last, Function f, std::string sep)
 
 std::string Grammar::toString() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   std::stringstream ss;
   ss << "  ("  // pre-declaration
      << join(
@@ -3011,19 +3798,25 @@ std::string Grammar::toString() const
      << ')';
 
   return ss.str();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Grammar::resolve()
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+
   d_isResolved = true;
 
   Term bvl;
 
   if (!d_sygusVars.empty())
   {
-    bvl = Term(d_solver,
-               d_solver->getExprManager()->mkExpr(
-                   CVC4::kind::BOUND_VAR_LIST, termVectorToExprs(d_sygusVars)));
+    bvl = Term(
+        d_solver,
+        d_solver->getNodeManager()->mkNode(
+            cvc5::kind::BOUND_VAR_LIST, Term::termVectorToNodes(d_sygusVars)));
   }
 
   std::unordered_map<Term, Sort, TermHashFunction> ntsToUnres(d_ntSyms.size());
@@ -3036,7 +3829,7 @@ Sort Grammar::resolve()
         Sort(d_solver, d_solver->getNodeManager()->mkSort(ntsymbol.toString()));
   }
 
-  std::vector<CVC4::DType> datatypes;
+  std::vector<cvc5::DType> datatypes;
   std::set<TypeNode> unresTypes;
 
   datatypes.reserve(d_ntSyms.size());
@@ -3078,13 +3871,21 @@ Sort Grammar::resolve()
 
   // return is the first datatype
   return Sort(d_solver, datatypeTypes[0]);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 void Grammar::addSygusConstructorTerm(
     DatatypeDecl& dt,
-    Term term,
+    const Term& term,
     const std::unordered_map<Term, Sort, TermHashFunction>& ntsToUnres) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_DTDECL(dt);
+  CVC4_API_CHECK_TERM(term);
+  CVC4_API_CHECK_TERMS_MAP(ntsToUnres);
+  //////// all checks before this line
+
   // At this point, we should know that dt is well founded, and that its
   // builtin sygus operators are well-typed.
   // Now, purify each occurrence of a non-terminal symbol in term, replace by
@@ -3100,25 +3901,34 @@ void Grammar::addSygusConstructorTerm(
   ssCName << op.getKind();
   if (!args.empty())
   {
-    Term lbvl = Term(d_solver,
-                     d_solver->getExprManager()->mkExpr(
-                         CVC4::kind::BOUND_VAR_LIST, termVectorToExprs(args)));
+    Term lbvl =
+        Term(d_solver,
+             d_solver->getNodeManager()->mkNode(cvc5::kind::BOUND_VAR_LIST,
+                                                Term::termVectorToNodes(args)));
     // its operator is a lambda
-    op = Term(
-        d_solver,
-        d_solver->getExprManager()->mkExpr(
-            CVC4::kind::LAMBDA, {lbvl.d_node->toExpr(), op.d_node->toExpr()}));
+    op = Term(d_solver,
+              d_solver->getNodeManager()->mkNode(
+                  cvc5::kind::LAMBDA, *lbvl.d_node, *op.d_node));
   }
-  std::vector<TypeNode> cargst = sortVectorToTypeNodes(cargs);
+  std::vector<TypeNode> cargst = Sort::sortVectorToTypeNodes(cargs);
   dt.d_dtype->addSygusConstructor(*op.d_node, ssCName.str(), cargst);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Grammar::purifySygusGTerm(
-    Term term,
+    const Term& term,
     std::vector<Term>& args,
     std::vector<Sort>& cargs,
     const std::unordered_map<Term, Sort, TermHashFunction>& ntsToUnres) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_TERM(term);
+  CVC4_API_CHECK_TERMS(args);
+  CVC4_API_CHECK_SORTS(cargs);
+  CVC4_API_CHECK_TERMS_MAP(ntsToUnres);
+  //////// all checks before this line
+
   std::unordered_map<Term, Sort, TermHashFunction>::const_iterator itn =
       ntsToUnres.find(term);
   if (itn != ntsToUnres.cend())
@@ -3137,8 +3947,7 @@ Term Grammar::purifySygusGTerm(
     Term ptermc = purifySygusGTerm(
         Term(d_solver, (*term.d_node)[i]), args, cargs, ntsToUnres);
     pchildren.push_back(ptermc);
-    childChanged =
-        childChanged || ptermc.d_node->toExpr() != (term.d_node->toExpr())[i];
+    childChanged = childChanged || *ptermc.d_node != (*term.d_node)[i];
   }
   if (!childChanged)
   {
@@ -3152,21 +3961,28 @@ Term Grammar::purifySygusGTerm(
     // it's an indexed operator so we should provide the op
     NodeBuilder<> nb(term.d_node->getKind());
     nb << term.d_node->getOperator();
-    nb.append(termVectorToNodes(pchildren));
+    nb.append(Term::termVectorToNodes(pchildren));
     nret = nb.constructNode();
   }
   else
   {
-    nret = d_solver->getNodeManager()->mkNode(term.d_node->getKind(),
-                                              termVectorToNodes(pchildren));
+    nret = d_solver->getNodeManager()->mkNode(
+        term.d_node->getKind(), Term::termVectorToNodes(pchildren));
   }
 
   return Term(d_solver, nret);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-void Grammar::addSygusConstructorVariables(DatatypeDecl& dt, Sort sort) const
+void Grammar::addSygusConstructorVariables(DatatypeDecl& dt,
+                                           const Sort& sort) const
 {
-  Assert(!sort.isNull());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK_DTDECL(dt);
+  CVC4_API_CHECK_SORT(sort);
+  //////// all checks before this line
+
   // each variable of appropriate type becomes a sygus constructor in dt.
   for (unsigned i = 0, size = d_sygusVars.size(); i < size; i++)
   {
@@ -3179,11 +3995,31 @@ void Grammar::addSygusConstructorVariables(DatatypeDecl& dt, Sort sort) const
       dt.d_dtype->addSygusConstructor(*v.d_node, ss.str(), cargs);
     }
   }
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
+
+bool Grammar::containsFreeVariables(const Term& rule) const
+{
+  std::unordered_set<TNode, TNodeHashFunction> scope;
+
+  for (const Term& sygusVar : d_sygusVars)
+  {
+    scope.emplace(*sygusVar.d_node);
+  }
+
+  for (const Term& ntsymbol : d_ntSyms)
+  {
+    scope.emplace(*ntsymbol.d_node);
+  }
+
+  std::unordered_set<Node, NodeHashFunction> fvs;
+  return expr::getFreeVariablesScope(*rule.d_node, fvs, scope, false);
 }
 
-std::ostream& operator<<(std::ostream& out, const Grammar& g)
+std::ostream& operator<<(std::ostream& out, const Grammar& grammar)
 {
-  return out << g.toString();
+  return out << grammar.toString();
 }
 
 /* -------------------------------------------------------------------------- */
@@ -3191,27 +4027,27 @@ std::ostream& operator<<(std::ostream& out, const Grammar& g)
 /* -------------------------------------------------------------------------- */
 
 const static std::
-    unordered_map<RoundingMode, CVC4::RoundingMode, RoundingModeHashFunction>
+    unordered_map<RoundingMode, cvc5::RoundingMode, RoundingModeHashFunction>
         s_rmodes{
             {ROUND_NEAREST_TIES_TO_EVEN,
-             CVC4::RoundingMode::ROUND_NEAREST_TIES_TO_EVEN},
-            {ROUND_TOWARD_POSITIVE, CVC4::RoundingMode::ROUND_TOWARD_POSITIVE},
-            {ROUND_TOWARD_NEGATIVE, CVC4::RoundingMode::ROUND_TOWARD_NEGATIVE},
-            {ROUND_TOWARD_ZERO, CVC4::RoundingMode::ROUND_TOWARD_ZERO},
+             cvc5::RoundingMode::ROUND_NEAREST_TIES_TO_EVEN},
+            {ROUND_TOWARD_POSITIVE, cvc5::RoundingMode::ROUND_TOWARD_POSITIVE},
+            {ROUND_TOWARD_NEGATIVE, cvc5::RoundingMode::ROUND_TOWARD_NEGATIVE},
+            {ROUND_TOWARD_ZERO, cvc5::RoundingMode::ROUND_TOWARD_ZERO},
             {ROUND_NEAREST_TIES_TO_AWAY,
-             CVC4::RoundingMode::ROUND_NEAREST_TIES_TO_AWAY},
+             cvc5::RoundingMode::ROUND_NEAREST_TIES_TO_AWAY},
         };
 
-const static std::unordered_map<CVC4::RoundingMode,
+const static std::unordered_map<cvc5::RoundingMode,
                                 RoundingMode,
-                                CVC4::RoundingModeHashFunction>
+                                cvc5::RoundingModeHashFunction>
     s_rmodes_internal{
-        {CVC4::RoundingMode::ROUND_NEAREST_TIES_TO_EVEN,
+        {cvc5::RoundingMode::ROUND_NEAREST_TIES_TO_EVEN,
          ROUND_NEAREST_TIES_TO_EVEN},
-        {CVC4::RoundingMode::ROUND_TOWARD_POSITIVE, ROUND_TOWARD_POSITIVE},
-        {CVC4::RoundingMode::ROUND_TOWARD_POSITIVE, ROUND_TOWARD_NEGATIVE},
-        {CVC4::RoundingMode::ROUND_TOWARD_ZERO, ROUND_TOWARD_ZERO},
-        {CVC4::RoundingMode::ROUND_NEAREST_TIES_TO_AWAY,
+        {cvc5::RoundingMode::ROUND_TOWARD_POSITIVE, ROUND_TOWARD_POSITIVE},
+        {cvc5::RoundingMode::ROUND_TOWARD_POSITIVE, ROUND_TOWARD_NEGATIVE},
+        {cvc5::RoundingMode::ROUND_TOWARD_ZERO, ROUND_TOWARD_ZERO},
+        {cvc5::RoundingMode::ROUND_NEAREST_TIES_TO_AWAY,
          ROUND_NEAREST_TIES_TO_AWAY},
     };
 
@@ -3226,25 +4062,62 @@ size_t RoundingModeHashFunction::operator()(const RoundingMode& rm) const
 
 Solver::Solver(Options* opts)
 {
-  d_exprMgr.reset(new ExprManager);
-  d_smtEngine.reset(new SmtEngine(d_exprMgr->getNodeManager(), opts));
+  d_nodeMgr.reset(new NodeManager());
+  d_originalOptions.reset(new Options());
+  if (opts != nullptr)
+  {
+    d_originalOptions->copyValues(*opts);
+  }
+  d_smtEngine.reset(new SmtEngine(d_nodeMgr.get(), d_originalOptions.get()));
   d_smtEngine->setSolver(this);
-  Options& o = d_smtEngine->getOptions();
-  d_rng.reset(new Random(o[options::seed]));
+  d_rng.reset(new Random(d_smtEngine->getOptions()[options::seed]));
+#if CVC4_STATISTICS_ON
+  d_stats.reset(new Statistics());
+  d_smtEngine->getStatisticsRegistry()->registerStat(&d_stats->d_consts);
+  d_smtEngine->getStatisticsRegistry()->registerStat(&d_stats->d_vars);
+  d_smtEngine->getStatisticsRegistry()->registerStat(&d_stats->d_terms);
+#endif
 }
 
 Solver::~Solver() {}
 
-/* Helpers                                                                    */
+/* Helpers and private functions                                              */
 /* -------------------------------------------------------------------------- */
 
+NodeManager* Solver::getNodeManager(void) const { return d_nodeMgr.get(); }
+
+void Solver::increment_term_stats(Kind kind) const
+{
+#ifdef CVC4_STATISTICS_ON
+  d_stats->d_terms << kind;
+#endif
+}
+
+void Solver::increment_vars_consts_stats(const Sort& sort, bool is_var) const
+{
+#ifdef CVC4_STATISTICS_ON
+  const TypeNode tn = sort.getTypeNode();
+  TypeConstant tc = tn.getKind() == cvc5::kind::TYPE_CONSTANT
+                        ? tn.getConst<TypeConstant>()
+                        : LAST_TYPE;
+  if (is_var)
+  {
+    d_stats->d_vars << tc;
+  }
+  else
+  {
+    d_stats->d_consts << tc;
+  }
+#endif
+}
+
 /* Split out to avoid nested API calls (problematic with API tracing).        */
 /* .......................................................................... */
 
 template <typename T>
 Term Solver::mkValHelper(T t) const
 {
-  NodeManagerScope scope(getNodeManager());
+  //////// all checks before this line
   Node res = getNodeManager()->mkConst(t);
   (void)res.getType(true); /* kick off type checking */
   return Term(this, res);
@@ -3252,15 +4125,18 @@ Term Solver::mkValHelper(T t) const
 
 Term Solver::mkRealFromStrHelper(const std::string& s) const
 {
+  //////// all checks before this line
   try
   {
-    CVC4::Rational r = s.find('/') != std::string::npos
-                           ? CVC4::Rational(s)
-                           : CVC4::Rational::fromDecimal(s);
-    return mkValHelper<CVC4::Rational>(r);
+    cvc5::Rational r = s.find('/') != std::string::npos
+                           ? cvc5::Rational(s)
+                           : cvc5::Rational::fromDecimal(s);
+    return mkValHelper<cvc5::Rational>(r);
   }
   catch (const std::invalid_argument& e)
   {
+    /* Catch to throw with a more meaningful error message. To be caught in
+     * enclosing CVC4_API_TRY_CATCH_* block to throw CVC4ApiException. */
     std::stringstream message;
     message << "Cannot construct Real or Int from string argument '" << s << "'"
             << std::endl;
@@ -3270,12 +4146,9 @@ Term Solver::mkRealFromStrHelper(const std::string& s) const
 
 Term Solver::mkBVFromIntHelper(uint32_t size, uint64_t val) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
   CVC4_API_ARG_CHECK_EXPECTED(size > 0, size) << "a bit-width > 0";
-
-  return mkValHelper<CVC4::BitVector>(CVC4::BitVector(size, val));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  //////// all checks before this line
+  return mkValHelper<cvc5::BitVector>(cvc5::BitVector(size, val));
 }
 
 Term Solver::mkBVFromStrHelper(const std::string& s, uint32_t base) const
@@ -3283,8 +4156,8 @@ Term Solver::mkBVFromStrHelper(const std::string& s, uint32_t base) const
   CVC4_API_ARG_CHECK_EXPECTED(!s.empty(), s) << "a non-empty string";
   CVC4_API_ARG_CHECK_EXPECTED(base == 2 || base == 10 || base == 16, base)
       << "base 2, 10, or 16";
-
-  return mkValHelper<CVC4::BitVector>(CVC4::BitVector(s, base));
+  //////// all checks before this line
+  return mkValHelper<cvc5::BitVector>(cvc5::BitVector(s, base));
 }
 
 Term Solver::mkBVFromStrHelper(uint32_t size,
@@ -3294,6 +4167,7 @@ Term Solver::mkBVFromStrHelper(uint32_t size,
   CVC4_API_ARG_CHECK_EXPECTED(!s.empty(), s) << "a non-empty string";
   CVC4_API_ARG_CHECK_EXPECTED(base == 2 || base == 10 || base == 16, base)
       << "base 2, 10, or 16";
+  //////// all checks before this line
 
   Integer val(s, base);
 
@@ -3310,7 +4184,7 @@ Term Solver::mkBVFromStrHelper(uint32_t size,
         << size << " too small to hold value " << s << ")";
   }
 
-  return mkValHelper<CVC4::BitVector>(CVC4::BitVector(size, val));
+  return mkValHelper<cvc5::BitVector>(cvc5::BitVector(size, val));
 }
 
 Term Solver::mkCharFromStrHelper(const std::string& s) const
@@ -3322,13 +4196,16 @@ Term Solver::mkCharFromStrHelper(const std::string& s) const
   uint32_t val = static_cast<uint32_t>(std::stoul(s, 0, 16));
   CVC4_API_CHECK(val < String::num_codes())
       << "Not a valid code point for hexadecimal character " << s;
+  //////// all checks before this line
   std::vector<unsigned> cpts;
   cpts.push_back(val);
-  return mkValHelper<CVC4::String>(CVC4::String(cpts));
+  return mkValHelper<cvc5::String>(cvc5::String(cpts));
 }
 
-Term Solver::getValueHelper(Term term) const
+Term Solver::getValueHelper(const Term& term) const
 {
+  // Note: Term is checked in the caller to avoid double checks
+  //////// all checks before this line
   Node value = d_smtEngine->getValue(*term.d_node);
   Term res = Term(this, value);
   // May need to wrap in real cast so that user know this is a real.
@@ -3340,87 +4217,81 @@ Term Solver::getValueHelper(Term term) const
   return res;
 }
 
+Sort Solver::mkTupleSortHelper(const std::vector<Sort>& sorts) const
+{
+  // Note: Sorts are checked in the caller to avoid double checks
+  //////// all checks before this line
+  std::vector<TypeNode> typeNodes = Sort::sortVectorToTypeNodes(sorts);
+  return Sort(this, getNodeManager()->mkTupleType(typeNodes));
+}
+
 Term Solver::mkTermFromKind(Kind kind) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
   CVC4_API_KIND_CHECK_EXPECTED(
       kind == PI || kind == REGEXP_EMPTY || kind == REGEXP_SIGMA, kind)
       << "PI or REGEXP_EMPTY or REGEXP_SIGMA";
-
-  Expr res;
+  //////// all checks before this line
+  Node res;
   if (kind == REGEXP_EMPTY || kind == REGEXP_SIGMA)
   {
-    CVC4::Kind k = extToIntKind(kind);
+    cvc5::Kind k = extToIntKind(kind);
     Assert(isDefinedIntKind(k));
-    res = d_exprMgr->mkExpr(k, std::vector<Expr>());
+    res = d_nodeMgr->mkNode(k, std::vector<Node>());
   }
   else
   {
     Assert(kind == PI);
-    res = d_exprMgr->mkNullaryOperator(d_exprMgr->realType(), CVC4::kind::PI);
+    res = d_nodeMgr->mkNullaryOperator(d_nodeMgr->realType(), cvc5::kind::PI);
   }
   (void)res.getType(true); /* kick off type checking */
+  increment_term_stats(kind);
   return Term(this, res);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
 }
 
 Term Solver::mkTermHelper(Kind kind, const std::vector<Term>& children) const
 {
-  NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  for (size_t i = 0, size = children.size(); i < size; ++i)
-  {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        !children[i].isNull(), "child term", children[i], i)
-        << "non-null term";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == children[i].d_solver, "child term", children[i], i)
-        << "a child term associated to this solver object";
-  }
-
-  std::vector<Expr> echildren = termVectorToExprs(children);
-  CVC4::Kind k = extToIntKind(kind);
-  Assert(isDefinedIntKind(k))
-      << "Not a defined internal kind : " << k << " " << kind;
+  // Note: Kind and children are checked in the caller to avoid double checks
+  //////// all checks before this line
 
-  Expr res;
+  std::vector<Node> echildren = Term::termVectorToNodes(children);
+  cvc5::Kind k = extToIntKind(kind);
+  Node res;
   if (echildren.size() > 2)
   {
     if (kind == INTS_DIVISION || kind == XOR || kind == MINUS
         || kind == DIVISION || kind == HO_APPLY || kind == REGEXP_DIFF)
     {
       // left-associative, but CVC4 internally only supports 2 args
-      res = d_exprMgr->mkLeftAssociative(k, echildren);
+      res = d_nodeMgr->mkLeftAssociative(k, echildren);
     }
     else if (kind == IMPLIES)
     {
       // right-associative, but CVC4 internally only supports 2 args
-      res = d_exprMgr->mkRightAssociative(k, echildren);
+      res = d_nodeMgr->mkRightAssociative(k, echildren);
     }
     else if (kind == EQUAL || kind == LT || kind == GT || kind == LEQ
              || kind == GEQ)
     {
       // "chainable", but CVC4 internally only supports 2 args
-      res = d_exprMgr->mkChain(k, echildren);
+      res = d_nodeMgr->mkChain(k, echildren);
     }
     else if (kind::isAssociative(k))
     {
       // mkAssociative has special treatment for associative operators with lots
       // of children
-      res = d_exprMgr->mkAssociative(k, echildren);
+      res = d_nodeMgr->mkAssociative(k, echildren);
     }
     else
     {
       // default case, must check kind
       checkMkTerm(kind, children.size());
-      res = d_exprMgr->mkExpr(k, echildren);
+      res = d_nodeMgr->mkNode(k, echildren);
     }
   }
   else if (kind::isAssociative(k))
   {
     // associative case, same as above
-    res = d_exprMgr->mkAssociative(k, echildren);
+    res = d_nodeMgr->mkAssociative(k, echildren);
   }
   else
   {
@@ -3436,8 +4307,7 @@ Term Solver::mkTermHelper(Kind kind, const std::vector<Term>& children) const
       // integers and reals (both are Rationals).
       // At the API, mkReal and mkInteger are different and therefore the
       // element type can be used safely here.
-      Node singleton = getNodeManager()->mkSingleton(type, *children[0].d_node);
-      res = Term(this, singleton).getExpr();
+      res = getNodeManager()->mkSingleton(type, *children[0].d_node);
     }
     else if (kind == api::MK_BAG)
     {
@@ -3449,82 +4319,189 @@ Term Solver::mkTermHelper(Kind kind, const std::vector<Term>& children) const
       // integers and reals (both are Rationals).
       // At the API, mkReal and mkInteger are different and therefore the
       // element type can be used safely here.
-      Node bag = getNodeManager()->mkBag(
+      res = getNodeManager()->mkBag(
           type, *children[0].d_node, *children[1].d_node);
-      res = Term(this, bag).getExpr();
     }
     else
     {
-      res = d_exprMgr->mkExpr(k, echildren);
+      res = d_nodeMgr->mkNode(k, echildren);
     }
   }
 
+  (void)res.getType(true); /* kick off type checking */
+  increment_term_stats(kind);
+  return Term(this, res);
+}
+
+Term Solver::mkTermHelper(const Op& op, const std::vector<Term>& children) const
+{
+  // Note: Op and children are checked in the caller to avoid double checks
+  checkMkTerm(op.d_kind, children.size());
+  //////// all checks before this line
+
+  if (!op.isIndexedHelper())
+  {
+    return mkTermHelper(op.d_kind, children);
+  }
+
+  const cvc5::Kind int_kind = extToIntKind(op.d_kind);
+  std::vector<Node> echildren = Term::termVectorToNodes(children);
+
+  NodeBuilder<> nb(int_kind);
+  nb << *op.d_node;
+  nb.append(echildren);
+  Node res = nb.constructNode();
+
   (void)res.getType(true); /* kick off type checking */
   return Term(this, res);
-  CVC4_API_SOLVER_TRY_CATCH_END;
 }
 
 std::vector<Sort> Solver::mkDatatypeSortsInternal(
     const std::vector<DatatypeDecl>& dtypedecls,
     const std::set<Sort>& unresolvedSorts) const
 {
-  NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  // Note: dtypedecls and unresolvedSorts are checked in the caller to avoid
+  //       double checks
+  //////// all checks before this line
 
-  std::vector<CVC4::DType> datatypes;
+  std::vector<cvc5::DType> datatypes;
   for (size_t i = 0, ndts = dtypedecls.size(); i < ndts; ++i)
   {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(this == dtypedecls[i].d_solver,
-                                         "datatype declaration",
-                                         dtypedecls[i],
-                                         i)
-        << "a datatype declaration associated to this solver object";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(dtypedecls[i].getNumConstructors() > 0,
-                                         "datatype declaration",
-                                         dtypedecls[i],
-                                         i)
-        << "a datatype declaration with at least one constructor";
     datatypes.push_back(dtypedecls[i].getDatatype());
   }
-  for (auto& sort : unresolvedSorts)
-  {
-    CVC4_API_SOLVER_CHECK_SORT(sort);
-  }
 
-  std::set<TypeNode> utypes = sortSetToTypeNodes(unresolvedSorts);
-  std::vector<CVC4::TypeNode> dtypes =
+  std::set<TypeNode> utypes = Sort::sortSetToTypeNodes(unresolvedSorts);
+  std::vector<cvc5::TypeNode> dtypes =
       getNodeManager()->mkMutualDatatypeTypes(datatypes, utypes);
-  std::vector<Sort> retTypes = typeNodeVectorToSorts(this, dtypes);
+  std::vector<Sort> retTypes = Sort::typeNodeVectorToSorts(this, dtypes);
   return retTypes;
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
 }
 
-/* Helpers for converting vectors.                                            */
-/* .......................................................................... */
+Term Solver::synthFunHelper(const std::string& symbol,
+                            const std::vector<Term>& boundVars,
+                            const Sort& sort,
+                            bool isInv,
+                            Grammar* grammar) const
+{
+  // Note: boundVars, sort and grammar are checked in the caller to avoid
+  //       double checks.
+  std::vector<TypeNode> varTypes;
+  for (const auto& bv : boundVars)
+  {
+    if (grammar)
+    {
+      CVC4_API_CHECK(grammar->d_ntSyms[0].d_node->getType() == *sort.d_type)
+          << "Invalid Start symbol for grammar, Expected Start's sort to be "
+          << *sort.d_type << " but found "
+          << grammar->d_ntSyms[0].d_node->getType();
+    }
+    varTypes.push_back(bv.d_node->getType());
+  }
+  //////// all checks before this line
+
+  TypeNode funType = varTypes.empty() ? *sort.d_type
+                                      : getNodeManager()->mkFunctionType(
+                                          varTypes, *sort.d_type);
 
-std::vector<Type> Solver::sortVectorToTypes(
-    const std::vector<Sort>& sorts) const
+  Node fun = getNodeManager()->mkBoundVar(symbol, funType);
+  (void)fun.getType(true); /* kick off type checking */
+
+  std::vector<Node> bvns = Term::termVectorToNodes(boundVars);
+
+  d_smtEngine->declareSynthFun(
+      fun,
+      grammar == nullptr ? funType : *grammar->resolve().d_type,
+      isInv,
+      bvns);
+
+  return Term(this, fun);
+}
+
+Term Solver::ensureTermSort(const Term& term, const Sort& sort) const
 {
-  std::vector<Type> res;
-  for (const Sort& s : sorts)
+  // Note: Term and sort are checked in the caller to avoid double checks
+  CVC4_API_CHECK(term.getSort() == sort
+                 || (term.getSort().isInteger() && sort.isReal()))
+      << "Expected conversion from Int to Real";
+  //////// all checks before this line
+
+  Sort t = term.getSort();
+  if (term.getSort() == sort)
+  {
+    return term;
+  }
+
+  // Integers are reals, too
+  Assert(t.isReal());
+  Term res = term;
+  if (t.isInteger())
   {
-    CVC4_API_SOLVER_CHECK_SORT(s);
-    res.push_back(s.d_type->toType());
+    // Must cast to Real to ensure correct type is passed to parametric type
+    // constructors. We do this cast using division with 1. This has the
+    // advantage wrt using TO_REAL since (constant) division is always included
+    // in the theory.
+    res = Term(this,
+               d_nodeMgr->mkNode(extToIntKind(DIVISION),
+                                 *res.d_node,
+                                 d_nodeMgr->mkConst(cvc5::Rational(1))));
   }
+  Assert(res.getSort() == sort);
   return res;
 }
 
-std::vector<Expr> Solver::termVectorToExprs(
-    const std::vector<Term>& terms) const
+Term Solver::ensureRealSort(const Term& t) const
 {
-  std::vector<Expr> res;
-  for (const Term& t : terms)
+  Assert(this == t.d_solver);
+  CVC4_API_ARG_CHECK_EXPECTED(
+      t.getSort() == getIntegerSort() || t.getSort() == getRealSort(),
+      " an integer or real term");
+  // Note: Term is checked in the caller to avoid double checks
+  //////// all checks before this line
+  if (t.getSort() == getIntegerSort())
   {
-    CVC4_API_SOLVER_CHECK_TERM(t);
-    res.push_back(t.d_node->toExpr());
+    Node n = getNodeManager()->mkNode(kind::CAST_TO_REAL, *t.d_node);
+    return Term(this, n);
   }
-  return res;
+  return t;
+}
+
+bool Solver::isValidInteger(const std::string& s) const
+{
+  //////// all checks before this line
+  if (s.length() == 0)
+  {
+    // string should not be empty
+    return false;
+  }
+
+  size_t index = 0;
+  if (s[index] == '-')
+  {
+    if (s.length() == 1)
+    {
+      // negative integers should contain at least one digit
+      return false;
+    }
+    index = 1;
+  }
+
+  if (s[index] == '0' && s.length() > (index + 1))
+  {
+    // From SMT-Lib 2.6: A <numeral> is the digit 0 or a non-empty sequence of
+    // digits not starting with 0. So integers like 001, 000 are not allowed
+    return false;
+  }
+
+  // all remaining characters should be decimal digits
+  for (; index < s.length(); ++index)
+  {
+    if (!std::isdigit(s[index]))
+    {
+      return false;
+    }
+  }
+
+  return true;
 }
 
 /* Helpers for mkTerm checks.                                                 */
@@ -3534,7 +4511,7 @@ void Solver::checkMkTerm(Kind kind, uint32_t nchildren) const
 {
   CVC4_API_KIND_CHECK(kind);
   Assert(isDefinedIntKind(extToIntKind(kind)));
-  const CVC4::kind::MetaKind mk = kind::metaKindOf(extToIntKind(kind));
+  const cvc5::kind::MetaKind mk = kind::metaKindOf(extToIntKind(kind));
   CVC4_API_KIND_CHECK_EXPECTED(
       mk == kind::metakind::PARAMETERIZED || mk == kind::metakind::OPERATOR,
       kind)
@@ -3554,7 +4531,11 @@ void Solver::checkMkTerm(Kind kind, uint32_t nchildren) const
 
 bool Solver::supportsFloatingPoint() const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return Configuration::isBuiltWithSymFPU();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Sorts Handling                                                             */
@@ -3562,327 +4543,296 @@ bool Solver::supportsFloatingPoint() const
 
 Sort Solver::getNullSort(void) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return Sort(this, TypeNode());
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::getBooleanSort(void) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return Sort(this, getNodeManager()->booleanType());
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::getIntegerSort(void) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return Sort(this, getNodeManager()->integerType());
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::getRealSort(void) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return Sort(this, getNodeManager()->realType());
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::getRegExpSort(void) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return Sort(this, getNodeManager()->regExpType());
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::getStringSort(void) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return Sort(this, getNodeManager()->stringType());
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::getRoundingModeSort(void) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
       << "Expected CVC4 to be compiled with SymFPU support";
+  //////// all checks before this line
   return Sort(this, getNodeManager()->roundingModeType());
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Create sorts ------------------------------------------------------- */
 
-Sort Solver::mkArraySort(Sort indexSort, Sort elemSort) const
+Sort Solver::mkArraySort(const Sort& indexSort, const Sort& elemSort) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(!indexSort.isNull(), indexSort)
-      << "non-null index sort";
-  CVC4_API_ARG_CHECK_EXPECTED(!elemSort.isNull(), elemSort)
-      << "non-null element sort";
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_SORT(indexSort);
   CVC4_API_SOLVER_CHECK_SORT(elemSort);
-
+  //////// all checks before this line
   return Sort(
       this, getNodeManager()->mkArrayType(*indexSort.d_type, *elemSort.d_type));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::mkBitVectorSort(uint32_t size) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_ARG_CHECK_EXPECTED(size > 0, size) << "size > 0";
-
+  //////// all checks before this line
   return Sort(this, getNodeManager()->mkBitVectorType(size));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::mkFloatingPointSort(uint32_t exp, uint32_t sig) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
       << "Expected CVC4 to be compiled with SymFPU support";
   CVC4_API_ARG_CHECK_EXPECTED(exp > 0, exp) << "exponent size > 0";
   CVC4_API_ARG_CHECK_EXPECTED(sig > 0, sig) << "significand size > 0";
-
+  //////// all checks before this line
   return Sort(this, getNodeManager()->mkFloatingPointType(exp, sig));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Sort Solver::mkDatatypeSort(DatatypeDecl dtypedecl) const
+Sort Solver::mkDatatypeSort(const DatatypeDecl& dtypedecl) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_CHECK(this == dtypedecl.d_solver)
-      << "Given datatype declaration is not associated with this solver";
-  CVC4_API_ARG_CHECK_EXPECTED(dtypedecl.getNumConstructors() > 0, dtypedecl)
-      << "a datatype declaration with at least one constructor";
-
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_DTDECL(dtypedecl);
+  //////// all checks before this line
   return Sort(this, getNodeManager()->mkDatatypeType(*dtypedecl.d_dtype));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::vector<Sort> Solver::mkDatatypeSorts(
-    std::vector<DatatypeDecl>& dtypedecls) const
+    const std::vector<DatatypeDecl>& dtypedecls) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  std::set<Sort> unresolvedSorts;
-  return mkDatatypeSortsInternal(dtypedecls, unresolvedSorts);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_SOLVER_CHECK_DTDECLS(dtypedecls);
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return mkDatatypeSortsInternal(dtypedecls, {});
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::vector<Sort> Solver::mkDatatypeSorts(
     const std::vector<DatatypeDecl>& dtypedecls,
     const std::set<Sort>& unresolvedSorts) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_DTDECLS(dtypedecls);
+  CVC4_API_SOLVER_CHECK_SORTS(unresolvedSorts);
+  //////// all checks before this line
   return mkDatatypeSortsInternal(dtypedecls, unresolvedSorts);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Sort Solver::mkFunctionSort(Sort domain, Sort codomain) const
+Sort Solver::mkFunctionSort(const Sort& domain, const Sort& codomain) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(!codomain.isNull(), codomain)
-      << "non-null codomain sort";
-  CVC4_API_SOLVER_CHECK_SORT(domain);
-  CVC4_API_SOLVER_CHECK_SORT(codomain);
-  CVC4_API_ARG_CHECK_EXPECTED(domain.isFirstClass(), domain)
-      << "first-class sort as domain sort for function sort";
-  CVC4_API_ARG_CHECK_EXPECTED(codomain.isFirstClass(), codomain)
-      << "first-class sort as codomain sort for function sort";
-  Assert(!codomain.isFunction()); /* A function sort is not first-class. */
-
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_DOMAIN_SORT(domain);
+  CVC4_API_SOLVER_CHECK_CODOMAIN_SORT(codomain);
+  //////// all checks before this line
   return Sort(
       this, getNodeManager()->mkFunctionType(*domain.d_type, *codomain.d_type));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Sort Solver::mkFunctionSort(const std::vector<Sort>& sorts, Sort codomain) const
+Sort Solver::mkFunctionSort(const std::vector<Sort>& sorts,
+                            const Sort& codomain) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_ARG_SIZE_CHECK_EXPECTED(sorts.size() >= 1, sorts)
       << "at least one parameter sort for function sort";
-  for (size_t i = 0, size = sorts.size(); i < size; ++i)
-  {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        !sorts[i].isNull(), "parameter sort", sorts[i], i)
-        << "non-null sort";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == sorts[i].d_solver, "parameter sort", sorts[i], i)
-        << "sort associated to this solver object";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        sorts[i].isFirstClass(), "parameter sort", sorts[i], i)
-        << "first-class sort as parameter sort for function sort";
-  }
-  CVC4_API_ARG_CHECK_EXPECTED(!codomain.isNull(), codomain)
-      << "non-null codomain sort";
-  CVC4_API_SOLVER_CHECK_SORT(codomain);
-  CVC4_API_ARG_CHECK_EXPECTED(codomain.isFirstClass(), codomain)
-      << "first-class sort as codomain sort for function sort";
-  Assert(!codomain.isFunction()); /* A function sort is not first-class. */
-
-  std::vector<TypeNode> argTypes = sortVectorToTypeNodes(sorts);
+  CVC4_API_SOLVER_CHECK_DOMAIN_SORTS(sorts);
+  CVC4_API_SOLVER_CHECK_CODOMAIN_SORT(codomain);
+  //////// all checks before this line
+  std::vector<TypeNode> argTypes = Sort::sortVectorToTypeNodes(sorts);
   return Sort(this,
               getNodeManager()->mkFunctionType(argTypes, *codomain.d_type));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::mkParamSort(const std::string& symbol) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return Sort(
       this,
       getNodeManager()->mkSort(symbol, NodeManager::SORT_FLAG_PLACEHOLDER));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::mkPredicateSort(const std::vector<Sort>& sorts) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_ARG_SIZE_CHECK_EXPECTED(sorts.size() >= 1, sorts)
       << "at least one parameter sort for predicate sort";
-  for (size_t i = 0, size = sorts.size(); i < size; ++i)
-  {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        !sorts[i].isNull(), "parameter sort", sorts[i], i)
-        << "non-null sort";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == sorts[i].d_solver, "parameter sort", sorts[i], i)
-        << "sort associated to this solver object";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        sorts[i].isFirstClass(), "parameter sort", sorts[i], i)
-        << "first-class sort as parameter sort for predicate sort";
-  }
-  std::vector<TypeNode> types = sortVectorToTypeNodes(sorts);
-
-  return Sort(this, getNodeManager()->mkPredicateType(types));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  CVC4_API_SOLVER_CHECK_DOMAIN_SORTS(sorts);
+  //////// all checks before this line
+  return Sort(
+      this,
+      getNodeManager()->mkPredicateType(Sort::sortVectorToTypeNodes(sorts)));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::mkRecordSort(
     const std::vector<std::pair<std::string, Sort>>& fields) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   std::vector<std::pair<std::string, TypeNode>> f;
-  size_t i = 0;
-  for (const auto& p : fields)
+  for (size_t i = 0, size = fields.size(); i < size; ++i)
   {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        !p.second.isNull(), "parameter sort", p.second, i)
+    const auto& p = fields[i];
+    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(!p.second.isNull(), "sort", fields, i)
         << "non-null sort";
     CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == p.second.d_solver, "parameter sort", p.second, i)
-        << "sort associated to this solver object";
-    i += 1;
+        this == p.second.d_solver, "sort", fields, i)
+        << "sort associated with this solver object";
     f.emplace_back(p.first, *p.second.d_type);
   }
-
+  //////// all checks before this line
   return Sort(this, getNodeManager()->mkRecordType(f));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Sort Solver::mkSetSort(Sort elemSort) const
+Sort Solver::mkSetSort(const Sort& elemSort) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(!elemSort.isNull(), elemSort)
-      << "non-null element sort";
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_SORT(elemSort);
-
+  //////// all checks before this line
   return Sort(this, getNodeManager()->mkSetType(*elemSort.d_type));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Sort Solver::mkBagSort(Sort elemSort) const
+Sort Solver::mkBagSort(const Sort& elemSort) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(!elemSort.isNull(), elemSort)
-      << "non-null element sort";
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_SORT(elemSort);
-
+  //////// all checks before this line
   return Sort(this, getNodeManager()->mkBagType(*elemSort.d_type));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Sort Solver::mkSequenceSort(Sort elemSort) const
+Sort Solver::mkSequenceSort(const Sort& elemSort) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(!elemSort.isNull(), elemSort)
-      << "non-null element sort";
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_SORT(elemSort);
-
+  //////// all checks before this line
   return Sort(this, getNodeManager()->mkSequenceType(*elemSort.d_type));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::mkUninterpretedSort(const std::string& symbol) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return Sort(this, getNodeManager()->mkSort(symbol));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::mkSortConstructorSort(const std::string& symbol,
                                    size_t arity) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_ARG_CHECK_EXPECTED(arity > 0, arity) << "an arity > 0";
-
+  //////// all checks before this line
   return Sort(this, getNodeManager()->mkSortConstructor(symbol, arity));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Sort Solver::mkTupleSort(const std::vector<Sort>& sorts) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  for (size_t i = 0, size = sorts.size(); i < size; ++i)
-  {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        !sorts[i].isNull(), "parameter sort", sorts[i], i)
-        << "non-null sort";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == sorts[i].d_solver, "parameter sort", sorts[i], i)
-        << "sort associated to this solver object";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        !sorts[i].isFunctionLike(), "parameter sort", sorts[i], i)
-        << "non-function-like sort as parameter sort for tuple sort";
-  }
-  std::vector<TypeNode> typeNodes = sortVectorToTypeNodes(sorts);
-  return Sort(this, getNodeManager()->mkTupleType(typeNodes));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_SORTS_NOT_FUNCTION_LIKE(sorts);
+  //////// all checks before this line
+  return mkTupleSortHelper(sorts);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Create consts                                                              */
@@ -3890,292 +4840,291 @@ Sort Solver::mkTupleSort(const std::vector<Sort>& sorts) const
 
 Term Solver::mkTrue(void) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  return Term(this, d_exprMgr->mkConst<bool>(true));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return Term(this, d_nodeMgr->mkConst<bool>(true));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkFalse(void) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  return Term(this, d_exprMgr->mkConst<bool>(false));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return Term(this, d_nodeMgr->mkConst<bool>(false));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkBoolean(bool val) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  return Term(this, d_exprMgr->mkConst<bool>(val));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return Term(this, d_nodeMgr->mkConst<bool>(val));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkPi() const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-
-  Expr res =
-      d_exprMgr->mkNullaryOperator(d_exprMgr->realType(), CVC4::kind::PI);
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  Node res =
+      d_nodeMgr->mkNullaryOperator(d_nodeMgr->realType(), cvc5::kind::PI);
   (void)res.getType(true); /* kick off type checking */
   return Term(this, res);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
-}
-
-bool Solver::isValidInteger(const std::string& s) const
-{
-  if (s.length() == 0)
-  {
-    // string should not be empty
-    return false;
-  }
-
-  size_t index = 0;
-  if (s[index] == '-')
-  {
-    if (s.length() == 1)
-    {
-      // negative integers should contain at least one digit
-      return false;
-    }
-    index = 1;
-  }
-
-  if (s[index] == '0' && s.length() > (index + 1))
-  {
-    // From SMT-Lib 2.6: A〈numeral〉is the digit 0 or a non-empty sequence of
-    // digits not starting with 0. So integers like 001, 000 are not allowed
-    return false;
-  }
-
-  // all remaining characters should be decimal digits
-  for (; index < s.length(); ++index)
-  {
-    if (!std::isdigit(s[index]))
-    {
-      return false;
-    }
-  }
-
-  return true;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkInteger(const std::string& s) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_ARG_CHECK_EXPECTED(isValidInteger(s), s) << " an integer ";
   Term integer = mkRealFromStrHelper(s);
   CVC4_API_ARG_CHECK_EXPECTED(integer.getSort() == getIntegerSort(), s)
-      << " an integer";
+      << " a string representing an integer";
+  //////// all checks before this line
   return integer;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkInteger(int64_t val) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  Term integer = mkValHelper<CVC4::Rational>(CVC4::Rational(val));
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  Term integer = mkValHelper<cvc5::Rational>(cvc5::Rational(val));
   Assert(integer.getSort() == getIntegerSort());
   return integer;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkReal(const std::string& s) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   /* CLN and GMP handle this case differently, CLN interprets it as 0, GMP
    * throws an std::invalid_argument exception. For consistency, we treat it
    * as invalid. */
   CVC4_API_ARG_CHECK_EXPECTED(s != ".", s)
       << "a string representing a real or rational value.";
+  //////// all checks before this line
   Term rational = mkRealFromStrHelper(s);
   return ensureRealSort(rational);
-  CVC4_API_SOLVER_TRY_CATCH_END;
-}
-
-Term Solver::ensureRealSort(const Term t) const
-{
-  CVC4_API_ARG_CHECK_EXPECTED(
-      t.getSort() == getIntegerSort() || t.getSort() == getRealSort(),
-      " an integer or real term");
-  if (t.getSort() == getIntegerSort())
-  {
-    Node n = getNodeManager()->mkNode(kind::CAST_TO_REAL, *t.d_node);
-    return Term(this, n);
-  }
-  return t;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkReal(int64_t val) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  Term rational = mkValHelper<CVC4::Rational>(CVC4::Rational(val));
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  Term rational = mkValHelper<cvc5::Rational>(cvc5::Rational(val));
   return ensureRealSort(rational);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkReal(int64_t num, int64_t den) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  Term rational = mkValHelper<CVC4::Rational>(CVC4::Rational(num, den));
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  Term rational = mkValHelper<cvc5::Rational>(cvc5::Rational(num, den));
   return ensureRealSort(rational);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkRegexpEmpty() const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-
-  Expr res =
-      d_exprMgr->mkExpr(CVC4::kind::REGEXP_EMPTY, std::vector<CVC4::Expr>());
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  Node res =
+      d_nodeMgr->mkNode(cvc5::kind::REGEXP_EMPTY, std::vector<cvc5::Node>());
   (void)res.getType(true); /* kick off type checking */
   return Term(this, res);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkRegexpSigma() const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-
-  Expr res =
-      d_exprMgr->mkExpr(CVC4::kind::REGEXP_SIGMA, std::vector<CVC4::Expr>());
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  Node res =
+      d_nodeMgr->mkNode(cvc5::kind::REGEXP_SIGMA, std::vector<cvc5::Node>());
   (void)res.getType(true); /* kick off type checking */
   return Term(this, res);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkEmptySet(Sort s) const
+Term Solver::mkEmptySet(const Sort& sort) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(s.isNull() || s.isSet(), s)
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_ARG_CHECK_EXPECTED(sort.isNull() || sort.isSet(), sort)
       << "null sort or set sort";
-  CVC4_API_ARG_CHECK_EXPECTED(s.isNull() || this == s.d_solver, s)
-      << "set sort associated to this solver object";
-
-  return mkValHelper<CVC4::EmptySet>(CVC4::EmptySet(*s.d_type));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  CVC4_API_ARG_CHECK_EXPECTED(sort.isNull() || this == sort.d_solver, sort)
+      << "set sort associated with this solver object";
+  //////// all checks before this line
+  return mkValHelper<cvc5::EmptySet>(cvc5::EmptySet(*sort.d_type));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkEmptyBag(Sort s) const
+Term Solver::mkEmptyBag(const Sort& sort) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(s.isNull() || s.isBag(), s)
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_ARG_CHECK_EXPECTED(sort.isNull() || sort.isBag(), sort)
       << "null sort or bag sort";
-
-  CVC4_API_ARG_CHECK_EXPECTED(s.isNull() || this == s.d_solver, s)
-      << "bag sort associated to this solver object";
-
-  return mkValHelper<CVC4::EmptyBag>(CVC4::EmptyBag(*s.d_type));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  CVC4_API_ARG_CHECK_EXPECTED(sort.isNull() || this == sort.d_solver, sort)
+      << "bag sort associated with this solver object";
+  //////// all checks before this line
+  return mkValHelper<cvc5::EmptyBag>(cvc5::EmptyBag(*sort.d_type));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkSepNil(Sort sort) const
+Term Solver::mkSepNil(const Sort& sort) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_SORT(sort);
-
+  //////// all checks before this line
   Node res =
-      getNodeManager()->mkNullaryOperator(*sort.d_type, CVC4::kind::SEP_NIL);
+      getNodeManager()->mkNullaryOperator(*sort.d_type, cvc5::kind::SEP_NIL);
   (void)res.getType(true); /* kick off type checking */
   return Term(this, res);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkString(const std::string& s, bool useEscSequences) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  return mkValHelper<CVC4::String>(CVC4::String(s, useEscSequences));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return mkValHelper<cvc5::String>(cvc5::String(s, useEscSequences));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkString(const unsigned char c) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  return mkValHelper<CVC4::String>(CVC4::String(std::string(1, c)));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return mkValHelper<cvc5::String>(cvc5::String(std::string(1, c)));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkString(const std::vector<unsigned>& s) const
+Term Solver::mkString(const std::vector<uint32_t>& s) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  return mkValHelper<CVC4::String>(CVC4::String(s));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  return mkValHelper<cvc5::String>(cvc5::String(s));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkChar(const std::string& s) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return mkCharFromStrHelper(s);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkEmptySequence(Sort sort) const
+Term Solver::mkEmptySequence(const Sort& sort) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_SORT(sort);
-
+  //////// all checks before this line
   std::vector<Node> seq;
-  Expr res = d_exprMgr->mkConst(Sequence(*sort.d_type, seq));
+  Node res = d_nodeMgr->mkConst(Sequence(*sort.d_type, seq));
   return Term(this, res);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkUniverseSet(Sort sort) const
+Term Solver::mkUniverseSet(const Sort& sort) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_SORT(sort);
+  //////// all checks before this line
 
   Node res = getNodeManager()->mkNullaryOperator(*sort.d_type,
-                                                 CVC4::kind::UNIVERSE_SET);
+                                                 cvc5::kind::UNIVERSE_SET);
   // TODO(#2771): Reenable?
   // (void)res->getType(true); /* kick off type checking */
   return Term(this, res);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkBitVector(uint32_t size, uint64_t val) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return mkBVFromIntHelper(size, val);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkBitVector(const std::string& s, uint32_t base) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return mkBVFromStrHelper(s, base);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkBitVector(uint32_t size,
                          const std::string& s,
                          uint32_t base) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return mkBVFromStrHelper(size, s, base);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkConstArray(Sort sort, Term val) const
+Term Solver::mkConstArray(const Sort& sort, const Term& val) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
-  CVC4_API_ARG_CHECK_NOT_NULL(sort);
-  CVC4_API_ARG_CHECK_NOT_NULL(val);
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_SORT(sort);
   CVC4_API_SOLVER_CHECK_TERM(val);
-  CVC4_API_CHECK(sort.isArray()) << "Not an array sort.";
+  CVC4_API_ARG_CHECK_EXPECTED(sort.isArray(), sort) << "an array sort";
   CVC4_API_CHECK(val.getSort().isSubsortOf(sort.getArrayElementSort()))
-      << "Value does not match element sort.";
+      << "Value does not match element sort";
+  //////// all checks before this line
+
   // handle the special case of (CAST_TO_REAL n) where n is an integer
   Node n = *val.d_node;
   if (val.isCastedReal())
@@ -4183,188 +5132,202 @@ Term Solver::mkConstArray(Sort sort, Term val) const
     // this is safe because the constant array stores its type
     n = n[0];
   }
-  Term res = mkValHelper<CVC4::ArrayStoreAll>(
-      CVC4::ArrayStoreAll(*sort.d_type, n));
+  Term res =
+      mkValHelper<cvc5::ArrayStoreAll>(cvc5::ArrayStoreAll(*sort.d_type, n));
   return res;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkPosInf(uint32_t exp, uint32_t sig) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
       << "Expected CVC4 to be compiled with SymFPU support";
-
-  return mkValHelper<CVC4::FloatingPoint>(
+  //////// all checks before this line
+  return mkValHelper<cvc5::FloatingPoint>(
       FloatingPoint::makeInf(FloatingPointSize(exp, sig), false));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkNegInf(uint32_t exp, uint32_t sig) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
       << "Expected CVC4 to be compiled with SymFPU support";
-
-  return mkValHelper<CVC4::FloatingPoint>(
+  //////// all checks before this line
+  return mkValHelper<cvc5::FloatingPoint>(
       FloatingPoint::makeInf(FloatingPointSize(exp, sig), true));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkNaN(uint32_t exp, uint32_t sig) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
       << "Expected CVC4 to be compiled with SymFPU support";
-
-  return mkValHelper<CVC4::FloatingPoint>(
+  //////// all checks before this line
+  return mkValHelper<cvc5::FloatingPoint>(
       FloatingPoint::makeNaN(FloatingPointSize(exp, sig)));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkPosZero(uint32_t exp, uint32_t sig) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
       << "Expected CVC4 to be compiled with SymFPU support";
-
-  return mkValHelper<CVC4::FloatingPoint>(
+  //////// all checks before this line
+  return mkValHelper<cvc5::FloatingPoint>(
       FloatingPoint::makeZero(FloatingPointSize(exp, sig), false));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkNegZero(uint32_t exp, uint32_t sig) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
       << "Expected CVC4 to be compiled with SymFPU support";
-
-  return mkValHelper<CVC4::FloatingPoint>(
+  //////// all checks before this line
+  return mkValHelper<cvc5::FloatingPoint>(
       FloatingPoint::makeZero(FloatingPointSize(exp, sig), true));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkRoundingMode(RoundingMode rm) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
       << "Expected CVC4 to be compiled with SymFPU support";
-  return mkValHelper<CVC4::RoundingMode>(s_rmodes.at(rm));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  //////// all checks before this line
+  return mkValHelper<cvc5::RoundingMode>(s_rmodes.at(rm));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkUninterpretedConst(Sort sort, int32_t index) const
+Term Solver::mkUninterpretedConst(const Sort& sort, int32_t index) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_SORT(sort);
-
-  return mkValHelper<CVC4::UninterpretedConstant>(
-      CVC4::UninterpretedConstant(*sort.d_type, index));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  //////// all checks before this line
+  return mkValHelper<cvc5::UninterpretedConstant>(
+      cvc5::UninterpretedConstant(*sort.d_type, index));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkAbstractValue(const std::string& index) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_ARG_CHECK_EXPECTED(!index.empty(), index) << "a non-empty string";
 
-  CVC4::Integer idx(index, 10);
+  cvc5::Integer idx(index, 10);
   CVC4_API_ARG_CHECK_EXPECTED(idx > 0, index)
       << "a string representing an integer > 0";
-  return Term(this, getNodeManager()->mkConst(CVC4::AbstractValue(idx)));
+  //////// all checks before this line
+  return Term(this, getNodeManager()->mkConst(cvc5::AbstractValue(idx)));
   // do not call getType(), for abstract values, type can not be computed
   // until it is substituted away
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkAbstractValue(uint64_t index) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_ARG_CHECK_EXPECTED(index > 0, index) << "an integer > 0";
-
+  //////// all checks before this line
   return Term(this,
-              getNodeManager()->mkConst(CVC4::AbstractValue(Integer(index))));
+              getNodeManager()->mkConst(cvc5::AbstractValue(Integer(index))));
   // do not call getType(), for abstract values, type can not be computed
   // until it is substituted away
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkFloatingPoint(uint32_t exp, uint32_t sig, Term val) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(Configuration::isBuiltWithSymFPU())
       << "Expected CVC4 to be compiled with SymFPU support";
+  CVC4_API_SOLVER_CHECK_TERM(val);
   CVC4_API_ARG_CHECK_EXPECTED(exp > 0, exp) << "a value > 0";
   CVC4_API_ARG_CHECK_EXPECTED(sig > 0, sig) << "a value > 0";
   uint32_t bw = exp + sig;
   CVC4_API_ARG_CHECK_EXPECTED(bw == val.getSort().getBVSize(), val)
       << "a bit-vector constant with bit-width '" << bw << "'";
-  CVC4_API_ARG_CHECK_EXPECTED(!val.isNull(), val) << "non-null term";
-  CVC4_API_SOLVER_CHECK_TERM(val);
   CVC4_API_ARG_CHECK_EXPECTED(
       val.getSort().isBitVector() && val.d_node->isConst(), val)
       << "bit-vector constant";
-
-  return mkValHelper<CVC4::FloatingPoint>(
-      CVC4::FloatingPoint(exp, sig, val.d_node->getConst<BitVector>()));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  //////// all checks before this line
+  return mkValHelper<cvc5::FloatingPoint>(
+      cvc5::FloatingPoint(exp, sig, val.d_node->getConst<BitVector>()));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Create constants                                                           */
 /* -------------------------------------------------------------------------- */
 
-Term Solver::mkConst(Sort sort, const std::string& symbol) const
+Term Solver::mkConst(const Sort& sort, const std::string& symbol) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_SORT(sort);
-
-  Expr res = d_exprMgr->mkVar(symbol, sort.d_type->toType());
+  //////// all checks before this line
+  Node res = d_nodeMgr->mkVar(symbol, *sort.d_type);
   (void)res.getType(true); /* kick off type checking */
+  increment_vars_consts_stats(sort, false);
   return Term(this, res);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkConst(Sort sort) const
+Term Solver::mkConst(const Sort& sort) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_SORT(sort);
-
-  Expr res = d_exprMgr->mkVar(sort.d_type->toType());
+  //////// all checks before this line
+  Node res = d_nodeMgr->mkVar(*sort.d_type);
   (void)res.getType(true); /* kick off type checking */
+  increment_vars_consts_stats(sort, false);
   return Term(this, res);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Create variables                                                           */
 /* -------------------------------------------------------------------------- */
 
-Term Solver::mkVar(Sort sort, const std::string& symbol) const
+Term Solver::mkVar(const Sort& sort, const std::string& symbol) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(!sort.isNull(), sort) << "non-null sort";
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_SORT(sort);
-
-  Expr res = symbol.empty()
-                 ? d_exprMgr->mkBoundVar(sort.d_type->toType())
-                 : d_exprMgr->mkBoundVar(symbol, sort.d_type->toType());
+  //////// all checks before this line
+  Node res = symbol.empty() ? d_nodeMgr->mkBoundVar(*sort.d_type)
+                            : d_nodeMgr->mkBoundVar(symbol, *sort.d_type);
   (void)res.getType(true); /* kick off type checking */
+  increment_vars_consts_stats(sort, true);
   return Term(this, res);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Create datatype constructor declarations                                   */
@@ -4374,7 +5337,11 @@ DatatypeConstructorDecl Solver::mkDatatypeConstructorDecl(
     const std::string& name)
 {
   NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return DatatypeConstructorDecl(this, name);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Create datatype declarations                                               */
@@ -4383,7 +5350,11 @@ DatatypeConstructorDecl Solver::mkDatatypeConstructorDecl(
 DatatypeDecl Solver::mkDatatypeDecl(const std::string& name, bool isCoDatatype)
 {
   NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return DatatypeDecl(this, name, isCoDatatype);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 DatatypeDecl Solver::mkDatatypeDecl(const std::string& name,
@@ -4391,7 +5362,12 @@ DatatypeDecl Solver::mkDatatypeDecl(const std::string& name,
                                     bool isCoDatatype)
 {
   NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_SORT(param);
+  //////// all checks before this line
   return DatatypeDecl(this, name, param, isCoDatatype);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 DatatypeDecl Solver::mkDatatypeDecl(const std::string& name,
@@ -4399,7 +5375,12 @@ DatatypeDecl Solver::mkDatatypeDecl(const std::string& name,
                                     bool isCoDatatype)
 {
   NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_SORTS(params);
+  //////// all checks before this line
   return DatatypeDecl(this, name, params, isCoDatatype);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Create terms                                                               */
@@ -4407,128 +5388,163 @@ DatatypeDecl Solver::mkDatatypeDecl(const std::string& name,
 
 Term Solver::mkTerm(Kind kind) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_KIND_CHECK(kind);
+  //////// all checks before this line
   return mkTermFromKind(kind);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkTerm(Kind kind, Term child) const
+Term Solver::mkTerm(Kind kind, const Term& child) const
 {
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_KIND_CHECK(kind);
+  CVC4_API_SOLVER_CHECK_TERM(child);
+  //////// all checks before this line
   return mkTermHelper(kind, std::vector<Term>{child});
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkTerm(Kind kind, Term child1, Term child2) const
+Term Solver::mkTerm(Kind kind, const Term& child1, const Term& child2) const
 {
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_KIND_CHECK(kind);
+  CVC4_API_SOLVER_CHECK_TERM(child1);
+  CVC4_API_SOLVER_CHECK_TERM(child2);
+  //////// all checks before this line
   return mkTermHelper(kind, std::vector<Term>{child1, child2});
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkTerm(Kind kind, Term child1, Term child2, Term child3) const
+Term Solver::mkTerm(Kind kind,
+                    const Term& child1,
+                    const Term& child2,
+                    const Term& child3) const
 {
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_KIND_CHECK(kind);
+  CVC4_API_SOLVER_CHECK_TERM(child1);
+  CVC4_API_SOLVER_CHECK_TERM(child2);
+  CVC4_API_SOLVER_CHECK_TERM(child3);
+  //////// all checks before this line
   // need to use internal term call to check e.g. associative construction
   return mkTermHelper(kind, std::vector<Term>{child1, child2, child3});
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkTerm(Kind kind, const std::vector<Term>& children) const
 {
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_KIND_CHECK(kind);
+  CVC4_API_SOLVER_CHECK_TERMS(children);
+  //////// all checks before this line
   return mkTermHelper(kind, children);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkTerm(Op op) const
+Term Solver::mkTerm(const Op& op) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_OP(op);
   checkMkTerm(op.d_kind, 0);
+  //////// all checks before this line
 
   if (!op.isIndexedHelper())
   {
     return mkTermFromKind(op.d_kind);
   }
 
-  const CVC4::Kind int_kind = extToIntKind(op.d_kind);
+  const cvc5::Kind int_kind = extToIntKind(op.d_kind);
   Term res = Term(this, getNodeManager()->mkNode(int_kind, *op.d_node));
 
   (void)res.d_node->getType(true); /* kick off type checking */
   return res;
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkTerm(Op op, Term child) const
+Term Solver::mkTerm(const Op& op, const Term& child) const
 {
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_OP(op);
+  CVC4_API_SOLVER_CHECK_TERM(child);
+  //////// all checks before this line
   return mkTermHelper(op, std::vector<Term>{child});
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkTerm(Op op, Term child1, Term child2) const
+Term Solver::mkTerm(const Op& op, const Term& child1, const Term& child2) const
 {
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_OP(op);
+  CVC4_API_SOLVER_CHECK_TERM(child1);
+  CVC4_API_SOLVER_CHECK_TERM(child2);
+  //////// all checks before this line
   return mkTermHelper(op, std::vector<Term>{child1, child2});
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkTerm(Op op, Term child1, Term child2, Term child3) const
+Term Solver::mkTerm(const Op& op,
+                    const Term& child1,
+                    const Term& child2,
+                    const Term& child3) const
 {
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_OP(op);
+  CVC4_API_SOLVER_CHECK_TERM(child1);
+  CVC4_API_SOLVER_CHECK_TERM(child2);
+  CVC4_API_SOLVER_CHECK_TERM(child3);
+  //////// all checks before this line
   return mkTermHelper(op, std::vector<Term>{child1, child2, child3});
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkTerm(Op op, const std::vector<Term>& children) const
+Term Solver::mkTerm(const Op& op, const std::vector<Term>& children) const
 {
-  return mkTermHelper(op, children);
-}
-
-Term Solver::mkTermHelper(const Op& op, const std::vector<Term>& children) const
-{
-  if (!op.isIndexedHelper())
-  {
-    return mkTermHelper(op.d_kind, children);
-  }
-
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_OP(op);
-  checkMkTerm(op.d_kind, children.size());
-  for (size_t i = 0, size = children.size(); i < size; ++i)
-  {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        !children[i].isNull(), "child term", children[i], i)
-        << "non-null term";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == children[i].d_solver, "child term", children[i], i)
-        << "child term associated to this solver object";
-  }
-
-  const CVC4::Kind int_kind = extToIntKind(op.d_kind);
-  std::vector<Node> echildren = termVectorToNodes(children);
-
-  NodeBuilder<> nb(int_kind);
-  nb << *op.d_node;
-  nb.append(echildren);
-  Node res = nb.constructNode();
-
-  (void)res.getType(true); /* kick off type checking */
-  return Term(this, res);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  CVC4_API_SOLVER_CHECK_TERMS(children);
+  //////// all checks before this line
+  return mkTermHelper(op, children);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::mkTuple(const std::vector<Sort>& sorts,
                      const std::vector<Term>& terms) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(sorts.size() == terms.size())
       << "Expected the same number of sorts and elements";
-  std::vector<CVC4::Node> args;
+  CVC4_API_SOLVER_CHECK_SORTS(sorts);
+  CVC4_API_SOLVER_CHECK_TERMS(terms);
+  //////// all checks before this line
+  std::vector<cvc5::Node> args;
   for (size_t i = 0, size = sorts.size(); i < size; i++)
   {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == terms[i].d_solver, "child term", terms[i], i)
-        << "child term associated to this solver object";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == sorts[i].d_solver, "child sort", sorts[i], i)
-        << "child sort associated to this solver object";
     args.push_back(*(ensureTermSort(terms[i], sorts[i])).d_node);
   }
 
-  Sort s = mkTupleSort(sorts);
+  Sort s = mkTupleSortHelper(sorts);
   Datatype dt = s.getDatatype();
   NodeBuilder<> nb(extToIntKind(APPLY_CONSTRUCTOR));
   nb << *dt[0].getConstructorTerm().d_node;
@@ -4536,8 +5552,8 @@ Term Solver::mkTuple(const std::vector<Sort>& sorts,
   Node res = nb.constructNode();
   (void)res.getType(true); /* kick off type checking */
   return Term(this, res);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Create operators                                                           */
@@ -4545,25 +5561,30 @@ Term Solver::mkTuple(const std::vector<Sort>& sorts,
 
 Op Solver::mkOp(Kind kind) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_KIND_CHECK(kind);
   CVC4_API_CHECK(s_indexed_kinds.find(kind) == s_indexed_kinds.end())
       << "Expected a kind for a non-indexed operator.";
+  //////// all checks before this line
   return Op(this, kind);
-  CVC4_API_SOLVER_TRY_CATCH_END
+  ////////
+  CVC4_API_TRY_CATCH_END
 }
 
 Op Solver::mkOp(Kind kind, const std::string& arg) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_KIND_CHECK(kind);
   CVC4_API_KIND_CHECK_EXPECTED((kind == RECORD_UPDATE) || (kind == DIVISIBLE),
                                kind)
       << "RECORD_UPDATE or DIVISIBLE";
+  //////// all checks before this line
   Op res;
   if (kind == RECORD_UPDATE)
   {
     res = Op(this,
              kind,
-             *mkValHelper<CVC4::RecordUpdate>(CVC4::RecordUpdate(arg)).d_node);
+             *mkValHelper<cvc5::RecordUpdate>(cvc5::RecordUpdate(arg)).d_node);
   }
   else
   {
@@ -4574,95 +5595,95 @@ Op Solver::mkOp(Kind kind, const std::string& arg) const
         << "a string representing an integer, real or rational value.";
     res = Op(this,
              kind,
-             *mkValHelper<CVC4::Divisible>(CVC4::Divisible(CVC4::Integer(arg)))
+             *mkValHelper<cvc5::Divisible>(cvc5::Divisible(cvc5::Integer(arg)))
                   .d_node);
   }
   return res;
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Op Solver::mkOp(Kind kind, uint32_t arg) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_KIND_CHECK(kind);
-
+  //////// all checks before this line
   Op res;
   switch (kind)
   {
     case DIVISIBLE:
       res = Op(this,
                kind,
-               *mkValHelper<CVC4::Divisible>(CVC4::Divisible(arg)).d_node);
+               *mkValHelper<cvc5::Divisible>(cvc5::Divisible(arg)).d_node);
       break;
     case BITVECTOR_REPEAT:
       res = Op(this,
                kind,
-               mkValHelper<CVC4::BitVectorRepeat>(CVC4::BitVectorRepeat(arg))
-                   .d_node->toExpr());
+               *mkValHelper<cvc5::BitVectorRepeat>(cvc5::BitVectorRepeat(arg))
+                    .d_node);
       break;
     case BITVECTOR_ZERO_EXTEND:
       res = Op(this,
                kind,
-               *mkValHelper<CVC4::BitVectorZeroExtend>(
-                    CVC4::BitVectorZeroExtend(arg))
+               *mkValHelper<cvc5::BitVectorZeroExtend>(
+                    cvc5::BitVectorZeroExtend(arg))
                     .d_node);
       break;
     case BITVECTOR_SIGN_EXTEND:
       res = Op(this,
                kind,
-               *mkValHelper<CVC4::BitVectorSignExtend>(
-                    CVC4::BitVectorSignExtend(arg))
+               *mkValHelper<cvc5::BitVectorSignExtend>(
+                    cvc5::BitVectorSignExtend(arg))
                     .d_node);
       break;
     case BITVECTOR_ROTATE_LEFT:
       res = Op(this,
                kind,
-               *mkValHelper<CVC4::BitVectorRotateLeft>(
-                    CVC4::BitVectorRotateLeft(arg))
+               *mkValHelper<cvc5::BitVectorRotateLeft>(
+                    cvc5::BitVectorRotateLeft(arg))
                     .d_node);
       break;
     case BITVECTOR_ROTATE_RIGHT:
       res = Op(this,
                kind,
-               *mkValHelper<CVC4::BitVectorRotateRight>(
-                    CVC4::BitVectorRotateRight(arg))
+               *mkValHelper<cvc5::BitVectorRotateRight>(
+                    cvc5::BitVectorRotateRight(arg))
                     .d_node);
       break;
     case INT_TO_BITVECTOR:
       res = Op(
           this,
           kind,
-          *mkValHelper<CVC4::IntToBitVector>(CVC4::IntToBitVector(arg)).d_node);
+          *mkValHelper<cvc5::IntToBitVector>(cvc5::IntToBitVector(arg)).d_node);
       break;
     case IAND:
       res =
-          Op(this, kind, *mkValHelper<CVC4::IntAnd>(CVC4::IntAnd(arg)).d_node);
+          Op(this, kind, *mkValHelper<cvc5::IntAnd>(cvc5::IntAnd(arg)).d_node);
       break;
     case FLOATINGPOINT_TO_UBV:
       res = Op(
           this,
           kind,
-          *mkValHelper<CVC4::FloatingPointToUBV>(CVC4::FloatingPointToUBV(arg))
+          *mkValHelper<cvc5::FloatingPointToUBV>(cvc5::FloatingPointToUBV(arg))
                .d_node);
       break;
     case FLOATINGPOINT_TO_SBV:
       res = Op(
           this,
           kind,
-          *mkValHelper<CVC4::FloatingPointToSBV>(CVC4::FloatingPointToSBV(arg))
+          *mkValHelper<cvc5::FloatingPointToSBV>(cvc5::FloatingPointToSBV(arg))
                .d_node);
       break;
     case TUPLE_UPDATE:
       res = Op(this,
                kind,
-               *mkValHelper<CVC4::TupleUpdate>(CVC4::TupleUpdate(arg)).d_node);
+               *mkValHelper<cvc5::TupleUpdate>(cvc5::TupleUpdate(arg)).d_node);
       break;
     case REGEXP_REPEAT:
       res =
           Op(this,
              kind,
-             *mkValHelper<CVC4::RegExpRepeat>(CVC4::RegExpRepeat(arg)).d_node);
+             *mkValHelper<cvc5::RegExpRepeat>(cvc5::RegExpRepeat(arg)).d_node);
       break;
     default:
       CVC4_API_KIND_CHECK_EXPECTED(false, kind)
@@ -4670,14 +5691,15 @@ Op Solver::mkOp(Kind kind, uint32_t arg) const
   }
   Assert(!res.isNull());
   return res;
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Op Solver::mkOp(Kind kind, uint32_t arg1, uint32_t arg2) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_KIND_CHECK(kind);
+  //////// all checks before this line
 
   Op res;
   switch (kind)
@@ -4685,57 +5707,57 @@ Op Solver::mkOp(Kind kind, uint32_t arg1, uint32_t arg2) const
     case BITVECTOR_EXTRACT:
       res = Op(this,
                kind,
-               *mkValHelper<CVC4::BitVectorExtract>(
-                    CVC4::BitVectorExtract(arg1, arg2))
+               *mkValHelper<cvc5::BitVectorExtract>(
+                    cvc5::BitVectorExtract(arg1, arg2))
                     .d_node);
       break;
     case FLOATINGPOINT_TO_FP_IEEE_BITVECTOR:
       res = Op(this,
                kind,
-               *mkValHelper<CVC4::FloatingPointToFPIEEEBitVector>(
-                    CVC4::FloatingPointToFPIEEEBitVector(arg1, arg2))
+               *mkValHelper<cvc5::FloatingPointToFPIEEEBitVector>(
+                    cvc5::FloatingPointToFPIEEEBitVector(arg1, arg2))
                     .d_node);
       break;
     case FLOATINGPOINT_TO_FP_FLOATINGPOINT:
       res = Op(this,
                kind,
-               *mkValHelper<CVC4::FloatingPointToFPFloatingPoint>(
-                    CVC4::FloatingPointToFPFloatingPoint(arg1, arg2))
+               *mkValHelper<cvc5::FloatingPointToFPFloatingPoint>(
+                    cvc5::FloatingPointToFPFloatingPoint(arg1, arg2))
                     .d_node);
       break;
     case FLOATINGPOINT_TO_FP_REAL:
       res = Op(this,
                kind,
-               *mkValHelper<CVC4::FloatingPointToFPReal>(
-                    CVC4::FloatingPointToFPReal(arg1, arg2))
+               *mkValHelper<cvc5::FloatingPointToFPReal>(
+                    cvc5::FloatingPointToFPReal(arg1, arg2))
                     .d_node);
       break;
     case FLOATINGPOINT_TO_FP_SIGNED_BITVECTOR:
       res = Op(this,
                kind,
-               *mkValHelper<CVC4::FloatingPointToFPSignedBitVector>(
-                    CVC4::FloatingPointToFPSignedBitVector(arg1, arg2))
+               *mkValHelper<cvc5::FloatingPointToFPSignedBitVector>(
+                    cvc5::FloatingPointToFPSignedBitVector(arg1, arg2))
                     .d_node);
       break;
     case FLOATINGPOINT_TO_FP_UNSIGNED_BITVECTOR:
       res = Op(this,
                kind,
-               *mkValHelper<CVC4::FloatingPointToFPUnsignedBitVector>(
-                    CVC4::FloatingPointToFPUnsignedBitVector(arg1, arg2))
+               *mkValHelper<cvc5::FloatingPointToFPUnsignedBitVector>(
+                    cvc5::FloatingPointToFPUnsignedBitVector(arg1, arg2))
                     .d_node);
       break;
     case FLOATINGPOINT_TO_FP_GENERIC:
       res = Op(this,
                kind,
-               *mkValHelper<CVC4::FloatingPointToFPGeneric>(
-                    CVC4::FloatingPointToFPGeneric(arg1, arg2))
+               *mkValHelper<cvc5::FloatingPointToFPGeneric>(
+                    cvc5::FloatingPointToFPGeneric(arg1, arg2))
                     .d_node);
       break;
     case REGEXP_LOOP:
       res = Op(
           this,
           kind,
-          *mkValHelper<CVC4::RegExpLoop>(CVC4::RegExpLoop(arg1, arg2)).d_node);
+          *mkValHelper<cvc5::RegExpLoop>(cvc5::RegExpLoop(arg1, arg2)).d_node);
       break;
     default:
       CVC4_API_KIND_CHECK_EXPECTED(false, kind)
@@ -4743,8 +5765,38 @@ Op Solver::mkOp(Kind kind, uint32_t arg1, uint32_t arg2) const
   }
   Assert(!res.isNull());
   return res;
+  ////////
+  CVC4_API_TRY_CATCH_END;
+}
 
-  CVC4_API_SOLVER_TRY_CATCH_END;
+Op Solver::mkOp(Kind kind, const std::vector<uint32_t>& args) const
+{
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_KIND_CHECK(kind);
+  //////// all checks before this line
+
+  Op res;
+  switch (kind)
+  {
+    case TUPLE_PROJECT:
+    {
+      res = Op(this,
+               kind,
+               *mkValHelper<cvc5::TupleProjectOp>(cvc5::TupleProjectOp(args))
+                    .d_node);
+    }
+    break;
+    default:
+    {
+      std::string message = "operator kind with " + std::to_string(args.size())
+                            + " uint32_t arguments";
+      CVC4_API_KIND_CHECK_EXPECTED(false, kind) << message;
+    }
+  }
+  Assert(!res.isNull());
+  return res;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* Non-SMT-LIB commands                                                       */
@@ -4752,52 +5804,44 @@ Op Solver::mkOp(Kind kind, uint32_t arg1, uint32_t arg2) const
 
 Term Solver::simplify(const Term& term)
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
-  CVC4_API_ARG_CHECK_NOT_NULL(term);
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_TERM(term);
-
-  return Term(this, d_smtEngine->simplify(term.d_node->toExpr()));
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  //////// all checks before this line
+  return Term(this, d_smtEngine->simplify(*term.d_node));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Result Solver::checkEntailed(Term term) const
+Result Solver::checkEntailed(const Term& term) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(!d_smtEngine->isQueryMade()
                  || d_smtEngine->getOptions()[options::incrementalSolving])
       << "Cannot make multiple queries unless incremental solving is enabled "
          "(try --incremental)";
-  CVC4_API_ARG_CHECK_NOT_NULL(term);
   CVC4_API_SOLVER_CHECK_TERM(term);
-
-  CVC4::Result r = d_smtEngine->checkEntailed(*term.d_node);
+  //////// all checks before this line
+  cvc5::Result r = d_smtEngine->checkEntailed(*term.d_node);
   return Result(r);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Result Solver::checkEntailed(const std::vector<Term>& terms) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  CVC4_API_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
   CVC4_API_CHECK(!d_smtEngine->isQueryMade()
                  || d_smtEngine->getOptions()[options::incrementalSolving])
       << "Cannot make multiple queries unless incremental solving is enabled "
          "(try --incremental)";
-  for (const Term& term : terms)
-  {
-    CVC4_API_SOLVER_CHECK_TERM(term);
-    CVC4_API_ARG_CHECK_NOT_NULL(term);
-  }
-
-  std::vector<Node> exprs = termVectorToNodes(terms);
-  CVC4::Result r = d_smtEngine->checkEntailed(exprs);
-  return Result(r);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  CVC4_API_SOLVER_CHECK_TERMS(terms);
+  //////// all checks before this line
+  return d_smtEngine->checkEntailed(Term::termVectorToNodes(terms));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /* SMT-LIB commands                                                           */
@@ -4806,13 +5850,15 @@ Result Solver::checkEntailed(const std::vector<Term>& terms) const
 /**
  *  ( assert <term> )
  */
-void Solver::assertFormula(Term term) const
+void Solver::assertFormula(const Term& term) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_TERM(term);
-  CVC4_API_ARG_CHECK_NOT_NULL(term);
+  CVC4_API_SOLVER_CHECK_TERM_WITH_SORT(term, getBooleanSort());
+  //////// all checks before this line
   d_smtEngine->assertFormula(*term.d_node);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -4820,32 +5866,36 @@ void Solver::assertFormula(Term term) const
  */
 Result Solver::checkSat(void) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  CVC4_API_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
   CVC4_API_CHECK(!d_smtEngine->isQueryMade()
                  || d_smtEngine->getOptions()[options::incrementalSolving])
       << "Cannot make multiple queries unless incremental solving is enabled "
          "(try --incremental)";
-  CVC4::Result r = d_smtEngine->checkSat();
+  //////// all checks before this line
+  cvc5::Result r = d_smtEngine->checkSat();
   return Result(r);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
  *  ( check-sat-assuming ( <prop_literal> ) )
  */
-Result Solver::checkSatAssuming(Term assumption) const
+Result Solver::checkSatAssuming(const Term& assumption) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  CVC4_API_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
   CVC4_API_CHECK(!d_smtEngine->isQueryMade()
                  || d_smtEngine->getOptions()[options::incrementalSolving])
       << "Cannot make multiple queries unless incremental solving is enabled "
          "(try --incremental)";
-  CVC4_API_SOLVER_CHECK_TERM(assumption);
-  CVC4::Result r = d_smtEngine->checkSat(*assumption.d_node);
+  CVC4_API_SOLVER_CHECK_TERM_WITH_SORT(assumption, getBooleanSort());
+  //////// all checks before this line
+  cvc5::Result r = d_smtEngine->checkSat(*assumption.d_node);
   return Result(r);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -4853,21 +5903,23 @@ Result Solver::checkSatAssuming(Term assumption) const
  */
 Result Solver::checkSatAssuming(const std::vector<Term>& assumptions) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  CVC4_API_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
   CVC4_API_CHECK(!d_smtEngine->isQueryMade() || assumptions.size() == 0
                  || d_smtEngine->getOptions()[options::incrementalSolving])
       << "Cannot make multiple queries unless incremental solving is enabled "
          "(try --incremental)";
+  CVC4_API_SOLVER_CHECK_TERMS_WITH_SORT(assumptions, getBooleanSort());
+  //////// all checks before this line
   for (const Term& term : assumptions)
   {
     CVC4_API_SOLVER_CHECK_TERM(term);
-    CVC4_API_ARG_CHECK_NOT_NULL(term);
   }
-  std::vector<Node> eassumptions = termVectorToNodes(assumptions);
-  CVC4::Result r = d_smtEngine->checkSat(eassumptions);
+  std::vector<Node> eassumptions = Term::termVectorToNodes(assumptions);
+  cvc5::Result r = d_smtEngine->checkSat(eassumptions);
   return Result(r);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -4877,21 +5929,19 @@ Sort Solver::declareDatatype(
     const std::string& symbol,
     const std::vector<DatatypeConstructorDecl>& ctors) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_ARG_CHECK_EXPECTED(ctors.size() > 0, ctors)
       << "a datatype declaration with at least one constructor";
+  CVC4_API_SOLVER_CHECK_DTCTORDECLS(ctors);
+  //////// all checks before this line
   DatatypeDecl dtdecl(this, symbol);
   for (size_t i = 0, size = ctors.size(); i < size; i++)
   {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(this == ctors[i].d_solver,
-                                         "datatype constructor declaration",
-                                         ctors[i],
-                                         i)
-        << "datatype constructor declaration associated to this solver object";
     dtdecl.addConstructor(ctors[i]);
   }
   return Sort(this, getNodeManager()->mkDatatypeType(*dtdecl.d_dtype));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -4899,30 +5949,22 @@ Sort Solver::declareDatatype(
  */
 Term Solver::declareFun(const std::string& symbol,
                         const std::vector<Sort>& sorts,
-                        Sort sort) const
+                        const Sort& sort) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  for (size_t i = 0, size = sorts.size(); i < size; ++i)
-  {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == sorts[i].d_solver, "parameter sort", sorts[i], i)
-        << "parameter sort associated to this solver object";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        sorts[i].isFirstClass(), "parameter sort", sorts[i], i)
-        << "first-class sort as parameter sort for function sort";
-  }
-  CVC4_API_ARG_CHECK_EXPECTED(sort.isFirstClass(), sort)
-      << "first-class sort as function codomain sort";
-  CVC4_API_SOLVER_CHECK_SORT(sort);
-  Assert(!sort.isFunction()); /* A function sort is not first-class. */
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_DOMAIN_SORTS(sorts);
+  CVC4_API_SOLVER_CHECK_CODOMAIN_SORT(sort);
+  //////// all checks before this line
+
   TypeNode type = *sort.d_type;
   if (!sorts.empty())
   {
-    std::vector<TypeNode> types = sortVectorToTypeNodes(sorts);
+    std::vector<TypeNode> types = Sort::sortVectorToTypeNodes(sorts);
     type = getNodeManager()->mkFunctionType(types, type);
   }
-  return Term(this, d_exprMgr->mkVar(symbol, type.toType()));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  return Term(this, d_nodeMgr->mkVar(symbol, type));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -4930,13 +5972,15 @@ Term Solver::declareFun(const std::string& symbol,
  */
 Sort Solver::declareSort(const std::string& symbol, uint32_t arity) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   if (arity == 0)
   {
     return Sort(this, getNodeManager()->mkSort(symbol));
   }
   return Sort(this, getNodeManager()->mkSortConstructor(symbol, arity));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -4944,79 +5988,52 @@ Sort Solver::declareSort(const std::string& symbol, uint32_t arity) const
  */
 Term Solver::defineFun(const std::string& symbol,
                        const std::vector<Term>& bound_vars,
-                       Sort sort,
-                       Term term,
+                       const Sort& sort,
+                       const Term& term,
                        bool global) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_EXPECTED(sort.isFirstClass(), sort)
-      << "first-class sort as codomain sort for function sort";
-  std::vector<TypeNode> domain_types;
-  for (size_t i = 0, size = bound_vars.size(); i < size; ++i)
-  {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == bound_vars[i].d_solver, "bound variable", bound_vars[i], i)
-        << "bound variable associated to this solver object";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        bound_vars[i].d_node->getKind() == CVC4::Kind::BOUND_VARIABLE,
-        "bound variable",
-        bound_vars[i],
-        i)
-        << "a bound variable";
-    CVC4::TypeNode t = bound_vars[i].d_node->getType();
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        t.isFirstClass(), "sort of parameter", bound_vars[i], i)
-        << "first-class sort of parameter of defined function";
-    domain_types.push_back(t);
-  }
-  CVC4_API_SOLVER_CHECK_SORT(sort);
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_CODOMAIN_SORT(sort);
+  CVC4_API_SOLVER_CHECK_TERM(term);
   CVC4_API_CHECK(sort == term.getSort())
       << "Invalid sort of function body '" << term << "', expected '" << sort
       << "'";
-  NodeManager* nm = getNodeManager();
-  TypeNode type = *sort.d_type;
-  if (!domain_types.empty())
+
+  std::vector<Sort> domain_sorts;
+  for (const auto& bv : bound_vars)
   {
-    type = nm->mkFunctionType(domain_types, type);
+    domain_sorts.push_back(bv.getSort());
   }
-  Node fun = Node::fromExpr(d_exprMgr->mkVar(symbol, type.toType()));
-  std::vector<Node> ebound_vars = termVectorToNodes(bound_vars);
-  d_smtEngine->defineFunction(fun, ebound_vars, *term.d_node, global);
-  return Term(this, fun);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  Sort fun_sort =
+      domain_sorts.empty()
+          ? sort
+          : Sort(this,
+                 getNodeManager()->mkFunctionType(
+                     Sort::sortVectorToTypeNodes(domain_sorts), *sort.d_type));
+  Term fun = mkConst(fun_sort, symbol);
+
+  CVC4_API_SOLVER_CHECK_BOUND_VARS_DEF_FUN(fun, bound_vars, domain_sorts);
+  //////// all checks before this line
+
+  d_smtEngine->defineFunction(
+      *fun.d_node, Term::termVectorToNodes(bound_vars), *term.d_node, global);
+  return fun;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::defineFun(Term fun,
+Term Solver::defineFun(const Term& fun,
                        const std::vector<Term>& bound_vars,
-                       Term term,
+                       const Term& term,
                        bool global) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_TERM(fun);
+  CVC4_API_SOLVER_CHECK_TERM(term);
   if (fun.getSort().isFunction())
   {
     std::vector<Sort> domain_sorts = fun.getSort().getFunctionDomainSorts();
-    size_t size = bound_vars.size();
-    CVC4_API_ARG_SIZE_CHECK_EXPECTED(size == domain_sorts.size(), bound_vars)
-        << "'" << domain_sorts.size() << "'";
-    for (size_t i = 0; i < size; ++i)
-    {
-      CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-          this == bound_vars[i].d_solver, "bound variable", bound_vars[i], i)
-          << "bound variable associated to this solver object";
-      CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-          bound_vars[i].d_node->getKind() == CVC4::Kind::BOUND_VARIABLE,
-          "bound variable",
-          bound_vars[i],
-          i)
-          << "a bound variable";
-      CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-          domain_sorts[i] == bound_vars[i].getSort(),
-          "sort of parameter",
-          bound_vars[i],
-          i)
-          << "'" << domain_sorts[i] << "'";
-    }
+    CVC4_API_SOLVER_CHECK_BOUND_VARS_DEF_FUN(fun, bound_vars, domain_sorts);
     Sort codomain = fun.getSort().getFunctionCodomainSort();
     CVC4_API_CHECK(codomain == term.getSort())
         << "Invalid sort of function body '" << term << "', expected '"
@@ -5024,16 +6041,16 @@ Term Solver::defineFun(Term fun,
   }
   else
   {
+    CVC4_API_SOLVER_CHECK_BOUND_VARS(bound_vars);
     CVC4_API_ARG_CHECK_EXPECTED(bound_vars.size() == 0, fun)
         << "function or nullary symbol";
   }
-
-  CVC4_API_SOLVER_CHECK_TERM(term);
-
-  std::vector<Node> ebound_vars = termVectorToNodes(bound_vars);
+  //////// all checks before this line
+  std::vector<Node> ebound_vars = Term::termVectorToNodes(bound_vars);
   d_smtEngine->defineFunction(*fun.d_node, ebound_vars, *term.d_node, global);
   return fun;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5041,12 +6058,12 @@ Term Solver::defineFun(Term fun,
  */
 Term Solver::defineFunRec(const std::string& symbol,
                           const std::vector<Term>& bound_vars,
-                          Sort sort,
-                          Term term,
+                          const Sort& sort,
+                          const Term& term,
                           bool global) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
 
   CVC4_API_CHECK(d_smtEngine->getUserLogicInfo().isQuantified())
       << "recursive function definitions require a logic with quantifiers";
@@ -5055,53 +6072,43 @@ Term Solver::defineFunRec(const std::string& symbol,
       << "recursive function definitions require a logic with uninterpreted "
          "functions";
 
-  CVC4_API_ARG_CHECK_EXPECTED(sort.isFirstClass(), sort)
-      << "first-class sort as function codomain sort";
-  Assert(!sort.isFunction()); /* A function sort is not first-class. */
-  std::vector<TypeNode> domain_types;
-  for (size_t i = 0, size = bound_vars.size(); i < size; ++i)
-  {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == bound_vars[i].d_solver, "bound variable", bound_vars[i], i)
-        << "bound variable associated to this solver object";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        bound_vars[i].d_node->getKind() == CVC4::Kind::BOUND_VARIABLE,
-        "bound variable",
-        bound_vars[i],
-        i)
-        << "a bound variable";
-    CVC4::TypeNode t = bound_vars[i].d_node->getType();
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        t.isFirstClass(), "sort of parameter", bound_vars[i], i)
-        << "first-class sort of parameter of defined function";
-    domain_types.push_back(t);
-  }
-  CVC4_API_SOLVER_CHECK_SORT(sort);
+  CVC4_API_SOLVER_CHECK_TERM(term);
+  CVC4_API_SOLVER_CHECK_CODOMAIN_SORT(sort);
   CVC4_API_CHECK(sort == term.getSort())
       << "Invalid sort of function body '" << term << "', expected '" << sort
       << "'";
-  CVC4_API_SOLVER_CHECK_TERM(term);
-  NodeManager* nm = getNodeManager();
-  TypeNode type = *sort.d_type;
-  if (!domain_types.empty())
+
+  std::vector<Sort> domain_sorts;
+  for (const auto& bv : bound_vars)
   {
-    type = nm->mkFunctionType(domain_types, type);
+    domain_sorts.push_back(bv.getSort());
   }
-  Node fun = Node::fromExpr(d_exprMgr->mkVar(symbol, type.toType()));
-  std::vector<Node> ebound_vars = termVectorToNodes(bound_vars);
+  Sort fun_sort =
+      domain_sorts.empty()
+          ? sort
+          : Sort(this,
+                 getNodeManager()->mkFunctionType(
+                     Sort::sortVectorToTypeNodes(domain_sorts), *sort.d_type));
+  Term fun = mkConst(fun_sort, symbol);
+
+  CVC4_API_SOLVER_CHECK_BOUND_VARS_DEF_FUN(fun, bound_vars, domain_sorts);
+  //////// all checks before this line
+
   d_smtEngine->defineFunctionRec(
-      fun, ebound_vars, term.d_node->toExpr(), global);
-  return Term(this, fun);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+      *fun.d_node, Term::termVectorToNodes(bound_vars), *term.d_node, global);
+
+  return fun;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::defineFunRec(Term fun,
+Term Solver::defineFunRec(const Term& fun,
                           const std::vector<Term>& bound_vars,
-                          Term term,
+                          const Term& term,
                           bool global) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
 
   CVC4_API_CHECK(d_smtEngine->getUserLogicInfo().isQuantified())
       << "recursive function definitions require a logic with quantifiers";
@@ -5110,30 +6117,12 @@ Term Solver::defineFunRec(Term fun,
       << "recursive function definitions require a logic with uninterpreted "
          "functions";
 
+  CVC4_API_SOLVER_CHECK_TERM(fun);
+  CVC4_API_SOLVER_CHECK_TERM(term);
   if (fun.getSort().isFunction())
   {
     std::vector<Sort> domain_sorts = fun.getSort().getFunctionDomainSorts();
-    size_t size = bound_vars.size();
-    CVC4_API_ARG_SIZE_CHECK_EXPECTED(size == domain_sorts.size(), bound_vars)
-        << "'" << domain_sorts.size() << "'";
-    for (size_t i = 0; i < size; ++i)
-    {
-      CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-          this == bound_vars[i].d_solver, "bound variable", bound_vars[i], i)
-          << "bound variable associated to this solver object";
-      CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-          bound_vars[i].d_node->getKind() == CVC4::Kind::BOUND_VARIABLE,
-          "bound variable",
-          bound_vars[i],
-          i)
-          << "a bound variable";
-      CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-          domain_sorts[i] == bound_vars[i].getSort(),
-          "sort of parameter",
-          bound_vars[i],
-          i)
-          << "'" << domain_sorts[i] << "'";
-    }
+    CVC4_API_SOLVER_CHECK_BOUND_VARS_DEF_FUN(fun, bound_vars, domain_sorts);
     Sort codomain = fun.getSort().getFunctionCodomainSort();
     CVC4_API_CHECK(codomain == term.getSort())
         << "Invalid sort of function body '" << term << "', expected '"
@@ -5141,16 +6130,18 @@ Term Solver::defineFunRec(Term fun,
   }
   else
   {
+    CVC4_API_SOLVER_CHECK_BOUND_VARS(bound_vars);
     CVC4_API_ARG_CHECK_EXPECTED(bound_vars.size() == 0, fun)
         << "function or nullary symbol";
   }
+  //////// all checks before this line
 
-  CVC4_API_SOLVER_CHECK_TERM(term);
-  std::vector<Node> ebound_vars = termVectorToNodes(bound_vars);
+  std::vector<Node> ebound_vars = Term::termVectorToNodes(bound_vars);
   d_smtEngine->defineFunctionRec(
       *fun.d_node, ebound_vars, *term.d_node, global);
   return fun;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5162,7 +6153,7 @@ void Solver::defineFunsRec(const std::vector<Term>& funs,
                            bool global) const
 {
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
 
   CVC4_API_CHECK(d_smtEngine->getUserLogicInfo().isQuantified())
       << "recursive function definitions require a logic with quantifiers";
@@ -5170,10 +6161,15 @@ void Solver::defineFunsRec(const std::vector<Term>& funs,
       d_smtEngine->getUserLogicInfo().isTheoryEnabled(theory::THEORY_UF))
       << "recursive function definitions require a logic with uninterpreted "
          "functions";
+  CVC4_API_SOLVER_CHECK_TERMS(funs);
+  CVC4_API_SOLVER_CHECK_TERMS(terms);
 
   size_t funs_size = funs.size();
   CVC4_API_ARG_SIZE_CHECK_EXPECTED(funs_size == bound_vars.size(), bound_vars)
       << "'" << funs_size << "'";
+  CVC4_API_ARG_SIZE_CHECK_EXPECTED(funs_size == terms.size(), terms)
+      << "'" << funs_size << "'";
+
   for (size_t j = 0; j < funs_size; ++j)
   {
     const Term& fun = funs[j];
@@ -5181,58 +6177,39 @@ void Solver::defineFunsRec(const std::vector<Term>& funs,
     const Term& term = terms[j];
 
     CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == fun.d_solver, "function", fun, j)
-        << "function associated to this solver object";
-    CVC4_API_SOLVER_CHECK_TERM(term);
+        this == fun.d_solver, "function", funs, j)
+        << "function associated with this solver object";
+    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
+        this == term.d_solver, "term", terms, j)
+        << "term associated with this solver object";
 
     if (fun.getSort().isFunction())
     {
       std::vector<Sort> domain_sorts = fun.getSort().getFunctionDomainSorts();
-      size_t size = bvars.size();
-      CVC4_API_ARG_SIZE_CHECK_EXPECTED(size == domain_sorts.size(), bvars)
-          << "'" << domain_sorts.size() << "'";
-      for (size_t i = 0; i < size; ++i)
-      {
-        for (size_t k = 0, nbvars = bvars.size(); k < nbvars; ++k)
-        {
-          CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-              this == bvars[k].d_solver, "bound variable", bvars[k], k)
-              << "bound variable associated to this solver object";
-          CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-              bvars[k].d_node->getKind() == CVC4::Kind::BOUND_VARIABLE,
-              "bound variable",
-              bvars[k],
-              k)
-              << "a bound variable";
-        }
-        CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-            domain_sorts[i] == bvars[i].getSort(),
-            "sort of parameter",
-            bvars[i],
-            i)
-            << "'" << domain_sorts[i] << "' in parameter bound_vars[" << j
-            << "]";
-      }
+      CVC4_API_SOLVER_CHECK_BOUND_VARS_DEF_FUN(fun, bvars, domain_sorts);
       Sort codomain = fun.getSort().getFunctionCodomainSort();
       CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-          codomain == term.getSort(), "sort of function body", term, j)
+          codomain == term.getSort(), "sort of function body", terms, j)
           << "'" << codomain << "'";
     }
     else
     {
+      CVC4_API_SOLVER_CHECK_BOUND_VARS(bvars);
       CVC4_API_ARG_CHECK_EXPECTED(bvars.size() == 0, fun)
           << "function or nullary symbol";
     }
   }
-  std::vector<Node> efuns = termVectorToNodes(funs);
+  //////// all checks before this line
+  std::vector<Node> efuns = Term::termVectorToNodes(funs);
   std::vector<std::vector<Node>> ebound_vars;
   for (const auto& v : bound_vars)
   {
-    ebound_vars.push_back(termVectorToNodes(v));
+    ebound_vars.push_back(Term::termVectorToNodes(v));
   }
-  std::vector<Node> exprs = termVectorToNodes(terms);
-  d_smtEngine->defineFunctionsRec(efuns, ebound_vars, exprs, global);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  std::vector<Node> nodes = Term::termVectorToNodes(terms);
+  d_smtEngine->defineFunctionsRec(efuns, ebound_vars, nodes, global);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5248,7 +6225,8 @@ void Solver::echo(std::ostream& out, const std::string& str) const
  */
 std::vector<Term> Solver::getAssertions(void) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   std::vector<Node> assertions = d_smtEngine->getAssertions();
   /* Can not use
    *   return std::vector<Term>(assertions.begin(), assertions.end());
@@ -5259,7 +6237,8 @@ std::vector<Term> Solver::getAssertions(void) const
     res.push_back(Term(this, e));
   }
   return res;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5267,12 +6246,13 @@ std::vector<Term> Solver::getAssertions(void) const
  */
 std::string Solver::getInfo(const std::string& flag) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_RECOVERABLE_CHECK(d_smtEngine->isValidGetInfoFlag(flag))
       << "Unrecognized flag for getInfo.";
-
+  //////// all checks before this line
   return d_smtEngine->getInfo(flag).toString();
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5280,10 +6260,12 @@ std::string Solver::getInfo(const std::string& flag) const
  */
 std::string Solver::getOption(const std::string& option) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  SExpr res = d_smtEngine->getOption(option);
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
+  Node res = d_smtEngine->getOption(option);
   return res.toString();
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5291,8 +6273,8 @@ std::string Solver::getOption(const std::string& option) const
  */
 std::vector<Term> Solver::getUnsatAssumptions(void) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  CVC4_API_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
   CVC4_API_CHECK(d_smtEngine->getOptions()[options::incrementalSolving])
       << "Cannot get unsat assumptions unless incremental solving is enabled "
          "(try --incremental)";
@@ -5301,18 +6283,20 @@ std::vector<Term> Solver::getUnsatAssumptions(void) const
          "(try --produce-unsat-assumptions)";
   CVC4_API_CHECK(d_smtEngine->getSmtMode() == SmtMode::UNSAT)
       << "Cannot get unsat assumptions unless in unsat mode.";
+  //////// all checks before this line
 
   std::vector<Node> uassumptions = d_smtEngine->getUnsatAssumptions();
   /* Can not use
    *   return std::vector<Term>(uassumptions.begin(), uassumptions.end());
    * here since constructor is private */
   std::vector<Term> res;
-  for (const Node& e : uassumptions)
+  for (const Node& n : uassumptions)
   {
-    res.push_back(Term(this, e.toExpr()));
+    res.push_back(Term(this, n));
   }
   return res;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5320,13 +6304,14 @@ std::vector<Term> Solver::getUnsatAssumptions(void) const
  */
 std::vector<Term> Solver::getUnsatCore(void) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  CVC4_API_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
   CVC4_API_CHECK(d_smtEngine->getOptions()[options::unsatCores])
       << "Cannot get unsat core unless explicitly enabled "
          "(try --produce-unsat-cores)";
   CVC4_API_RECOVERABLE_CHECK(d_smtEngine->getSmtMode() == SmtMode::UNSAT)
       << "Cannot get unsat core unless in unsat mode.";
+  //////// all checks before this line
   UnsatCore core = d_smtEngine->getUnsatCore();
   /* Can not use
    *   return std::vector<Term>(core.begin(), core.end());
@@ -5337,18 +6322,21 @@ std::vector<Term> Solver::getUnsatCore(void) const
     res.push_back(Term(this, e));
   }
   return res;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
  *  ( get-value ( <term> ) )
  */
-Term Solver::getValue(Term term) const
+Term Solver::getValue(const Term& term) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_TERM(term);
+  //////// all checks before this line
   return getValueHelper(term);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5356,91 +6344,103 @@ Term Solver::getValue(Term term) const
  */
 std::vector<Term> Solver::getValue(const std::vector<Term>& terms) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  CVC4_API_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
   CVC4_API_RECOVERABLE_CHECK(d_smtEngine->getOptions()[options::produceModels])
       << "Cannot get value unless model generation is enabled "
          "(try --produce-models)";
   CVC4_API_RECOVERABLE_CHECK(d_smtEngine->isSmtModeSat())
       << "Cannot get value unless after a SAT or unknown response.";
+  CVC4_API_SOLVER_CHECK_TERMS(terms);
+  //////// all checks before this line
+
   std::vector<Term> res;
   for (size_t i = 0, n = terms.size(); i < n; ++i)
   {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == terms[i].d_solver, "term", terms[i], i)
-        << "term associated to this solver object";
     /* Can not use emplace_back here since constructor is private. */
     res.push_back(getValueHelper(terms[i]));
   }
   return res;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::getQuantifierElimination(api::Term q) const
+Term Solver::getQuantifierElimination(const Term& q) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_NOT_NULL(q);
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_TERM(q);
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  //////// all checks before this line
   return Term(this,
               d_smtEngine->getQuantifierElimination(q.getNode(), true, true));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::getQuantifierEliminationDisjunct(api::Term q) const
+Term Solver::getQuantifierEliminationDisjunct(const Term& q) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_NOT_NULL(q);
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_TERM(q);
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  //////// all checks before this line
   return Term(
       this, d_smtEngine->getQuantifierElimination(q.getNode(), false, true));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-void Solver::declareSeparationHeap(api::Sort locSort, api::Sort dataSort) const
+void Solver::declareSeparationHeap(const Sort& locSort,
+                                   const Sort& dataSort) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_SORT(locSort);
+  CVC4_API_SOLVER_CHECK_SORT(dataSort);
   CVC4_API_CHECK(
       d_smtEngine->getLogicInfo().isTheoryEnabled(theory::THEORY_SEP))
       << "Cannot obtain separation logic expressions if not using the "
          "separation logic theory.";
+  //////// all checks before this line
   d_smtEngine->declareSepHeap(locSort.getTypeNode(), dataSort.getTypeNode());
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::getSeparationHeap() const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(
       d_smtEngine->getLogicInfo().isTheoryEnabled(theory::THEORY_SEP))
       << "Cannot obtain separation logic expressions if not using the "
          "separation logic theory.";
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
   CVC4_API_CHECK(d_smtEngine->getOptions()[options::produceModels])
       << "Cannot get separation heap term unless model generation is enabled "
          "(try --produce-models)";
   CVC4_API_RECOVERABLE_CHECK(d_smtEngine->isSmtModeSat())
       << "Can only get separtion heap term after sat or unknown response.";
+  //////// all checks before this line
   return Term(this, d_smtEngine->getSepHeapExpr());
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::getSeparationNilTerm() const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(
       d_smtEngine->getLogicInfo().isTheoryEnabled(theory::THEORY_SEP))
       << "Cannot obtain separation logic expressions if not using the "
          "separation logic theory.";
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
   CVC4_API_CHECK(d_smtEngine->getOptions()[options::produceModels])
       << "Cannot get separation nil term unless model generation is enabled "
          "(try --produce-models)";
   CVC4_API_RECOVERABLE_CHECK(d_smtEngine->isSmtModeSat())
       << "Can only get separtion nil term after sat or unknown response.";
+  //////// all checks before this line
   return Term(this, d_smtEngine->getSepNilExpr());
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5448,25 +6448,27 @@ Term Solver::getSeparationNilTerm() const
  */
 void Solver::pop(uint32_t nscopes) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(d_smtEngine->getOptions()[options::incrementalSolving])
       << "Cannot pop when not solving incrementally (use --incremental)";
   CVC4_API_CHECK(nscopes <= d_smtEngine->getNumUserLevels())
       << "Cannot pop beyond first pushed context";
-
+  //////// all checks before this line
   for (uint32_t n = 0; n < nscopes; ++n)
   {
     d_smtEngine->pop();
   }
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-bool Solver::getInterpolant(Term conj, Term& output) const
+bool Solver::getInterpolant(const Term& conj, Term& output) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_TERM(conj);
+  //////// all checks before this line
   Node result;
   bool success = d_smtEngine->getInterpol(*conj.d_node, result);
   if (success)
@@ -5474,28 +6476,36 @@ bool Solver::getInterpolant(Term conj, Term& output) const
     output = Term(this, result);
   }
   return success;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-bool Solver::getInterpolant(Term conj, Grammar& g, Term& output) const
+bool Solver::getInterpolant(const Term& conj,
+                            Grammar& grammar,
+                            Term& output) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_TERM(conj);
+  //////// all checks before this line
   Node result;
   bool success =
-      d_smtEngine->getInterpol(*conj.d_node, *g.resolve().d_type, result);
+      d_smtEngine->getInterpol(*conj.d_node, *grammar.resolve().d_type, result);
   if (success)
   {
     output = Term(this, result);
   }
   return success;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-bool Solver::getAbduct(Term conj, Term& output) const
+bool Solver::getAbduct(const Term& conj, Term& output) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_TERM(conj);
+  //////// all checks before this line
   Node result;
   bool success = d_smtEngine->getAbduct(*conj.d_node, result);
   if (success)
@@ -5503,40 +6513,47 @@ bool Solver::getAbduct(Term conj, Term& output) const
     output = Term(this, result);
   }
   return success;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-bool Solver::getAbduct(Term conj, Grammar& g, Term& output) const
+bool Solver::getAbduct(const Term& conj, Grammar& grammar, Term& output) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_TERM(conj);
+  //////// all checks before this line
   Node result;
   bool success =
-      d_smtEngine->getAbduct(*conj.d_node, *g.resolve().d_type, result);
+      d_smtEngine->getAbduct(*conj.d_node, *grammar.resolve().d_type, result);
   if (success)
   {
     output = Term(this, result);
   }
   return success;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 void Solver::blockModel() const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(d_smtEngine->getOptions()[options::produceModels])
       << "Cannot get value unless model generation is enabled "
          "(try --produce-models)";
   CVC4_API_RECOVERABLE_CHECK(d_smtEngine->isSmtModeSat())
       << "Can only block model after sat or unknown response.";
+  //////// all checks before this line
   d_smtEngine->blockModel();
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 void Solver::blockModelValues(const std::vector<Term>& terms) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(d_smtEngine->getOptions()[options::produceModels])
       << "Cannot get value unless model generation is enabled "
          "(try --produce-models)";
@@ -5544,26 +6561,21 @@ void Solver::blockModelValues(const std::vector<Term>& terms) const
       << "Can only block model values after sat or unknown response.";
   CVC4_API_ARG_SIZE_CHECK_EXPECTED(!terms.empty(), terms)
       << "a non-empty set of terms";
-  for (size_t i = 0, tsize = terms.size(); i < tsize; ++i)
-  {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        !terms[i].isNull(), "term", terms[i], i)
-        << "a non-null term";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == terms[i].d_solver, "term", terms[i], i)
-        << "a term associated to this solver object";
-  }
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
-  d_smtEngine->blockModelValues(termVectorToNodes(terms));
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  CVC4_API_SOLVER_CHECK_TERMS(terms);
+  //////// all checks before this line
+  d_smtEngine->blockModelValues(Term::termVectorToNodes(terms));
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 void Solver::printInstantiations(std::ostream& out) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   d_smtEngine->printInstantiations(out);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5571,17 +6583,17 @@ void Solver::printInstantiations(std::ostream& out) const
  */
 void Solver::push(uint32_t nscopes) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4::ExprManagerScope exmgrs(*(d_exprMgr.get()));
+  NodeManagerScope scope(getNodeManager());
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(d_smtEngine->getOptions()[options::incrementalSolving])
       << "Cannot push when not solving incrementally (use --incremental)";
-
+  //////// all checks before this line
   for (uint32_t n = 0; n < nscopes; ++n)
   {
     d_smtEngine->push();
   }
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5589,9 +6601,11 @@ void Solver::push(uint32_t nscopes) const
  */
 void Solver::resetAssertions(void) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   d_smtEngine->resetAssertions();
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5599,7 +6613,7 @@ void Solver::resetAssertions(void) const
  */
 void Solver::setInfo(const std::string& keyword, const std::string& value) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_RECOVERABLE_ARG_CHECK_EXPECTED(
       keyword == "source" || keyword == "category" || keyword == "difficulty"
           || keyword == "filename" || keyword == "license" || keyword == "name"
@@ -5617,9 +6631,10 @@ void Solver::setInfo(const std::string& keyword, const std::string& value) const
                                   || value == "unsat" || value == "unknown",
                               value)
       << "'sat', 'unsat' or 'unknown'";
-
+  //////// all checks before this line
   d_smtEngine->setInfo(keyword, value);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5627,12 +6642,14 @@ void Solver::setInfo(const std::string& keyword, const std::string& value) const
  */
 void Solver::setLogic(const std::string& logic) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(!d_smtEngine->isFullyInited())
       << "Invalid call to 'setLogic', solver is already fully initialized";
-  CVC4::LogicInfo logic_info(logic);
+  cvc5::LogicInfo logic_info(logic);
+  //////// all checks before this line
   d_smtEngine->setLogic(logic_info);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5641,196 +6658,111 @@ void Solver::setLogic(const std::string& logic) const
 void Solver::setOption(const std::string& option,
                        const std::string& value) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_CHECK(!d_smtEngine->isFullyInited())
       << "Invalid call to 'setOption', solver is already fully initialized";
+  //////// all checks before this line
   d_smtEngine->setOption(option, value);
-  CVC4_API_SOLVER_TRY_CATCH_END;
-}
-
-Term Solver::ensureTermSort(const Term& term, const Sort& sort) const
-{
-  CVC4_API_CHECK(term.getSort() == sort
-                 || (term.getSort().isInteger() && sort.isReal()))
-      << "Expected conversion from Int to Real";
-
-  Sort t = term.getSort();
-  if (term.getSort() == sort)
-  {
-    return term;
-  }
-
-  // Integers are reals, too
-  Assert(t.isReal());
-  Term res = term;
-  if (t.isInteger())
-  {
-    // Must cast to Real to ensure correct type is passed to parametric type
-    // constructors. We do this cast using division with 1. This has the
-    // advantage wrt using TO_REAL since (constant) division is always included
-    // in the theory.
-    res = Term(this,
-               d_exprMgr->mkExpr(extToIntKind(DIVISION),
-                                 res.d_node->toExpr(),
-                                 d_exprMgr->mkConst(CVC4::Rational(1))));
-  }
-  Assert(res.getSort() == sort);
-  return res;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-Term Solver::mkSygusVar(Sort sort, const std::string& symbol) const
+Term Solver::mkSygusVar(const Sort& sort, const std::string& symbol) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_NOT_NULL(sort);
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_SORT(sort);
-
+  //////// all checks before this line
   Node res = getNodeManager()->mkBoundVar(symbol, *sort.d_type);
   (void)res.getType(true); /* kick off type checking */
 
   d_smtEngine->declareSygusVar(res);
 
   return Term(this, res);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Grammar Solver::mkSygusGrammar(const std::vector<Term>& boundVars,
                                const std::vector<Term>& ntSymbols) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_ARG_SIZE_CHECK_EXPECTED(!ntSymbols.empty(), ntSymbols)
       << "a non-empty vector";
-
-  for (size_t i = 0, n = boundVars.size(); i < n; ++i)
-  {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == boundVars[i].d_solver, "bound variable", boundVars[i], i)
-        << "bound variable associated to this solver object";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        !boundVars[i].isNull(), "bound variable", boundVars[i], i)
-        << "a non-null term";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        boundVars[i].d_node->getKind() == CVC4::Kind::BOUND_VARIABLE,
-        "bound variable",
-        boundVars[i],
-        i)
-        << "a bound variable";
-  }
-
-  for (size_t i = 0, n = ntSymbols.size(); i < n; ++i)
-  {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == ntSymbols[i].d_solver, "non-terminal", ntSymbols[i], i)
-        << "term associated to this solver object";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        !ntSymbols[i].isNull(), "non-terminal", ntSymbols[i], i)
-        << "a non-null term";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        ntSymbols[i].d_node->getKind() == CVC4::Kind::BOUND_VARIABLE,
-        "non-terminal",
-        ntSymbols[i],
-        i)
-        << "a bound variable";
-  }
-
+  CVC4_API_SOLVER_CHECK_BOUND_VARS(boundVars);
+  CVC4_API_SOLVER_CHECK_BOUND_VARS(ntSymbols);
+  //////// all checks before this line
   return Grammar(this, boundVars, ntSymbols);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::synthFun(const std::string& symbol,
                       const std::vector<Term>& boundVars,
-                      Sort sort) const
+                      const Sort& sort) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_BOUND_VARS(boundVars);
+  CVC4_API_SOLVER_CHECK_SORT(sort);
+  //////// all checks before this line
   return synthFunHelper(symbol, boundVars, sort);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::synthFun(const std::string& symbol,
                       const std::vector<Term>& boundVars,
                       Sort sort,
-                      Grammar& g) const
+                      Grammar& grammar) const
 {
-  return synthFunHelper(symbol, boundVars, sort, false, &g);
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_BOUND_VARS(boundVars);
+  CVC4_API_SOLVER_CHECK_SORT(sort);
+  //////// all checks before this line
+  return synthFunHelper(symbol, boundVars, sort, false, &grammar);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::synthInv(const std::string& symbol,
                       const std::vector<Term>& boundVars) const
 {
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_BOUND_VARS(boundVars);
+  //////// all checks before this line
   return synthFunHelper(
       symbol, boundVars, Sort(this, getNodeManager()->booleanType()), true);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::synthInv(const std::string& symbol,
                       const std::vector<Term>& boundVars,
-                      Grammar& g) const
-{
-  return synthFunHelper(
-      symbol, boundVars, Sort(this, getNodeManager()->booleanType()), true, &g);
-}
-
-Term Solver::synthFunHelper(const std::string& symbol,
-                            const std::vector<Term>& boundVars,
-                            const Sort& sort,
-                            bool isInv,
-                            Grammar* g) const
+                      Grammar& grammar) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_NOT_NULL(sort);
-
-  std::vector<TypeNode> varTypes;
-  for (size_t i = 0, n = boundVars.size(); i < n; ++i)
-  {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == boundVars[i].d_solver, "bound variable", boundVars[i], i)
-        << "bound variable associated to this solver object";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        !boundVars[i].isNull(), "bound variable", boundVars[i], i)
-        << "a non-null term";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        boundVars[i].d_node->getKind() == CVC4::Kind::BOUND_VARIABLE,
-        "bound variable",
-        boundVars[i],
-        i)
-        << "a bound variable";
-    varTypes.push_back(boundVars[i].d_node->getType());
-  }
-  CVC4_API_SOLVER_CHECK_SORT(sort);
-
-  if (g != nullptr)
-  {
-    CVC4_API_CHECK(g->d_ntSyms[0].d_node->getType() == *sort.d_type)
-        << "Invalid Start symbol for Grammar g, Expected Start's sort to be "
-        << *sort.d_type << " but found " << g->d_ntSyms[0].d_node->getType();
-  }
-
-  TypeNode funType = varTypes.empty() ? *sort.d_type
-                                      : getNodeManager()->mkFunctionType(
-                                            varTypes, *sort.d_type);
-
-  Node fun = getNodeManager()->mkBoundVar(symbol, funType);
-  (void)fun.getType(true); /* kick off type checking */
-
-  std::vector<Node> bvns = termVectorToNodes(boundVars);
-
-  d_smtEngine->declareSynthFun(
-      fun, g == nullptr ? funType : *g->resolve().d_type, isInv, bvns);
-
-  return Term(this, fun);
-
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  CVC4_API_TRY_CATCH_BEGIN;
+  CVC4_API_SOLVER_CHECK_BOUND_VARS(boundVars);
+  //////// all checks before this line
+  return synthFunHelper(symbol,
+                        boundVars,
+                        Sort(this, getNodeManager()->booleanType()),
+                        true,
+                        &grammar);
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
-void Solver::addSygusConstraint(Term term) const
+void Solver::addSygusConstraint(const Term& term) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
   NodeManagerScope scope(getNodeManager());
-  CVC4_API_ARG_CHECK_NOT_NULL(term);
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_TERM(term);
   CVC4_API_ARG_CHECK_EXPECTED(
       term.d_node->getType() == getNodeManager()->booleanType(), term)
       << "boolean term";
-
+  //////// all checks before this line
   d_smtEngine->assertSygusConstraint(*term.d_node);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 void Solver::addSygusInvConstraint(Term inv,
@@ -5838,14 +6770,10 @@ void Solver::addSygusInvConstraint(Term inv,
                                    Term trans,
                                    Term post) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_NOT_NULL(inv);
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_TERM(inv);
-  CVC4_API_ARG_CHECK_NOT_NULL(pre);
   CVC4_API_SOLVER_CHECK_TERM(pre);
-  CVC4_API_ARG_CHECK_NOT_NULL(trans);
   CVC4_API_SOLVER_CHECK_TERM(trans);
-  CVC4_API_ARG_CHECK_NOT_NULL(post);
   CVC4_API_SOLVER_CHECK_TERM(post);
 
   CVC4_API_ARG_CHECK_EXPECTED(inv.d_node->getType().isFunction(), inv)
@@ -5861,6 +6789,7 @@ void Solver::addSygusInvConstraint(Term inv,
 
   CVC4_API_CHECK(post.d_node->getType() == invType)
       << "Expected inv and post to have the same sort";
+  //////// all checks before this line
 
   const std::vector<TypeNode>& invArgTypes = invType.getArgTypes();
 
@@ -5881,62 +6810,57 @@ void Solver::addSygusInvConstraint(Term inv,
 
   d_smtEngine->assertSygusInvConstraint(
       *inv.d_node, *pre.d_node, *trans.d_node, *post.d_node);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Result Solver::checkSynth() const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   return d_smtEngine->checkSynth();
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 Term Solver::getSynthSolution(Term term) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
-  CVC4_API_ARG_CHECK_NOT_NULL(term);
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_SOLVER_CHECK_TERM(term);
 
-  std::map<CVC4::Node, CVC4::Node> map;
+  std::map<cvc5::Node, cvc5::Node> map;
   CVC4_API_CHECK(d_smtEngine->getSynthSolutions(map))
       << "The solver is not in a state immediately preceded by a "
          "successful call to checkSynth";
 
-  std::map<CVC4::Node, CVC4::Node>::const_iterator it = map.find(*term.d_node);
+  std::map<cvc5::Node, cvc5::Node>::const_iterator it = map.find(*term.d_node);
 
   CVC4_API_CHECK(it != map.cend()) << "Synth solution not found for given term";
-
+  //////// all checks before this line
   return Term(this, it->second);
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 std::vector<Term> Solver::getSynthSolutions(
     const std::vector<Term>& terms) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
   CVC4_API_ARG_SIZE_CHECK_EXPECTED(!terms.empty(), terms) << "non-empty vector";
+  CVC4_API_SOLVER_CHECK_TERMS(terms);
 
-  for (size_t i = 0, n = terms.size(); i < n; ++i)
-  {
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        this == terms[i].d_solver, "parameter term", terms[i], i)
-        << "parameter term associated to this solver object";
-    CVC4_API_ARG_AT_INDEX_CHECK_EXPECTED(
-        !terms[i].isNull(), "parameter term", terms[i], i)
-        << "non-null term";
-  }
-
-  std::map<CVC4::Node, CVC4::Node> map;
+  std::map<cvc5::Node, cvc5::Node> map;
   CVC4_API_CHECK(d_smtEngine->getSynthSolutions(map))
       << "The solver is not in a state immediately preceded by a "
          "successful call to checkSynth";
+  //////// all checks before this line
 
   std::vector<Term> synthSolution;
   synthSolution.reserve(terms.size());
 
   for (size_t i = 0, n = terms.size(); i < n; ++i)
   {
-    std::map<CVC4::Node, CVC4::Node>::const_iterator it =
+    std::map<cvc5::Node, cvc5::Node>::const_iterator it =
         map.find(*terms[i].d_node);
 
     CVC4_API_CHECK(it != map.cend())
@@ -5946,29 +6870,17 @@ std::vector<Term> Solver::getSynthSolutions(
   }
 
   return synthSolution;
-  CVC4_API_SOLVER_TRY_CATCH_END;
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 void Solver::printSynthSolution(std::ostream& out) const
 {
-  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_TRY_CATCH_BEGIN;
+  //////// all checks before this line
   d_smtEngine->printSynthSolution(out);
-  CVC4_API_SOLVER_TRY_CATCH_END;
-}
-
-/**
- * !!! This is only temporarily available until the parser is fully migrated to
- * the new API. !!!
- */
-ExprManager* Solver::getExprManager(void) const { return d_exprMgr.get(); }
-
-/**
- * !!! This is only temporarily available until the parser is fully migrated to
- * the new API. !!!
- */
-NodeManager* Solver::getNodeManager(void) const
-{
-  return d_exprMgr->getNodeManager();
+  ////////
+  CVC4_API_TRY_CATCH_END;
 }
 
 /**
@@ -5983,116 +6895,6 @@ SmtEngine* Solver::getSmtEngine(void) const { return d_smtEngine.get(); }
  */
 Options& Solver::getOptions(void) { return d_smtEngine->getOptions(); }
 
-/* -------------------------------------------------------------------------- */
-/* Conversions                                                                */
-/* -------------------------------------------------------------------------- */
-
-std::vector<Expr> termVectorToExprs(const std::vector<Term>& terms)
-{
-  std::vector<Expr> exprs;
-  for (size_t i = 0, tsize = terms.size(); i < tsize; i++)
-  {
-    exprs.push_back(terms[i].getExpr());
-  }
-  return exprs;
-}
-
-std::vector<Node> termVectorToNodes(const std::vector<Term>& terms)
-{
-  std::vector<Node> res;
-  for (const Term& t : terms)
-  {
-    res.push_back(t.getNode());
-  }
-  return res;
-}
-
-std::vector<Type> sortVectorToTypes(const std::vector<Sort>& sorts)
-{
-  std::vector<Type> types;
-  for (size_t i = 0, ssize = sorts.size(); i < ssize; i++)
-  {
-    types.push_back(sorts[i].getTypeNode().toType());
-  }
-  return types;
-}
-
-std::vector<TypeNode> sortVectorToTypeNodes(const std::vector<Sort>& sorts)
-{
-  std::vector<TypeNode> typeNodes;
-  for (const Sort& sort : sorts)
-  {
-    typeNodes.push_back(sort.getTypeNode());
-  }
-  return typeNodes;
-}
-
-std::set<TypeNode> sortSetToTypeNodes(const std::set<Sort>& sorts)
-{
-  std::set<TypeNode> types;
-  for (const Sort& s : sorts)
-  {
-    types.insert(s.getTypeNode());
-  }
-  return types;
-}
-
-std::vector<Term> exprVectorToTerms(const Solver* slv,
-                                    const std::vector<Expr>& exprs)
-{
-  std::vector<Term> terms;
-  for (size_t i = 0, esize = exprs.size(); i < esize; i++)
-  {
-    terms.push_back(Term(slv, exprs[i]));
-  }
-  return terms;
-}
-
-std::vector<Sort> typeVectorToSorts(const Solver* slv,
-                                    const std::vector<Type>& types)
-{
-  std::vector<Sort> sorts;
-  for (size_t i = 0, tsize = types.size(); i < tsize; i++)
-  {
-    sorts.push_back(Sort(slv, TypeNode::fromType(types[i])));
-  }
-  return sorts;
-}
-std::vector<Sort> typeNodeVectorToSorts(const Solver* slv,
-                                        const std::vector<TypeNode>& types)
-{
-  std::vector<Sort> sorts;
-  for (size_t i = 0, tsize = types.size(); i < tsize; i++)
-  {
-    sorts.push_back(Sort(slv, types[i]));
-  }
-  return sorts;
-}
-
 }  // namespace api
 
-/* -------------------------------------------------------------------------- */
-/* Kind Conversions                                                           */
-/* -------------------------------------------------------------------------- */
-
-CVC4::api::Kind intToExtKind(CVC4::Kind k)
-{
-  auto it = api::s_kinds_internal.find(k);
-  if (it == api::s_kinds_internal.end())
-  {
-    return api::INTERNAL_KIND;
-  }
-  return it->second;
-}
-
-CVC4::Kind extToIntKind(CVC4::api::Kind k)
-{
-  auto it = api::s_kinds.find(k);
-  if (it == api::s_kinds.end())
-  {
-    return CVC4::Kind::UNDEFINED_KIND;
-  }
-  return it->second;
-}
-
-}  // namespace CVC4
+}  // namespace cvc5