diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,6 +1,35 @@
 * Hackage: <http://hackage.haskell.org/package/sbv>
 * GitHub:  <http://github.com/LeventErkok/sbv>
 
+### Version 13.0, 2025-10-31
+
+  * SBV now supports algebraic data-types. A new function 'mkSymbolic' is introduced, which take a list of types
+    and turns them into types that you can symbolically process. Clearly, Haskell ADTs are extremely rich:
+    Parameterized, self-referential, and mutually-recursive datatypes are supported. GADTs and more complicated
+    forms of data-types (with higher-order fields, for instance) are not supported. What SBV covers should handle
+    most use cases, please get in touch if you have a use case that is currently not supported.
+
+  * Introduced a new quasiquoter, named sCase, which allows writing case-expressions over symbolic ADTs. It supports
+    wildcards and guards. It does not support pattern guards, nor complex patterns. (Each pattern is either a
+    variable or an underscore.) Symbolic-boolean guards allow for concise expressions. This construct makes
+    symbolic programming with ADTs easier.
+
+  * Added examples under Documentation.SBV.Examples.ADT, demonstrating the use of basic ADTs and a case study 
+    of modeling type-checking constraints.
+
+  * Added Documentation.SBV.Examples.TP.Peano, modeling peano numbers using an ADT and demonstrating many proofs.
+
+  * Added Documentation.SBV.Examples.TP.VM demonstrating the correctness of a simple interpreter over an expression
+    language with respect to a version that compiles the expression and runs the insturctions over a virtual machine.
+
+  * [BACKWARDS COMPATIBILITY] The old functions 'mkSymbolicEnumeration' and 'mkUninterpretedSort' are now removed,
+    since their functionality is subsumed by 'mkSymbolic'.
+
+  * [BACKWARDS COMPATIBILITY] Strong-induction now takes extra proof objects that can be used to establish that
+    the measure provided is non-negative. This is usually not needed, so simply pass []. However, in case of strong
+    induction over ADTs in particular, it can come in handy to aid the solver in establishing the given measure
+    is valid.
+
 ### Version 12.2, 2025-08-15
 
   * Fix floating-point constant-folding code, which inadvertently constant-folded for symbolic rounding modes.
@@ -43,7 +72,7 @@
     implications and ask them to use custom-functions instead.
 
 ### Version 12.0, 2025-07-04
-  
+
   * [BACKWARDS COMPATIBILITY] Renamed KnuckleDragger to TP, for theorem-proving. The original name was confusing, and
     the design has diverged from Phil's tool in significant ways and goals.
 
@@ -2520,10 +2549,6 @@
   * C code generation: Correctly translate square-root and fusedMA functions to C.
 
 ### Version 3.1, 2014-07-12
-
- NB: GHC 7.8.1 and 7.8.2 has a serious bug <https://gitlab.haskell.org/ghc/ghc/-/issues/9078>
-     that causes SBV to crash under heavy/repeated calls. The bug is addressed
-     in GHC 7.8.3; so upgrading to GHC 7.8.3 is essential for using SBV!
 
  New features/bug-fixes in v3.1:
 
diff --git a/Data/SBV.hs b/Data/SBV.hs
--- a/Data/SBV.hs
+++ b/Data/SBV.hs
@@ -81,6 +81,8 @@
 --
 --   * Uninterpreted sorts, and proofs over such sorts, potentially with axioms.
 --
+--   *  Algebraic data types, including recursive fields..
+--
 --   * Ability to define SMTLib functions, generated directly from Haskell versions,
 --     including support for recursive and mutually recursive functions.
 --
@@ -156,7 +158,7 @@
 -- solvers are not good at proofs that require induction, or those that require complex chains of reasoning. Induction is necessary to reason about
 -- any recursive algorithm, and most such proofs require carefully constructed equational steps.
 --
--- SBV allows for a style of semi-automated theorem proving, called TP. which can be used to construct such proofs.
+-- SBV allows for a style of semi-automated theorem proving, called TP, which can be used to construct such proofs.
 -- The documentation includes example proofs for many list functions, and even inductive proofs for
 -- the familiar insertion, merge, quick-sort algorithms, along with a proof that the square-root of 2 is irrational.
 -- While a proper theorem prover (such as Lean, Isabelle etc.) is a more appropriate choice for such proofs, with some
@@ -211,7 +213,7 @@
   , SWord8, SWord16, SWord32, SWord64, SWord, WordN
   -- *** Signed bit-vectors
   , SInt8, SInt16, SInt32, SInt64, SInt, IntN
-  -- *** Converting between fixed-size and arbitrary bitvectors
+  -- *** Converting between fixed-size and arbitrary bit-vectors
   , BVIsNonZero, FromSized, ToSized, fromSized, toSized
   -- ** Unbounded integers
   -- $unboundedLimitations
@@ -239,11 +241,11 @@
   , SList
   -- ** Symbolic enumerators
   , EnumSymbolic(..), sEnum
+  -- ** Symbolic case-expressions
+  , sCase
   -- ** Tuples
   -- $tuples
   , SymTuple, STuple, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7, STuple8
-  -- ** Sum types
-  , SMaybe, SEither
   -- ** Sets
   , RCSet(..), SSet
   -- * Arrays of symbolic values
@@ -270,10 +272,14 @@
   , sString, sString_
   , sList, sList_
   , sTuple, sTuple_
-  , sEither, sEither_
-  , sMaybe, sMaybe_
   , sSet, sSet_
 
+  -- * Symbolic 'Maybe'
+  , SMaybe, sMaybe, sMaybe_, sMaybes
+
+  -- * Symbolic 'Either'
+  , SEither, sEither, sEither_, sEithers
+
   -- ** List of values
   -- $createSyms
   , sBools
@@ -294,8 +300,6 @@
   , sStrings
   , sLists
   , sTuples
-  , sEithers
-  , sMaybes
   , sSets
 
   -- * Symbolic Equality and Comparisons
@@ -343,13 +347,9 @@
   -- ** Showing values in detail
   , crack
 
-  -- * Enumerations
-  -- $enumerations
-  , mkSymbolicEnumeration
-
-  -- * Uninterpreted sorts, constants, and functions
-  -- $uninterpreted
-  , mkUninterpretedSort
+  -- * Symbolic data types
+  -- $symbolicADT
+  , mkSymbolic
 
   -- * Stopping unrolling: Defined functions
   , SMTDefinable(..), smtHOFunction, Closure(..), registerType
@@ -442,7 +442,7 @@
   -- ** Programmable model extraction
   -- $programmableExtraction
   , Modelable(..), displayModels, extractModels
-  , getModelDictionaries, getModelValues, getModelUninterpretedValues
+  , getModelDictionaries, getModelValues
 
   -- * SMT Interface
   , SMTConfig(..), TPOptions(..), Timing(..), SMTLibVersion(..), Solver(..), SMTSolver(..)
@@ -497,7 +497,7 @@
                                         sRational, sRational_, sRationals,
                                         sWord8, sWord8_, sWord8s, sWord16, sWord16_, sWord16s,
                                         sWord32, sWord32_, sWord32s, sWord64, sWord64_, sWord64s,
-                                        sMaybe, sMaybe_, sMaybes, sEither, sEither_, sEithers, sSet, sSet_, sSets,
+                                        sSet, sSet_, sSets,
                                         sArray, sArray_, sArrays,
                                         sBarrelRotateLeft, sBarrelRotateRight, zeroExtend, signExtend, sObserve)
 
@@ -508,6 +508,9 @@
 
 import Data.SBV.Core.SizedFloats
 
+import Data.SBV.Maybe hiding (map)
+import Data.SBV.Either
+
 import Data.SBV.Core.Floating
 import Data.SBV.Core.Symbolic   ( MonadSymbolic(..), SymbolicT, registerKind
                                 , ProgInfo(..), rProgInfo, SpecialRelOp(..), UICodeKind(UINone)
@@ -548,6 +551,7 @@
 import Data.Char (isSpace, isPunctuation)
 import Data.SBV.List (EnumSymbolic(..))
 import Data.SBV.SEnum (sEnum)
+import Data.SBV.SCase (sCase)
 
 import Data.SBV.Rational
 
@@ -1114,78 +1118,72 @@
 See 'Data.SBV.Control.getUnsatCore' for details and "Documentation.SBV.Examples.Queries.UnsatCore" for an example use case.
 -}
 
-{- $uninterpreted
+{- $symbolicADT
 Users can introduce new uninterpreted sorts simply by defining an empty data-type in Haskell and registering it as such. The
 following example demonstrates:
 
   @
      data B
-     mkUninterpretedSort ''B
+     mkSymbolic [''B]
   @
 
-(Note that you'll also need to use pragmas @TemplateHaskell@, @StandAloneDeriving@, @DeriveDataTypeable@, and @DeriveAnyClass@ for this to work, follow GHC's error messages!)
-
 This is all it takes to introduce @B@ as an uninterpreted sort in SBV, which makes the type @SBV B@ automagically become available as the type
 of symbolic values that ranges over @B@ values. Note that this will also introduce the type @SB@ into your environment, which is a synonym
 for @SBV B@.
 
-
-Uninterpreted functions over both uninterpreted and regular sorts can be declared using the facilities introduced by
-the 'Data.SBV.Core.Model.SMTDefinable' class.
--}
-
-{- $enumerations
 If the uninterpreted sort definition takes the form of an enumeration (i.e., a simple data type with all nullary constructors), then
-you can use the 'mkSymbolicEnumeration' function to turn it into an enumeration in SMTLib.
-A simple example is:
+it will turn into an enumeration in SMTLib.  A simple example is:
 
 @
-    data X = A | B | C deriving (Enum, Bounded)
-    mkSymbolicEnumeration ''X
+    data X = A | B | C
+    mkSymbolic [''X]
 @
 
-Note the magic incantation @mkSymbolicEnumeration ''X@. For this to work, you need to have the following
-options turned on:
-
->   LANGUAGE TemplateHaskell
->   LANGUAGE StandaloneDeriving
->   LANGUAGE DeriveDataTypeable
->   LANGUAGE DeriveAnyClass
->   LANGUAGE FlexibleInstances
+Note the magic incantation @mkSymbolic [''X]@, requires certain extensions to be turned on. Simply follow GHC's advice.
 
-and your own declaration must have instances of 'Enum' and 'Bounded'. (The instances can be derived, as above.)
-This will automatically introduce the type:
+SBV also supports good old ADT's as well, with fields. The support for this is similar, where SBV will create the
+corresponding datatype in a symbolic manner:
 
 @
-    type SX = SBV X
+-- | A basic arithmetic expression type.
+data Expr = Num Integer
+          | Var String
+          | Add Expr Expr
+          | Mul Expr Expr
+          | Let String Expr Expr
+
+-- | Create a symbolic version of expressions.
+mkSymbolic [''Expr]
 @
 
-along with symbolic values of each of the enumerated values @sA@, @sB@, and @sC@. This way,
-you can refer to the symbolic version as @SX@, treating it as a regular symbolic type ranging over the values @A@, @B@, and @C@. Such values can be compared for equality, and with the usual
-other comparison operators, such as @.==@, @./=@, @.>@, @.>=@, @<@, and @<=@. For each enumerated value @X@, the symbolic versions @sX@ is defined to be equal to @literal X@. Furthermore, the symbolic type will be an instance of 'EnumSymbolic', allowing you to use
-arithmetic progressions on symbolic values.
+These types can also be parameterized, per usual Haskell usage.
 
-A simple query would look like:
+We also support a symbolic case-expression quasi-quoter, allowing us to write:
 
 @
-     allSat $ \x -> x .== (x :: SX)
-@
-
-which would list all three elements of this domain as satisfying solutions.
+eval :: SExpr -> SInteger
+eval = go SL.nil
+ where go :: SList (String, Integer) -> SExpr -> SInteger
+       go = smtFunction "eval" $ \env expr -> [sCase|Expr expr of
+                                                 Num i     -> i
+                                                 Var s     -> get env s
+                                                 Add l r   -> go env l + go env r
+                                                 Mul l r   -> go env l * go env r
+                                                 Let s e r -> go (tuple (s, go env e) SL..: env) r
+                                              |]
 
-@
-     Solution #1:
-       s0 = A :: X
-     Solution #2:
-       s0 = B :: X
-     Solution #3:
-       s0 = C :: X
-     Found 3 different solutions.
+       get :: SList (String, Integer) -> SString -> SInteger
+       get = smtFunction "get" $ \env s -> ite (SL.null env) 0
+                                         $ let (k, v) = untuple (SL.head env)
+                                           in ite (s .== k) v (get (SL.tail env) s)
 @
 
-Note that the result is properly typed as @X@ elements; these are not mere strings.
+which defines an interpreter for this data-type. Such definitions also come with an induction principle
+to perform TP based proofs on. These can be accessed using the 'Data.SBV.TP.inductiveLemma' function.
 
-See "Documentation.SBV.Examples.Misc.Enumerate" for an extended example on how to use symbolic enumerations.
+The argument to @mkSymbolic@ is typically a list of types. The requirement is that if the types you pass on
+are mutually recursively defined, you should give them as a list. Otherwise, you can give them all together,
+or one at a time.
 -}
 
 {- $cardIntro
@@ -1400,7 +1398,7 @@
 -}
 
 -- | An implementation of rotate-left, using a barrel shifter like design. Only works when both
--- arguments are finite bitvectors, and furthermore when the second argument is unsigned.
+-- arguments are finite bit-vectors, and furthermore when the second argument is unsigned.
 -- The first condition is enforced by the type, but the second is dynamically checked.
 -- We provide this implementation as an alternative to `sRotateLeft` since SMTLib logic
 -- does not support variable argument rotates (as opposed to shifts), and thus this
@@ -1435,7 +1433,7 @@
                                       -> SBV (bv (i - j + 1))   -- ^ Output is of size @i - j + 1@
 bvExtract = CD.bvExtract
 
--- | Join two bitvectors.
+-- | Join two bit-vectors.
 --
 -- >>> prove $ \x y -> x .== bvExtract (Proxy @79) (Proxy @71) ((x :: SWord 9) # (y :: SWord 71))
 -- Q.E.D.
@@ -1756,7 +1754,11 @@
                        unless (op `elem` curSpecialRels) $ do
 
                           registerKind st ka
-                          nm' <- newUninterpreted st (UIGiven nm) Nothing (SBVType [ka, ka, KBool]) (UINone True)
+                          uop <- newUninterpreted st (UIGiven nm) Nothing (SBVType [ka, ka, KBool]) (UINone True)
+
+                          let nm' = case uop of
+                                      Uninterpreted s -> s
+                                      _               -> error "Data.SBV: Impossible happened: checkSpecialRelation received: " ++ show op
 
                           -- Add to the end so if we get incremental ones the order doesn't change for old ones!
                           modifyIORef' (rProgInfo st) (\u -> u{progSpecialRels = curSpecialRels ++ [iop]})
diff --git a/Data/SBV/Char.hs b/Data/SBV/Char.hs
--- a/Data/SBV/Char.hs
+++ b/Data/SBV/Char.hs
@@ -21,12 +21,10 @@
 -- we will provide full unicode versions as well.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE CPP                 #-}
-{-# LANGUAGE OverloadedLists     #-}
-{-# LANGUAGE OverloadedStrings   #-}
-{-# LANGUAGE Rank2Types          #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications    #-}
+{-# LANGUAGE CPP               #-}
+{-# LANGUAGE OverloadedLists   #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeApplications  #-}
 
 {-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
 
diff --git a/Data/SBV/Client.hs b/Data/SBV/Client.hs
--- a/Data/SBV/Client.hs
+++ b/Data/SBV/Client.hs
@@ -10,46 +10,64 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DeriveLift          #-}
+{-# LANGUAGE LambdaCase          #-}
 {-# LANGUAGE PackageImports      #-}
-{-# LANGUAGE QuasiQuotes         #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TupleSections       #-}
 
 #if MIN_VERSION_template_haskell(2,22,1)
-{-# OPTIONS_GHC -Wall -Werror #-}
+-- No need for newer versions of TH
 #else
-{-# LANGUAGE DeriveLift #-}
-{-# OPTIONS_GHC -Wall -Werror -fno-warn-orphans #-}
+{-# LANGUAGE FlexibleInstances   #-}
 #endif
 
+{-# OPTIONS_GHC -Wall -Werror -fno-warn-orphans #-}
+
 module Data.SBV.Client
   ( sbvCheckSolverInstallation
   , defaultSolverConfig
   , getAvailableSolvers
-  , mkSymbolicEnumeration
-  , mkUninterpretedSort
+  , mkSymbolic
+  , getConstructors
   ) where
 
-import Control.Monad (filterM)
 import Data.Generics
 
-import Test.QuickCheck (Arbitrary(..), arbitraryBoundedEnum)
-
-import qualified Data.SBV.List as SL
+import Control.Monad (filterM, mapAndUnzipM, zipWithM)
+import Test.QuickCheck (Arbitrary(..), elements)
 
 import qualified Control.Exception as C
 
+import Data.Maybe (fromMaybe)
+
+import Data.Char
+import Data.Word
+import Data.Int
+import Data.Ratio
+
 import qualified "template-haskell" Language.Haskell.TH        as TH
 #if MIN_VERSION_template_haskell(2,18,0)
 import qualified "template-haskell" Language.Haskell.TH.Syntax as TH
 #endif
 
+import Language.Haskell.TH.ExpandSyns as TH
+
+import Data.SBV.Core.Concrete (cvRank)
 import Data.SBV.Core.Data
 import Data.SBV.Core.Model
-import Data.SBV.Core.Operations
+import Data.SBV.Core.SizedFloats
+import Data.SBV.Core.Symbolic (registerKind)
+
 import Data.SBV.Provers.Prover
+import qualified Data.SBV.List as SL
 
+import Data.List (genericLength)
+
+import Data.SBV.TP.Kernel
+
 -- | Check whether the given solver is installed and is ready to go. This call does a
 -- simple call to the solver to ensure all is well.
 sbvCheckSolverInstallation :: SMTConfig -> IO Bool
@@ -85,159 +103,772 @@
 deriving instance TH.Lift TH.ModName
 deriving instance TH.Lift TH.NameFlavour
 deriving instance TH.Lift TH.Name
+deriving instance TH.Lift TH.Type
+deriving instance TH.Lift TH.Specificity
+deriving instance TH.Lift (TH.TyVarBndr TH.Specificity)
+deriving instance TH.Lift (TH.TyVarBndr ())
+deriving instance TH.Lift TH.TyLit
 #endif
 
--- | Turn a name into a symbolic type. If first argument is true, then we're doing an enumeration, otherwise it's an uninterpreted type
-declareSymbolic :: Bool -> TH.Name -> TH.Q [TH.Dec]
-declareSymbolic isEnum typeName = do
-    let typeCon  = TH.conT typeName
-        sTypeCon = TH.conT ''SBV `TH.appT` typeCon
+-- A few other things we need to TH lift
+deriving instance TH.Lift Kind
 
-    cstrs <- if isEnum then ensureEnumeration typeName
-                       else ensureEmptyData   typeName
+data ADTKind = ADTUninterpreted -- Completely uninterpreted
+             | ADTEnum          -- Enumeration
+             | ADTFull          -- A full datatype
 
-    derives <- [d| deriving instance Show     $typeCon
-                   deriving instance Read     $typeCon
-                   deriving instance Data     $typeCon
-                   deriving instance HasKind  $typeCon
-                   deriving instance SatModel $typeCon
-               |]
+-- | Create a mutually recursive group of ADTs.
+mkSymbolic :: [TH.Name] -> TH.Q [TH.Dec]
+mkSymbolic ts = concat <$> mapM mkSymbolicADT ts
 
-    symVals <- if isEnum
-                  then [d| instance SymVal $typeCon where
-                             minMaxBound = Just (minBound, maxBound)
+-- | Create a symbolic ADT.
+mkSymbolicADT :: TH.Name -> TH.Q [TH.Dec]
+mkSymbolicADT typeName = do
 
-                           instance Arbitrary $typeCon where
-                             arbitrary = arbitraryBoundedEnum
-                       |]
-                  else [d| instance SymVal $typeCon where
-                             minMaxBound = Nothing
+     (tKind, params, cstrs) <- dissect typeName
+     ds <- mkADT tKind typeName params cstrs
 
-                           -- It's unfortunate we have to give this instance to make things
-                           -- simple; but uninterpreted types don't really fit with the testing strategy.
-                           instance {-# OVERLAPPABLE #-} Arbitrary $typeCon where
-                             arbitrary = error $ unlines [ ""
-                                                         , "*** Data.SBV: Cannot quickcheck the given property."
-                                                         , "***"
-                                                         , "*** Default arbitrary instance for " ++ TH.nameBase typeName ++ " is too limited."
-                                                         , "***"
-                                                         , "*** You can overcome this by giving your own Arbitrary instance."
-                                                         , "*** Please get in touch if this workaround is not suitable for your case."
-                                                         ]
-                       |]
+     -- declare an "undefiner" so we don't have stray names
+     nm <- TH.newName $ "_undefiner_" ++ TH.nameBase typeName
+     addDoc "Autogenerated definition to avoid unused-variable warnings from GHC." nm
 
-    symEnum <- if isEnum
-                  then [d| instance SL.EnumSymbolic $typeCon where
-                              succ     x = let elts = [minBound .. maxBound] in x `SL.lookup` literal (zip elts (drop 1 elts))
-                              pred     x = let elts = [minBound .. maxBound] in x `SL.lookup` literal (zip (drop 1 elts) elts)
+     -- undefiner must be careful in putting ascriptions
+     aVar <- TH.newName "a"
+     let undefine n
+           | base == "sCase" ++ tbase = wrap 1   -- Needs an extra param
+           | True                     = wrap 0
+           where tbase  = TH.nameBase typeName
+                 base   = TH.nameBase n
+                 wrap c = foldl TH.AppTypeE (TH.VarE n) (replicate (c + length params) (TH.ConT ''Integer))
 
-                              toEnum   x = let elts = [minBound .. maxBound] in x `SL.lookup` literal (zip [0..] elts)
-                              fromEnum x = let elts = [minBound .. maxBound] in x `SL.lookup` literal (zip elts [0..])
+         names     = [undefine n | TH.FunD n _ <- ds]
+         body      = foldl TH.AppE (TH.VarE 'undefined)
+                                   (names ++ [TH.SigE (TH.VarE 'undefined)
+                                                      (foldl TH.AppT (TH.ConT (TH.mkName ('S' : TH.nameBase typeName)))
+                                                                     (map (const (TH.ConT ''Integer)) params))])
 
-                              enumFrom n = SL.map SL.toEnum (SL.enumFromTo (SL.fromEnum n) (SL.fromEnum (literal (maxBound :: $typeCon))))
+         undefSig  = TH.SigD nm (TH.ForallT [] [] (TH.VarT aVar))
+         undefBody = TH.FunD nm [TH.Clause [] (TH.NormalB body) []]
 
-                              enumFromThen = smtFunction ("EnumSymbolic." ++ TH.nameBase typeName ++ ".enumFromThen") $ \n1 n2 ->
-                                                         let i_n1, i_n2 :: SInteger
-                                                             i_n1 = SL.fromEnum n1
-                                                             i_n2 = SL.fromEnum n2
-                                                         in SL.map SL.toEnum (ite (i_n2 .>= i_n1)
-                                                                                  (SL.enumFromThenTo i_n1 i_n2 (SL.fromEnum (literal (maxBound :: $typeCon))))
-                                                                                  (SL.enumFromThenTo i_n1 i_n2 (SL.fromEnum (literal (minBound :: $typeCon)))))
+     pure $ ds ++ [undefSig, undefBody]
 
-                              enumFromTo     n m   = SL.map SL.toEnum (SL.enumFromTo     (SL.fromEnum n) (SL.fromEnum m))
+-- | Add document to a generated declaration for the declaration
+addDeclDocs :: (TH.Name, String) -> [(TH.Name, String)] -> TH.Q ()
+#if MIN_VERSION_template_haskell(2,18,0)
+addDeclDocs (tnm, ts) cnms = do add True (tnm, ts)
+                                mapM_  (add False) cnms
+   where add True  (cnm, cs) = TH.addModFinalizer $ TH.putDoc (TH.DeclDoc cnm) $ "Symbolic version of the type '"        ++ cs ++ "'."
+         add False (cnm, cs) = TH.addModFinalizer $ TH.putDoc (TH.DeclDoc cnm) $ "Symbolic version of the constructor '" ++ cs ++ "'."
+#else
+addDeclDocs _ _ = pure ()
+#endif
 
-                              enumFromThenTo n m t = SL.map SL.toEnum (SL.enumFromThenTo (SL.fromEnum n) (SL.fromEnum m) (SL.fromEnum t))
+-- | Add document to a generated function
+addDoc :: String -> TH.Name -> TH.Q ()
+#if MIN_VERSION_template_haskell(2,18,0)
+addDoc what tnm = TH.addModFinalizer $ TH.putDoc (TH.DeclDoc tnm) what
+#else
+addDoc _ _ = pure ()
+#endif
 
-                           instance OrdSymbolic $sTypeCon where
-                             SBV a .<  SBV b = SBV (a `svLessThan`    b)
-                             SBV a .<= SBV b = SBV (a `svLessEq`      b)
-                             SBV a .>  SBV b = SBV (a `svGreaterThan` b)
-                             SBV a .>= SBV b = SBV (a `svGreaterEq`   b)
-                       |]
-                  else pure []
+-- | Symbolic version of a type
+mkSBV :: TH.Type -> TH.Type
+mkSBV a = TH.ConT ''SBV `TH.AppT` a
 
-    sType <- sTypeCon
+-- | Saturate the type with its parameters
+saturate :: TH.Type -> [TH.Name] -> TH.Type
+saturate t ps = foldr (\p b -> TH.AppT b (TH.VarT p)) t (reverse ps)
 
-    let declConstructor c = ((nm, bnm), [sig, def])
-          where bnm  = TH.nameBase c
-                nm   = TH.mkName $ 's' : bnm
-                def  = TH.FunD nm [TH.Clause [] (TH.NormalB body) []]
-                body = TH.AppE (TH.VarE 'literal) (TH.ConE c)
-                sig  = TH.SigD nm sType
+-- | Create a symbolic ADT
+mkADT ::  ADTKind                                       -- What kind of ADT are we generating?
+       -> TH.Name                                       -- type name
+       -> [TH.Name]                                     -- parameters
+       -> [(TH.Name, [(Maybe TH.Name, TH.Type, Kind)])] -- constructors
+       -> TH.Q [TH.Dec]                                 -- declarations
+mkADT adtKind typeName params cstrs = do
 
-        (constrNames, cdecls) = unzip (map declConstructor cstrs)
+    let typeCon = saturate (TH.ConT typeName) params
+        sType   = mkSBV typeCon
 
+        inSymValContext = TH.ForallT [] [TH.AppT (TH.ConT ''SymVal) (TH.VarT n) | n <- params]
+
+        isEnum = case adtKind of
+                  ADTUninterpreted -> False
+                  ADTEnum          -> True
+                  ADTFull          -> False
+
+        -- Given Cstr f1 f2 f3, generate the clause:
+        --     inp@(Cstr [f1, f2, f3]) = case sequenceA [unlitCV (literal f1), unlitCV (literal f2), unlitCV (literal f3)] of
+        --                                 Just c  -> let k = kindOf inp
+        --                                            in SBV $ SVal k (Left (CV k (CADT (Cstr, c))))
+        --                                 Nothing -> sCstr (literal f1)
+        --
+        mkLitClause (n, fs) = do
+           as  <- mapM (const (TH.newName "a")) fs
+           inp <- TH.newName "inp"
+           c   <- TH.newName "c"
+
+           let app a b = [| $a (literal $b) |]
+
+           TH.clause [TH.asP inp (TH.conP n (map TH.varP as))]
+                     (TH.normalB
+                           (TH.caseE [| sequenceA $(TH.listE [ [| unlitCV (literal $(TH.varE a)) |] | a <- as ]) |]
+                                     [ TH.match [p|Just $(TH.varP c)|]
+                                                (TH.normalB [| let k = kindOf $(TH.varE inp)
+                                                               in SBV $ SVal k (Left (CV k (CADT (TH.nameBase n, $(TH.varE c)))))
+                                                            |])
+                                                []
+                                     , TH.match [p|Nothing|]
+                                                (TH.normalB (foldl app (TH.varE (TH.mkName ('s' : TH.nameBase n))) (map TH.varE as)))
+                                                []
+                                     ]))
+                     []
+
+    litFun <- case adtKind of
+                ADTUninterpreted -> do noLit <- [| error $ unlines [ "Data.SBV: unexpected call to derived literal implementation"
+                                                                   , "***"
+                                                                   , "*** Type: " ++ show typeName
+                                                                   , ""
+                                                                   , "***Please report this as a bug!"
+                                                                   ]
+                                                |]
+                                       pure $ TH.FunD 'literal [TH.Clause [TH.WildP] (TH.NormalB noLit) []]
+
+                ADTEnum          -> TH.FunD 'literal <$> mapM mkLitClause cstrs
+                ADTFull          -> TH.FunD 'literal <$> mapM mkLitClause cstrs
+
+    fromCVFunName <- TH.newName ("cv2" ++ TH.nameBase typeName)
+    addDoc ("Conversion from SMT values to " ++ TH.nameBase typeName ++ " values.") fromCVFunName
+
+    let fromCVSig = TH.SigD fromCVFunName
+                            (inSymValContext (foldr (TH.AppT . TH.AppT TH.ArrowT) typeCon
+                                                    [TH.ConT ''String, TH.AppT TH.ListT (TH.ConT ''CV)]))
+
+        fromCVCls :: (TH.Name, [(Maybe TH.Name, TH.Type, Kind)]) -> TH.Q TH.Clause
+        fromCVCls (nm, args) = do
+            ns <- mapM (\(i, _) -> TH.newName ("a" ++ show i)) (zip [(1::Int)..] args)
+            let pat = foldr ((\p acc -> TH.ConP '(:) [] [p, acc]) . TH.VarP) (TH.ConP '[] [] []) ns
+            pure $ TH.Clause [TH.LitP (TH.StringL (TH.nameBase nm)), pat]
+                             (TH.NormalB (foldl TH.AppE (TH.ConE nm)
+                                                        [TH.AppE (TH.VarE 'fromCV) (TH.VarE n) | n <- ns]))
+                             []
+
+    catchAll <- do s <- TH.newName "s"
+                   l <- TH.newName "l"
+                   let errStr   = TH.LitE (TH.StringL ("fromCV " ++ TH.nameBase typeName ++ ": Unexpected constructor/arity: "))
+                       tup      = TH.TupE [Just (TH.VarE s), Just (TH.AppE (TH.VarE 'length) (TH.VarE l))]
+                       showCall = TH.AppE (TH.VarE 'show) tup
+                       errMsg   = TH.InfixE (Just errStr) (TH.VarE '(++)) (Just showCall)
+                   pure $ TH.Clause [TH.VarP s, TH.VarP l] (TH.NormalB (TH.AppE (TH.VarE 'error) errMsg)) []
+
+    fromCVFun <- do clss <- mapM fromCVCls cstrs
+                    pure $ TH.FunD fromCVFunName (clss ++ [catchAll])
+
+    getFromCV <- [| let unexpected w = error $ "fromCV: " ++ show typeName ++ ": " ++ w
+                        kindName (KADT n _ _) = n
+                        kindName (KApp n _)   = n
+                        kindName k            = unexpected $ "An ADT kind was expected, but got: " ++ show k
+                    in \case CV k (CADT (c, kvs)) | kindName k == unmod typeName
+                                                 -> $(TH.varE fromCVFunName) c (map (uncurry CV) kvs)
+                             CV k e -> unexpected $ "Was expecting a CADT value, but got kind: " ++ show k ++ " (rank: " ++ show (cvRank e) ++ ")"
+                 |]
+
+    symCtx  <- TH.cxt [TH.appT (TH.conT ''SymVal) (TH.varT n) | n <- params]
+
+    mmBound <- if isEnum
+                  then let universe     = [TH.conE con | (con, _) <- cstrs]
+                           (minb, maxb) = case (universe, reverse universe) of
+                                             (x:_, y:_) -> (x, y)
+                                             _          -> error $ "Impossible: Ran out of elements in determining bounds: " ++ show cstrs
+                       in [| Just ($minb, $maxb) |]
+                  else [| Nothing |]
+
+    -- make the initializer to get the subtypes registered
+    st <- TH.newName "_st"  -- Get an underscored name here, since st might go unused if there're no subtypes
+    register <- do let concretize b@TH.ConT{}     = b
+                       concretize TH.VarT{}       = TH.ConT ''Integer
+                       concretize (TH.AppT l arg) = TH.AppT (concretize l) (concretize arg)
+                       concretize r               = r
+
+                   end <- TH.noBindS [| return () |]
+                   pure $ TH.DoE Nothing $ [TH.NoBindS (TH.AppE (TH.AppE (TH.VarE 'registerKind) (TH.VarE st))
+                                                                (TH.AppE (TH.VarE 'kindOf)
+                                                                         (TH.AppTypeE (TH.ConE 'Proxy) (concretize t))))
+                                           | (_, fts) <- cstrs, (_, t, KApp n _) <- fts, n /= TH.nameBase typeName
+                                           ] ++ [end]
+
+    let regFun = TH.FunD 'mkSymValInit [TH.Clause [TH.VarP st, TH.WildP] (TH.NormalB register) []]
+
+    let symVal = TH.InstanceD
+                      Nothing
+                      symCtx
+                      (TH.AppT (TH.ConT ''SymVal) typeCon)
+                      [ litFun
+                      , regFun
+                      , TH.FunD 'minMaxBound [TH.Clause [] (TH.NormalB mmBound)   []]
+                      , TH.FunD 'fromCV      [TH.Clause [] (TH.NormalB getFromCV) []]
+                       ]
+
+    defCstrs <- [| [(unmod n, map (\(_, _, t) -> t) ntks) | (n, ntks) <- cstrs] |]
+
+    kindCtx <- TH.cxt [TH.appT (TH.conT ''HasKind) (TH.varT p) | p <- params]
+
+    let mkPair a b = TH.TupE [Just a, Just b]
+        kindDef = foldl1 TH.AppE [ TH.ConE 'KADT
+                                 , TH.LitE (TH.StringL (unmod typeName))
+                                 , TH.ListE [ mkPair (TH.LitE (TH.StringL (TH.nameBase p)))
+                                                     (TH.AppE (TH.VarE 'kindOf) (TH.AppTypeE (TH.ConE 'Proxy) (TH.VarT p)))
+                                            | p <- params
+                                            ]
+                                 , defCstrs
+                                 ]
+
+        kindDecl = TH.InstanceD
+                        Nothing
+                        kindCtx
+                        (TH.AppT (TH.ConT ''HasKind) typeCon)
+                        [TH.FunD 'kindOf [TH.Clause [TH.WildP] (TH.NormalB kindDef) []]]
+
+    hasArbitrary <- TH.isInstance ''Arbitrary [typeCon]
+    arbDecl <- case () of
+                () | hasArbitrary -> pure []
+                   | isEnum       -> let universe  = TH.listE [TH.conE con | (con, _) <- cstrs]
+                                     in [d|instance Arbitrary $(pure typeCon) where
+                                             arbitrary = elements $universe
+                                        |]
+                   | True         -> [d|instance {-# OVERLAPPABLE #-} Arbitrary $(pure typeCon) where
+                                          arbitrary = error $ unlines [ ""
+                                                                      , "*** Data.SBV: Cannot quickcheck the given property."
+                                                                      , "***"
+                                                                      , "*** Default arbitrary instance for " ++ TH.nameBase typeName ++ " is too limited."
+                                                                      , "***"
+                                                                      , "*** You can overcome this by giving your own Arbitrary instance."
+                                                                      , "*** Please get in touch if this workaround is not suitable for your case."
+                                                                      ]
+                                    |]
+
+    -- Declare constructors
+    let declConstructor :: (TH.Name, [(Maybe TH.Name, TH.Type, Kind)]) -> TH.Q ((TH.Name, String), [TH.Dec])
+        declConstructor (n, ntks) = do
+            let ats = map (mkSBV . (\(_, t, _) -> t)) ntks
+                ty  = inSymValContext $ foldr (TH.AppT . TH.AppT TH.ArrowT) sType ats
+                bnm = TH.nameBase n
+                nm  = TH.mkName $ 's' : bnm
+
+            as    <- mapM (const (TH.newName "a")) ntks
+            c     <- TH.newName "c"
+
+            cls <- TH.clause (map TH.varP as)
+                             (TH.normalB
+                                   (TH.caseE [| sequenceA $(TH.listE [ [| unlitCV $(TH.varE a) |] | a <- as ]) |]
+                                             [ TH.match [p|Just $(TH.varP c)|]
+                                                        (TH.normalB [| let k   = kindOf (undefined `asTypeOf` res)
+                                                                           res = SBV $ SVal k (Left (CV k (CADT (bnm, $(TH.varE c)))))
+                                                                       in res
+                                                                    |])
+                                                        []
+                                             , TH.match [p|Nothing|]
+                                                        (TH.normalB (foldl (\a b -> [| $a $b |]) [| mkADTConstructor bnm |] (map TH.varE as)))
+                                                        []
+                                             ]))
+                             []
+
+            pure ((nm, bnm), [TH.SigD nm ty, TH.FunD nm [cls]])
+
+    (constrNames, cdecls) <- mapAndUnzipM declConstructor cstrs
+
     let btname = TH.nameBase typeName
         tname  = TH.mkName ('S' : btname)
-        tdecl  = TH.TySynD tname [] sType
+        tdecl  = TH.TySynD tname [TH.PlainTV p TH.BndrReq | p <- params] sType
 
-    addDocs (tname, btname) constrNames
+    addDeclDocs (tname, btname) constrNames
 
-    pure $ derives ++ symVals ++ symEnum ++ [tdecl] ++ concat cdecls
+    -- Declare accessors
+    let -- NB. field count starts at 1!
+        declAccessor :: TH.Name -> (Maybe TH.Name, TH.Type, Kind) -> Int -> TH.Q [((TH.Name, String), [TH.Dec])]
+        declAccessor c (mbUN, ft, _) i = do
+                let bnm  = TH.nameBase c
+                    anm  = "get" ++ bnm ++ "_" ++ show i
+                    nm   = TH.mkName anm
+                    ty    = inSymValContext $ TH.AppT (TH.AppT TH.ArrowT sType) (mkSBV ft)
 
- where addDocs :: (TH.Name, String) -> [(TH.Name, String)] -> TH.Q ()
-#if MIN_VERSION_template_haskell(2,18,0)
-       addDocs (tnm, ts) cnms = do addDoc True (tnm, ts)
-                                   mapM_  (addDoc False) cnms
-          where addDoc True  (cnm, cs) = TH.addModFinalizer $ TH.putDoc (TH.DeclDoc cnm) $ "Symbolic version of the type '"        ++ cs ++ "'."
-                addDoc False (cnm, cs) = TH.addModFinalizer $ TH.putDoc (TH.DeclDoc cnm) $ "Symbolic version of the constructor '" ++ cs ++ "'."
-#else
-       addDocs _ _ = pure ()
-#endif
+                cls <- do inp <- TH.newName "inp"
+                          TH.clause [TH.varP inp]
+                                    (TH.normalB
+                                          (TH.caseE [| unlitCV $(TH.varE inp) |]
+                                                    [ TH.match [p|Just (_, CADT (got, kv))|]
+                                                               (TH.guardedB [do g <- TH.normalG [| got == bnm |]
+                                                                                e <- [| let (k, v) = (kv !! (i-1))
+                                                                                        in SBV $ SVal k (Left (CV k v))
+                                                                                     |]
+                                                                                pure (g, e)
+                                                                            ])
+                                                               []
+                                                    , TH.match [p|_|]
+                                                               (TH.normalB [| mkADTAccessor anm $(TH.varE inp) |])
+                                                               []
+                                                    ]))
+                                    []
 
--- | Make an enumeration a symbolic type.
-mkSymbolicEnumeration :: TH.Name -> TH.Q [TH.Dec]
-mkSymbolicEnumeration = declareSymbolic True
+                -- If there's a custom accessor given, declare that here too
+                extras <- case mbUN of
+                            Nothing -> pure []
+                            Just un -> do let sun = TH.mkName $ 's' : TH.nameBase un
+                                          pure [((sun, bnm), [TH.SigD sun ty, TH.FunD sun [cls]])]
 
--- | Make an uninterpred sort.
-mkUninterpretedSort :: TH.Name -> TH.Q [TH.Dec]
-mkUninterpretedSort = declareSymbolic False
+                pure $ ((nm, bnm), [TH.SigD nm ty, TH.FunD nm [cls]]) : extras
 
--- | Make sure the given type is an enumeration
-ensureEnumeration :: TH.Name -> TH.Q [TH.Name]
-ensureEnumeration nm = do
-        c <- TH.reify nm
-        case c of
-          TH.TyConI d -> case d of
-                           TH.DataD _ _ _ _ cons _ -> case cons of
-                                                        [] -> bad "The datatype given has no constructors."
-                                                        xs -> concat <$> mapM check xs
-                           _                       -> bad "The name given is not a datatype."
+    allDefs <- sequence [zipWithM (declAccessor c) fs [(1::Int) ..] | (c, fs) <- cstrs]
+    let (accessorNames, accessorDecls) = unzip $ concat (concat allDefs)
 
-          _        -> bad "The name given is not a datatype."
- where n = TH.nameBase nm
+    mapM_ (addDoc "Field accessor function." . fst) accessorNames
 
-       check (TH.NormalC c xs) = case xs of
-                                   [] -> pure [c]
-                                   _  -> bad $ "Constructor " ++ show c ++ " has arguments."
+    testerDecls <- mkTesters sType inSymValContext cstrs
 
-       check c                 = bad $ "Constructor " ++ show c ++ " is not an enumeration value."
+    -- Get the case analyzer
+    caseSigFuns <- mkCaseAnalyzer adtKind typeName params cstrs
 
-       bad m = do TH.reportError $ unlines [ "Data.SBV.mkSymbolicEnumeration: Invalid argument " ++ show n
-                                           , ""
-                                           , "    Expected an enumeration. " ++ m
-                                           , ""
-                                           , "    To create an enumerated sort, use a simple Haskell enumerated type."
-                                           ]
-                  pure []
+    -- Get the induction schema, upto 5 extra args. Only for enums and adts
+    indDecs <- do let schemas = mapM (mkInductionSchema typeName params cstrs) [0 .. 5]
+                  case adtKind of
+                    ADTUninterpreted -> pure []
+                    ADTEnum          -> schemas
+                    ADTFull          -> schemas
 
--- | Make sure the given type is an empty data
-ensureEmptyData :: TH.Name -> TH.Q [TH.Name]
-ensureEmptyData nm = do
-        c <- TH.reify nm
-        case c of
-          TH.TyConI d -> case d of
-                           TH.DataD _ _ _ _ cons _ -> case cons of
-                                                        [] -> pure []
-                                                        _  -> bad "The datatype given has constructors."
-                           _                       -> bad "The name given is not a datatype."
+    -- If this is an enumeration get EnumSymbolic and OrSymbolic instances
+    symEnum <- case adtKind of
+                ADTUninterpreted -> pure []
+                ADTFull          -> pure []
+                ADTEnum          ->
+                  let universe  = TH.listE [TH.conE                          con   | (con, _) <- cstrs]
+                      universeS = TH.listE [TH.litE (TH.stringL (TH.nameBase con)) | (con, _) <- cstrs]
+                  in [d| instance SatModel $(TH.conT typeName) where
+                           parseCVs (CV _ (CADT (s, [])) : r)
+                             | Just v <- s `lookup` zip $universeS $universe
+                             = Just (v, r)
+                           parseCVs _ = Nothing
 
-          _        -> bad "The name given is not a datatype."
- where n = TH.nameBase nm
-       bad m = do TH.reportError $ unlines [ "Data.SBV.mkUninterpretedSort: Invalid argument " ++ show n
-                                           , ""
-                                           , "    Expected an empty datatype. " ++ m
-                                           , ""
-                                           , "    To create an uninterpreted sort, use an empty datatype declaration."
-                                           ]
-                  pure []
+                         instance SL.EnumSymbolic $(TH.conT typeName) where
+                           succ x = go (zip $universe (drop 1 $universe))
+                             where go []              = some ("succ_" ++ show typeName ++ "_maximal") (const sTrue)
+                                   go ((c, s) : rest) = ite (x .== literal c) (literal s) (go rest)
+
+                           pred x = go (zip (drop 1 $universe) $universe)
+                             where go []              = some ("pred_" ++ show typeName ++ "_minimal") (const sTrue)
+                                   go ((c, s) : rest) = ite (x .== literal c) (literal s) (go rest)
+
+                           toEnum x = go (zip $universe [0..])
+                             where go []              = some ("toEnum_" ++ show typeName ++ "_out_of_range") (const sTrue)
+                                   go ((c, i) : rest) = ite (x .== literal i) (literal c) (go rest)
+
+                           fromEnum x = go 0 $universe
+                             where go _ []     = error "fromEnum: Impossible happened, ran out of elements."
+                                   go i [_]    = i
+                                   go i (c:cs) = ite (x .== literal c) i (go (i+1) cs)
+
+                           enumFrom n = SL.map SL.toEnum (SL.enumFromTo (SL.fromEnum n) (genericLength $universe - 1))
+
+                           enumFromThen = smtFunction ("EnumSymbolic." ++ TH.nameBase typeName ++ ".enumFromThen") $ \n1 n2 ->
+                                                      let i_n1, i_n2 :: SInteger
+                                                          i_n1 = SL.fromEnum n1
+                                                          i_n2 = SL.fromEnum n2
+                                                      in SL.map SL.toEnum (ite (i_n2 .>= i_n1)
+                                                                               (SL.enumFromThenTo i_n1 i_n2 (genericLength $universe - 1))
+                                                                               (SL.enumFromThenTo i_n1 i_n2 0))
+
+                           enumFromTo     n m   = SL.map SL.toEnum (SL.enumFromTo     (SL.fromEnum n) (SL.fromEnum m))
+
+                           enumFromThenTo n m t = SL.map SL.toEnum (SL.enumFromThenTo (SL.fromEnum n) (SL.fromEnum m) (SL.fromEnum t))
+
+                         instance OrdSymbolic (SBV $(TH.conT typeName)) where
+                           a .<  b = SL.fromEnum a .<  SL.fromEnum b
+                           a .<= b = SL.fromEnum a .<= SL.fromEnum b
+                           a .>  b = SL.fromEnum a .>  SL.fromEnum b
+                           a .>= b = SL.fromEnum a .>= SL.fromEnum b
+                     |]
+
+    pure $  [tdecl, symVal, kindDecl]
+         ++ arbDecl
+         ++ concat cdecls
+         ++ testerDecls
+         ++ concat accessorDecls
+         ++ symEnum
+         ++ [fromCVSig, fromCVFun]
+         ++ caseSigFuns
+         ++ concat indDecs
+
+-- | Make a case analyzer for the type. Works for ADTs and enums. Returns sig and defn
+mkCaseAnalyzer :: ADTKind -> TH.Name -> [TH.Name] -> [(TH.Name, [(Maybe TH.Name, TH.Type, Kind)])] -> TH.Q [TH.Dec]
+mkCaseAnalyzer kind typeName params cstrs = case kind of
+                                              ADTUninterpreted -> pure [] -- no case analyzer for fully uninterpreted types
+                                              ADTEnum          -> mk
+                                              ADTFull          -> mk
+  where mk = do let typeCon = saturate (TH.ConT typeName) params
+                    sType   = mkSBV typeCon
+
+                    bnm = TH.nameBase typeName
+                    cnm = TH.mkName $ "sCase" ++ bnm
+
+                se   <- TH.newName ('s' : bnm)
+                fs   <- mapM (\(nm, _) -> TH.newName ('f' : TH.nameBase nm)) cstrs
+                res  <- TH.newName "result"
+
+                let def = TH.FunD cnm [TH.Clause (map TH.VarP (se : fs)) (TH.NormalB (iteChain (zipWith (mkCase se) fs cstrs))) []]
+
+                    iteChain :: [(TH.Exp, TH.Exp)] -> TH.Exp
+                    iteChain []       = error $ unlines [ "Data.SBV.mkADT: Impossible happened!"
+                                                        , ""
+                                                        , "   Received an empty list for: " ++ show typeName
+                                                        , ""
+                                                        , "While building the case-analyzer."
+                                                        , "Please report this as a bug."
+                                                        ]
+                    iteChain [(_, l)]        = l
+                    iteChain ((t, e) : rest) = foldl TH.AppE (TH.VarE 'ite) [TH.AppE t (TH.VarE se), e, iteChain rest]
+
+                    mkCase :: TH.Name -> TH.Name -> (TH.Name, [(Maybe TH.Name, TH.Type, Kind)]) -> (TH.Exp, TH.Exp)
+                    mkCase cexpr func (c, fields) = (TH.VarE (TH.mkName ("is" ++ TH.nameBase c)), foldl TH.AppE (TH.VarE func) args)
+                       where getters = [TH.mkName ("get" ++ TH.nameBase c ++ "_" ++ show i) | (i, _) <- zip [(1 :: Int) ..] fields]
+                             args    = map (\g -> TH.AppE (TH.VarE g) (TH.VarE cexpr)) getters
+
+                    rvar   = TH.VarT res
+                    mkFun  = foldr (TH.AppT . TH.AppT TH.ArrowT) rvar
+                    fTypes = [mkFun (map (mkSBV . (\(_, t, _) -> t)) ftks) | (_, ftks) <- cstrs]
+                    sig    = TH.SigD cnm (TH.ForallT []
+                                                     (TH.AppT (TH.ConT ''Mergeable) (TH.VarT res)
+                                                     : [TH.AppT (TH.ConT ''SymVal) (TH.VarT p) | p <- params]
+                                                     )
+                                                     (mkFun (sType : fTypes)))
+
+                addDoc ("Case analyzer for the type " ++ bnm ++ ".") cnm
+                pure [sig, def]
+
+-- | Declare testers
+mkTesters :: TH.Type -> (TH.Type -> TH.Type) -> [(TH.Name, [(Maybe TH.Name, TH.Type, Kind)])] -> TH.Q [TH.Dec]
+mkTesters sType inSymValContext cstrs = do
+    let declTester :: (TH.Name, [(Maybe TH.Name, TH.Type, Kind)]) -> TH.Q ((TH.Name, String), [TH.Dec])
+        declTester (c, _) = do
+             let ty  = inSymValContext $ TH.AppT (TH.AppT TH.ArrowT sType) (TH.ConT ''SBool)
+                 bnm = TH.nameBase c
+                 nm  = TH.mkName $ "is" ++ bnm
+
+             inp <- TH.newName "inp"
+             cls <- TH.clause [TH.varP inp]
+                              (TH.normalB
+                                    (TH.caseE [| unlitCV $(TH.varE inp) |]
+                                              [ TH.match [p|Just (_, CADT (got, _))|]
+                                                         (TH.normalB [| literal (got == bnm) |])
+                                                         []
+                                              , TH.match [p|Nothing|]
+                                                         (TH.normalB [| mkADTTester ("is-" ++ bnm) $(TH.varE inp) |])
+                                                         []
+                                              ]))
+                              []
+             pure ((nm, bnm), [TH.SigD nm ty, TH.FunD nm [cls]])
+
+    (testerNames, testerDecls) <- mapAndUnzipM declTester cstrs
+
+    mapM_ (addDoc "Field recognizer predicate." . fst) testerNames
+
+    pure $ concat testerDecls
+
+-- We'll just drop the modules to keep this simple
+-- If you use multiple expressions named the same (coming from different modules), oh well.
+unmod :: TH.Name -> String
+unmod = reverse . takeWhile (/= '.') . reverse . show
+
+-- | Given a type name, determine what kind of a data-type it is.
+dissect :: TH.Name -> TH.Q (ADTKind, [TH.Name], [(TH.Name, [(Maybe TH.Name, TH.Type, Kind)])])
+dissect typeName = do
+        (args, tcs) <- getConstructors typeName
+
+        let mk n (mbfn, t) = do k <- expandSyns t >>= toSBV typeName n
+                                pure (mbfn, t, k)
+
+        cs <- mapM (\(n, ts) -> (n,) <$> mapM (mk n) ts) tcs
+
+        let k | null cs             = ADTUninterpreted
+              | all (null . snd) cs = ADTEnum
+              | True                = ADTFull
+
+        pure (k, args, cs)
+
+bad :: MonadFail m => String -> [String] -> m a
+bad what extras = fail $ unlines $ ("mkSymbolic: " ++ what) : map ("      " ++) extras
+
+report :: String
+report = "Please report this as a feature request."
+
+-- | Collect the constructors
+getConstructors :: TH.Name -> TH.Q ([TH.Name], [(TH.Name, [(Maybe TH.Name, TH.Type)])])
+getConstructors typeName = do res@(_, cstrs) <- getConstructorsFromType (TH.ConT typeName)
+
+                              -- make sure accessors are unique
+                              let noDup [] = pure ()
+                                  noDup (n:ns)
+                                    | n `elem` ns = bad "Unsupported field accessor definition."
+                                                        [ "Multiply used: " ++ TH.nameBase n
+                                                        , ""
+                                                        , "SBV does not support cases where accessor fields are replicated."
+                                                        , "Please use each accessor only once."
+                                                        ]
+                                    | True        = noDup ns
+                              noDup [n | (_, fs) <- cstrs, (Just n, _) <- fs]
+
+                              pure res
+
+  where getConstructorsFromType :: TH.Type -> TH.Q ([TH.Name], [(TH.Name, [(Maybe TH.Name, TH.Type)])])
+        getConstructorsFromType ty = do ty' <- expandSyns ty
+                                        case headCon ty' of
+                                          Just (n, args) -> reifyFromHead n args
+                                          Nothing        -> bad "Not a type constructor"
+                                                                [ "Name    : " ++ show typeName
+                                                                , "Type    : " ++ show ty
+                                                                , "Expanded: " ++ show ty'
+                                                                ]
+
+        headCon :: TH.Type -> Maybe (TH.Name, [TH.Type])
+        headCon = go []
+          where go args (TH.ConT n)    = Just (n, reverse args)
+                go args (TH.AppT t a)  = go   (a:args) t
+                go args (TH.SigT t _)  = go      args t
+                go args (TH.ParensT t) = go      args t
+                go _    _              = Nothing
+
+        reifyFromHead :: TH.Name -> [TH.Type] -> TH.Q ([TH.Name], [(TH.Name, [(Maybe TH.Name, TH.Type)])])
+        reifyFromHead n args = do info <- TH.reify n
+                                  case info of
+                                    TH.TyConI (TH.DataD    _ _ tvs _ cons _) -> (map tvName tvs,) <$> mapM (expandCon (mkSubst tvs args)) cons
+                                    TH.TyConI (TH.NewtypeD _ _ tvs _ con  _) -> (map tvName tvs,) <$> mapM (expandCon (mkSubst tvs args)) [con]
+                                    TH.TyConI (TH.TySynD _ tvs rhs)          -> getConstructorsFromType (applySubst (mkSubst tvs args) rhs)
+                                    _ -> bad "Unsupported kind"
+                                             [ "Type : " ++ show typeName
+                                             , "Name : " ++ show n
+                                             , "Kind : " ++ show info
+                                             ]
+
+        onSnd f (a, b) = (a,) <$> f b
+
+        expandCon :: [(TH.Name, TH.Type)] -> TH.Con -> TH.Q (TH.Name, [(Maybe TH.Name, TH.Type)])
+        expandCon sub (TH.NormalC  n fields)          = (n,) <$> mapM (onSnd (expandSyns . applySubst sub) . (\(   _,t) -> (Nothing, t))) fields
+        expandCon sub (TH.RecC     n fields)          = (n,) <$> mapM (onSnd (expandSyns . applySubst sub) . (\(fn,_,t) -> (Just fn, t))) fields
+        expandCon sub (TH.InfixC   (_, t1) n (_, t2)) = (n,) <$> mapM (onSnd (expandSyns . applySubst sub)) [(Nothing, t1), (Nothing, t2)]
+        {- These don't have proper correspondences in SMTLib; so ignore.
+        expandCon sub (TH.ForallC  _ _ c)             = expandCon sub c
+        expandCon sub (TH.GadtC    [n] fields _)      = (n,) <$> mapM (onSnd (expandSyns . applySubst sub) . (\(   _,t) -> (Nothing, t))) fields
+        expandCon sub (TH.RecGadtC [n] fields _)      = (n,) <$> mapM (onSnd (expandSyns . applySubst sub) . (\(fn,_,t) -> (Just fn, t))) fields
+        -}
+        expandCon _   c                               = bad "Unsupported constructor form: "
+                                                            [ "Type       : " ++ show typeName
+                                                            , "Constructor: " ++ show c
+                                                            , ""
+                                                            , report
+                                                            ]
+
+        tvName :: TH.TyVarBndr TH.BndrVis -> TH.Name
+        tvName (TH.PlainTV  n _)   = n
+        tvName (TH.KindedTV n _ _) = n
+
+        -- | Make substitution from type variables to actual args
+        mkSubst :: [TH.TyVarBndr TH.BndrVis] -> [TH.Type] -> [(TH.Name, TH.Type)]
+        mkSubst tvs = zip (map tvName tvs)
+
+        -- | Apply substitution to a Type
+        applySubst :: [(TH.Name, TH.Type)] -> TH.Type -> TH.Type
+        applySubst sub = go
+          where go (TH.VarT    n)        = fromMaybe  (TH.VarT n) (n `lookup` sub)
+                go (TH.AppT    t1 t2)    = TH.AppT    (go t1) (go t2)
+                go (TH.SigT    t k)      = TH.SigT    (go t)  k
+                go (TH.ParensT t)        = TH.ParensT (go t)
+                go (TH.InfixT  t1 n t2)  = TH.InfixT  (go t1) n (go t2)
+                go (TH.UInfixT t1 n t2)  = TH.UInfixT (go t1) n (go t2)
+                go (TH.ForallT bs ctx t) = TH.ForallT bs (map goPred ctx) (go t)
+                go t                     = t
+
+                goPred (TH.AppT t1 t2) = TH.AppT (go t1) (go t2)
+                goPred p               = p
+
+-- | Find the SBV kind for this type
+toSBV :: TH.Name -> TH.Name -> TH.Type -> TH.Q Kind
+toSBV typeName constructorName = go
+  where hasArrows (TH.AppT TH.ArrowT _)   = True
+        hasArrows (TH.AppT lhs       rhs) = hasArrows lhs || hasArrows rhs
+        hasArrows _                       = False
+
+        -- Handle type variables (parameters)
+        go (TH.VarT v) = pure $ KVar (TH.nameBase v)
+
+        -- tuples
+        go t | Just ps <- getTuple t = KTuple <$> mapM go ps
+
+        -- recognize strings, since we don't (yet) support chars
+        go (TH.AppT TH.ListT (TH.ConT t)) | t == ''Char = pure KString
+
+        -- lists
+        go (TH.AppT TH.ListT t) = KList <$> go t
+
+        -- arbitrary words/ints
+        go (TH.AppT (TH.ConT nm) (TH.LitT (TH.NumTyLit n)))
+            | nm == ''WordN = pure $ KBounded False (fromIntegral n)
+            | nm == ''IntN  = pure $ KBounded True  (fromIntegral n)
+
+        -- arbitrary floats
+        go (TH.AppT (TH.AppT (TH.ConT nm) (TH.LitT (TH.NumTyLit eb))) (TH.LitT (TH.NumTyLit sb)))
+            | nm == ''FloatingPoint = pure $ KFP (fromIntegral eb) (fromIntegral sb)
+
+        -- Rational
+        go (TH.AppT (TH.ConT nm) (TH.ConT i))
+            | nm == ''Ratio && i == ''Integer
+            = pure KRational
+
+        -- deal with base types
+        go t@(TH.ConT constr)
+            | Just base <- getBase constr
+            = case base of
+                Left (w, r) -> bad w $ [ "Datatype   : " ++ show typeName
+                                       , "Constructor: " ++ show constructorName
+                                       , "Kind       : " ++ TH.pprint t
+                                       , ""
+                                       ] ++ r
+                Right k     -> pure k
+
+        -- deal with constructors
+        go t
+           | Just (c, ps) <- getConApp t
+           = KApp (TH.nameBase c) <$> mapM go ps
+
+        -- giving up
+        go t = bad "Unsupported constructor kind" [ "Datatype   : " ++ TH.nameBase typeName
+                                                  , "Constructor: " ++ TH.nameBase constructorName
+                                                  , "Kind       : " ++ TH.pprint t
+                                                  , ""
+                                                  , if hasArrows t
+                                                    then "Higher order fields (i.e., function values) are not supported."
+                                                    else report
+                                                  ]
+
+        -- Extract application of a constructor to some type-variables
+        getConApp t = locate t []
+          where locate (TH.ConT c)     sofar = Just (c, sofar)
+                locate (TH.AppT l arg) sofar = locate l (arg : sofar)
+                locate _               _     = Nothing
+
+        -- Extract an N-tuple
+        getTuple = tup []
+          where tup sofar (TH.TupleT _) = Just sofar
+                tup sofar (TH.AppT t p) = tup (p : sofar) t
+                tup _     _             = Nothing
+
+        -- Given the name of a base type, what's the equivalent in the SBV domain (if we have it)
+        getBase :: TH.Name -> Maybe (Either (String, [String]) Kind)
+        getBase t
+          | t == ''Bool     = Just $ Right KBool
+          | t == ''Integer  = Just $ Right KUnbounded
+          | t == ''Float    = Just $ Right KFloat
+          | t == ''Double   = Just $ Right KDouble
+          | t == ''Char     = Just $ Right KChar
+          | t == ''String   = Just $ Right KString
+          | t == ''AlgReal  = Just $ Right KReal
+          | t == ''Rational = Just $ Right KRational
+          | t == ''Word8    = Just $ Right $ KBounded False  8
+          | t == ''Word16   = Just $ Right $ KBounded False 16
+          | t == ''Word32   = Just $ Right $ KBounded False 32
+          | t == ''Word64   = Just $ Right $ KBounded False 64
+          | t == ''Int8     = Just $ Right $ KBounded True   8
+          | t == ''Int16    = Just $ Right $ KBounded True  16
+          | t == ''Int32    = Just $ Right $ KBounded True  32
+          | t == ''Int64    = Just $ Right $ KBounded True  64
+
+          -- Platform specific, flag:
+          |    t == ''Int
+            || t == ''Word  = Just $ Left ( "Platform specific type: " ++ show t
+                                          , [ "Please pick a more specific type, such as"
+                                            , "Integer, Word8, WordN 32, IntN 16 etc."
+                                            ])
+
+          -- Otherwise, can't translate
+          | True            = Nothing
+
+-- | Make an induction schema for the type, with n extra arguments.
+mkInductionSchema :: TH.Name -> [TH.Name] -> [(TH.Name, [(Maybe TH.Name, TH.Type, Kind)])] -> Int -> TH.Q [TH.Dec]
+mkInductionSchema typeName params cstrs extraArgCnt = do
+   let btype = TH.nameBase typeName
+       nm    = "induct" ++ btype ++ if extraArgCnt == 0 then "" else show extraArgCnt
+
+   pf <- TH.newName "pf"
+
+   extraNames <- mapM (const (TH.newName "extraN")) [0 .. extraArgCnt-1]
+   extraSyms  <- mapM (const (TH.newName "extraS")) [0 .. extraArgCnt-1]
+   extraTypes <- mapM (const (TH.newName "extraT")) [0 .. extraArgCnt-1]
+
+   let mkLam = TH.lamE . map (\a -> TH.conP 'Forall [TH.varP a])
+
+   let mkIndCase :: (TH.Name, [(Maybe TH.Name, TH.Type, Kind)]) -> TH.Q TH.Exp
+       mkIndCase (cstr, flds)
+         | null flds && null extraNames
+         = [| $(TH.varE pf) $(scstr) |]
+         | True
+         = do as <- mapM (const (TH.newName "a")) flds
+              let -- When can we have the inductive hypothesis?
+                  --  (1) same type
+                  --  (2) applied at exactly the same types
+                  isRecursive (_, _, k) = case k of
+                                            KApp t ps -> t == btype && ps == map (KVar . TH.nameBase) params
+                                            _         -> False
+                  recFields = [a | (a, f) <- zip as flds, isRecursive f]
+
+              TH.appE (TH.varE 'quantifiedBool)
+                      (mkLam (as ++ extraNames)
+                             (mkImp recFields (foldl TH.appE
+                                                     (TH.appE (TH.varE pf) (foldl TH.appE scstr (map TH.varE as)))
+                                                     (map TH.varE extraNames))))
+         where cnm   = TH.nameBase cstr
+               lcnm  = map toLower cnm
+               scstr = TH.varE (TH.mkName ('s' : cnm))
+
+               mkImp []  e = e
+               mkImp [i] e = foldl1 TH.appE [TH.varE '(.=>), assume i, e]
+               mkImp is  e = foldl1 TH.appE [TH.varE '(.=>), foldl1 TH.appE [TH.varE 'sAnd, TH.listE (map assume is)], e]
+
+               assume :: TH.Name -> TH.Q TH.Exp
+               assume n = do en <- mapM (const (TH.newName (lcnm ++ "_extraN"))) [0 .. extraArgCnt-1]
+                             TH.appE (TH.varE 'quantifiedBool)
+                                     (mkLam en (foldl TH.appE (TH.varE pf) (map TH.varE (n : en))))
+
+   cases <- mapM mkIndCase cstrs
+   post  <- do a <- TH.newName "recVal"
+               TH.appE (TH.varE 'quantifiedBool)
+                       (mkLam (a : extraNames) $ foldl TH.appE (TH.varE pf) (map TH.varE (a : extraNames)))
+
+   propName <- TH.newName "prop"
+   argName  <- TH.newName "a"
+   taName   <- TH.newName "ta"
+
+   let pre    = foldl1 TH.AppE [TH.VarE 'sAnd,  TH.ListE cases]
+       schema = foldl1 TH.AppE [TH.VarE '(.=>), pre, post]
+       ihB    = TH.AppE (TH.VarE 'proofOf) (foldl1 TH.AppE [TH.VarE 'internalAxiom, TH.LitE (TH.StringL nm), schema])
+
+       instHead = TH.AppT (TH.ConT ''HasInductionSchema)
+                          (foldr (TH.AppT . TH.AppT TH.ArrowT)
+                                 (TH.ConT ''SBool)
+                                 [  TH.AppT (TH.ConT ''Forall) (TH.VarT es) `TH.AppT` et
+                                  | (es, et) <- zip (taName : extraSyms)
+                                                    (saturate (TH.ConT typeName) params : map TH.VarT extraTypes)
+                                 ])
+
+       pfFun = TH.FunD pf [TH.Clause (map TH.VarP (argName : extraNames))
+                                     (TH.NormalB (foldl TH.AppE
+                                                        (TH.VarE propName)
+                                                        [TH.AppE (TH.ConE 'Forall) (TH.VarE a) | a <- argName : extraNames]))
+                                     []
+                          ]
+
+       method = TH.FunD 'inductionSchema
+                        [TH.Clause [TH.VarP propName]
+                                   (TH.NormalB (TH.LetE [pfFun] ihB))
+                                   []
+                        ]
+
+   context <- TH.cxt [TH.appT (TH.conT ''SymVal) (TH.varT n) | n <- params ++ extraTypes]
+
+   pure [TH.InstanceD Nothing context instHead [method]]
diff --git a/Data/SBV/Client/BaseIO.hs b/Data/SBV/Client/BaseIO.hs
--- a/Data/SBV/Client/BaseIO.hs
+++ b/Data/SBV/Client/BaseIO.hs
@@ -23,7 +23,7 @@
                                 SFPHalf, SFPBFloat, SFPSingle, SFPDouble, SFPQuad, SFloatingPoint,
                                 SInt8, SInt16, SInt32, SInt64, SInteger, SList,
                                 SReal, SString, SV, SWord8, SWord16, SWord32,
-                                SWord64, SEither, SRational, SMaybe, SSet, SArray, constrain, (.==))
+                                SWord64, SRational, SSet, SArray, constrain, (.==))
 import Data.SBV.Core.Kind      (BVIsNonZero, ValidFloat)
 import Data.SBV.Core.Model     (Metric(..), SymTuple)
 import Data.SBV.Core.Symbolic  (Objective, OptimizeStyle, Result, VarContext, Symbolic, SBVRunMode, SMTConfig,
@@ -725,24 +725,6 @@
 sTuples :: (SymTuple tup, SymVal tup) => [String] -> Symbolic [SBV tup]
 sTuples = Trans.sTuples
 
--- | Declare a named 'Data.SBV.SEither'.
---
--- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sEither'
-sEither :: (SymVal a, SymVal b) => String -> Symbolic (SEither a b)
-sEither = Trans.sEither
-
--- | Declare an unnamed 'Data.SBV.SEither'.
---
--- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sEither_'
-sEither_ :: (SymVal a, SymVal b) => Symbolic (SEither a b)
-sEither_ = Trans.sEither_
-
--- | Declare a list of 'Data.SBV.SEither' values.
---
--- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sEithers'
-sEithers :: (SymVal a, SymVal b) => [String] -> Symbolic [SEither a b]
-sEithers = Trans.sEithers
-
 -- | Declare a named 'Data.SBV.SRational'.
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sRational'
@@ -760,24 +742,6 @@
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sRationals'
 sRationals :: [String] -> Symbolic [SRational]
 sRationals = Trans.sRationals
-
--- | Declare a named 'Data.SBV.SMaybe'.
---
--- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sMaybe'
-sMaybe :: SymVal a => String -> Symbolic (SMaybe a)
-sMaybe = Trans.sMaybe
-
--- | Declare an unnamed 'Data.SBV.SMaybe'.
---
--- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sMaybe_'
-sMaybe_ :: SymVal a => Symbolic (SMaybe a)
-sMaybe_ = Trans.sMaybe_
-
--- | Declare a list of 'Data.SBV.SMaybe' values.
---
--- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sMaybes'
-sMaybes :: SymVal a => [String] -> Symbolic [SMaybe a]
-sMaybes = Trans.sMaybes
 
 -- | Declare a named 'Data.SBV.SSet'.
 --
diff --git a/Data/SBV/Compilers/C.hs b/Data/SBV/Compilers/C.hs
--- a/Data/SBV/Compilers/C.hs
+++ b/Data/SBV/Compilers/C.hs
@@ -9,8 +9,6 @@
 -- Compilation of symbolic programs to C
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE CPP           #-}
-{-# LANGUAGE PatternGuards #-}
 {-# LANGUAGE TupleSections #-}
 
 {-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-uni-patterns #-}
@@ -33,6 +31,7 @@
 import qualified Text.PrettyPrint.HughesPJ as P ((<>))
 
 import Data.SBV.Core.Data
+import Data.SBV.Core.Kind (kRoundingMode)
 import Data.SBV.Compilers.CodeGen
 
 import Data.SBV.Utils.PrettyNum   (chex, showCFloat, showCDouble)
@@ -198,6 +197,7 @@
 -- | The printf specifier for the type
 specifier :: CgConfig -> SV -> Doc
 specifier cfg sv = case kindOf sv of
+                     KVar{}        -> die $ "variable sort: " ++ show (kindOf sv)
                      KBool         -> spec (False, 1)
                      KBounded b i  -> spec (b, i)
                      KUnbounded    -> spec (True, fromJust (cgInteger cfg))
@@ -210,10 +210,9 @@
                      KFP{}         -> die   "arbitrary float sort"
                      KList k       -> die $ "list sort: "   ++ show k
                      KSet  k       -> die $ "set sort: "    ++ show k
-                     KUserSort s _ -> die $ "user sort: "   ++ s
+                     KApp s _      -> die $ "ADT app: "     ++ s
+                     KADT s _ _    -> die $ "ADT: "         ++ s
                      KTuple k      -> die $ "tuple sort: "  ++ show k
-                     KMaybe  k     -> die $ "maybe sort: "  ++ show k
-                     KEither k1 k2 -> die $ "either sort: " ++ show (k1, k2)
                      KArray  k1 k2 -> die $ "array sort: "  ++ show (k1, k2)
   where u8InHex = cgShowU8InHex cfg
 
@@ -463,10 +462,6 @@
   = notyet "Lists (SList)"
   | any isTuple kindInfo
   = notyet "Tuples (STupleN)"
-  | any isMaybe kindInfo
-  = notyet "Optional (SMaybe) values"
-  | any isEither kindInfo
-  = notyet "Either (SEither) values"
   | isNothing (cgReal cfg) && KReal `Set.member` kindInfo
   = error $ "SBV->C: SReal values are not supported by the C compiler."
           ++ "\nUse 'cgSRealType' to specify a custom type for SReal representation."
@@ -489,7 +484,7 @@
        asserts | cgIgnoreAsserts cfg = []
                | True                = origAsserts
 
-       usorts = [s | KUserSort s _ <- Set.toList kindInfo, s /= "RoundingMode"] -- No support for any sorts other than RoundingMode!
+       usorts = [s | k@(KADT s _ _) <- Set.toList kindInfo, isADT k && not (isRoundingMode k)] -- No support for any sorts other than RoundingMode!
 
        pre    =  text "/* File:" <+> doubleQuotes (nm P.<> text ".c") P.<> text ". Automatically generated by SBV. Do not edit! */"
               $$ text ""
@@ -533,7 +528,8 @@
                ResultLamInps is       -> die $ "Unexpected inputs  : " ++ show is
 
        typeWidth = getMax 0 $ [len (kindOf s) | (s, _) <- assignments] ++ [len (kindOf s) | NamedSymVar s _ <- ins]
-                where len KReal{}            = 5
+                where len (KVar s)           = die $ "Variable: " ++ s
+                      len KReal{}            = 5
                       len KFloat{}           = 6 -- SFloat
                       len KDouble{}          = 7 -- SDouble
                       len KString{}          = 7 -- SString
@@ -547,10 +543,9 @@
                       len (KList s)          = die $ "List sort: "   ++ show s
                       len (KSet  s)          = die $ "Set sort: "    ++ show s
                       len (KTuple s)         = die $ "Tuple sort: "  ++ show s
-                      len (KMaybe k)         = die $ "Maybe sort: "  ++ show k
-                      len (KEither k1 k2)    = die $ "Either sort: " ++ show (k1, k2)
                       len (KArray  k1 k2)    = die $ "Array sort:  " ++ show (k1, k2)
-                      len (KUserSort s _)    = die $ "Uninterpreted sort: " ++ s
+                      len (KApp s _)         = die $ "Uninterpreted ADT app: " ++ s
+                      len (KADT s _ _)       = die $ "Uninterpreted ADT: "     ++ s
 
                       getMax 8 _      = 8  -- 8 is the max we can get with SInteger, so don't bother looking any further
                       getMax m []     = m
@@ -695,21 +690,21 @@
         -- grab the rounding-mode, if present, and make sure it's RoundNearestTiesToEven. Otherwise skip.
         fpArgs = case as of
                    []            -> []
-                   ((m, _):args) -> case kindOf m of
-                                      KUserSort "RoundingMode" _ -> case checkRM (m `lookup` consts) of
-                                                                      Nothing          -> args
-                                                                      Just (Left  msg) -> die msg
-                                                                      Just (Right msg) -> tbd msg
-                                      _                          -> as
+                   ((m, _):args)
+                     | isRoundingMode m -> case checkRM (m `lookup` consts) of
+                                             Nothing          -> args
+                                             Just (Left  msg) -> die msg
+                                             Just (Right msg) -> tbd msg
+                     | True              -> as
 
         -- Check that the RM is RoundNearestTiesToEven.
         -- If we start supporting other rounding-modes, this would be the point where we'd insert the rounding-mode set/reset code
         -- instead of merely returning OK or not
-        checkRM (Just cv@(CV (KUserSort "RoundingMode" _) v)) =
-              case v of
-                CUserSort (_, "RoundNearestTiesToEven") -> Nothing
-                CUserSort (_, s)                        -> Just (Right $ "handleIEEE: Unsupported rounding-mode: " ++ show s ++ " for: " ++ show w)
-                _                                       -> Just (Left  $ "handleIEEE: Unexpected value for rounding-mode: " ++ show cv ++ " for: " ++ show w)
+        checkRM (Just cv@(CV k v))
+          | k == kRoundingMode = case v of
+                                   CADT ("RoundNearestTiesToEven", []) -> Nothing
+                                   CADT (s,                        []) -> Just (Right $ "handleIEEE: Unsupported rounding-mode: " ++ show s ++ " for: " ++ show w)
+                                   _                                   -> Just (Left  $ "handleIEEE: Unexpected value for rounding-mode: " ++ show cv ++ " for: " ++ show w)
         checkRM (Just cv) = Just (Left  $ "handleIEEE: Expected rounding-mode, but got: " ++ show cv ++ " for: " ++ show w)
         checkRM Nothing   = Just (Right $ "handleIEEE: Non-constant rounding-mode for: " ++ show w)
 
@@ -800,6 +795,7 @@
                 canOverflow False sz = (2::Integer)^sz    -1 >= fromIntegral len
 
                 (needsCheckL, needsCheckR) = case k of
+                                               KVar{}          -> die $ "array index with variable: " ++ show k
                                                KBool           -> (False, canOverflow False (1::Int))
                                                KBounded sg sz  -> (sg, canOverflow sg sz)
                                                KReal           -> die "array index with real value"
@@ -815,10 +811,9 @@
                                                KList     s     -> die $ "List sort "   ++ show s
                                                KSet      s     -> die $ "Set sort "    ++ show s
                                                KTuple    s     -> die $ "Tuple sort "  ++ show s
-                                               KMaybe    ek    -> die $ "Maybe sort "  ++ show ek
-                                               KEither   k1 k2 -> die $ "Either sort " ++ show (k1, k2)
                                                KArray    k1 k2 -> die $ "Array  sort " ++ show (k1, k2)
-                                               KUserSort s _   -> die $ "Uninterpreted sort: " ++ s
+                                               KApp      s _   -> die $ "ADT app: " ++ s
+                                               KADT      s _ _ -> die $ "ADT: "     ++ s
 
         -- Div/Rem should be careful on 0, in the SBV world x `div` 0 is 0, x `rem` 0 is x
         -- NB: Quot is supposed to truncate toward 0; Not clear to me if C guarantees this behavior.
diff --git a/Data/SBV/Compilers/CodeGen.hs b/Data/SBV/Compilers/CodeGen.hs
--- a/Data/SBV/Compilers/CodeGen.hs
+++ b/Data/SBV/Compilers/CodeGen.hs
@@ -10,7 +10,6 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE CPP                        #-}
-{-# LANGUAGE FlexibleInstances          #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
diff --git a/Data/SBV/Control.hs b/Data/SBV/Control.hs
--- a/Data/SBV/Control.hs
+++ b/Data/SBV/Control.hs
@@ -22,7 +22,7 @@
 
      -- * Querying the solver
      -- ** Extracting values
-     , getFunction, getUninterpretedValue, getModel, getAssignment, getSMTResult, getUnknownReason, getObservables
+     , getFunction, getModel, getAssignment, getSMTResult, getUnknownReason, getObservables
 
      -- ** Extracting the unsat core
      , getUnsatCore
diff --git a/Data/SBV/Control/BaseIO.hs b/Data/SBV/Control/BaseIO.hs
--- a/Data/SBV/Control/BaseIO.hs
+++ b/Data/SBV/Control/BaseIO.hs
@@ -11,8 +11,6 @@
 -- @Data.SBV.Control@, where we restrict the underlying monad to be IO.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE FlexibleContexts #-}
-
 {-# OPTIONS_GHC -Wall -Werror #-}
 
 module Data.SBV.Control.BaseIO where
@@ -20,7 +18,7 @@
 import Data.SBV.Control.Query (Assignment)
 import Data.SBV.Control.Types (CheckSatResult, SMTInfoFlag, SMTInfoResponse, SMTOption, SMTReasonUnknown)
 import Data.SBV.Core.Concrete (CV)
-import Data.SBV.Core.Data     (HasKind, Symbolic, SymVal, SBool, SBV, SBVType)
+import Data.SBV.Core.Data     (Symbolic, SymVal, SBool, SBV, SBVType)
 import Data.SBV.Core.Symbolic (Query, QueryContext, QueryState, State, SMTModel, SMTResult, SV, Name)
 
 import qualified Data.SBV.Control.Query as Trans
@@ -435,12 +433,6 @@
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getValue'
 getValue :: SymVal a => SBV a -> Query a
 getValue = Trans.getValue
-
--- | Get the value of an uninterpreted sort, as a String
---
--- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getUninterpretedValue'
-getUninterpretedValue :: HasKind a => SBV a -> Query String
-getUninterpretedValue = Trans.getUninterpretedValue
 
 -- | Get the value of an uninterpreted function, as a list of domain, value pairs.
 -- The final value is the "else" clause, i.e., what the function maps values outside
diff --git a/Data/SBV/Control/Query.hs b/Data/SBV/Control/Query.hs
--- a/Data/SBV/Control/Query.hs
+++ b/Data/SBV/Control/Query.hs
@@ -24,7 +24,7 @@
      , CheckSatResult(..), checkSat, checkSatUsing, checkSatAssuming, checkSatAssumingWithUnsatisfiableSet
      , getUnsatCore, getProof, getInterpolantMathSAT, getInterpolantZ3, getAbduct, getAbductNext, getAssignment, getOption
      , push, pop, getAssertionStackDepth
-     , inNewAssertionStack, echo, caseSplit, resetAssertions, exit, getAssertions, getUninterpretedValue, getModel, getSMTResult
+     , inNewAssertionStack, echo, caseSplit, resetAssertions, exit, getAssertions, getModel, getSMTResult
      , getLexicographicOptResults, getIndependentOptResults, getParetoOptResults, getAllSatResult, getUnknownReason, getObservables, ensureSat
      , SMTOption(..), SMTInfoFlag(..), SMTErrorBehavior(..), SMTReasonUnknown(..), SMTInfoResponse(..), getInfo
      , Logic(..), Assignment(..)
@@ -86,7 +86,7 @@
 -- Collect strings appearing, used in 'getOption' only
 stringsOf :: SExpr -> [String]
 stringsOf (ECon s)           = [s]
-stringsOf (ENum (i, _))      = [show i]
+stringsOf (ENum (i, _, _))   = [show i]
 stringsOf (EReal   r)        = [show r]
 stringsOf (EFloat  f)        = [show f]
 stringsOf (EFloatingPoint f) = [show f]
@@ -97,7 +97,7 @@
 serialize :: Bool -> SExpr -> String
 serialize removeQuotes = go
   where go (ECon s)           = if removeQuotes then unQuote s else s
-        go (ENum (i, _))      = showNegativeNumber i
+        go (ENum (i, _, _))   = showNegativeNumber i
         go (EReal   r)        = showNegativeNumber r
         go (EFloat  f)        = showNegativeNumber f
         go (EDouble d)        = showNegativeNumber d
@@ -133,7 +133,7 @@
           then return $ Resp_AllStatistics $ grabAllStats pe
           else case pe of
                  ECon "unsupported"                                        -> return Resp_Unsupported
-                 EApp [ECon ":assertion-stack-levels", ENum (i, _)]        -> return $ Resp_AssertionStackLevels i
+                 EApp [ECon ":assertion-stack-levels", ENum (i, _, _)]     -> return $ Resp_AssertionStackLevels i
                  EApp (ECon ":authors" : ns)                               -> return $ Resp_Authors (map render ns)
                  EApp [ECon ":error-behavior", ECon "immediate-exit"]      -> return $ Resp_Error ErrorImmediateExit
                  EApp [ECon ":error-behavior", ECon "continued-execution"] -> return $ Resp_Error ErrorContinuedExecution
@@ -189,12 +189,12 @@
         string c (ECon s) _ = return $ Just $ c s
         string _ e        k = k $ Just ["Expected string, but got: " ++ show (serialize False e)]
 
-        bool c (ENum (0, _)) _ = return $ Just $ c False
-        bool c (ENum (1, _)) _ = return $ Just $ c True
-        bool _ e             k = k $ Just ["Expected boolean, but got: " ++ show (serialize False e)]
+        bool c (ENum (0, _, True)) _ = return $ Just $ c False
+        bool c (ENum (1, _, True)) _ = return $ Just $ c True
+        bool _ e                   k = k $ Just ["Expected boolean, but got: " ++ show (serialize False e)]
 
-        integer c (ENum (i, _)) _ = return $ Just $ c i
-        integer _ e             k = k $ Just ["Expected integer, but got: " ++ show (serialize False e)]
+        integer c (ENum (i, _, _)) _ = return $ Just $ c i
+        integer _ e                k = k $ Just ["Expected integer, but got: " ++ show (serialize False e)]
 
         -- free format, really
         stringList c e _ = return $ Just $ c $ stringsOf e
@@ -368,14 +368,16 @@
 
                         r <- ask cmd
 
+                        si <- queryState >>= getSInfo
+
                         inputs <- F.toList <$> getTopLevelInputs
 
-                        parse r bad $ \case EApp (ECon "objectives" : es) -> catMaybes <$> mapM (getObjValue (bad r) inputs) es
+                        parse r bad $ \case EApp (ECon "objectives" : es) -> catMaybes <$> mapM (getObjValue si (bad r) inputs) es
                                             _                             -> bad r Nothing
 
   where -- | Parse an objective value out.
-        getObjValue :: (forall a. Maybe [String] -> m a) -> [NamedSymVar] -> SExpr -> m (Maybe (String, GeneralizedCV))
-        getObjValue bailOut inputs expr =
+        getObjValue :: SInfo -> (forall a. Maybe [String] -> m a) -> [NamedSymVar] -> SExpr -> m (Maybe (String, GeneralizedCV))
+        getObjValue si bailOut inputs expr =
                 case expr of
                   EApp [_]          -> return Nothing            -- Happens when a soft-assertion has no associated group.
                   EApp [ECon nm, v] -> locate nm v               -- Regular case
@@ -391,8 +393,8 @@
 
                 grab :: SV -> SExpr -> m GeneralizedCV
                 grab s topExpr
-                  | Just v <- recoverKindedValue k topExpr = return $ RegularCV v
-                  | True                                   = ExtendedCV <$> cvt (simplify topExpr)
+                  | Just v <- recoverKindedValue si k topExpr = return $ RegularCV v
+                  | True                                      = ExtendedCV <$> cvt (simplify topExpr)
                   where k = kindOf s
 
                         -- Convert to an extended expression. Hopefully complete!
@@ -400,7 +402,7 @@
                         cvt (ECon "oo")                    = return $ Infinite  k
                         cvt (ECon "epsilon")               = return $ Epsilon   k
                         cvt (EApp [ECon "interval", x, y]) =          Interval  <$> cvt x <*> cvt y
-                        cvt (ENum    (i, _))               = return $ BoundedCV $ mkConstCV k i
+                        cvt (ENum    (i, _, _))            = return $ BoundedCV $ mkConstCV k i
                         cvt (EReal   r)                    = return $ BoundedCV $ CV k $ CAlgReal r
                         cvt (EFloat  f)                    = return $ BoundedCV $ CV k $ CFloat   f
                         cvt (EDouble d)                    = return $ BoundedCV $ CV k $ CDouble  d
@@ -733,9 +735,9 @@
                                   ]
 
             -- we're expecting boolean assignment to labels, essentially
-            grab (EApp [ECon s, ENum (0, _)]) = Just (unQuote s, False)
-            grab (EApp [ECon s, ENum (1, _)]) = Just (unQuote s, True)
-            grab _                            = Nothing
+            grab (EApp [ECon s, ENum (0, _, _)]) = Just (unQuote s, False)
+            grab (EApp [ECon s, ENum (1, _, _)]) = Just (unQuote s, True)
+            grab _                               = Nothing
 
         r <- ask cmd
 
diff --git a/Data/SBV/Control/Types.hs b/Data/SBV/Control/Types.hs
--- a/Data/SBV/Control/Types.hs
+++ b/Data/SBV/Control/Types.hs
@@ -167,11 +167,11 @@
   | AUFLIRA            -- ^ Linear formulas with free sort and function symbols over one- and two-dimentional arrays of integer index and real value.
   | AUFNIRA            -- ^ Formulas with free function and predicate symbols over a theory of arrays of arrays of integer index and real value.
   | LRA                -- ^ Linear formulas in linear real arithmetic.
-  | QF_ABV             -- ^ Quantifier-free formulas over the theory of bitvectors and bitvector arrays.
-  | QF_AUFBV           -- ^ Quantifier-free formulas over the theory of bitvectors and bitvector arrays extended with free sort and function symbols.
+  | QF_ABV             -- ^ Quantifier-free formulas over the theory of bit-vectors and bit-vector arrays.
+  | QF_AUFBV           -- ^ Quantifier-free formulas over the theory of bit-vectors and bit-vector arrays extended with free sort and function symbols.
   | QF_AUFLIA          -- ^ Quantifier-free linear formulas over the theory of integer arrays extended with free sort and function symbols.
   | QF_AX              -- ^ Quantifier-free formulas over the theory of arrays with extensionality.
-  | QF_BV              -- ^ Quantifier-free formulas over the theory of fixed-size bitvectors.
+  | QF_BV              -- ^ Quantifier-free formulas over the theory of fixed-size bit-vectors.
   | QF_IDL             -- ^ Difference Logic over the integers. Boolean combinations of inequations of the form x - y < b where x and y are integer variables and b is an integer constant.
   | QF_LIA             -- ^ Unquantified linear integer arithmetic. In essence, Boolean combinations of inequations between linear polynomials over integer variables.
   | QF_LRA             -- ^ Unquantified linear real arithmetic. In essence, Boolean combinations of inequations between linear polynomials over real variables.
@@ -179,7 +179,7 @@
   | QF_NRA             -- ^ Quantifier-free real arithmetic.
   | QF_RDL             -- ^ Difference Logic over the reals. In essence, Boolean combinations of inequations of the form x - y < b where x and y are real variables and b is a rational constant.
   | QF_UF              -- ^ Unquantified formulas built over a signature of uninterpreted (i.e., free) sort and function symbols.
-  | QF_UFBV            -- ^ Unquantified formulas over bitvectors with uninterpreted sort function and symbols.
+  | QF_UFBV            -- ^ Unquantified formulas over bit-vectors with uninterpreted sort function and symbols.
   | QF_UFIDL           -- ^ Difference Logic over the integers (in essence) but with uninterpreted sort and function symbols.
   | QF_UFLIA           -- ^ Unquantified linear integer arithmetic with uninterpreted sort and function symbols.
   | QF_UFLRA           -- ^ Unquantified linear real arithmetic with uninterpreted sort and function symbols.
diff --git a/Data/SBV/Control/Utils.hs b/Data/SBV/Control/Utils.hs
--- a/Data/SBV/Control/Utils.hs
+++ b/Data/SBV/Control/Utils.hs
@@ -10,25 +10,22 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE BangPatterns           #-}
-{-# LANGUAGE InstanceSigs           #-}
-{-# LANGUAGE FlexibleContexts       #-}
 {-# LANGUAGE FlexibleInstances      #-}
 {-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE InstanceSigs           #-}
 {-# LANGUAGE LambdaCase             #-}
 {-# LANGUAGE NamedFieldPuns         #-}
 {-# LANGUAGE OverloadedStrings      #-}
 {-# LANGUAGE ScopedTypeVariables    #-}
 {-# LANGUAGE TupleSections          #-}
 {-# LANGUAGE TypeApplications       #-}
-{-# LANGUAGE TypeFamilies           #-}
 {-# LANGUAGE ViewPatterns           #-}
-{-# LANGUAGE UndecidableInstances   #-}
 
 {-# OPTIONS_GHC -Wall -Werror -fno-warn-orphans #-}
 
 module Data.SBV.Control.Utils (
        io
-     , ask, send, getValue, getFunction, getUninterpretedValue
+     , ask, send, getValue, getFunction
      , getValueCV, getUICVal, getUIFunCVAssoc, getUnsatAssumptions
      , SMTFunction(..), getQueryState, modifyQueryState, getConfig, getObjectives, getUIs
      , getSBVAssertions, getSBVPgm, getObservables
@@ -38,7 +35,7 @@
      , timeout, queryDebug, retrieveResponse, recoverKindedValue, runProofOn, executeQuery
      ) where
 
-import Data.List  (sortBy, sortOn, elemIndex, partition, groupBy, tails, intercalate, nub, sort, isPrefixOf, isSuffixOf)
+import Data.List  (sortBy, sortOn, partition, groupBy, tails, intercalate, nub, sort, isPrefixOf, isSuffixOf)
 
 import Data.Char      (isPunctuation, isSpace, isDigit)
 import Data.Function  (on)
@@ -71,7 +68,7 @@
                               , SolverContext(..), SBool, Objective(..), SolverCapabilities(..), capabilities
                               , Result(..), SMTProblem(..), trueSV, SymVal(..), SBVPgm(..), SMTSolver(..), SBVRunMode(..)
                               , SBVType(..), forceSVArg, RoundingMode(RoundNearestTiesToEven), (.=>)
-                              , RCSet(..), QuantifiedBool(..), ArrayModel(..)
+                              , RCSet(..), QuantifiedBool(..), ArrayModel(..), SInfo(..), getSInfo
                               )
 
 import Data.SBV.Core.Symbolic ( IncState(..), withNewIncState, State(..), svToSV, symbolicEnv, SymbolicT
@@ -86,7 +83,7 @@
 
 import Data.SBV.Core.AlgReals    (mergeAlgReals, AlgReal(..), RealPoint(..))
 import Data.SBV.Core.SizedFloats (fpZero, fpFromInteger, fpFromFloat, fpFromDouble)
-import Data.SBV.Core.Kind        (smtType, hasUninterpretedSorts)
+import Data.SBV.Core.Kind        (smtType, hasUninterpretedSorts, expandKinds, isSomeKindOfFloat, substituteADTVars)
 import Data.SBV.Core.Operations  (svNot, svNotEqual, svOr, svEqual)
 
 import Data.SBV.SMT.SMT     (showModel, parseCVs, SatModel, AllSatResult(..))
@@ -94,7 +91,6 @@
 import Data.SBV.SMT.SMTLib2 (setSMTOption)
 import Data.SBV.SMT.Utils   ( showTimeoutValue, addAnnotations, alignPlain, debug
                             , mergeSExpr, SBVException(..), recordTranscript, TranscriptMsg(..)
-                            , witnessName
                             )
 
 import Data.SBV.Utils.ExtractIO
@@ -366,7 +362,7 @@
 
 -- | A class which allows for sexpr-conversion to functions
 class (HasKind r, SatModel r) => SMTFunction fun a r | fun -> a r where
-  sexprToArg     :: fun -> [SExpr] -> Maybe a
+  sexprToArg     :: (MonadIO m, SolverContext m) => fun -> [SExpr] -> m (Maybe a)
   smtFunName     :: (MonadIO m, SolverContext m) => fun -> m ((String, Maybe [String]), Bool)
   smtFunSaturate :: fun -> SBV r
   smtFunType     :: fun -> SBVType
@@ -423,17 +419,23 @@
                             _                                           -> cantFind uiMap
 
   sexprToFun f (s, e) = do nm    <- fst . fst <$> smtFunName f
+                           si    <- contextState >>= getSInfo
                            mbRes <- case parseSExprFunction e of
                                       Just (Left nm') -> case (nm == nm', smtFunDefault f) of
                                                            (True, Just v)  -> return $ Just ([], v)
                                                            _               -> bailOut nm
-                                      Just (Right v)  -> return $ convert v
+                                      Just (Right v)  -> convert si v
                                       Nothing         -> do mbPVS <- pointWiseExtract nm (smtFunType f)
-                                                            return $ mbPVS >>= convert
+                                                            case mbPVS of
+                                                              Nothing  -> pure Nothing
+                                                              Just pts -> convert si pts
                            pure $ maybe (Left s) Right mbRes
-    where convert    (vs, d) = (,) <$> mapM sexprPoint vs <*> sexprToVal d
-          sexprPoint (as, v) = (,) <$> sexprToArg f as    <*> sexprToVal v
+    where convert st (vs, d) = do ps <- mapM (sexprPoint st) vs
+                                  pure $ (,) <$> sequenceA ps <*> sexprToVal st d
 
+          sexprPoint st (as, v) = do mbA <- sexprToArg f as
+                                     pure $ (,) <$> mbA <*> sexprToVal st v
+
           bailOut nm = error $ unlines [ ""
                                        , "*** Data.SBV.getFunction: Unable to extract an interpretation for function " ++ show nm
                                        , "***"
@@ -448,12 +450,12 @@
 -- up. And I think it'll only be necessary then, I haven't seen z3 try anything smarter in other scenarios.
 pointWiseExtract ::  forall m. (MonadIO m, MonadQuery m) => String -> SBVType -> m (Maybe ([([SExpr], SExpr)], SExpr))
 pointWiseExtract nm typ = tryPointWise
-  where trueSExpr  = ENum (1, Nothing)
-        falseSExpr = ENum (0, Nothing)
+  where trueSExpr  = ENum (1, Nothing, True)
+        falseSExpr = ENum (0, Nothing, True)
 
-        isTrueSExpr (ENum (1, Nothing)) = True
-        isTrueSExpr (ENum (0, Nothing)) = False
-        isTrueSExpr s                   = error $ "Data.SBV.pointWiseExtract: Impossible happened: Received: " ++ show s
+        isTrueSExpr (ENum (1, Nothing, True)) = True
+        isTrueSExpr (ENum (0, Nothing, True)) = False
+        isTrueSExpr s                         = error $ "Data.SBV.pointWiseExtract: Impossible happened: Received: " ++ show s
 
         (nArgs, isBoolFunc) = case typ of
                                 SBVType ts -> (length ts - 1, all (== KBool) ts)
@@ -500,8 +502,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction (SBV a -> SBV r) a r
          where
-  sexprToArg _ [a0] = sexprToVal a0
-  sexprToArg _ _    = Nothing
+  sexprToArg _ [a0] = contextState >>= getSInfo >>= \si -> pure $ sexprToVal si a0
+  sexprToArg _ _    = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @r)]
 
@@ -513,8 +515,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction (SBV a -> SBV b -> SBV r) (a, b) r
          where
-  sexprToArg _ [a0, a1] = (,) <$> sexprToVal a0 <*> sexprToVal a1
-  sexprToArg _ _        = Nothing
+  sexprToArg _ [a0, a1] = contextState >>= getSInfo >>= \si -> pure $ (,) <$> sexprToVal si a0 <*> sexprToVal si a1
+  sexprToArg _ _        = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @r)]
 
@@ -528,8 +530,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV r) (a, b, c) r
          where
-  sexprToArg _ [a0, a1, a2] = (,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2
-  sexprToArg _ _            = Nothing
+  sexprToArg _ [a0, a1, a2] = contextState >>= getSInfo >>= \si -> pure $ (,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2
+  sexprToArg _ _            = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @r)]
 
@@ -545,8 +547,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV d -> SBV r) (a, b, c, d) r
          where
-  sexprToArg _ [a0, a1, a2, a3] = (,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3
-  sexprToArg _ _               = Nothing
+  sexprToArg _ [a0, a1, a2, a3] = contextState >>= getSInfo >>= \si -> pure $ (,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3
+  sexprToArg _ _                = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @r)]
 
@@ -564,8 +566,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> SBV r) (a, b, c, d, e) r
          where
-  sexprToArg _ [a0, a1, a2, a3, a4] = (,,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3 <*> sexprToVal a4
-  sexprToArg _ _                    = Nothing
+  sexprToArg _ [a0, a1, a2, a3, a4] = contextState >>= getSInfo >>= \si -> pure $ (,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4
+  sexprToArg _ _                    = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @r)]
 
@@ -585,8 +587,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> SBV f -> SBV r) (a, b, c, d, e, f) r
          where
-  sexprToArg _ [a0, a1, a2, a3, a4, a5] = (,,,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3 <*> sexprToVal a4 <*> sexprToVal a5
-  sexprToArg _ _                        = Nothing
+  sexprToArg _ [a0, a1, a2, a3, a4, a5] = contextState >>= getSInfo >>= \si -> pure $ (,,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4 <*> sexprToVal si a5
+  sexprToArg _ _                        = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @f), kindOf (Proxy @r)]
 
@@ -608,8 +610,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> SBV f -> SBV g -> SBV r) (a, b, c, d, e, f, g) r
          where
-  sexprToArg _ [a0, a1, a2, a3, a4, a5, a6] = (,,,,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3 <*> sexprToVal a4 <*> sexprToVal a5 <*> sexprToVal a6
-  sexprToArg _ _                            = Nothing
+  sexprToArg _ [a0, a1, a2, a3, a4, a5, a6] = contextState >>= getSInfo >>= \si -> pure $ (,,,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4 <*> sexprToVal si a5 <*> sexprToVal si a6
+  sexprToArg _ _                            = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @f), kindOf (Proxy @g), kindOf (Proxy @r)]
 
@@ -633,8 +635,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> SBV f -> SBV g -> SBV h -> SBV r) (a, b, c, d, e, f, g, h) r
          where
-  sexprToArg _ [a0, a1, a2, a3, a4, a5, a6, a7] = (,,,,,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3 <*> sexprToVal a4 <*> sexprToVal a5 <*> sexprToVal a6 <*> sexprToVal a7
-  sexprToArg _ _                                = Nothing
+  sexprToArg _ [a0, a1, a2, a3, a4, a5, a6, a7] = contextState >>= getSInfo >>= \si -> pure $ (,,,,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4 <*> sexprToVal si a5 <*> sexprToVal si a6 <*> sexprToVal si a7
+  sexprToArg _ _                                = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @f), kindOf (Proxy @g), kindOf (Proxy @h), kindOf (Proxy @r)]
 
@@ -653,8 +655,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction ((SBV a, SBV b) -> SBV r) (a, b) r
          where
-  sexprToArg _ [a0, a1] = (,) <$> sexprToVal a0 <*> sexprToVal a1
-  sexprToArg _ _        = Nothing
+  sexprToArg _ [a0, a1] = contextState >>= getSInfo >>= \si -> pure $ (,) <$> sexprToVal si a0 <*> sexprToVal si a1
+  sexprToArg _ _        = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @r)]
 
@@ -669,8 +671,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction ((SBV a, SBV b, SBV c) -> SBV r) (a, b, c) r
          where
-  sexprToArg _ [a0, a1, a2] = (,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2
-  sexprToArg _ _            = Nothing
+  sexprToArg _ [a0, a1, a2] = contextState >>= getSInfo >>= \si -> pure $ (,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2
+  sexprToArg _ _            = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @r)]
 
@@ -687,8 +689,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction ((SBV a, SBV b, SBV c, SBV d) -> SBV r) (a, b, c, d) r
          where
-  sexprToArg _ [a0, a1, a2, a3] = (,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3
-  sexprToArg _ _                = Nothing
+  sexprToArg _ [a0, a1, a2, a3] = contextState >>= getSInfo >>= \si -> pure $ (,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3
+  sexprToArg _ _                = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @r)]
 
@@ -707,8 +709,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction ((SBV a, SBV b, SBV c, SBV d, SBV e) -> SBV r) (a, b, c, d, e) r
          where
-  sexprToArg _ [a0, a1, a2, a3, a4] = (,,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3 <*> sexprToVal a4
-  sexprToArg _ _                    = Nothing
+  sexprToArg _ [a0, a1, a2, a3, a4] = contextState >>= getSInfo >>= \si -> pure $ (,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4
+  sexprToArg _ _                    = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @r)]
 
@@ -729,8 +731,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) -> SBV r) (a, b, c, d, e, f) r
          where
-  sexprToArg _ [a0, a1, a2, a3, a4, a5] = (,,,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3 <*> sexprToVal a4 <*> sexprToVal a5
-  sexprToArg _ _                        = Nothing
+  sexprToArg _ [a0, a1, a2, a3, a4, a5] = contextState >>= getSInfo >>= \si -> pure $ (,,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4 <*> sexprToVal si a5
+  sexprToArg _ _                        = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @f), kindOf (Proxy @r)]
 
@@ -753,8 +755,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) -> SBV r) (a, b, c, d, e, f, g) r
          where
-  sexprToArg _ [a0, a1, a2, a3, a4, a5, a6] = (,,,,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3 <*> sexprToVal a4 <*> sexprToVal a5 <*> sexprToVal a6
-  sexprToArg _ _                            = Nothing
+  sexprToArg _ [a0, a1, a2, a3, a4, a5, a6] = contextState >>= getSInfo >>= \si -> pure $ (,,,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4 <*> sexprToVal si a5 <*> sexprToVal si a6
+  sexprToArg _ _                            = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @f), kindOf (Proxy @g), kindOf (Proxy @r)]
 
@@ -779,8 +781,8 @@
          , SatModel r, HasKind r
          ) => SMTFunction ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g, SBV h) -> SBV r) (a, b, c, d, e, f, g, h) r
          where
-  sexprToArg _ [a0, a1, a2, a3, a4, a5, a6, a7] = (,,,,,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3 <*> sexprToVal a4 <*> sexprToVal a5 <*> sexprToVal a6 <*> sexprToVal a7
-  sexprToArg _ _                                = Nothing
+  sexprToArg _ [a0, a1, a2, a3, a4, a5, a6, a7] = contextState >>= getSInfo >>= \si -> pure $ (,,,,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4 <*> sexprToVal si a5 <*> sexprToVal si a6 <*> sexprToVal si a7
+  sexprToArg _ _                                = pure Nothing
 
   smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @f), kindOf (Proxy @g), kindOf (Proxy @h), kindOf (Proxy @r)]
 
@@ -819,40 +821,27 @@
 
                    r <- ask cmd
 
-                   parse r bad $ \case EApp [EApp [ECon o, e]] | o == nm -> do mbAssocs <- sexprToFun f (trimFunctionResponse r nm isCurried args, e)
-                                                                               case mbAssocs of
-                                                                                 Right assocs -> return $ Right assocs
-                                                                                 Left  raw    -> do mbPVS <- pointWiseExtract nm (smtFunType f)
-                                                                                                    case mbPVS >>= convert of
-                                                                                                      Just x  -> return $ Right x
-                                                                                                      Nothing -> return $ Left (raw, (isCurried, args, e))
-                                       _                                 -> bad r Nothing
-    where convert    (vs, d) = (,) <$> mapM sexprPoint vs <*> sexprToVal d
-          sexprPoint (as, v) = (,) <$> sexprToArg f as    <*> sexprToVal v
-
--- | Generalization of 'Data.SBV.Control.getUninterpretedValue'
-getUninterpretedValue :: (MonadIO m, MonadQuery m, HasKind a) => SBV a -> m String
-getUninterpretedValue s =
-        case kindOf s of
-          KUserSort _ Nothing -> do sv <- inNewContext (`sbvToSV` s)
-
-                                    let nm  = show sv
-                                        cmd = "(get-value (" ++ nm ++ "))"
-                                        bad = unexpected "getValue" cmd "a model value" Nothing
-
-                                    r <- ask cmd
+                   si <- contextState >>= getSInfo
 
-                                    parse r bad $ \case EApp [EApp [ECon o,  ECon v]] | o == show sv -> return v
-                                                        _                                            -> bad r Nothing
+                   parse r bad $ \case EApp [EApp [ECon o, e]] | o == nm -> do
+                                          mbAssocs <- sexprToFun f (trimFunctionResponse r nm isCurried args, e)
+                                          case mbAssocs of
+                                            Right assocs -> return $ Right assocs
+                                            Left  raw    -> do
+                                               let rawRes = Left (raw, (isCurried, args, e))
+                                               mbPVS <- pointWiseExtract nm (smtFunType f)
+                                               case mbPVS of
+                                                 Just ps -> do rs <- convert si ps
+                                                               case rs of
+                                                                  Just x  -> return $ Right x
+                                                                  Nothing -> return rawRes
+                                                 Nothing -> return rawRes
+                                       _ -> bad r Nothing
+    where convert si (vs, d) = do ps <- mapM (sexprPoint si) vs
+                                  pure $ (,) <$> sequenceA ps <*> sexprToVal si d
 
-          k                   -> error $ unlines [""
-                                                 , "*** SBV.getUninterpretedValue: Called on an 'interpreted' kind"
-                                                 , "*** "
-                                                 , "***    Kind: " ++ show k
-                                                 , "***    Hint: Use 'getValue' to extract value for interpreted kinds."
-                                                 , "*** "
-                                                 , "*** Only truly uninterpreted sorts should be used with 'getUninterpretedValue.'"
-                                                 ]
+          sexprPoint si (as, v) = do mbA <- sexprToArg f as
+                                     pure $ (,) <$> mbA <*> sexprToVal si v
 
 -- | Get the value of a term, but in CV form. Used internally. The model-index, in particular is extremely Z3 specific!
 getValueCVHelper :: (MonadIO m, MonadQuery m) => Maybe Int -> SV -> m CV
@@ -868,11 +857,11 @@
 defaultKindedValue :: Kind -> CV
 defaultKindedValue k = CV k $ cvt k
   where cvt :: Kind -> CVal
+        cvt (KVar s)         = error ("defaultKindedValue: Unexpected kind: " ++ s)
         cvt KBool            = CInteger 0
         cvt KBounded{}       = CInteger 0
         cvt KUnbounded       = CInteger 0
         cvt KReal            = CAlgReal 0
-        cvt (KUserSort s ui) = uninterp s ui
         cvt KFloat           = CFloat 0
         cvt KDouble          = CDouble 0
         cvt KRational        = CRational 0
@@ -882,73 +871,82 @@
         cvt (KList  _)       = CList []
         cvt (KSet  _)        = CSet $ RegularSet Set.empty -- why not? Arguably, could be the universal set
         cvt (KTuple ks)      = CTuple $ map cvt ks
-        cvt (KMaybe _)       = CMaybe Nothing
-        cvt (KEither k1 _)   = CEither . Left $ cvt k1     -- why not?
         cvt (KArray  _  k2)  = CArray $ ArrayModel [] (cvt k2)
 
-        -- Tricky case of uninterpreted
-        uninterp _ (Just (c:_)) = CUserSort (Just 0, c)
-        uninterp _ (Just [])    = error "defaultKindedValue: enumerated kind with no constructors!"
+        cvt (KApp s _)       = error ("defaultKindedValue not supported for ADT app: " ++ s) -- tough luck
 
-        -- A completely uninterpreted sort, i.e., no elements. Return the witness element for it.
-        uninterp s Nothing      = CUserSort (Nothing, witnessName s)
+        -- For ADTs, just return the first element if there's any
+        cvt (KADT s _ cstrs) = case cstrs of
+                                 []            -> error ("defaultKindedValue not supported for ADT: "     ++ s) -- tough luck
+                                 ((c, ks) : _) -> CADT (c, [(k, cvt fk) | fk <- ks])
 
 -- | Go from an SExpr directly to a value
-sexprToVal :: forall a. SymVal a => SExpr -> Maybe a
-sexprToVal e = fromCV <$> recoverKindedValue (kindOf (Proxy @a)) e
+sexprToVal :: forall a. SymVal a => SInfo -> SExpr -> Maybe a
+sexprToVal si e = fromCV <$> recoverKindedValue si (kindOf (Proxy @a)) e
 
 -- | Recover a given solver-printed value with a possible interpretation
-recoverKindedValue :: Kind -> SExpr -> Maybe CV
-recoverKindedValue k e = case k of
-                           KBool       | ENum (i, _) <- e      -> Just $ mkConstCV k i
-                                       | True                  -> Nothing
+recoverKindedValue :: SInfo -> Kind -> SExpr -> Maybe CV
+recoverKindedValue si k e =
+    case k of
+      KVar{}      -> error $ "Data.SBV.recoverKindedValue: Unexpected var kind: " ++ show k
 
-                           KBounded{}  | ENum (i, _) <- e      -> Just $ mkConstCV k i
-                                       | True                  -> Nothing
+      KApp n ks   -> case [(s, ps, cstrs) | KADT s ps cstrs <- sInfoKinds si, s == n] of
+                       [(s, ps, cstr)]
+                         | length ks == length ps -> recoverKindedValue si (KADT s (zip (map fst ps) ks) cstr) e
+                       xs -> error $ unlines [ "Data.SBV.recoverKindedValue: Can't uniquely locate reference to ADT: "
+                                             , "***"
+                                             , "*** ADT    : " ++ show n
+                                             , "*** Params : " ++ show ks
+                                             , "*** Matched: " ++ show xs
+                                             , "*** Expr   : " ++ show e
+                                             , "***"
+                                             , "*** Please report this as a bug."
+                                             ]
 
-                           KUnbounded  | ENum (i, _) <- e      -> Just $ mkConstCV k i
-                                       | True                  -> Nothing
+      KBool       | ENum (i, _, _) <- e   -> Just $ mkConstCV k i
+                  | True                  -> Nothing
 
-                           KReal       | ENum (i, _) <- e      -> Just $ mkConstCV k i
-                                       | EReal i     <- e      -> Just $ CV KReal (CAlgReal i)
-                                       | True                  -> interpretInterval e
+      KBounded{}  | ENum (i, _, _) <- e   -> Just $ mkConstCV k i
+                  | True                  -> Nothing
 
-                           KUserSort{} | ECon s <- e           -> Just $ CV k $ CUserSort (getUIIndex k s, simplifyECon s)
-                                       | True                  -> Nothing
+      KUnbounded  | ENum (i, _, _) <- e   -> Just $ mkConstCV k i
+                  | True                  -> Nothing
 
-                           KFloat      | ENum (i, _) <- e      -> Just $ mkConstCV k i
-                                       | EFloat i    <- e      -> Just $ CV KFloat (CFloat i)
-                                       | True                  -> Nothing
+      KReal       | ENum (i, _, _) <- e   -> Just $ mkConstCV k i
+                  | EReal i        <- e   -> Just $ CV KReal (CAlgReal i)
+                  | True                  -> interpretInterval e
 
-                           KDouble     | ENum (i, _) <- e      -> Just $ mkConstCV k i
-                                       | EDouble i   <- e      -> Just $ CV KDouble (CDouble i)
-                                       | True                  -> Nothing
+      KADT nm dict def                    -> let k' = KADT nm dict [(c, map (substituteADTVars nm dict) ks) | (c, ks) <- def]
+                                             in Just $ CV k' $ CADT $ interpretADT k' e
 
-                           KFP eb sb   | ENum (i, _)      <- e -> Just $ CV k $ CFP $ fpFromInteger eb sb i
-                                       | EFloat f         <- e -> Just $ CV k $ CFP $ fpFromFloat   eb sb f
-                                       | EDouble d        <- e -> Just $ CV k $ CFP $ fpFromDouble  eb sb d
-                                       | EFloatingPoint c <- e -> Just $ CV k $ CFP c
-                                       | True                  -> Nothing
+      KFloat      | ENum (i, _, _) <- e   -> Just $ mkConstCV k i
+                  | EFloat i       <- e   -> Just $ CV KFloat (CFloat i)
+                  | True                  -> Nothing
 
-                           KChar       | ECon s      <- e      -> Just $ CV KChar $ CChar $ interpretChar s
-                                       | True                  -> Nothing
+      KDouble     | ENum (i, _, _) <- e   -> Just $ mkConstCV k i
+                  | EDouble i      <- e   -> Just $ CV KDouble (CDouble i)
+                  | True                  -> Nothing
 
-                           KString     | ECon s      <- e      -> Just $ CV KString $ CString $ interpretString s
-                                       | True                  -> Nothing
+      KFP eb sb   | ENum (i, _, _)   <- e -> Just $ CV k $ CFP $ fpFromInteger eb sb i
+                  | EFloat f         <- e -> Just $ CV k $ CFP $ fpFromFloat   eb sb f
+                  | EDouble d        <- e -> Just $ CV k $ CFP $ fpFromDouble  eb sb d
+                  | EFloatingPoint c <- e -> Just $ CV k $ CFP c
+                  | True                  -> Nothing
 
-                           KRational                           -> Just $ CV k $ CRational $ interpretRational       e
-                           KList ek                            -> Just $ CV k $ CList     $ interpretList ek        e
-                           KSet ek                             -> Just $ CV k $ CSet      $ interpretSet ek         e
-                           KTuple{}                            -> Just $ CV k $ CTuple    $ interpretTuple          e
-                           KMaybe{}                            -> Just $ CV k $ CMaybe    $ interpretMaybe    k     e
-                           KEither{}                           -> Just $ CV k $ CEither   $ interpretEither   k     e
-                           KArray k1 k2                        -> Just $ CV k $ CArray    $ interpretArray    k1 k2 e
+      KChar       | ECon s      <- e      -> Just $ CV KChar $ CChar $ interpretChar s
+                  | True                  -> Nothing
 
-  where getUIIndex (KUserSort  _ (Just xs)) i = i `elemIndex` xs
-        getUIIndex _                        _ = Nothing
+      KString     | ECon s      <- e      -> Just $ CV KString $ CString $ interpretString s
+                  | True                  -> Nothing
 
-        stringLike xs = length xs >= 2 && "\"" `isPrefixOf` xs && "\"" `isSuffixOf` xs
+      KRational                           -> Just $ CV k $ CRational $ interpretRational       e
+      KList ek                            -> Just $ CV k $ CList     $ interpretList ek        e
+      KSet ek                             -> Just $ CV k $ CSet      $ interpretSet ek         e
+      KTuple{}                            -> Just $ CV k $ CTuple    $ interpretTuple          e
+      KArray k1 k2                        -> Just $ CV k $ CArray    $ interpretArray    k1 k2 e
 
+  where stringLike xs = length xs >= 2 && "\"" `isPrefixOf` xs && "\"" `isSuffixOf` xs
+
         -- Make sure strings are really strings
         interpretString xs
           | not (stringLike xs)
@@ -961,15 +959,15 @@
                              _   -> error $ "Expected a singleton char constant, received: <" ++ xs ++ ">"
 
         interpretRational (EApp [ECon "SBV.Rational", v1, v2])
-           | Just (CV _ (CInteger n)) <- recoverKindedValue KUnbounded v1
-           , Just (CV _ (CInteger d)) <- recoverKindedValue KUnbounded v2
+           | Just (CV _ (CInteger n)) <- recoverKindedValue si KUnbounded v1
+           , Just (CV _ (CInteger d)) <- recoverKindedValue si KUnbounded v2
            = n % d
         interpretRational xs = error $ "Expected a rational constant, received: <" ++ show xs ++ ">"
 
         interpretList ek topExpr = walk topExpr
           where walk (EApp [ECon "as", v, _])      = walk v
                 walk (ECon "seq.empty")            = []
-                walk (EApp [ECon "seq.unit", v])   = case recoverKindedValue ek v of
+                walk (EApp [ECon "seq.unit", v])   = case recoverKindedValue si ek v of
                                                        Just w -> [cvVal w]
                                                        Nothing -> error $ "Cannot parse a sequence item of kind " ++ show ek ++ " from: " ++ show v ++ extra v
                 walk (EApp (ECon "seq.++" : rest)) = concatMap walk rest
@@ -999,8 +997,8 @@
                                          ]
 
 
-                 isTrue (ENum (1, Nothing)) = True
-                 isTrue (ENum (0, Nothing)) = False
+                 isTrue (ENum (1, Nothing, True)) = True
+                 isTrue (ENum (0, Nothing, True)) = False
                  isTrue bad                 = tbd $ "Non-boolean membership value seen: " ++ show bad
 
                  isUniversal (EApp [EApp [ECon "as", ECon "const", EApp [ECon "Array", _, ECon "Bool"]], r]) = isTrue r
@@ -1018,17 +1016,17 @@
                  contents _   bad      = tbd $ "Multi-valued set member seen: " ++ show bad
 
                  element cvt x = case (cvt, ke) of
-                                   (True, KChar) -> case recoverKindedValue KString x of
+                                   (True, KChar) -> case recoverKindedValue si KString x of
                                                       Just v  -> case cvVal v of
                                                                   CString [c] -> [CChar c]
                                                                   CString _   -> []
                                                                   _           -> tbd $ "Unexpected value for kind: " ++ show (x, ke)
                                                       Nothing -> tbd $ "Unexpected value for kind: " ++ show (x, ke)
-                                   _             -> case recoverKindedValue ke x of
+                                   _             -> case recoverKindedValue si ke x of
                                                       Just v  -> [cvVal v]
                                                       Nothing -> tbd $ "Unexpected value for kind: " ++ show (x, ke)
 
-        interpretTuple te = walk (1 :: Int) (zipWith recoverKindedValue ks args) []
+        interpretTuple te = walk (1 :: Int) (zipWith (recoverKindedValue si) ks args) []
                 where (ks, n) = case k of
                                   KTuple eks -> (eks, length eks)
                                   _          -> error $ unlines [ "Impossible: Expected a tuple kind, but got: " ++ show k
@@ -1054,48 +1052,14 @@
                                                                   , "Expr: " ++ show te
                                                                   ]
 
-        -- SMaybe
-        interpretMaybe (KMaybe _)  (ECon "nothing_SBVMaybe")        = Nothing
-        interpretMaybe (KMaybe ek) (EApp [ECon "just_SBVMaybe", a]) = case recoverKindedValue ek a of
-                                                                        Just (CV _ v) -> Just v
-                                                                        Nothing       -> error $ unlines [ "Couldn't parse a maybe just value"
-                                                                                                         , "Kind: " ++ show ek
-                                                                                                         , "Expr: " ++ show a
-                                                                                                         ]
-        -- CVC4 puts in full ascriptions, handle those:
-        interpretMaybe _  (      EApp [ECon "as", ECon "nothing_SBVMaybe", _])     = Nothing
-        interpretMaybe mk (EApp [EApp [ECon "as", ECon "just_SBVMaybe",    _], a]) = interpretMaybe mk (EApp [ECon "just_SBVMaybe", a])
-
-        interpretMaybe _  other = error $ "Expected an SMaybe sexpr, but received: " ++ show (k, other)
-
-        -- SEither
-        interpretEither (KEither k1 _) (EApp [ECon "left_SBVEither",  a]) = case recoverKindedValue k1 a of
-                                                                              Just (CV _ v) -> Left v
-                                                                              Nothing       -> error $ unlines [ "Couldn't parse an either value on the left"
-                                                                                                               , "Kind: " ++ show k1
-                                                                                                               , "Expr: " ++ show a
-                                                                                                               ]
-        interpretEither (KEither _ k2) (EApp [ECon "right_SBVEither", b]) = case recoverKindedValue k2 b of
-                                                                              Just (CV _ v) -> Right v
-                                                                              Nothing       -> error $ unlines [ "Couldn't parse an either value on the right"
-                                                                                                               , "Kind: " ++ show k2
-                                                                                                               , "Expr: " ++ show b
-                                                                                                               ]
-
-        -- CVC4 puts full ascriptions:
-        interpretEither ek (EApp [EApp [ECon "as", ECon "left_SBVEither",  _], a]) = interpretEither ek (EApp [ECon "left_SBVEither", a])
-        interpretEither ek (EApp [EApp [ECon "as", ECon "right_SBVEither", _], b]) = interpretEither ek (EApp [ECon "right_SBVEither", b])
-
-        interpretEither _ other = error $ "Expected an SEither sexpr, but received: " ++ show (k, other)
-
         -- Intervals, for dReal
         interpretInterval expr = case expr of
                                    EApp [ECon "interval", lo, hi] -> do vlo <- getBorder lo
                                                                         vhi <- getBorder hi
                                                                         pure $ CV KReal (CAlgReal (AlgInterval vlo vhi))
                                    _                              -> Nothing
-          where getBorder (EApp [ECon "open",   v]) = recoverKindedValue KReal v >>= border OpenPoint
-                getBorder (EApp [ECon "closed", v]) = recoverKindedValue KReal v >>= border ClosedPoint
+          where getBorder (EApp [ECon "open",   v]) = recoverKindedValue si KReal v >>= border OpenPoint
+                getBorder (EApp [ECon "closed", v]) = recoverKindedValue si KReal v >>= border ClosedPoint
                 getBorder _                         = Nothing
 
                 border b (CV KReal (CAlgReal (AlgRational True v))) = pure $ b v
@@ -1119,11 +1083,49 @@
                                          ]
 
                  decode (args, d) = ArrayModel [(cvt k1 l, cvt k2 [r]) | (l, r) <- args] (cvt k2 [d])
-                   where cvt ek [v] = case recoverKindedValue ek v of
+                   where cvt ek [v] = case recoverKindedValue si ek v of
                                          Just (CV _ x) -> x
                                          _             -> tbd $ "Cannot convert value: " ++ show v
                          cvt _ vs   = tbd $ "Unexpected function-like-value as array index" ++ show vs
 
+        interpretADT :: Kind -> SExpr -> (String, [(Kind, CVal)])
+        interpretADT adtK@(KADT _ _ cks) expr
+           | isUninterpreted adtK
+           = case expr of
+               ECon s -> (simplifyECon s, [])
+               _      -> bad ["Unexpected expression value for uninterpreted kind."]
+           | Just ks <- cstr `lookup` cks
+           = if length fs == length ks
+             then (cstr, zipWith convert (zip [1..] ks) fs)
+             else bad ["Mismatching field count: " ++ show (fs, ks)]
+           | True
+           = bad ["Cannot find constructor in the kind: " ++ show (cstr, adtK)]
+          where (cstr, fs) = case removeAS expr of
+                               ECon c             -> (c, [])
+                               EApp (ECon c : cs) -> (c, cs)
+                               _                  -> bad ["Unexpected expression value; does not start with a constructor."]
+
+                removeAS :: SExpr -> SExpr
+                removeAS (EApp [ECon "as", i, _]) = removeAS i
+                removeAS (EApp xs)                = EApp $ map removeAS xs
+                removeAS ae                       = ae
+
+                bad :: [String] -> a
+                bad extras = error $ unlines $ [ "Data.SBV.interpretADT: Cannot recover ADT value from solver output."
+                                               , "   Kind: " ++ show adtK
+                                               , "   Expr: " ++ show expr
+                                               ] ++ extras
+
+                convert :: (Int, Kind) -> SExpr -> (Kind, CVal)
+                convert (i, fk) f = case recoverKindedValue si fk f of
+                                      Just (CV kv v) -> (kv, v)
+                                      Nothing        -> bad ["Couldn't convert field " ++ show i ++ ": " ++ show (fk, f)]
+
+        interpretADT someK expr = error $ unlines [ "Data.SBV.interpretADT: Expected an ADT kind, but got something else."
+                                                  , "   Expr: " ++ show expr
+                                                  , "   Kind: " ++ show someK
+                                                  ]
+
 -- | Generalization of 'Data.SBV.Control.getValueCV'
 getValueCV :: (MonadIO m, MonadQuery m) => Maybe Int -> SV -> m CV
 getValueCV mbi s
@@ -1158,7 +1160,9 @@
 
        r <- ask cmd
 
-       let recover val = case recoverKindedValue k val of
+       si <- queryState >>= getSInfo
+
+       let recover val = case recoverKindedValue si k val of
                            Just cv -> return cv
                            Nothing -> bad r Nothing
 
@@ -1184,17 +1188,19 @@
 
   r <- ask cmd
 
+  si <- queryState >>= getSInfo
+
   let (ats, rt) = case typ of
                     SBVType as | length as > 1 -> (init as, last as)
                     _                          -> error $ "Data.SBV.getUIFunCVAssoc: Expected a function type, got: " ++ show typ
 
   let convert (vs, d) = (,) <$> mapM toPoint vs <*> toRes d
       toPoint (as, v)
-         | length as == length ats = (,) <$> zipWithM recoverKindedValue ats as <*> toRes v
+         | length as == length ats = (,) <$> zipWithM (recoverKindedValue si) ats as <*> toRes v
          | True                    = error $ "Data.SBV.getUIFunCVAssoc: Mismatching type/value arity, got: " ++ show (as, ats)
 
       toRes :: SExpr -> Maybe CV
-      toRes = recoverKindedValue rt
+      toRes = recoverKindedValue si rt
 
       -- if we fail to parse, we'll return this answer as the string
       fallBack = trimFunctionResponse r nm isCurried mbArgs
@@ -1333,7 +1339,7 @@
                              Nothing   -> return ()
                              Just cmds -> mapM_ (send True) cmds
 
-                     let usorts = [s | us@(KUserSort s _) <- Set.toAscList ki, isFree us]
+                     let usorts = [s | us@(KADT s _ _) <- Set.toAscList ki, isUninterpreted us]
 
                      unless (null usorts) $ queryDebug [ "*** SBV.allSat: Uninterpreted sorts present: " ++ unwords usorts
                                                        , "***             SBV will use equivalence classes to generate all-satisfying instances."
@@ -1395,10 +1401,7 @@
                                 fastAllSat                                        allModelInputs (uiVars S.>< extractVars) (uiVars S.>< vars) cfg start
                         else    loop       topState (allUiFuns, uiFuns) allUiRegs allModelInputs                                        vars  cfg start
 
-   where isFree (KUserSort _ Nothing) = True
-         isFree _                     = False
-
-         finalize cnt cfg sofar extra
+   where finalize cnt cfg sofar extra
                 = when (allSatPrintAlong cfg && not (null (allSatResults sofar))) $ do
                            let msg 0 = "No solutions found."
                                msg 1 = "This is the only solution."
@@ -1497,7 +1500,7 @@
                                                        cstr shouldReject (sv, cv) = constrain (SBV $ mkEq (kindOf sv) sv (SVal (kindOf sv) (Left cv)) :: SBool)
                                                          where mkEq :: Kind -> SVal -> SVal -> SVal
                                                                mkEq k a b
-                                                                | isDouble k || isFloat k || isFP k
+                                                                | any isSomeKindOfFloat (expandKinds k)
                                                                 = if shouldReject
                                                                      then svNot  (a `fpEq` b)
                                                                      else         a `fpEq` b
@@ -1588,9 +1591,9 @@
                                                             }
                                            m = Satisfiable cfg model
 
-                                           (interpreteds, uninterpreteds) = S.partition (not . isFree . kindOf . fst) (fmap (snd . snd) assocs)
+                                           (interpreteds, uninterpreteds) = S.partition (not . isUninterpreted . kindOf . fst) (fmap (snd . snd) assocs)
 
-                                           interpretedRegUis = filter (not . isFree . kindOf . snd) uiRegVals
+                                           interpretedRegUis = filter (not . isUninterpreted . kindOf . snd) uiRegVals
 
                                            interpretedRegUiSVs = [(cvt n (kindOf cv), cv) | (n, cv) <- interpretedRegUis]
                                              where cvt :: String -> Kind -> SVal
diff --git a/Data/SBV/Core/Concrete.hs b/Data/SBV/Core/Concrete.hs
--- a/Data/SBV/Core/Concrete.hs
+++ b/Data/SBV/Core/Concrete.hs
@@ -10,11 +10,10 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveGeneric       #-}
 {-# LANGUAGE DeriveDataTypeable  #-}
+{-# LANGUAGE DeriveGeneric       #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications    #-}
-{-# LANGUAGE Rank2Types          #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -100,21 +99,19 @@
 -- | A constant value.
 -- Note: If you add a new constructor here, make sure you add the
 -- corresponding equality in the instance "Eq CVal" and "Ord CVal"!
-data CVal = CAlgReal  !AlgReal                -- ^ Algebraic real
-          | CInteger  !Integer                -- ^ Bit-vector/unbounded integer
-          | CFloat    !Float                  -- ^ Float
-          | CDouble   !Double                 -- ^ Double
-          | CFP       !FP                     -- ^ Arbitrary float
-          | CRational Rational                -- ^ Rational
-          | CChar     !Char                   -- ^ Character
-          | CString   !String                 -- ^ String
-          | CList     ![CVal]                 -- ^ List
-          | CSet      !(RCSet CVal)           -- ^ Set. Can be regular or complemented.
-          | CUserSort !(Maybe Int, String)    -- ^ Value of an uninterpreted/user kind. The Maybe Int shows index position for enumerations
-          | CTuple    ![CVal]                 -- ^ Tuple
-          | CMaybe    !(Maybe CVal)           -- ^ Maybe
-          | CEither   !(Either CVal CVal)     -- ^ Disjoint union
-          | CArray    !(ArrayModel CVal CVal) -- ^ Arrays are backed by look-up tables concretely
+data CVal = CAlgReal  !AlgReal                 -- ^ Algebraic real
+          | CInteger  !Integer                 -- ^ Bit-vector/unbounded integer
+          | CFloat    !Float                   -- ^ Float
+          | CDouble   !Double                  -- ^ Double
+          | CFP       !FP                      -- ^ Arbitrary float
+          | CRational Rational                 -- ^ Rational
+          | CChar     !Char                    -- ^ Character
+          | CString   !String                  -- ^ String
+          | CList     ![CVal]                  -- ^ List
+          | CSet      !(RCSet CVal)            -- ^ Set. Can be regular or complemented.
+          | CADT      (String, [(Kind, CVal)]) -- ^ ADT: Constructor, and fields
+          | CTuple    ![CVal]                  -- ^ Tuple
+          | CArray    !(ArrayModel CVal CVal)  -- ^ Arrays are backed by look-up tables concretely
           deriving (G.Data, Generic, NFData)
 
 -- | Assign a rank to constant values, this is structural and helps with ordering
@@ -129,11 +126,9 @@
 cvRank CString   {} =  7
 cvRank CList     {} =  8
 cvRank CSet      {} =  9
-cvRank CUserSort {} = 10
+cvRank CADT      {} = 10
 cvRank CTuple    {} = 11
-cvRank CMaybe    {} = 12
-cvRank CEither   {} = 13
-cvRank CArray    {} = 14
+cvRank CArray    {} = 12
 
 -- | Eq instance for CVal. Note that we cannot simply derive Eq/Ord, since CVAlgReal doesn't have proper
 -- instances for these when values are infinitely precise reals. However, we do
@@ -149,10 +144,8 @@
   CString   a == CString   b = a == b
   CList     a == CList     b = a == b
   CSet      a == CSet      b = a `eqRCSet` b
-  CUserSort a == CUserSort b = a == b
   CTuple    a == CTuple    b = a == b
-  CMaybe    a == CMaybe    b = a == b
-  CEither   a == CEither   b = a == b
+  CADT      a == CADT      b = a == b
 
   -- This is legit since we don't use this equality for actual semantic" equality, but rather as an index into maps
   CArray    (ArrayModel a1 d1) == CArray (ArrayModel a2 d2) = (a1, d1) == (a2, d2)
@@ -179,10 +172,8 @@
   CString   a `compare` CString   b = a `compare`                  b
   CList     a `compare` CList     b = a `compare`                  b
   CSet      a `compare` CSet      b = a `compareRCSet`             b
-  CUserSort a `compare` CUserSort b = a `compare`                  b
   CTuple    a `compare` CTuple    b = a `compare`                  b
-  CMaybe    a `compare` CMaybe    b = a `compare`                  b
-  CEither   a `compare` CEither   b = a `compare`                  b
+  CADT      a `compare` CADT      b = a `compare`                  b
 
   -- This is legit since we don't use this equality for actual semantic order, but rather as an index into maps
   CArray    (ArrayModel a1 d1) `compare` CArray (ArrayModel a2 d2) = (a1, d1) `compare` (a2, d2)
@@ -201,8 +192,8 @@
 
 -- | A t'CV' represents a concrete word of a fixed size:
 -- For signed words, the most significant digit is considered to be the sign.
-data CV = CV { _cvKind  :: !Kind
-             , cvVal    :: !CVal
+data CV = CV { cvKind  :: !Kind
+             , cvVal   :: !CVal
              }
              deriving (Eq, Ord, G.Data, NFData, Generic)
 
@@ -332,12 +323,10 @@
                                                     CRational a -> CRational (ra a)
                                                     CChar{}     -> error "Data.SBV.mapCV: Unexpected call through mapCV with chars!"
                                                     CString{}   -> error "Data.SBV.mapCV: Unexpected call through mapCV with strings!"
-                                                    CUserSort{} -> error "Data.SBV.mapCV: Unexpected call through mapCV with uninterpreted sorts!"
+                                                    CADT{}      -> error "Data.SBV.mapCV: Unexpected call through mapCV with ADTs!"
                                                     CList{}     -> error "Data.SBV.mapCV: Unexpected call through mapCV with lists!"
                                                     CSet{}      -> error "Data.SBV.mapCV: Unexpected call through mapCV with sets!"
                                                     CTuple{}    -> error "Data.SBV.mapCV: Unexpected call through mapCV with tuples!"
-                                                    CMaybe{}    -> error "Data.SBV.mapCV: Unexpected call through mapCV with maybe!"
-                                                    CEither{}   -> error "Data.SBV.mapCV: Unexpected call through mapCV with either!"
                                                     CArray{}    -> error "Data.SBV.mapCV: Unexpected call through mapCV with arrays!"
 
 -- | Map a binary function through a t'CV'.
@@ -357,11 +346,8 @@
                             (True, CRational a, CRational b) -> normCV $ CV (kindOf x) (CRational (ra a b))
                             (True, CChar{},     CChar{})     -> unexpected "chars!"
                             (True, CString{},   CString{})   -> unexpected "strings!"
-                            (True, CUserSort{}, CUserSort{}) -> unexpected "uninterpreted constants!"
                             (True, CList{},     CList{})     -> unexpected "lists!"
                             (True, CTuple{},    CTuple{})    -> unexpected "tuples!"
-                            (True, CMaybe{},    CMaybe{})    -> unexpected "maybes!"
-                            (True, CEither{},   CEither{})   -> unexpected "eithers!"
                             _                                -> unexpected $ "incompatible args: " ++ show (x, y)
    where unexpected w = error $ unlines [ ""
                                         , "*** Data.SBV.mapCV2: Unexpected call through mapCV2 with " ++ w
@@ -386,21 +372,19 @@
 
         wk = kindOf w
 
-        sh (CAlgReal  v) = show v
-        sh (CInteger  v) = show v
-        sh (CFloat    v) = show v
-        sh (CDouble   v) = show v
-        sh (CFP       v) = show v
-        sh (CRational v) = show v
-        sh (CChar     v) = show v
-        sh (CString   v) = show v
-        sh (CUserSort v) = snd  v
-        sh (CList     v) = shL  v
-        sh (CSet      v) = shS  v
-        sh (CTuple    v) = shT  v
-        sh (CMaybe    v) = shM  v
-        sh (CEither   v) = shE  v
-        sh (CArray    v) = shA  v
+        sh (CAlgReal  v) = show  v
+        sh (CInteger  v) = show  v
+        sh (CFloat    v) = show  v
+        sh (CDouble   v) = show  v
+        sh (CFP       v) = show  v
+        sh (CRational v) = show  v
+        sh (CChar     v) = show  v
+        sh (CString   v) = show  v
+        sh (CADT      c) = shADT c
+        sh (CList     v) = shL   v
+        sh (CSet      v) = shS   v
+        sh (CTuple    v) = shT   v
+        sh (CArray    v) = shA   v
 
         shL xs = "[" ++ intercalate "," (map (showCV False . CV ke) xs) ++ "]"
           where ke = case wk of
@@ -424,34 +408,24 @@
                         KTuple ks | length ks == length xs -> zipWith (\k x -> showCV False (CV k x)) ks xs
                         _   -> error $ "Data.SBV.showCV: Impossible happened, expected tuple (of length " ++ show (length xs) ++ "), got: " ++ show wk
 
-        shM :: Maybe CVal -> String
-        shM c = case (c, wk) of
-                  (Nothing, KMaybe{}) -> "Nothing"
-                  (Just x,  KMaybe k) -> "Just " ++ paren (showCV False (CV k x))
-                  _                   -> error $ "Data.SBV.showCV: Impossible happened, expected maybe, got: " ++ show wk
-
-        shE :: Either CVal CVal -> String
-        shE val
-          | KEither k1 k2 <- wk = case val of
-                                    Left  x -> "Left "  ++ paren (showCV False (CV k1 x))
-                                    Right y -> "Right " ++ paren (showCV False (CV k2 y))
-          | True                = error $ "Data.SBV.showCV: Impossible happened, expected sum, got: " ++ show wk
-
         shA :: ArrayModel CVal CVal -> String
         shA (ArrayModel assocs def)
           | KArray k1 k2 <- wk = "([" ++ intercalate "," [showCV False (CV (KTuple [k1, k2]) (CTuple [a, b])) | (a, b) <- assocs] ++ "], " ++ showCV False (CV k2 def) ++ ")"
           | True               = error $ "Data.SBV.showCV: Impossible happened, expected array, got: " ++ show wk
 
-        -- kind of crude, but works ok
-        paren v
-          | needsParen = '(' : v ++ ")"
-          | True       = v
-          where needsParen = case dropWhile isSpace v of
-                               []         -> False
-                               rest@(x:_) -> x == '-' || (any isSpace rest && x `notElem` "{[(")
+        shADT (c, kvs)
+          | null @[] flds = c
+          | True          = unwords (c : map wrap flds)
+          where wrap v
+                 | take 1 v `elem` ["(", "[", "{"]  = v
+                 | any isSpace v || take 1 v == "-" = '(' : v ++ ")"
+                 | True                             = v
 
+                flds = map (\(k, v) -> showCV False (CV k v)) kvs
+
 -- | Create a constant word from an integral.
 mkConstCV :: Integral a => Kind -> a -> CV
+mkConstCV k@(KVar{})      _ = error $ "mkConstCV: Unexpected kind: " ++ show k
 mkConstCV KBool           a = normCV $ CV KBool      (CInteger  (toInteger a))
 mkConstCV k@KBounded{}    a = normCV $ CV k          (CInteger  (toInteger a))
 mkConstCV KUnbounded      a = normCV $ CV KUnbounded (CInteger  (toInteger a))
@@ -462,18 +436,18 @@
 mkConstCV KRational       a = normCV $ CV KRational  (CRational (fromInteger (toInteger a)))
 mkConstCV KChar           a = error $ "Unexpected call to mkConstCV (Char) with value: "   ++ show (toInteger a)
 mkConstCV KString         a = error $ "Unexpected call to mkConstCV (String) with value: " ++ show (toInteger a)
-mkConstCV (KUserSort s _) a = error $ "Unexpected call to mkConstCV with user kind: " ++ s ++ " with value: " ++ show (toInteger a)
+mkConstCV (KApp s _)      a = error $ "Unexpected call to mkConstCV with kind: " ++ s ++ " with value: " ++ show (toInteger a)
+mkConstCV (KADT s _ _)    a = error $ "Unexpected call to mkConstCV with ADT: "  ++ s ++ " with value: " ++ show (toInteger a)
 mkConstCV k@KList{}       a = error $ "Unexpected call to mkConstCV (" ++ show k ++ ") with value: " ++ show (toInteger a)
 mkConstCV k@KSet{}        a = error $ "Unexpected call to mkConstCV (" ++ show k ++ ") with value: " ++ show (toInteger a)
 mkConstCV k@KTuple{}      a = error $ "Unexpected call to mkConstCV (" ++ show k ++ ") with value: " ++ show (toInteger a)
-mkConstCV k@KMaybe{}      a = error $ "Unexpected call to mkConstCV (" ++ show k ++ ") with value: " ++ show (toInteger a)
-mkConstCV k@KEither{}     a = error $ "Unexpected call to mkConstCV (" ++ show k ++ ") with value: " ++ show (toInteger a)
 mkConstCV k@KArray{}      a = error $ "Unexpected call to mkConstCV (" ++ show k ++ ") with value: " ++ show (toInteger a)
 
 -- | Generate a random constant value ('CVal') of the correct kind. We error out for a completely uninterpreted type.
 randomCVal :: Kind -> IO CVal
 randomCVal k =
   case k of
+    KVar{}             -> error $ "randomCVal: Unexpected kind: " ++ show k
     KBool              -> CInteger  <$> randomRIO (0, 1)
     KBounded s w       -> CInteger  <$> randomRIO (bounds s w)
     KUnbounded         -> CInteger  <$> randomIO
@@ -494,11 +468,15 @@
                              CString <$> replicateM l (chr <$> randomRIO (0, 255))
     KChar              -> CChar . chr <$> randomRIO (0, 255)
 
-    KUserSort s es     -> case es of
-                            Just vs@(_:_) -> do i <- randomRIO (0, length vs - 1)
-                                                pure $ CUserSort (Just i, vs !! i)
-                            _             -> error $ "randomCVal: Not supported for completely uninterpreted type: " ++ s
+    -- TODO: Can we do something here?
+    KApp s _           -> error $ "randomCVal: Not supported for KApp: " ++ s
 
+    KADT _ _ cstrs@(_:_) -> do i <- randomRIO (0, length cstrs - 1)
+                               let (c, fks) = cstrs !! i
+                               vs <- mapM randomCVal fks
+                               pure $ CADT (c, zip fks vs)
+    KADT s _ _         -> error $ "randomCVal: Not supported for ADT:  " ++ s
+
     KList ek           -> do l <- randomRIO (0, 100)
                              CList <$> replicateM l (randomCVal ek)
 
@@ -508,16 +486,6 @@
                              return $ CSet $ if i then RegularSet vals else ComplementSet vals
 
     KTuple ks          -> CTuple <$> traverse randomCVal ks
-
-    KMaybe ke          -> do i <- randomIO
-                             if i
-                                then return $ CMaybe Nothing
-                                else CMaybe . Just <$> randomCVal ke
-
-    KEither k1 k2      -> do i <- randomIO
-                             if i
-                                then CEither . Left  <$> randomCVal k1
-                                else CEither . Right <$> randomCVal k2
 
     KArray k1 k2       -> do l   <- randomRIO (0, 100)
                              ks  <- replicateM l (randomCVal k1)
diff --git a/Data/SBV/Core/Data.hs b/Data/SBV/Core/Data.hs
--- a/Data/SBV/Core/Data.hs
+++ b/Data/SBV/Core/Data.hs
@@ -17,11 +17,10 @@
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE PatternGuards         #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
 {-# LANGUAGE TypeApplications      #-}
-{-# LANGUAGE TypeOperators         #-}
 {-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeOperators         #-}
 {-# LANGUAGE UndecidableInstances  #-}
 
 {-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
@@ -33,12 +32,10 @@
  , SWord, SInt, WordN, IntN
  , SRational
  , SChar, SString, SList
- , SEither, SMaybe, SArray, ArrayModel(..)
+ , SArray, ArrayModel(..)
  , STuple, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7, STuple8
  , RCSet(..), SSet
  , nan, infinity, sNaN, sInfinity, RoundingMode(..), SRoundingMode
- , sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero
- , sRNE, sRNA, sRTP, sRTN, sRTZ
  , SymVal(..)
  , CV(..), CVal(..), AlgReal(..), AlgRealPoly(..), ExtCV(..), GeneralizedCV(..), isRegularCV, cvSameType, cvToBool
  , mkConstCV , mapCV, mapCV2
@@ -50,7 +47,7 @@
  , SBVExpr(..), newExpr
  , cache, Cached, uncache, HasKind(..)
  , Op(..), PBOp(..), FPOp(..), StrOp(..), RegExOp(..), SeqOp(..), RegExp(..), NamedSymVar(..), OvOp(..), getTableIndex
- , SBVPgm(..), Symbolic, runSymbolic, State, getPathCondition, extendPathCondition
+ , SBVPgm(..), Symbolic, runSymbolic, State, SInfo(..), getSInfo, getPathCondition, extendPathCondition
  , inSMTMode, SBVRunMode(..), Kind(..), Outputtable(..), Result(..)
  , SolverContext(..), internalConstraint, isCodeGenMode
  , SBVType(..), newUninterpreted
@@ -73,15 +70,16 @@
 import Control.Monad.Trans    (liftIO, MonadIO)
 import Data.Int               (Int8, Int16, Int32, Int64)
 import Data.Word              (Word8, Word16, Word32, Word64)
-import Data.List              (elemIndex)
 
 import Data.Kind (Type)
 import Data.Proxy
 import Data.Typeable          (Typeable)
 
+import Data.IORef
+import qualified Data.Set as Set (toList)
+
 import GHC.Generics (Generic, U1(..), M1(..), (:*:)(..), K1(..), (:+:)(..))
 import qualified GHC.Generics  as G
-import qualified Data.Generics as G (Data(..))
 
 import System.Random
 
@@ -96,6 +94,7 @@
 import Data.SBV.Control.Types
 
 import Data.SBV.Utils.Lib
+import Data.SBV.Utils.Numeric (RoundingMode(..))
 
 import Test.QuickCheck (Arbitrary(..))
 
@@ -196,12 +195,6 @@
 -- Note that lists can be nested, i.e., we do allow lists of lists of ... items.
 type SList a = SBV [a]
 
--- | Symbolic 'Either'
-type SEither a b = SBV (Either a b)
-
--- | Symbolic 'Maybe'
-type SMaybe a = SBV (Maybe a)
-
 -- | Symbolic arrays. A symbolic array is more akin to a function in SMTLib (and thus in SBV),
 -- as opposed to contagious-storage with a finite range as found in many programming languages.
 -- Additionally, the domain uses object-equality in the SMTLib semantics. Object equality is
@@ -336,52 +329,9 @@
 sAll :: (a -> SBool) -> [a] -> SBool
 sAll f = sAnd . map f
 
--- | 'RoundingMode' can be used symbolically
-instance SymVal RoundingMode
-
 -- | The symbolic variant of 'RoundingMode'
 type SRoundingMode = SBV RoundingMode
 
--- | Symbolic variant of 'RoundNearestTiesToEven'
-sRoundNearestTiesToEven :: SRoundingMode
-sRoundNearestTiesToEven = literal RoundNearestTiesToEven
-
--- | Symbolic variant of 'RoundNearestTiesToAway'
-sRoundNearestTiesToAway :: SRoundingMode
-sRoundNearestTiesToAway = literal RoundNearestTiesToAway
-
--- | Symbolic variant of 'RoundTowardPositive'
-sRoundTowardPositive :: SRoundingMode
-sRoundTowardPositive = literal RoundTowardPositive
-
--- | Symbolic variant of 'RoundTowardNegative'
-sRoundTowardNegative :: SRoundingMode
-sRoundTowardNegative = literal RoundTowardNegative
-
--- | Symbolic variant of 'RoundTowardZero'
-sRoundTowardZero :: SRoundingMode
-sRoundTowardZero = literal RoundTowardZero
-
--- | Alias for 'sRoundNearestTiesToEven'
-sRNE :: SRoundingMode
-sRNE = sRoundNearestTiesToEven
-
--- | Alias for 'sRoundNearestTiesToAway'
-sRNA :: SRoundingMode
-sRNA = sRoundNearestTiesToAway
-
--- | Alias for 'sRoundTowardPositive'
-sRTP :: SRoundingMode
-sRTP = sRoundTowardPositive
-
--- | Alias for 'sRoundTowardNegative'
-sRTN :: SRoundingMode
-sRTN = sRoundTowardNegative
-
--- | Alias for 'sRoundTowardZero'
-sRTZ :: SRoundingMode
-sRTZ = sRoundTowardZero
-
 -- | A 'Show' instance is not particularly "desirable," when the value is symbolic,
 -- but we do need this instance as otherwise we cannot simply evaluate Haskell functions
 -- that return symbolic values and have their constant values printed easily!
@@ -436,7 +386,7 @@
 -- will be prefixed in front of @_1@, @_2@, ..., @_n@ to form the names of the variables.
 newtype ExistsN (n :: Nat) (nm :: Symbol) a = ExistsN [SBV a]
 
--- | Exactly @n@ universal symbolic variables, used in in building quantified constraints. The name attached
+-- | Exactly @n@ universal symbolic variables, used in building quantified constraints. The name attached
 -- will be prefixed in front of @_1@, @_2@, ..., @_n@ to form the names of the variables.
 newtype ForallN (n :: Nat) (nm :: Symbol) a = ForallN [SBV a]
 
@@ -557,6 +507,14 @@
 registerType _ = do st <- contextState
                     liftIO $ registerKind st (kindOf (Proxy @a))
 
+-- | Various info we use in recoverKinded value
+newtype SInfo = SInfo { sInfoKinds :: [Kind] }
+
+-- | Turn state into SInfo
+getSInfo :: MonadIO m => State -> m SInfo
+getSInfo st = do rk <- liftIO $ readIORef (rUsedKinds st)
+                 pure $ SInfo { sInfoKinds = Set.toList rk }
+
 -- | A class representing what can be returned from a symbolic computation.
 class Outputtable a where
   -- | Generalization of 'Data.SBV.output'
@@ -602,6 +560,10 @@
   -- | Generalization of 'Data.SBV.mkSymVal'
   mkSymVal :: MonadSymbolic m => VarContext -> Maybe String -> m (SBV a)
 
+  -- | Certain types (ADTs) might need to do further initialization.
+  mkSymValInit :: State -> SBV a -> IO ()
+  mkSymValInit _ _ = pure ()
+
   -- | Turn a literal constant to symbolic
   literal :: a -> SBV a
 
@@ -615,32 +577,13 @@
   -- If the underlying type is bounded, we have a default below. Otherwise it's nothing.
   minMaxBound :: Maybe (a, a)
 
-  -- minimal complete definition: Nothing.
-  -- Giving no instances is okay when defining an uninterpreted/enumerated sort, but otherwise you really
-  -- want to define: literal, fromCV, mkSymVal
-
-  default mkSymVal :: (MonadSymbolic m, Read a, G.Data a) => VarContext -> Maybe String -> m (SBV a)
-  mkSymVal vc mbNm = SBV <$> (symbolicEnv >>= liftIO . svMkSymVar vc k mbNm)
-    where -- NB.A call of the form
-          --      constructUKind (Proxy @a)
-          -- would be wrong here, as it would uninterpret the Proxy datatype!
-          -- So, we have to use the dreaded undefined value in this case.
-          k = constructUKind (undefined :: a)
-
-  default literal :: Show a => a -> SBV a
-  literal x = let k  = kindOf x
-                  sx = show x
-                  conts = case k of
-                           KUserSort _ cts -> cts
-                           _               -> Nothing
-                  mbIdx = case conts of
-                            Just xs -> sx `elemIndex` xs
-                            Nothing -> Nothing
-              in SBV $ SVal k (Left (CV k (CUserSort (mbIdx, sx))))
+  {-# MINIMAL literal, fromCV #-}
 
-  default fromCV :: Read a => CV -> a
-  fromCV (CV _ (CUserSort (_, s))) = read s
-  fromCV cv                        = error $ "Cannot convert CV " ++ show cv ++ " to kind " ++ show (kindOf (Proxy @a))
+  default mkSymVal :: MonadSymbolic m => VarContext -> Maybe String -> m (SBV a)
+  mkSymVal vc mbNm = do st <- symbolicEnv
+                        liftIO $ do v <- SBV <$> svMkSymVar vc (kindOf (undefined :: a)) mbNm st
+                                    mkSymValInit st v
+                                    pure v
 
   default minMaxBound :: Bounded a => Maybe (a, a)
   minMaxBound = Just (minBound, maxBound)
@@ -674,6 +617,11 @@
   unliteral (SBV (SVal _ (Left c))) = Just $ fromCV c
   unliteral _                       = Nothing
 
+  -- | Get the underlying CV, if available
+  unlitCV :: SBV a -> Maybe (Kind, CVal)
+  unlitCV (SBV (SVal _ (Left (CV k v)))) = Just (k, v)
+  unlitCV _                              = Nothing
+
   -- | Is the symbolic word concrete?
   isConcrete :: SBV a -> Bool
   isConcrete (SBV (SVal _ (Left _))) = True
@@ -859,7 +807,7 @@
    where i  = fromIntegral (natVal start)
          j  = fromIntegral (natVal end)
 
--- | Join two bitvectors.
+-- | Join two bit-vectors.
 (#) :: ( KnownNat n, BVIsNonZero n, SymVal (bv n)
        , KnownNat m, BVIsNonZero m, SymVal (bv m)
        ) => SBV (bv n)                     -- ^ First input, of size @n@, becomes the left side
@@ -1001,7 +949,7 @@
   type NegatesTo (ExistsN nm n a -> r) = ForallN nm n a -> NegatesTo r
   qNot f (ForallN xs) = qNot (f (ExistsN xs))
 
--- | Negate over an unique existential quantifier
+-- | Negate over a unique existential quantifier
 instance (QNot r, QuantifiedBool r, EqSymbolic (SBV a)) => QNot (ExistsUnique nm a -> r) where
   type NegatesTo (ExistsUnique nm a -> r) =  Forall nm a
                                           -> Exists (AppendSymbol nm "_eu1") a
diff --git a/Data/SBV/Core/Floating.hs b/Data/SBV/Core/Floating.hs
--- a/Data/SBV/Core/Floating.hs
+++ b/Data/SBV/Core/Floating.hs
@@ -11,9 +11,7 @@
 
 {-# LANGUAGE DefaultSignatures    #-}
 {-# LANGUAGE FlexibleContexts     #-}
-{-# LANGUAGE FlexibleInstances    #-}
 {-# LANGUAGE InstanceSigs         #-}
-{-# LANGUAGE Rank2Types           #-}
 {-# LANGUAGE ScopedTypeVariables  #-}
 {-# LANGUAGE TypeApplications     #-}
 {-# LANGUAGE TypeFamilies         #-}
diff --git a/Data/SBV/Core/Kind.hs b/Data/SBV/Core/Kind.hs
--- a/Data/SBV/Core/Kind.hs
+++ b/Data/SBV/Core/Kind.hs
@@ -11,15 +11,14 @@
 
 {-# LANGUAGE CPP                  #-}
 {-# LANGUAGE DataKinds            #-}
-{-# LANGUAGE DefaultSignatures    #-}
 {-# LANGUAGE DeriveAnyClass       #-}
 {-# LANGUAGE DeriveDataTypeable   #-}
 {-# LANGUAGE DeriveGeneric        #-}
 {-# LANGUAGE FlexibleInstances    #-}
 {-# LANGUAGE LambdaCase           #-}
 {-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE TypeFamilies         #-}
 {-# LANGUAGE TypeApplications     #-}
+{-# LANGUAGE TypeFamilies         #-}
 {-# LANGUAGE TypeOperators        #-}
 {-# LANGUAGE ViewPatterns         #-}
 {-# LANGUAGE UndecidableInstances #-}
@@ -27,13 +26,15 @@
 {-# OPTIONS_GHC -Wall -Werror -fno-warn-orphans #-}
 
 module Data.SBV.Core.Kind (
-          Kind(..), HasKind(..), constructUKind, smtType, hasUninterpretedSorts
+          Kind(..), HasKind(..), smtType, hasUninterpretedSorts
         , BVIsNonZero, ValidFloat, intOfProxy
-        , showBaseKind, needsFlattening, RoundingMode(..), smtRoundingMode
+        , showBaseKind, needsFlattening
         , eqCheckIsObjectEq, containsFloats, isSomeKindOfFloat, expandKinds
+        , substituteADTVars
+        , kRoundingMode
         ) where
 
-import qualified Data.Generics as G (Data(..), DataType, dataTypeName, dataTypeOf, tyconUQname, dataTypeConstrs, constrFields)
+import qualified Data.Generics as G (Data(..), DataType, dataTypeName, tyconUQname)
 
 import Data.Char (isSpace)
 import Data.Int
@@ -43,7 +44,7 @@
 import Data.Proxy
 import Data.Kind
 
-import Data.List (isPrefixOf, intercalate, sort)
+import Data.List (intercalate, sort)
 import Control.DeepSeq (NFData)
 
 import Data.Containers.ListUtils (nubOrd)
@@ -54,47 +55,81 @@
 
 import GHC.TypeLits
 
-import Data.SBV.Utils.Lib (isKString)
+import Data.SBV.Utils.Lib     (isKString)
+import Data.SBV.Utils.Numeric (RoundingMode)
 
 import GHC.Generics
 import qualified Data.Generics.Uniplate.Data as G
 
-import Test.QuickCheck (Arbitrary(..), arbitraryBoundedEnum)
-
 -- | Kind of symbolic value
-data Kind = KBool
+data Kind =
+          -- Base types
+            KBool
+
+          -- Word and Int. Boolean is True for Int.
           | KBounded !Bool !Int
+
+          -- Unbounded integers
           | KUnbounded
+
+          -- Reals
           | KReal
-          | KUserSort String (Maybe [String])  -- name. Uninterpreted, or enumeration constants.
+
+          -- Floats, standard and generalized
           | KFloat
           | KDouble
           | KFP !Int !Int
+
+          -- Rationals
+          | KRational
+
+          -- Chars and strings
           | KChar
           | KString
+
+          -- Algebraic datatypes
+          | KVar String         -- only used temporarily during ADT construction
+          | KApp String [Kind]  -- Application of a constructor to a bunch of types
+          | KADT String
+                 [(String, Kind)]   -- Parameters, applied to these args
+                 [(String, [Kind])] -- Constructors, and their fields
+
+          -- Collections
           | KList Kind
           | KSet  Kind
           | KTuple [Kind]
-          | KMaybe  Kind
-          | KRational
-          | KEither Kind Kind
+
+          -- Arrays
           | KArray  Kind Kind
           deriving (Eq, Ord, G.Data, NFData, Generic)
 
--- Expand such that the resulting list has all the kinds we touch
+-- | Built in kind for rounding mode
+kRoundingMode :: Kind
+kRoundingMode = KADT "RoundingMode" [] (map (\r -> (show r, [])) [minBound .. maxBound :: RoundingMode])
+
+-- | Expand such that the resulting list has all the kinds we touch
 expandKinds :: Kind -> [Kind]
 expandKinds = sort . nubOrd . G.universe
 
--- | The interesting about the show instance is that it can tell apart two kinds nicely; since it conveniently
--- ignores the enumeration constructors. Also, when we construct a 'KUserSort', we make sure we don't use any of
--- the reserved names; see 'constructUKind' for details.
+-- | For an ADT kind, substitute kinds for the variables.
+substituteADTVars :: String -> [(String, Kind)] -> Kind -> Kind
+substituteADTVars t dict = G.transform sub
+  where sub :: Kind -> Kind
+        sub (KVar v)
+          | Just k <- v `lookup` dict = k
+          | True                      = error $ "Data.SBV.ADT: Kind find variable in param subst: " ++ show (t, v, dict)
+        sub k = k
+
+-- | The interesting about the show instance is that it can tell apart two kinds nicely. Otherwise the string produced isn't parsed back.
 instance Show Kind where
+  show (KVar s)           = s
   show KBool              = "SBool"
   show (KBounded False n) = pickType n "SWord" "SWord " ++ show n
   show (KBounded True n)  = pickType n "SInt"  "SInt "  ++ show n
   show KUnbounded         = "SInteger"
   show KReal              = "SReal"
-  show (KUserSort s _)    = s
+  show (KApp c ks)        = unwords (c : map (kindParen . showBaseKind      )  ks)
+  show (KADT s pks _)     = unwords (s : map (kindParen . showBaseKind . snd) pks)
   show KFloat             = "SFloat"
   show KDouble            = "SDouble"
   show (KFP eb sb)        = "SFloatingPoint " ++ show eb ++ " " ++ show sb
@@ -104,19 +139,19 @@
   show (KSet  e)          = "{" ++ show e ++ "}"
   show (KTuple m)         = "(" ++ intercalate ", " (show <$> m) ++ ")"
   show KRational          = "SRational"
-  show (KMaybe k)         = "SMaybe "  ++ kindParen (showBaseKind k)
-  show (KEither k1 k2)    = "SEither " ++ kindParen (showBaseKind k1) ++ " " ++ kindParen (showBaseKind k2)
   show (KArray k1 k2)     = "SArray "  ++ kindParen (showBaseKind k1) ++ " " ++ kindParen (showBaseKind k2)
 
--- | A version of show for kinds that says Bool instead of SBool
+-- | A version of show for kinds that says Bool instead of SBool, Float instead of SFloat, etc.
 showBaseKind :: Kind -> String
 showBaseKind = sh
-  where sh k@KBool            = noS (show k)
+  where sh (KVar s)           = s
+        sh k@KBool            = noS (show k)
         sh (KBounded False n) = pickType n "Word" "WordN " ++ show n
         sh (KBounded True n)  = pickType n "Int"  "IntN "  ++ show n
+        sh (KApp s ks)        = unwords (s : map (kindParen . sh) ks)
         sh k@KUnbounded       = noS (show k)
         sh k@KReal            = noS (show k)
-        sh k@KUserSort{}      = show k     -- Leave user-sorts untouched!
+        sh k@KADT{}           = show k     -- Leave user-sorts untouched!
         sh k@KFloat           = noS (show k)
         sh k@KDouble          = noS (show k)
         sh k@KFP{}            = noS (show k)
@@ -126,8 +161,6 @@
         sh (KList k)          = "[" ++ sh k ++ "]"
         sh (KSet k)           = "{" ++ sh k ++ "}"
         sh (KTuple ks)        = "(" ++ intercalate ", " (map sh ks) ++ ")"
-        sh (KMaybe k)         = "Maybe "  ++ kindParen (sh k)
-        sh (KEither k1 k2)    = "Either " ++ kindParen (sh k1) ++ " " ++ kindParen (sh k2)
         sh (KArray  k1 k2)    = "Array "  ++ kindParen (sh k1) ++ " " ++ kindParen (sh k2)
 
         -- Drop the initial S if it's there
@@ -149,6 +182,7 @@
 
 -- | How the type maps to SMT land
 smtType :: Kind -> String
+smtType (KVar s)        = s
 smtType KBool           = "Bool"
 smtType (KBounded _ sz) = "(_ BitVec " ++ show sz ++ ")"
 smtType KUnbounded      = "Int"
@@ -160,12 +194,11 @@
 smtType KChar           = "String"
 smtType (KList k)       = "(Seq "   ++ smtType k ++ ")"
 smtType (KSet  k)       = "(Array " ++ smtType k ++ " Bool)"
-smtType (KUserSort s _) = s
+smtType (KApp s ks)     = kindParen $ unwords (s : map smtType          ks)
+smtType (KADT s pks _)  = kindParen $ unwords (s : map (smtType . snd) pks)
 smtType (KTuple [])     = "SBVTuple0"
 smtType (KTuple kinds)  = "(SBVTuple" ++ show (length kinds) ++ " " ++ unwords (smtType <$> kinds) ++ ")"
 smtType KRational       = "SBVRational"
-smtType (KMaybe k)      = "(SBVMaybe " ++ smtType k ++ ")"
-smtType (KEither k1 k2) = "(SBVEither "  ++ smtType k1 ++ " " ++ smtType k2 ++ ")"
 smtType (KArray  k1 k2) = "(Array "      ++ smtType k1 ++ " " ++ smtType k2 ++ ")"
 
 instance Eq  G.DataType where
@@ -176,7 +209,8 @@
 
 -- | Does this kind represent a signed quantity?
 kindHasSign :: Kind -> Bool
-kindHasSign = \case KBool        -> False
+kindHasSign = \case KVar _       -> False
+                    KBool        -> False
                     KBounded b _ -> b
                     KUnbounded   -> True
                     KReal        -> True
@@ -184,79 +218,49 @@
                     KDouble      -> True
                     KFP{}        -> True
                     KRational    -> True
-                    KUserSort{}  -> False
+                    KApp{}       -> False
+                    KADT{}       -> False
                     KString      -> False
                     KChar        -> False
                     KList{}      -> False
                     KSet{}       -> False
                     KTuple{}     -> False
-                    KMaybe{}     -> False
-                    KEither{}    -> False
                     KArray{}     -> False
 
--- | Construct an uninterpreted/enumerated kind from a piece of data; we distinguish simple enumerations as those
--- are mapped to proper SMT-Lib2 data-types; while others go completely uninterpreted
-constructUKind :: forall a. (Read a, G.Data a) => a -> Kind
-constructUKind a
-  | any (`isPrefixOf` sortName) badPrefixes
-  = error $ unlines [ "*** Data.SBV: Cannot construct user-sort with name: " ++ show sortName
-                    , "***"
-                    , "***  Must not start with any of: " ++ intercalate ", " badPrefixes
-                    ]
-  | True
-  = case (constrs, concatMap G.constrFields constrs) of
-      ([], _)  -> KUserSort sortName   Nothing
-      (cs, []) -> KUserSort sortName $ Just (map show cs)
-      _        -> error $ unlines [ "*** Data.SBV: " ++ sortName ++ " is not an enumeration."
-                                  , "***"
-                                  , "*** To declare an enumeration, constructors should not have any fields."
-                                  , "*** To declare an uninterpreted sort, use a datatype with no constructors."
-                                  ]
-
-  where -- make sure we don't step on ourselves:
-        -- NB. The sort "RoundingMode" is special. It's treated by SBV as a user-defined
-        -- sort, even though it's internally handled differently. So, that name doesn't appear
-        -- below.
-        badPrefixes = [ "SBool",   "SWord", "SInt", "SInteger", "SReal",  "SFloat", "SDouble"
-                      , "SString", "SChar", "[",    "SSet",     "STuple", "SMaybe", "SEither"
-                      , "SRational"
-                      ]
-
-        dataType    = G.dataTypeOf a
-        sortName    = G.tyconUQname . G.dataTypeName $ dataType
-        constrs     = G.dataTypeConstrs dataType
-
 -- | A class for capturing values that have a sign and a size (finite or infinite)
 -- minimal complete definition: kindOf, unless you can take advantage of the default
 -- signature: This class can be automatically derived for data-types that have
 -- a 'G.Data' instance; this is useful for creating uninterpreted sorts. So, in
 -- reality, end users should almost never need to define any methods.
 class HasKind a where
-  kindOf      :: a -> Kind
-  hasSign     :: a -> Bool
-  intSizeOf   :: a -> Int
-  isBoolean   :: a -> Bool
-  isBounded   :: a -> Bool   -- NB. This really means word/int; i.e., Real/Float will test False
-  isReal      :: a -> Bool
-  isFloat     :: a -> Bool
-  isDouble    :: a -> Bool
-  isRational  :: a -> Bool
-  isFP        :: a -> Bool
-  isUnbounded :: a -> Bool
-  isUserSort  :: a -> Bool
-  isChar      :: a -> Bool
-  isString    :: a -> Bool
-  isList      :: a -> Bool
-  isSet       :: a -> Bool
-  isTuple     :: a -> Bool
-  isMaybe     :: a -> Bool
-  isEither    :: a -> Bool
-  isArray     :: a -> Bool
-  showType    :: a -> String
+  kindOf          :: a -> Kind
+  hasSign         :: a -> Bool
+  intSizeOf       :: a -> Int
+  isBoolean       :: a -> Bool
+  isBounded       :: a -> Bool   -- NB. This really means word/int; i.e., Real/Float will test False
+  isReal          :: a -> Bool
+  isFloat         :: a -> Bool
+  isDouble        :: a -> Bool
+  isRational      :: a -> Bool
+  isFP            :: a -> Bool
+  isUnbounded     :: a -> Bool
+  isADT           :: a -> Bool
+  isChar          :: a -> Bool
+  isString        :: a -> Bool
+  isList          :: a -> Bool
+  isSet           :: a -> Bool
+  isTuple         :: a -> Bool
+  isArray         :: a -> Bool
+  isRoundingMode  :: a -> Bool
+  isUninterpreted :: a -> Bool
+
+  showType        :: a -> String
+
   -- defaults
   hasSign x = kindHasSign (kindOf x)
 
   intSizeOf x = case kindOf x of
+                  KVar{}        -> error "SBV.HasKind.intSizeOf(KVar)"
                   KBool         -> error "SBV.HasKind.intSizeOf((S)Bool)"
                   KBounded _ s  -> s
                   KUnbounded    -> error "SBV.HasKind.intSizeOf((S)Integer)"
@@ -265,14 +269,13 @@
                   KDouble       -> 64
                   KFP i j       -> i + j
                   KRational     -> error "SBV.HasKind.intSizeOf((S)Rational)"
-                  KUserSort s _ -> error $ "SBV.HasKind.intSizeOf: Uninterpreted sort: " ++ s
+                  KApp s _      -> error $ "SBV.HasKind.intSizeOf: Type application: "    ++ s
+                  KADT s _ _    -> error $ "SBV.HasKind.intSizeOf: Algebraic data type: " ++ s
                   KString       -> error "SBV.HasKind.intSizeOf((S)Double)"
                   KChar         -> error "SBV.HasKind.intSizeOf((S)Char)"
                   KList ek      -> error $ "SBV.HasKind.intSizeOf((S)List)"   ++ show ek
                   KSet  ek      -> error $ "SBV.HasKind.intSizeOf((S)Set)"    ++ show ek
                   KTuple tys    -> error $ "SBV.HasKind.intSizeOf((S)Tuple)"  ++ show tys
-                  KMaybe k      -> error $ "SBV.HasKind.intSizeOf((S)Maybe)"  ++ show k
-                  KEither k1 k2 -> error $ "SBV.HasKind.intSizeOf((S)Either)" ++ show (k1, k2)
                   KArray  k1 k2 -> error $ "SBV.HasKind.intSizeOf((S)Array)"  ++ show (k1, k2)
 
   isBoolean       (kindOf -> KBool{})      = True
@@ -299,8 +302,8 @@
   isUnbounded     (kindOf -> KUnbounded{}) = True
   isUnbounded     _                        = False
 
-  isUserSort      (kindOf -> KUserSort{})  = True
-  isUserSort      _                        = False
+  isADT           (kindOf -> KADT{})       = True
+  isADT           _                        = False
 
   isChar          (kindOf -> KChar{})      = True
   isChar          _                        = False
@@ -317,41 +320,40 @@
   isTuple         (kindOf -> KTuple{})     = True
   isTuple         _                        = False
 
-  isMaybe         (kindOf -> KMaybe{})     = True
-  isMaybe         _                        = False
-
-  isEither        (kindOf -> KEither{})    = True
-  isEither        _                        = False
-
   isArray         (kindOf -> KArray{})     = True
   isArray         _                        = False
 
+  -- Derived kinds
+  isRoundingMode  (kindOf -> k)            = k == kRoundingMode
+  isUninterpreted (kindOf -> k)            = case k of
+                                               KADT _ [] [] -> True
+                                               _            -> False
+
   showType = show . kindOf
 
-  -- default signature for uninterpreted/enumerated kinds
-  default kindOf :: (Read a, G.Data a) => a -> Kind
-  kindOf = constructUKind
+  {-# MINIMAL kindOf #-}
 
 -- | This instance allows us to use the `kindOf (Proxy @a)` idiom instead of
 -- the `kindOf (undefined :: a)`, which is safer and looks more idiomatic.
 instance HasKind a => HasKind (Proxy a) where
   kindOf _ = kindOf (undefined :: a)
 
-instance HasKind Bool     where kindOf _ = KBool
-instance HasKind Int8     where kindOf _ = KBounded True  8
-instance HasKind Word8    where kindOf _ = KBounded False 8
-instance HasKind Int16    where kindOf _ = KBounded True  16
-instance HasKind Word16   where kindOf _ = KBounded False 16
-instance HasKind Int32    where kindOf _ = KBounded True  32
-instance HasKind Word32   where kindOf _ = KBounded False 32
-instance HasKind Int64    where kindOf _ = KBounded True  64
-instance HasKind Word64   where kindOf _ = KBounded False 64
-instance HasKind Integer  where kindOf _ = KUnbounded
-instance HasKind AlgReal  where kindOf _ = KReal
-instance HasKind Rational where kindOf _ = KRational
-instance HasKind Float    where kindOf _ = KFloat
-instance HasKind Double   where kindOf _ = KDouble
-instance HasKind Char     where kindOf _ = KChar
+instance HasKind Bool         where kindOf _ = KBool
+instance HasKind Int8         where kindOf _ = KBounded True  8
+instance HasKind Word8        where kindOf _ = KBounded False 8
+instance HasKind Int16        where kindOf _ = KBounded True  16
+instance HasKind Word16       where kindOf _ = KBounded False 16
+instance HasKind Int32        where kindOf _ = KBounded True  32
+instance HasKind Word32       where kindOf _ = KBounded False 32
+instance HasKind Int64        where kindOf _ = KBounded True  64
+instance HasKind Word64       where kindOf _ = KBounded False 64
+instance HasKind Integer      where kindOf _ = KUnbounded
+instance HasKind AlgReal      where kindOf _ = KReal
+instance HasKind Rational     where kindOf _ = KRational
+instance HasKind Float        where kindOf _ = KFloat
+instance HasKind Double       where kindOf _ = KDouble
+instance HasKind Char         where kindOf _ = KChar
+instance HasKind RoundingMode where kindOf _ = kRoundingMode
 
 -- | Grab the bit-size from the proxy. If the nat is too large to fit in an int,
 -- we throw an error. (This would mean too big of a bit-size, that we can't
@@ -390,10 +392,7 @@
 
 -- | Do we have a completely uninterpreted sort lying around anywhere?
 hasUninterpretedSorts :: Kind -> Bool
-hasUninterpretedSorts = any check . expandKinds
-  where check (KUserSort _ Nothing)  = True   -- These are the completely uninterpreted sorts, which we are looking for here
-        check (KUserSort _ (Just{})) = False  -- These are the enumerated sorts, and they are perfectly fine
-        check _                      = False
+hasUninterpretedSorts = any isUninterpreted . expandKinds
 
 instance (Typeable a, HasKind a) => HasKind [a] where
    kindOf x | isKString @[a] x = KString
@@ -426,12 +425,6 @@
 instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g, HasKind h) => HasKind (a, b, c, d, e, f, g, h) where
   kindOf _ = KTuple [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @f), kindOf (Proxy @g), kindOf (Proxy @h)]
 
-instance (HasKind a, HasKind b) => HasKind (Either a b) where
-  kindOf _ = KEither (kindOf (Proxy @a)) (kindOf (Proxy @b))
-
-instance HasKind a => HasKind (Maybe a) where
-  kindOf _ = KMaybe (kindOf (Proxy @a))
-
 instance (HasKind a, HasKind b) => HasKind (a -> b) where
   kindOf _ = KArray (kindOf (Proxy @a)) (kindOf (Proxy @b))
 
@@ -443,16 +436,16 @@
   where check KList{}     = True
         check KSet{}      = True
         check KTuple{}    = True
-        check KMaybe{}    = True
-        check KEither{}   = True
         check KArray{}    = True
+        check KApp{}      = True
+        check k@KADT{}    = not (isUninterpreted k || isRoundingMode k)
 
         -- no need to expand bases
+        check KVar{}      = False
         check KBool       = False
         check KBounded{}  = False
         check KUnbounded  = False
         check KReal       = False
-        check KUserSort{} = False
         check KFloat      = False
         check KDouble     = False
         check KFP{}       = False
@@ -522,33 +515,3 @@
                                             (() :: Constraint)
                                             (TypeError (InvalidFloat eb sb))
                                        )
-
--- | Rounding mode to be used for the IEEE floating-point operations.
--- Note that Haskell's default is 'RoundNearestTiesToEven'. If you use
--- a different rounding mode, then the counter-examples you get may not
--- match what you observe in Haskell.
-data RoundingMode = RoundNearestTiesToEven  -- ^ Round to nearest representable floating point value.
-                                            -- If precisely at half-way, pick the even number.
-                                            -- (In this context, /even/ means the lowest-order bit is zero.)
-                  | RoundNearestTiesToAway  -- ^ Round to nearest representable floating point value.
-                                            -- If precisely at half-way, pick the number further away from 0.
-                                            -- (That is, for positive values, pick the greater; for negative values, pick the smaller.)
-                  | RoundTowardPositive     -- ^ Round towards positive infinity. (Also known as rounding-up or ceiling.)
-                  | RoundTowardNegative     -- ^ Round towards negative infinity. (Also known as rounding-down or floor.)
-                  | RoundTowardZero         -- ^ Round towards zero. (Also known as truncation.)
-                  deriving (Eq, Ord, Show, Read, G.Data, Bounded, Enum)
-
--- | 'RoundingMode' kind
-instance HasKind RoundingMode
-
--- | An arbitrary rounding mode
-instance Arbitrary RoundingMode where
-  arbitrary = arbitraryBoundedEnum
-
--- | Convert a rounding mode to the format SMT-Lib2 understands.
-smtRoundingMode :: RoundingMode -> String
-smtRoundingMode RoundNearestTiesToEven = "roundNearestTiesToEven"
-smtRoundingMode RoundNearestTiesToAway = "roundNearestTiesToAway"
-smtRoundingMode RoundTowardPositive    = "roundTowardPositive"
-smtRoundingMode RoundTowardNegative    = "roundTowardNegative"
-smtRoundingMode RoundTowardZero        = "roundTowardZero"
diff --git a/Data/SBV/Core/Model.hs b/Data/SBV/Core/Model.hs
--- a/Data/SBV/Core/Model.hs
+++ b/Data/SBV/Core/Model.hs
@@ -16,10 +16,8 @@
 {-# LANGUAGE DeriveFunctor           #-}
 {-# LANGUAGE FlexibleContexts        #-}
 {-# LANGUAGE FlexibleInstances       #-}
-{-# LANGUAGE InstanceSigs            #-}
 {-# LANGUAGE MultiParamTypeClasses   #-}
 {-# LANGUAGE NamedFieldPuns          #-}
-{-# LANGUAGE Rank2Types              #-}
 {-# LANGUAGE ScopedTypeVariables     #-}
 {-# LANGUAGE TypeApplications        #-}
 {-# LANGUAGE TypeFamilies            #-}
@@ -41,10 +39,11 @@
   , sWord, sWord_, sWords, sInt, sInt_, sInts
   , sFPHalf, sFPHalf_, sFPHalfs, sFPBFloat, sFPBFloat_, sFPBFloats, sFPSingle, sFPSingle_, sFPSingles, sFPDouble, sFPDouble_, sFPDoubles, sFPQuad, sFPQuad_, sFPQuads, sArray, sArray_, sArrays
   , sFloatingPoint, sFloatingPoint_, sFloatingPoints
+  , sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero
+  , sRNE, sRNA, sRTP, sRTN, sRTZ
   , sChar, sChar_, sChars, sString, sString_, sStrings, sList, sList_, sLists
   , sRational, sRational_, sRationals
   , SymTuple, sTuple, sTuple_, sTuples
-  , sEither, sEither_, sEithers, sMaybe, sMaybe_, sMaybes
   , sSet, sSet_, sSets
   , sEDivMod, sEDiv, sEMod
   , sDivides
@@ -111,7 +110,7 @@
 import Data.SBV.Core.Operations
 import Data.SBV.Core.Kind
 import Data.SBV.Lambda
-import Data.SBV.Utils.ExtractIO(ExtractIO)
+import Data.SBV.Utils.ExtractIO (ExtractIO)
 
 import Data.SBV.Provers.Prover (defaultSMTCfg, SafeResult(..), defs2smt, prove)
 import Data.SBV.SMT.SMT        (ThmResult, showModel)
@@ -246,6 +245,55 @@
   -- and in the presence of NaN's it would be incorrect to do any optimization
   isConcretely _ _ = False
 
+instance SymVal RoundingMode where
+  literal s = SBV $ SVal kRoundingMode $ Left $ CV kRoundingMode $ CADT (show s, [])
+  fromCV (CV k (CADT (s, [])))
+    | k == kRoundingMode
+    , Just mode <- s `lookup` [(show m, m) | m <- [minBound .. maxBound :: RoundingMode]]
+    = mode
+  fromCV c = error $ "SymVal.RoundingMode: Unexpected non-rounding mode value: " ++ show c
+
+-- | Symbolic variant of 'RoundNearestTiesToEven'
+sRoundNearestTiesToEven :: SRoundingMode
+sRoundNearestTiesToEven = literal RoundNearestTiesToEven
+
+-- | Symbolic variant of 'RoundNearestTiesToAway'
+sRoundNearestTiesToAway :: SRoundingMode
+sRoundNearestTiesToAway = literal RoundNearestTiesToAway
+
+-- | Symbolic variant of 'RoundTowardPositive'
+sRoundTowardPositive :: SRoundingMode
+sRoundTowardPositive = literal RoundTowardPositive
+
+-- | Symbolic variant of 'RoundTowardNegative'
+sRoundTowardNegative :: SRoundingMode
+sRoundTowardNegative = literal RoundTowardNegative
+
+-- | Symbolic variant of 'RoundTowardZero'
+sRoundTowardZero :: SRoundingMode
+sRoundTowardZero = literal RoundTowardZero
+
+-- | Alias for 'sRoundNearestTiesToEven'
+sRNE :: SRoundingMode
+sRNE = sRoundNearestTiesToEven
+
+-- | Alias for 'sRoundNearestTiesToAway'
+sRNA :: SRoundingMode
+sRNA = sRoundNearestTiesToAway
+
+-- | Alias for 'sRoundTowardPositive'
+sRTP :: SRoundingMode
+sRTP = sRoundTowardPositive
+
+-- | Alias for 'sRoundTowardNegative'
+sRTN :: SRoundingMode
+sRTN = sRoundTowardNegative
+
+-- | Alias for 'sRoundTowardZero'
+sRTZ :: SRoundingMode
+sRTZ = sRoundTowardZero
+
+
 instance SymVal Char where
   mkSymVal                = genMkSymVar KChar
   literal c               = SBV . SVal KChar . Left . CV KChar $ CChar c
@@ -320,38 +368,6 @@
          lcs = length cs
 fromCVTup i inp = error $ "SymVal.fromCVTup: Impossible happened. Non-tuple received: " ++ show (i, inp)
 
-instance (SymVal a, SymVal b) => SymVal (Either a b) where
-  mkSymVal = genMkSymVar (kindOf (Proxy @(Either a b)))
-
-  literal s
-    | Left  a <- s = mk $ Left  (toCV a)
-    | Right b <- s = mk $ Right (toCV b)
-    where k  = kindOf (Proxy @(Either a b))
-
-          mk = SBV . SVal k . Left . CV k . CEither
-
-  fromCV (CV (KEither k1 _ ) (CEither (Left c)))  = Left  $ fromCV $ CV k1 c
-  fromCV (CV (KEither _  k2) (CEither (Right c))) = Right $ fromCV $ CV k2 c
-  fromCV bad                                      = error $ "SymVal.fromCV (Either): Malformed either received: " ++ show bad
-
-  minMaxBound = Nothing
-
-instance SymVal a => SymVal (Maybe a) where
-  mkSymVal = genMkSymVar (kindOf (Proxy @(Maybe a)))
-
-  literal s
-    | Nothing <- s = mk Nothing
-    | Just  a <- s = mk $ Just (toCV a)
-    where k = kindOf (Proxy @(Maybe a))
-
-          mk = SBV . SVal k . Left . CV k . CMaybe
-
-  fromCV (CV (KMaybe _) (CMaybe Nothing))  = Nothing
-  fromCV (CV (KMaybe k) (CMaybe (Just x))) = Just $ fromCV $ CV k x
-  fromCV bad                               = error $ "SymVal.fromCV (Maybe): Malformed sum received: " ++ show bad
-
-  minMaxBound = Nothing
-
 instance (HasKind a, HasKind b, SymVal a, SymVal b) => SymVal (ArrayModel a b) where
   mkSymVal = genMkSymVar (KArray (kindOf (Proxy @a)) (kindOf (Proxy @b)))
 
@@ -794,30 +810,6 @@
 sRationals :: MonadSymbolic m => [String] -> m [SRational]
 sRationals = symbolics
 
--- | Generalization of 'Data.SBV.sEither'
-sEither :: (SymVal a, SymVal b, MonadSymbolic m) => String -> m (SEither a b)
-sEither = symbolic
-
--- | Generalization of 'Data.SBV.sEither_'
-sEither_ :: (SymVal a, SymVal b, MonadSymbolic m) => m (SEither a b)
-sEither_ = free_
-
--- | Generalization of 'Data.SBV.sEithers'
-sEithers :: (SymVal a, SymVal b, MonadSymbolic m) => [String] -> m [SEither a b]
-sEithers = symbolics
-
--- | Generalization of 'Data.SBV.sMaybe'
-sMaybe :: (SymVal a, MonadSymbolic m) => String -> m (SMaybe a)
-sMaybe = symbolic
-
--- | Generalization of 'Data.SBV.sMaybe_'
-sMaybe_ :: (SymVal a, MonadSymbolic m) => m (SMaybe a)
-sMaybe_ = free_
-
--- | Generalization of 'Data.SBV.sMaybes'
-sMaybes :: (SymVal a, MonadSymbolic m) => [String] -> m [SMaybe a]
-sMaybes = symbolics
-
 -- | Generalization of 'Data.SBV.sSet'
 sSet :: (Ord a, SymVal a, MonadSymbolic m) => String -> m (SSet a)
 sSet = symbolic
@@ -1045,9 +1037,7 @@
 MKSORD((),                          SInt64)
 MKSORD((),                          SFloat)
 MKSORD((),                          SChar)
-MKSORD((SymVal a),                  (SMaybe  a))
-MKSORD((SymVal a),                  (SList   a))
-MKSORD((SymVal a, SymVal b),        (SEither a b))
+MKSORD((SymVal a),                  (SList a))
 MKSORD((),                          SDouble)
 MKSORD((),                          SReal)
 MKSORD((KnownNat n, BVIsNonZero n), (SWord n))
@@ -1072,11 +1062,13 @@
   = True
   | True
   = case k of
+      KVar       {} -> False
       KBool         -> True
       KBounded   {} -> True
       KUnbounded {} -> True
       KReal      {} -> True
-      KUserSort  {} -> True
+      KApp       {} -> True
+      KADT       {} -> True
       KFloat        -> True
       KDouble       -> True
       KRational  {} -> True
@@ -1086,8 +1078,6 @@
       KList      {} -> nope     -- Unfortunately, no way for us to desugar this
       KSet       {} -> nope     -- Ditto here..
       KTuple     {} -> False
-      KMaybe     {} -> False
-      KEither    {} -> False
       KArray     {} -> True
  where k    = kindOf x
        nope = error $ "Data.SBV.OrdSymbolic: SMTLib does not support " ++ op ++ " for " ++ show k
@@ -1544,6 +1534,7 @@
        where res  = SBV (svDivide x y)
              -- Identify those kinds where we have a div-0 equals 0 exception
              div0 = case kindOf sy of
+                      KVar{}             -> error $ "Unexpected Fractional case for: " ++ show (kindOf sy)
                       KFloat             -> False
                       KDouble            -> False
                       KFP{}              -> False
@@ -1557,10 +1548,9 @@
                       k@KChar       -> error $ "Unexpected Fractional case for: " ++ show k
                       k@KList{}     -> error $ "Unexpected Fractional case for: " ++ show k
                       k@KSet{}      -> error $ "Unexpected Fractional case for: " ++ show k
-                      k@KUserSort{} -> error $ "Unexpected Fractional case for: " ++ show k
+                      k@KApp{}      -> error $ "Unexpected Fractional case for: " ++ show k
+                      k@KADT{}      -> error $ "Unexpected Fractional case for: " ++ show k
                       k@KTuple{}    -> error $ "Unexpected Fractional case for: " ++ show k
-                      k@KMaybe{}    -> error $ "Unexpected Fractional case for: " ++ show k
-                      k@KEither{}   -> error $ "Unexpected Fractional case for: " ++ show k
                       k@KArray{}    -> error $ "Unexpected Fractional case for: " ++ show k
 
 -- | Define Floating instance on SBV's; only for base types that are already floating; i.e., 'SFloat', 'SDouble', and 'SReal'.
@@ -1760,7 +1750,7 @@
         y st   = do xsv <- sbvToSV st x
                     newExpr st kTo (SBVApp (KindCast kFrom kTo) [xsv])
 
--- | Lift a binary operation thru it's dynamic counterpart. Note that
+-- | Lift a binary operation thru its dynamic counterpart. Note that
 -- we still want the actual functions here as differ in their type
 -- compared to their dynamic counterparts, but the implementations
 -- are the same.
@@ -1804,7 +1794,7 @@
 sRotateLeft = liftViaSVal svRotateLeft
 
 -- | An implementation of rotate-left, using a barrel shifter like design. Only works when both
--- arguments are finite bitvectors, and furthermore when the second argument is unsigned.
+-- arguments are finite bit-vectors, and furthermore when the second argument is unsigned.
 -- The first condition is enforced by the type, but the second is dynamically checked.
 -- We provide this implementation as an alternative to `sRotateLeft` since SMTLib logic
 -- does not support variable argument rotates (as opposed to shifts), and thus this
@@ -2607,12 +2597,17 @@
                   let pre = atProxy (Proxy @a) inpName
                       nm  | ctr == 0 = pre
                           | True     = pre ++ "_" ++ show ctr
-                  nm' <- newUninterpreted st (UIGiven nm) Nothing (SBVType [k]) (UINone False)
-                  chosen <- newExpr st k $ SBVApp (Uninterpreted nm') []
+                  op <- newUninterpreted st (UIGiven nm) Nothing (SBVType [k]) (UINone False)
+                  chosen <- newExpr st k $ SBVApp op []
                   let ifExists  = quantifiedBool $ \(Exists ex) -> cond ex
                   internalConstraint st False [] (unSBV (ifExists .=> cond (mk (pure (pure chosen)))))
                   pure chosen
 
+-- | Find the final part of a kind that looks like an array
+resKind :: Kind -> Kind
+resKind (KArray _ k) = resKind k
+resKind k            = k
+
 -- | SMT definable constants and functions, which can also be uninterpeted.
 -- This class captures functions that we can generate standalone-code for
 -- in the SMT solver. Note that we also allow uninterpreted constants and
@@ -2679,7 +2674,7 @@
   --
   -- __Known issues__
   --
-  -- Usually using an uninterpret function will register itself to the solver, but sometimes the lazyness
+  -- Usually using an uninterpret function will register itself to the solver, but sometimes the laziness
   -- of the evaluation might render this unreliable.
   --
   -- For example, when working with quantifiers and uninterpreted functions with the following code:
@@ -2726,14 +2721,23 @@
   -- | Render an uninterpeted value as an SMTLib definition
   sbv2smt :: ExtractIO m => a -> m String
 
+  -- | Make this name a constructor, coming from an ADT. Only used internally
+  mkADTConstructor :: HasKind a => String -> a
+  mkADTTester      :: HasKind a => String -> a
+  mkADTAccessor    :: HasKind a => String -> a
+
   {-# MINIMAL sbvDefineValue, sbv2smt #-}
 
   -- defaults:
-  uninterpret         nm         = sbvDefineValue (UIGiven nm) Nothing   $ UIFree True
-  uninterpretWithArgs nm  as     = sbvDefineValue (UIGiven nm) (Just as) $ UIFree True
-  cgUninterpret       nm  code v = sbvDefineValue (UIGiven nm) Nothing   $ UICodeC (v, code)
-  sym                            = uninterpret
+  uninterpret         nm        = sbvDefineValue (UIGiven nm) Nothing   $ UIFree True
+  uninterpretWithArgs nm as     = sbvDefineValue (UIGiven nm) (Just as) $ UIFree True
+  cgUninterpret       nm code v = sbvDefineValue (UIGiven nm) Nothing   $ UICodeC (v, code)
+  sym                           = uninterpret
 
+  mkADTConstructor nm = let k = resKind (kindOf v); v = sbvDefineValue (UIADT (ADTConstructor nm k)) Nothing $ UIFree True in v
+  mkADTTester      nm = let k = resKind (kindOf v); v = sbvDefineValue (UIADT (ADTTester      nm k)) Nothing $ UIFree True in v
+  mkADTAccessor    nm = let k = resKind (kindOf v); v = sbvDefineValue (UIADT (ADTAccessor    nm k)) Nothing $ UIFree True in v
+
   smtFunction nm v = sbvDefineValue (UIGiven (atProxy (Proxy @a) nm)) Nothing $ UIFun (v, \st fk -> lambda st TopLevel fk v)
 
   default registerFunction :: forall b c. (a ~ (SBV b -> c), SymVal b, SMTDefinable c) => a -> Symbolic ()
@@ -2743,7 +2747,6 @@
                           let b = SBV $ SVal k $ Right $ cache (const (pure v))
                           registerFunction $ f b
 
-
 -- | Kind of uninterpretation
 data UIKind a = UIFree  Bool                            -- ^ completely uninterpreted. If Bool is true, then this is curried.
               | UIFun   (a, State -> Kind -> IO SMTDef) -- ^ has code for SMTLib, with final type of kind (note this is the result
@@ -2753,13 +2756,14 @@
 
 -- Get the code associated with the UI, unless we've already did this once. (To support recursive defs.)
 retrieveUICode :: UIName -> State -> Kind -> UIKind a -> IO UICodeKind
-retrieveUICode _             _  _  (UIFree  c)      = pure $ UINone c
-retrieveUICode (UIGiven  nm) st fk (UIFun   (_, f)) = do userFuncs <- readIORef (rUserFuncs st)
-                                                         if nm `Set.member` userFuncs
-                                                            then pure $ UINone True
-                                                            else do modifyState st rUserFuncs (Set.insert nm) (pure ())
-                                                                    UISMT <$> f st fk
-retrieveUICode _             _  _  (UICodeC (_, c)) = pure $ UICgC c
+retrieveUICode _            _  _  (UIFree  c)      = pure $ UINone c
+retrieveUICode (UIADT   _)  _  _  _                = pure $ UINone True
+retrieveUICode (UIGiven nm) st fk (UIFun   (_, f)) = do userFuncs <- readIORef (rUserFuncs st)
+                                                        if nm `Set.member` userFuncs
+                                                           then pure $ UINone True
+                                                           else do modifyState st rUserFuncs (Set.insert nm) (pure ())
+                                                                   UISMT <$> f st fk
+retrieveUICode _            _  _  (UICodeC (_, c)) = pure $ UICgC c
 
 -- Get the constant value associated with the UI
 retrieveConstCode :: UIKind a -> Maybe a
@@ -2787,8 +2791,8 @@
           result st = do isSMT <- inSMTMode st
                          case (isSMT, uiKind) of
                            (True, UICodeC (v, _)) -> sbvToSV st v
-                           _                      -> do nm' <- newUninterpreted st nm mbArgs (SBVType [ka]) =<< retrieveUICode nm st ka uiKind
-                                                        newExpr st ka $ SBVApp (Uninterpreted nm') []
+                           _                      -> do op <- newUninterpreted st nm mbArgs (SBVType [ka]) =<< retrieveUICode nm st ka uiKind
+                                                        newExpr st ka $ SBVApp op []
 
 -- Functions of one argument
 instance (SymVal b, SymVal a, HasKind a) => SMTDefinable (SBV b -> SBV a) where
@@ -2805,10 +2809,10 @@
                  result st = do isSMT <- inSMTMode st
                                 case (isSMT, uiKind) of
                                   (True, UICodeC (v, _)) -> sbvToSV st (v arg0)
-                                  _                      -> do nm' <- newUninterpreted st nm mbArgs (SBVType [kb, ka]) =<< retrieveUICode nm st ka uiKind
+                                  _                      -> do op <- newUninterpreted st nm mbArgs (SBVType [kb, ka]) =<< retrieveUICode nm st ka uiKind
                                                                sw0 <- sbvToSV st arg0
                                                                mapM_ forceSVArg [sw0]
-                                                               newExpr st ka $ SBVApp (Uninterpreted nm') [sw0]
+                                                               newExpr st ka $ SBVApp op [sw0]
 
 -- Functions of two arguments
 instance (SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable (SBV c -> SBV b -> SBV a) where
@@ -2826,11 +2830,11 @@
                  result st = do isSMT <- inSMTMode st
                                 case (isSMT, uiKind) of
                                   (True, UICodeC (v, _)) -> sbvToSV st (v arg0 arg1)
-                                  _                      -> do nm' <- newUninterpreted st nm mbArgs (SBVType [kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
+                                  _                      -> do op <- newUninterpreted st nm mbArgs (SBVType [kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
                                                                sw0 <- sbvToSV st arg0
                                                                sw1 <- sbvToSV st arg1
                                                                mapM_ forceSVArg [sw0, sw1]
-                                                               newExpr st ka $ SBVApp (Uninterpreted nm') [sw0, sw1]
+                                                               newExpr st ka $ SBVApp op [sw0, sw1]
 
 -- Functions of three arguments
 instance (SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable (SBV d -> SBV c -> SBV b -> SBV a) where
@@ -2849,12 +2853,12 @@
                  result st = do isSMT <- inSMTMode st
                                 case (isSMT, uiKind) of
                                   (True, UICodeC (v, _)) -> sbvToSV st (v arg0 arg1 arg2)
-                                  _                      -> do nm' <- newUninterpreted st nm mbArgs (SBVType [kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
+                                  _                      -> do op <- newUninterpreted st nm mbArgs (SBVType [kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
                                                                sw0 <- sbvToSV st arg0
                                                                sw1 <- sbvToSV st arg1
                                                                sw2 <- sbvToSV st arg2
                                                                mapM_ forceSVArg [sw0, sw1, sw2]
-                                                               newExpr st ka $ SBVApp (Uninterpreted nm') [sw0, sw1, sw2]
+                                                               newExpr st ka $ SBVApp op [sw0, sw1, sw2]
 
 -- Functions of four arguments
 instance (SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable (SBV e -> SBV d -> SBV c -> SBV b -> SBV a) where
@@ -2874,13 +2878,13 @@
                  result st = do isSMT <- inSMTMode st
                                 case (isSMT, uiKind) of
                                   (True, UICodeC (v, _)) -> sbvToSV st (v arg0 arg1 arg2 arg3)
-                                  _                      -> do nm' <- newUninterpreted st nm mbArgs (SBVType [ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
+                                  _                      -> do op <- newUninterpreted st nm mbArgs (SBVType [ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
                                                                sw0 <- sbvToSV st arg0
                                                                sw1 <- sbvToSV st arg1
                                                                sw2 <- sbvToSV st arg2
                                                                sw3 <- sbvToSV st arg3
                                                                mapM_ forceSVArg [sw0, sw1, sw2, sw3]
-                                                               newExpr st ka $ SBVApp (Uninterpreted nm') [sw0, sw1, sw2, sw3]
+                                                               newExpr st ka $ SBVApp op [sw0, sw1, sw2, sw3]
 
 -- Functions of five arguments
 instance (SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable (SBV f -> SBV e -> SBV d -> SBV c -> SBV b -> SBV a) where
@@ -2901,14 +2905,14 @@
                  result st = do isSMT <- inSMTMode st
                                 case (isSMT, uiKind) of
                                   (True, UICodeC (v, _)) -> sbvToSV st (v arg0 arg1 arg2 arg3 arg4)
-                                  _                      -> do nm' <- newUninterpreted st nm mbArgs (SBVType [kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
+                                  _                      -> do op <- newUninterpreted st nm mbArgs (SBVType [kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
                                                                sw0 <- sbvToSV st arg0
                                                                sw1 <- sbvToSV st arg1
                                                                sw2 <- sbvToSV st arg2
                                                                sw3 <- sbvToSV st arg3
                                                                sw4 <- sbvToSV st arg4
                                                                mapM_ forceSVArg [sw0, sw1, sw2, sw3, sw4]
-                                                               newExpr st ka $ SBVApp (Uninterpreted nm') [sw0, sw1, sw2, sw3, sw4]
+                                                               newExpr st ka $ SBVApp op [sw0, sw1, sw2, sw3, sw4]
 
 -- Functions of six arguments
 instance (SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable (SBV g -> SBV f -> SBV e -> SBV d -> SBV c -> SBV b -> SBV a) where
@@ -2930,7 +2934,7 @@
                  result st = do isSMT <- inSMTMode st
                                 case (isSMT, uiKind) of
                                   (True, UICodeC (v, _)) -> sbvToSV st (v arg0 arg1 arg2 arg3 arg4 arg5)
-                                  _                      -> do nm' <- newUninterpreted st nm mbArgs (SBVType [kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
+                                  _                      -> do op <- newUninterpreted st nm mbArgs (SBVType [kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
                                                                sw0 <- sbvToSV st arg0
                                                                sw1 <- sbvToSV st arg1
                                                                sw2 <- sbvToSV st arg2
@@ -2938,7 +2942,7 @@
                                                                sw4 <- sbvToSV st arg4
                                                                sw5 <- sbvToSV st arg5
                                                                mapM_ forceSVArg [sw0, sw1, sw2, sw3, sw4, sw5]
-                                                               newExpr st ka $ SBVApp (Uninterpreted nm') [sw0, sw1, sw2, sw3, sw4, sw5]
+                                                               newExpr st ka $ SBVApp op [sw0, sw1, sw2, sw3, sw4, sw5]
 
 -- Functions of seven arguments
 instance (SymVal h, SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a)
@@ -2962,7 +2966,7 @@
                  result st = do isSMT <- inSMTMode st
                                 case (isSMT, uiKind) of
                                   (True, UICodeC (v, _)) -> sbvToSV st (v arg0 arg1 arg2 arg3 arg4 arg5 arg6)
-                                  _                      -> do nm' <- newUninterpreted st nm mbArgs (SBVType [kh, kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
+                                  _                      -> do op  <- newUninterpreted st nm mbArgs (SBVType [kh, kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
                                                                sw0 <- sbvToSV st arg0
                                                                sw1 <- sbvToSV st arg1
                                                                sw2 <- sbvToSV st arg2
@@ -2971,7 +2975,7 @@
                                                                sw5 <- sbvToSV st arg5
                                                                sw6 <- sbvToSV st arg6
                                                                mapM_ forceSVArg [sw0, sw1, sw2, sw3, sw4, sw5, sw6]
-                                                               newExpr st ka $ SBVApp (Uninterpreted nm') [sw0, sw1, sw2, sw3, sw4, sw5, sw6]
+                                                               newExpr st ka $ SBVApp op [sw0, sw1, sw2, sw3, sw4, sw5, sw6]
 
 -- Functions of eight arguments
 instance (SymVal i, SymVal h, SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, SymVal a, HasKind a)
@@ -2996,7 +3000,7 @@
                  result st = do isSMT <- inSMTMode st
                                 case (isSMT, uiKind) of
                                   (True, UICodeC (v, _)) -> sbvToSV st (v arg0 arg1 arg2 arg3 arg4 arg5 arg6 arg7)
-                                  _                      -> do nm' <- newUninterpreted st nm mbArgs (SBVType [ki, kh, kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
+                                  _                      -> do op  <- newUninterpreted st nm mbArgs (SBVType [ki, kh, kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
                                                                sw0 <- sbvToSV st arg0
                                                                sw1 <- sbvToSV st arg1
                                                                sw2 <- sbvToSV st arg2
@@ -3006,7 +3010,7 @@
                                                                sw6 <- sbvToSV st arg6
                                                                sw7 <- sbvToSV st arg7
                                                                mapM_ forceSVArg [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7]
-                                                               newExpr st ka $ SBVApp (Uninterpreted nm') [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7]
+                                                               newExpr st ka $ SBVApp op [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7]
 
 -- Functions of nine arguments
 instance (SymVal j, SymVal i, SymVal h, SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a)
@@ -3032,7 +3036,7 @@
                  result st = do isSMT <- inSMTMode st
                                 case (isSMT, uiKind) of
                                   (True, UICodeC (v, _)) -> sbvToSV st (v arg0 arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8)
-                                  _                      -> do nm' <- newUninterpreted st nm mbArgs (SBVType [kj, ki, kh, kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
+                                  _                      -> do op  <- newUninterpreted st nm mbArgs (SBVType [kj, ki, kh, kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
                                                                sw0 <- sbvToSV st arg0
                                                                sw1 <- sbvToSV st arg1
                                                                sw2 <- sbvToSV st arg2
@@ -3043,7 +3047,7 @@
                                                                sw7 <- sbvToSV st arg7
                                                                sw8 <- sbvToSV st arg8
                                                                mapM_ forceSVArg [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7, sw8]
-                                                               newExpr st ka $ SBVApp (Uninterpreted nm') [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7, sw8]
+                                                               newExpr st ka $ SBVApp op [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7, sw8]
 
 -- Functions of ten arguments
 instance (SymVal k, SymVal j, SymVal i, SymVal h, SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a)
@@ -3070,7 +3074,7 @@
                  result st = do isSMT <- inSMTMode st
                                 case (isSMT, uiKind) of
                                   (True, UICodeC (v, _)) -> sbvToSV st (v arg0 arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9)
-                                  _                      -> do nm' <- newUninterpreted st nm mbArgs (SBVType [kk, kj, ki, kh, kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
+                                  _                      -> do op  <- newUninterpreted st nm mbArgs (SBVType [kk, kj, ki, kh, kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
                                                                sw0 <- sbvToSV st arg0
                                                                sw1 <- sbvToSV st arg1
                                                                sw2 <- sbvToSV st arg2
@@ -3082,7 +3086,7 @@
                                                                sw8 <- sbvToSV st arg8
                                                                sw9 <- sbvToSV st arg9
                                                                mapM_ forceSVArg [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7, sw8, sw9]
-                                                               newExpr st ka $ SBVApp (Uninterpreted nm') [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7, sw8, sw9]
+                                                               newExpr st ka $ SBVApp op [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7, sw8, sw9]
 
 -- Functions of eleven arguments
 instance (SymVal l, SymVal k, SymVal j, SymVal i, SymVal h, SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a)
@@ -3110,7 +3114,7 @@
                  result st = do isSMT <- inSMTMode st
                                 case (isSMT, uiKind) of
                                   (True, UICodeC (v, _)) -> sbvToSV st (v arg0 arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10)
-                                  _                      -> do nm' <- newUninterpreted st nm mbArgs (SBVType [kl, kk, kj, ki, kh, kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
+                                  _                      -> do op  <- newUninterpreted st nm mbArgs (SBVType [kl, kk, kj, ki, kh, kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
                                                                sw0  <- sbvToSV st arg0
                                                                sw1  <- sbvToSV st arg1
                                                                sw2  <- sbvToSV st arg2
@@ -3123,7 +3127,7 @@
                                                                sw9  <- sbvToSV st arg9
                                                                sw10 <- sbvToSV st arg10
                                                                mapM_ forceSVArg [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7, sw8, sw9, sw10]
-                                                               newExpr st ka $ SBVApp (Uninterpreted nm') [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7, sw8, sw9, sw10]
+                                                               newExpr st ka $ SBVApp op [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7, sw8, sw9, sw10]
 
 -- Functions of twelve arguments
 instance (SymVal m, SymVal l, SymVal k, SymVal j, SymVal i, SymVal h, SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a)
@@ -3152,7 +3156,7 @@
                  result st = do isSMT <- inSMTMode st
                                 case (isSMT, uiKind) of
                                   (True, UICodeC (v, _)) -> sbvToSV st (v arg0 arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10 arg11)
-                                  _                      -> do nm' <- newUninterpreted st nm mbArgs (SBVType [km, kl, kk, kj, ki, kh, kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
+                                  _                      -> do op  <- newUninterpreted st nm mbArgs (SBVType [km, kl, kk, kj, ki, kh, kg, kf, ke, kd, kc, kb, ka]) =<< retrieveUICode nm st ka uiKind
                                                                sw0  <- sbvToSV st arg0
                                                                sw1  <- sbvToSV st arg1
                                                                sw2  <- sbvToSV st arg2
@@ -3166,7 +3170,7 @@
                                                                sw10 <- sbvToSV st arg10
                                                                sw11 <- sbvToSV st arg11
                                                                mapM_ forceSVArg [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7, sw8, sw9, sw10, sw11]
-                                                               newExpr st ka $ SBVApp (Uninterpreted nm') [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7, sw8, sw9, sw10, sw11]
+                                                               newExpr st ka $ SBVApp op [sw0, sw1, sw2, sw3, sw4, sw5, sw6, sw7, sw8, sw9, sw10, sw11]
 
 -- Mark the UIKind as uncurried
 mkUncurried :: UIKind a -> UIKind a
diff --git a/Data/SBV/Core/Operations.hs b/Data/SBV/Core/Operations.hs
--- a/Data/SBV/Core/Operations.hs
+++ b/Data/SBV/Core/Operations.hs
@@ -51,8 +51,10 @@
 
 import Prelude hiding (Foldable(..))
 import Data.Bits (Bits(..))
-import Data.List (genericIndex, genericLength, genericTake, foldr, length, foldl', elem, nub, sort)
+import Data.List (genericIndex, genericLength, genericTake, foldr, length, foldl', elem, nub, sort, null, elemIndex)
 
+import Data.Maybe (isNothing)
+
 import Data.SBV.Core.AlgReals
 import Data.SBV.Core.Kind
 import Data.SBV.Core.Concrete
@@ -492,29 +494,6 @@
       (CAlgReal     a, CAlgReal  b) | isExactRational a && isExactRational b -> Just $ a `compare` b
                                     | True                                   -> Nothing
 
-      -- Structural cases
-      (CMaybe       a, CMaybe    b) -> case (a, b) of
-                                         (Nothing, Nothing) -> Just EQ
-                                         (Nothing, Just{})  -> Just LT
-                                         (Just{},  Nothing) -> Just GT
-                                         (Just av, Just bv) -> case k of
-                                                                 KMaybe ke -> cCompare ke op av bv
-                                                                 _         -> error $ "Unexpected kind in cCompare for maybe's: " ++ show k
-
-      (CEither      a, CEither   b) -> let (kl, kr) = case k of
-                                                        KEither l r -> (l, r)
-                                                        _           -> error $ "Unexpected kind in cCompare for either's: " ++ show k
-                                       in case (a, b) of
-                                            (Left{},   Right{})  -> Just LT
-                                            (Right{},  Left{})   -> Just GT
-                                            (Left av,  Left  bv) -> cCompare kl op av bv
-                                            (Right av, Right bv) -> cCompare kr op av bv
-
-      -- Uninterpreted sorts use the index
-      (CUserSort    a, CUserSort b) -> case (a, b) of
-                                         ((Just i, _), (Just j, _)) -> Just $ i `compare` j
-                                         _                          -> error $ "cCompare: Impossible happened while trying to compare: " ++ show (op, a, b)
-
       -- Lists and tuples use lexicographic ordering
       (CList        a, CList b) -> case k of
                                      KList ke -> lexCmp (map (ke,) a) (map (ke,) b)
@@ -532,9 +511,7 @@
                            -> case svSetEqual ke a b of
                                  Nothing    -> Nothing  -- We don't know
                                  Just True  -> Just EQ  -- They're equal
-                                 Just False -> Just $ if op `elem` [Equal True, Equal False]
-                                                         then GT  -- Pick GT, So equality    test will fail
-                                                         else EQ  -- Pick EQ, So in-equality test will fail
+                                 Just False -> Just GT  -- Pick GT; so equality test will fail, inequality will pass
                            | True
                            -> error $ "cCompare: Received unexpected set comparison: " ++ show (op, k)
 
@@ -543,16 +520,48 @@
                            -> case svArrEqual k1 k2 a b of
                                 Nothing    -> Nothing  -- We don't know
                                 Just True  -> Just EQ  -- They're equal
-                                Just False -> Just $ if op `elem` [Equal True, Equal False]
-                                                        then GT  -- Pick GT, So equality    test will fail
-                                                        else EQ  -- Pick EQ, So in-equality test will fail
+                                Just False -> Just GT  -- Pick GT; so equality test will fail, inequality will pass
                            | True
                            -> error $ "cCompare: Received unexpected array comparison: " ++ show (op, k)
 
+
+      -- ADTs. Only equal/inequal on full ADTs. Compares on enumerations.
+      (CADT (s, fks), CADT (s', fks'))
+         -> case k of
+              -- Enumerations. We do a straight comparison on the constructor index
+              KADT _ _ cstrs | all (null . snd) cstrs
+                             -> let cnms = map fst cstrs
+                                in case (s `elemIndex` cnms, s' `elemIndex` cnms) of
+                                     (Just i, Just j) -> Just (i `compare` j)
+                                     r                -> error $ "cCompare: Unable to locate indexes for CADT: " ++ show (k, s, s', r)
+
+              -- Arbitrary ADTs. Only allow equality/inequality
+              _ | op `notElem` [Equal True, Equal False, NotEqual]
+                -> error $ "cCompare: Received unexpected ADT comparison: " ++ show (op, k)
+
+                -- Different constructor
+                | s /= s'
+                -> Just GT -- Pick GT; so equality test will fail, inequality will pass
+
+                -- Same constructor
+                | map fst fks /= map fst fks'
+                -> error $ "cCompare: Mismatching ADT field kinds in comparison: " ++ show (op, k, map fst fks, map fst fks')
+                | True
+                -> let fmatch    = zipWith (\(fk, v1) (_, v2) -> cCompare fk op v1 v2) fks fks'
+                       undecided = any isNothing fmatch   -- Field comparison undecive
+                       allEq     = all (== Just EQ) fmatch -- All fields Equal
+                   in if undecided
+                      then Nothing
+                      else if allEq
+                           then Just EQ
+                           else -- all compared fine, but not all equal
+                                Just GT -- Pick GT; so equality test will fail, inequality will pass
+
+      -- Shouldn't happen:
       _ -> error $ unlines [ ""
                            , "*** Data.SBV.cCompare: Bug in SBV: Unhandled rank in comparison fallthru"
                            , "***"
-                           , "***   Ranks Received: " ++ show (cvRank x, cvRank y)
+                           , "***   Ranks Received: " ++ show (cvRank x, cvRank y, op)
                            , "***"
                            , "*** Please report this as a bug!"
                            ]
@@ -1471,10 +1480,6 @@
    = x `svLessThan` y
    | KTuple{} <- kx
    = tupleLT x y
-   | KMaybe{}  <- kx
-   = maybeLT x y
-   | KEither{} <- kx
-   = eitherLT x y
    | True
    = x `svLessThan` y
    where kx = kindOf x
@@ -1502,53 +1507,6 @@
                         walk ((lti, eqi) : rest) = lti `svOr` (eqi `svAnd` walk rest)
 
                     svToSV st $ walk $ zipWith chkElt [1..] ks
-
--- | Structural less-than for maybes
-maybeLT :: SVal -> SVal -> SVal
-maybeLT x y = sMaybeCase (       sMaybeCase svFalse (const svTrue)    y)
-                         (\jx -> sMaybeCase svFalse (jx `svStructuralLessThan`) y)
-                         x
-  where ka = case kindOf x of
-               KMaybe k' -> k'
-               k         -> error $ "Data.SBV: Impossible happened, maybeLT called with: " ++ show (k, x, y)
-
-        sMaybeCase brNothing brJust s = SVal KBool $ Right $ cache res
-           where res st = do sv <- svToSV st s
-
-                             let justVal = SVal ka $ Right $ cache $ \_ -> newExpr st ka $ SBVApp MaybeAccess [sv]
-                                 justRes = brJust justVal
-
-                             br1 <- svToSV st brNothing
-                             br2 <- svToSV st justRes
-
-                             -- Do we have a value?
-                             noVal <- newExpr st KBool $ SBVApp (MaybeIs ka False) [sv]
-                             newExpr st KBool $ SBVApp Ite [noVal, br1, br2]
-
--- | Structural less-than for either
-eitherLT :: SVal -> SVal -> SVal
-eitherLT x y = sEitherCase (\lx -> sEitherCase (lx `svStructuralLessThan`) (const svTrue)              y)
-                           (\rx -> sEitherCase (const svFalse)             (rx `svStructuralLessThan`) y)
-                           x
-  where (ka, kb) = case kindOf x of
-                     KEither k1 k2 -> (k1, k2)
-                     k             -> error $ "Data.SBV: Impossible happened, eitherLT called with: " ++ show (k, x, y)
-
-        sEitherCase brA brB sab = SVal KBool $ Right $ cache res
-          where res st = do abv <- svToSV st sab
-
-                            let leftVal  = SVal ka $ Right $ cache $ \_ -> newExpr st ka $ SBVApp (EitherAccess False) [abv]
-                                rightVal = SVal kb $ Right $ cache $ \_ -> newExpr st kb $ SBVApp (EitherAccess True)  [abv]
-
-                                leftRes  = brA leftVal
-                                rightRes = brB rightVal
-
-                            br1 <- svToSV st leftRes
-                            br2 <- svToSV st rightRes
-
-                            --  Which branch are we in? Return the appropriate value:
-                            onLeft <- newExpr st KBool $ SBVApp (EitherIs ka kb False) [abv]
-                            newExpr st KBool $ SBVApp Ite [onLeft, br1, br2]
 
 -- | Convert an 'Data.SBV.SFloat' to an 'Data.SBV.SWord32', preserving the bit-correspondence. Note that since the
 -- representation for @NaN@s are not unique, this function will return a symbolic value when given a
diff --git a/Data/SBV/Core/Sized.hs b/Data/SBV/Core/Sized.hs
--- a/Data/SBV/Core/Sized.hs
+++ b/Data/SBV/Core/Sized.hs
@@ -11,7 +11,6 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE DataKinds            #-}
-{-# LANGUAGE FlexibleInstances    #-}
 {-# LANGUAGE ScopedTypeVariables  #-}
 {-# LANGUAGE TypeApplications     #-}
 {-# LANGUAGE TypeFamilies         #-}
diff --git a/Data/SBV/Core/SizedFloats.hs b/Data/SBV/Core/SizedFloats.hs
--- a/Data/SBV/Core/SizedFloats.hs
+++ b/Data/SBV/Core/SizedFloats.hs
@@ -9,9 +9,8 @@
 -- Type-level sized floats.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveDataTypeable   #-}
 {-# LANGUAGE DataKinds            #-}
-{-# LANGUAGE FlexibleInstances    #-}
+{-# LANGUAGE DeriveDataTypeable   #-}
 {-# LANGUAGE ScopedTypeVariables  #-}
 {-# LANGUAGE TypeApplications     #-}
 {-# LANGUAGE TypeFamilies         #-}
diff --git a/Data/SBV/Core/Symbolic.hs b/Data/SBV/Core/Symbolic.hs
--- a/Data/SBV/Core/Symbolic.hs
+++ b/Data/SBV/Core/Symbolic.hs
@@ -18,16 +18,13 @@
 {-# LANGUAGE DeriveGeneric              #-}
 {-# LANGUAGE DerivingStrategies         #-}
 {-# LANGUAGE FlexibleInstances          #-}
-{-# LANGUAGE GADTs                      #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE MultiParamTypeClasses      #-}
 {-# LANGUAGE NamedFieldPuns             #-}
 {-# LANGUAGE OverloadedStrings          #-}
-{-# LANGUAGE PatternGuards              #-}
 {-# LANGUAGE Rank2Types                 #-}
 {-# LANGUAGE ScopedTypeVariables        #-}
 {-# LANGUAGE StandaloneDeriving         #-}
-{-# LANGUAGE TypeFamilies               #-}
 {-# LANGUAGE TypeOperators              #-}
 {-# LANGUAGE UndecidableInstances       #-}
 {-# LANGUAGE ViewPatterns               #-}
@@ -37,10 +34,9 @@
 module Data.SBV.Core.Symbolic
   ( NodeId(..)
   , SV(..), swKind, trueSV, falseSV, contextOfSV
-  , Op(..), PBOp(..), OvOp(..), FPOp(..), NROp(..), StrOp(..), RegExOp(..), SeqOp(..), SetOp(..), SpecialRelOp(..)
+  , Op(..), PBOp(..), OvOp(..), FPOp(..), NROp(..), StrOp(..), RegExOp(..), SeqOp(..), SetOp(..), SpecialRelOp(..), ADTOp(..)
   , RegExp(..), regExpToSMTString, SMTLambda(..)
   , Quantifier(..), needsExistentials, SBVContext(..), checkCompatibleContext, VarContext(..)
-  , RoundingMode(..)
   , SBVType(..), svUninterpreted, svUninterpretedNamedArgs, newUninterpreted, prefixNameToUnique
   , SVal(..)
   , svMkSymVar, sWordN, sWordN_, sIntN, sIntN_
@@ -66,7 +62,7 @@
   ) where
 
 import Control.DeepSeq             (NFData(..))
-import Control.Monad               (when)
+import Control.Monad               (when, unless)
 import Control.Monad.Except        (MonadError, ExceptT)
 import Control.Monad.Reader        (MonadReader(..), ReaderT, runReaderT,
                                     mapReaderT)
@@ -108,8 +104,9 @@
 import Data.SBV.Core.Kind
 import Data.SBV.Core.Concrete
 import Data.SBV.SMT.SMTLibNames
-import Data.SBV.Utils.TDiff (Timing)
-import Data.SBV.Utils.Lib   (stringToQFS, checkObservableName, barify)
+import Data.SBV.Utils.TDiff   (Timing)
+import Data.SBV.Utils.Lib     (stringToQFS, checkObservableName, barify)
+import Data.SBV.Utils.Numeric (RoundingMode)
 
 import Data.Containers.ListUtils (nubOrd)
 
@@ -247,18 +244,19 @@
         | SetOp SetOp                           -- Set operations, categorized separately
         | TupleConstructor Int                  -- Construct an n-tuple
         | TupleAccess Int Int                   -- Access element i of an n-tuple; second argument is n
-        | EitherConstructor Kind Kind Bool      -- Construct a sum; False: left, True: right
-        | EitherIs Kind Kind Bool               -- Either branch tester; False: left, True: right
-        | EitherAccess Bool                     -- Either branch access; False: left, True: right
         | RationalConstructor                   -- Construct a rational. Note that there's no access to numerator or denumerator, since we cannot store rationals in canonical form
-        | MaybeConstructor Kind Bool            -- Construct a maybe value; False: Nothing, True: Just
-        | MaybeIs Kind Bool                     -- Maybe tester; False: nothing, True: just
-        | MaybeAccess                           -- Maybe branch access; grab the contents of the just
+        | ADTOp ADTOp                           -- ADT access/construction/testing
         | ArrayLambda SMTLambda                 -- An array value, created from a lambda
         | ReadArray                             -- Reading an array value
         | WriteArray                            -- Writing to an array
         deriving (Eq, Ord, Generic, G.Data, NFData)
 
+-- | ADT operations
+data ADTOp = ADTConstructor String Kind    -- Construct an ADT. Kind is the kind of the resulting ADT
+           | ADTTester      String Kind    -- Check if top-level constructor matches. Kind is the kind of the argument
+           | ADTAccessor    String Kind    -- Extract a field from an ADT value. Kind is the kind of the argument
+           deriving (Eq, Ord, Generic, G.Data, NFData)
+
 -- | Special relations supported by z3
 data SpecialRelOp = IsPartialOrder         String
                   | IsLinearOrder          String
@@ -494,7 +492,7 @@
   show StrToCode   = "str.to_code"
   show StrFromCode = "str.from_code"
   -- Note the breakage here with respect to argument order. We fix this explicitly later.
-  show (StrInRe s) = "str.in.re " ++ regExpToSMTString s
+  show (StrInRe s) = "str.in_re " ++ regExpToSMTString s
 
 -- | Show instance for @RegExOp@.
 instance Show RegExOp where
@@ -605,24 +603,10 @@
   show (TupleConstructor   n) = "mkSBVTuple" ++ show n
   show (TupleAccess      i n) = "proj_" ++ show i ++ "_SBVTuple" ++ show n
 
-  -- Remember, while we try to maintain SMTLib compabitibility here, these output
-  -- is merely for debugging purposes. For how we actually render these in SMTLib,
-  -- look at the file SBV/SMT/SMTLib2.hs for these constructors.
-  show (EitherConstructor k1 k2  False) = "(_ left_SBVEither "  ++ show (KEither k1 k2) ++ ")"
-  show (EitherConstructor k1 k2  True ) = "(_ right_SBVEither " ++ show (KEither k1 k2) ++ ")"
-  show (EitherIs          k1 k2  False) = "(_ is (left_SBVEither ("  ++ show k1 ++ ") " ++ show (KEither k1 k2) ++ "))"
-  show (EitherIs          k1 k2  True ) = "(_ is (right_SBVEither (" ++ show k2 ++ ") " ++ show (KEither k1 k2) ++ "))"
-  show (EitherAccess             False) = "get_left_SBVEither"
-  show (EitherAccess             True ) = "get_right_SBVEither"
-  show RationalConstructor              = "SBV.Rational"
-  show (MaybeConstructor k False)       = "(_ nothing_SBVMaybe " ++ show (KMaybe k) ++ ")"
-  show (MaybeConstructor k True)        = "(_ just_SBVMaybe "    ++ show (KMaybe k) ++ ")"
-  show (MaybeIs          k False)       = "(_ is (nothing_SBVMaybe () "              ++ show (KMaybe k) ++ "))"
-  show (MaybeIs          k True )       = "(_ is (just_SBVMaybe (" ++ show k ++ ") " ++ show (KMaybe k) ++ "))"
-  show MaybeAccess                      = "get_just_SBVMaybe"
-  show (ArrayLambda s)                  = show s
-  show ReadArray                        = "select"
-  show WriteArray                       = "store"
+  show RationalConstructor    = "SBV.Rational"
+  show (ArrayLambda s)        = show s
+  show ReadArray              = "select"
+  show WriteArray             = "store"
 
   show op
     | Just s <- op `lookup` syms = s
@@ -905,9 +889,7 @@
     where sh2 :: Show a => [a] -> [String]
           sh2 = map (("  "++) . show)
 
-          usorts = [sh s t | KUserSort s t <- Set.toList kinds]
-                   where sh s Nothing   = s
-                         sh s (Just es) = s ++ " (" ++ intercalate ", " es ++ ")"
+          usorts = [s | KADT s _ _ <- filter isUninterpreted (Set.toList kinds)]
 
           shs sv = show sv ++ " :: " ++ show (swKind sv)
 
@@ -1287,9 +1269,9 @@
                 | UISMT  SMTDef   -- SMTLib, first argument are the free-variables in it
                 | UICgC  [String] -- Code-gen, currently only C
 
--- | A newtype wrapper for uninterpreted function names. This is in preparation
--- for a possibility of having other alternatives here, which we haven't needed so far.
-newtype UIName = UIGiven String -- ^ Full name
+-- | A newtype wrapper for uninterpreted function names. We distinguish between user names and those of constructors
+data UIName = UIGiven String -- ^ Full name
+            | UIADT   ADTOp  -- ^ The name of an ADT operation based on the constructor
 
 -- | Uninterpreted constants and functions. An uninterpreted constant is
 -- a value that is indexed by its name. The only property the prover assumes
@@ -1307,12 +1289,12 @@
 svUninterpretedGen :: Kind -> UIName -> UICodeKind -> [SVal] -> Maybe [String] -> SVal
 svUninterpretedGen k nm code args mbArgNames = SVal k $ Right $ cache result
   where result st = do let ty = SBVType (map kindOf args ++ [k])
-                       nm' <- newUninterpreted st nm mbArgNames ty code
+                       op <- newUninterpreted st nm mbArgNames ty code
                        sws <- mapM (svToSV st) args
                        mapM_ forceSVArg sws
-                       newExpr st k $ SBVApp (Uninterpreted nm') sws
+                       newExpr st k $ SBVApp op sws
 
--- | Generate a unique name for the fiven function based on the object's stable name
+-- | Generate a unique name for the given function based on the object's stable name
 prefixNameToUnique :: State -> String -> IO String
 prefixNameToUnique st pre = do
    uiMap <- readIORef (rUIMap st)
@@ -1324,18 +1306,23 @@
       (n:_) -> pure n
       []    -> error $ "genUniqueName: Can't generate a unique name for prefix: " ++ pre   -- can't happen
 
--- | Create a new uninterpreted symbol, possibly with user given code. This function might change
+-- | Create a new value, possibly with user given code. This function might change
 -- the name given, putting bars around it if needed. That's the name returned.
-newUninterpreted :: State -> UIName -> Maybe [String] -> SBVType -> UICodeKind -> IO String
+newUninterpreted :: State -> UIName -> Maybe [String] -> SBVType -> UICodeKind -> IO Op
 newUninterpreted st uiName mbArgNames t uiCode = do
 
-  candName <- case uiName of
-                UIGiven n -> pure n
+  let (adtOp, candName) = case uiName of
+                            UIGiven n -> (False, n)
+                            UIADT   o -> case o of
+                                           ADTConstructor n _ -> (True, n)
+                                           ADTTester      n _ -> (True, n)
+                                           ADTAccessor    n _ -> (True, n)
 
-      -- determine the final name
+  -- determine the final name. We leave constructors alone.
   let nm = case () of
-             () | "__internal_sbv_" `isPrefixOf` candName -> candName                -- internal names go thru
-                | True                                    -> barify candName         -- surround with bars if not legitimate in SMTLib
+             () | "__internal_sbv_" `isPrefixOf` candName -> candName        -- internal names go thru
+                | adtOp                                   -> candName        -- ADT names go thru
+                | True                                    -> barify candName -- surround with bars if not legitimate in SMTLib
 
       extraComment = case uiName of
                       UIGiven  n | nm /= n -> " (Given: " ++ n ++ ")"
@@ -1371,16 +1358,22 @@
                           ++ "      Previously used at: " ++ show t'
         | True    = cont
 
-  uiMap <- readIORef (rUIMap st)
-  case nm `Map.lookup` uiMap of
-    Just (_, _, t') -> checkType t' (return ())
-    Nothing         -> modifyState st rUIMap (Map.insert nm (isCurried, mbArgNames, t))
-                         $ modifyIncState st rNewUIs
-                                            (\newUIs -> case nm `Map.lookup` newUIs of
-                                                          Just (_, _, t') -> checkType t' newUIs
-                                                          Nothing         -> Map.insert nm (isCurried, mbArgNames, t) newUIs)
+  -- If we're not a constructor, register it:
+  unless adtOp $ do
+    uiMap <- readIORef (rUIMap st)
+    case nm `Map.lookup` uiMap of
+      Just (_, _, t') -> checkType t' (return ())
+      Nothing         -> modifyState st rUIMap (Map.insert nm (isCurried, mbArgNames, t))
+                           $ modifyIncState st rNewUIs
+                                              (\newUIs -> case nm `Map.lookup` newUIs of
+                                                            Just (_, _, t') -> checkType t' newUIs
+                                                            Nothing         -> Map.insert nm (isCurried, mbArgNames, t) newUIs)
 
-  pure nm
+  pure $ case uiName of
+          UIGiven{}                  -> Uninterpreted nm
+          UIADT (ADTConstructor _ k) -> ADTOp (ADTConstructor nm k)
+          UIADT (ADTTester      _ k) -> ADTOp (ADTTester      nm k)
+          UIADT (ADTAccessor    _ k) -> ADTOp (ADTAccessor    nm k)
 
 -- | Add a new sAssert based constraint
 addAssertion :: State -> Maybe CallStack -> String -> SV -> IO ()
@@ -1433,7 +1426,7 @@
 -- allow for this.
 registerKind :: State -> Kind -> IO ()
 registerKind st k
-  | KUserSort sortName _ <- k, isReserved sortName
+  | KADT sortName _ _ <- k, isReserved sortName
   = error $ "SBV: " ++ show sortName ++ " is a reserved sort; please use a different name."
   | True
   = do -- Adding a kind to the incState is tricky; we only need to add it
@@ -1443,39 +1436,44 @@
 
        existingKinds <- readIORef (rUsedKinds st)
 
-       modifyState st rUsedKinds (Set.insert k) $ do
+       -- For ADTs we need to make sure we haven't added it before
+       let adtExists = case k of
+                         KADT s _ _  -> s `elem` [s' | KADT s' _ _ <- Set.toList existingKinds]
+                         _           -> False
 
-                          -- Why do we discriminate here? Because the incremental context is sensitive to the
-                          -- order: In particular, if an uninterpreted kind is already in there, we don't
-                          -- want to re-add because double-declaration would be wrong. See 'cvtInc' for details.
-                          let needsAdding = case k of
-                                              KUserSort{} -> k `notElem` existingKinds
-                                              KList{}     -> k `notElem` existingKinds
-                                              KTuple nks  -> length nks `notElem` [length oks | KTuple oks <- Set.toList existingKinds]
-                                              KMaybe{}    -> k `notElem` existingKinds
-                                              KEither{}   -> k `notElem` existingKinds
-                                              _           -> False
+       unless adtExists $
+          modifyState st rUsedKinds (Set.insert k) $ do
 
-                          when needsAdding $ modifyIncState st rNewKinds (Set.insert k)
+              -- Why do we discriminate here? Because the incremental context is sensitive to the
+              -- order: In particular, if an uninterpreted kind is already in there, we don't
+              -- want to re-add because double-declaration would be wrong. See 'cvtInc' for details.
+              let needsAdding = case k of
+                                  KADT s _ _  -> s `notElem` [s' | KADT s' _ _ <- Set.toList existingKinds]
+                                  KList{}     -> k `notElem` existingKinds
+                                  KTuple nks  -> length nks `notElem` [length oks | KTuple oks <- Set.toList existingKinds]
+                                  _           -> False
 
+              when needsAdding $ modifyIncState st rNewKinds (Set.insert k)
+
        -- Don't forget to register subkinds!
        case k of
+         KVar      {}    -> return ()
          KBool     {}    -> return ()
          KBounded  {}    -> return ()
          KUnbounded{}    -> return ()
          KReal     {}    -> return ()
-         KUserSort {}    -> return ()
          KFloat    {}    -> return ()
          KDouble   {}    -> return ()
          KFP       {}    -> return ()
          KRational {}    -> return ()
          KChar     {}    -> return ()
          KString   {}    -> return ()
+
+         KApp _ ks       -> mapM_ (registerKind st) ks
+         KADT _ pks cks  -> mapM_ (registerKind st) (map snd pks ++ concatMap snd cks)
          KList     ek    -> registerKind st ek
          KSet      ek    -> registerKind st ek
          KTuple    eks   -> mapM_ (registerKind st) eks
-         KMaybe    ke    -> registerKind st ke
-         KEither   k1 k2 -> mapM_ (registerKind st) [k1, k2]
          KArray    k1 k2 -> mapM_ (registerKind st) [k1, k2]
 
 -- | Register a new label with the system, making sure they are unique and have no '|'s in them
@@ -1662,6 +1660,8 @@
 -- when used for @quickCheck@ or 'Data.SBV.Tools.GenTest.genTest' purposes.
 svMkSymVarGen :: Bool -> VarContext -> Kind -> Maybe String -> State -> IO SVal
 svMkSymVarGen isTracker varContext k mbNm st = do
+        registerKind st k
+
         rm <- readIORef (runMode st)
 
         let varInfo = case mbNm of
@@ -1675,10 +1675,6 @@
                                              , "*** In mode: " ++ show rm
                                              ]
 
-            noUI cont
-              | isUserSort k  = disallow "User defined sorts"
-              | True          = cont
-
             (isQueryVar, mbQ) = case varContext of
                                   NonQueryVar mq -> (False, mq)
                                   QueryVar       -> (True,  Just EX)
@@ -1687,8 +1683,7 @@
                        let nm = fromMaybe (T.unpack internalName) mbNm
                        introduceUserName st (isQueryVar, isTracker) nm k q sv
 
-            mkC cv = do registerKind st k
-                        modifyState st rCInfo ((fromMaybe "_" mbNm, cv):) (return ())
+            mkC cv = do modifyState st rCInfo ((fromMaybe "_" mbNm, cv):) (return ())
                         return $ SVal k (Left cv)
 
         case (mbQ, rm) of
@@ -1696,13 +1691,13 @@
           (Nothing, SMTMode _ _ isSAT _) -> mkS (if isSAT then EX else ALL)
 
           (Just EX, CodeGen{})           -> disallow "Existentially quantified variables"
-          (_      , CodeGen)             -> noUI $ mkS ALL  -- code generation, pick universal
+          (_      , CodeGen)             -> mkS ALL  -- code generation, pick universal
 
           (Just EX, Concrete Nothing)    -> disallow "Existentially quantified variables"
-          (_      , Concrete Nothing)    -> noUI (randomCV k >>= mkC)
+          (_      , Concrete Nothing)    -> randomCV k >>= mkC
 
           (Just EX, LambdaGen{})         -> disallow "Existentially quantified variables"
-          (_,       LambdaGen{})         -> noUI $ mkS ALL
+          (_,       LambdaGen{})         -> mkS ALL
 
           -- Model validation:
           (_      , Concrete (Just (_isSat, env))) -> do
@@ -1714,36 +1709,32 @@
                                                            , "*** " ++ conc
                                                            ]
 
-                            cant   = "Validation engine is not capable of handling this case. Failed to validate."
                             report = "Please report this as a bug in SBV!"
 
-                        case () of
-                          () | isUserSort k -> bad ("Cannot validate models in the presence of user defined kinds, saw: "             ++ show k) cant
-
-                          _  -> do (NamedSymVar sv internalName) <- newSV st k
+                        (NamedSymVar sv internalName) <- newSV st k
 
-                                   let nm = fromMaybe (T.unpack internalName) mbNm
-                                       nsv = toNamedSV' sv nm
+                        let nm = fromMaybe (T.unpack internalName) mbNm
+                            nsv = toNamedSV' sv nm
 
-                                       -- Ignore the context equivalence check here. When validating, we are in a different
-                                       -- context; so they won't match
-                                       same (NamedSymVar (SV _ (NodeId (_, ll1, li1))) _)
-                                            (NamedSymVar (SV _ (NodeId (_, ll2, li2))) _) = (ll1, li1) == (ll2, li2)
+                            -- Ignore the context equivalence check here. When validating, we are in a different
+                            -- context; so they won't match
+                            same (NamedSymVar (SV _ (NodeId (_, ll1, li1))) _)
+                                 (NamedSymVar (SV _ (NodeId (_, ll2, li2))) _) = (ll1, li1) == (ll2, li2)
 
-                                       cv = case [v | (nsv', v) <- env, nsv `same` nsv'] of
-                                              []    -> if isTracker
-                                                       then  -- The sole purpose of a tracker variable is to send the optimization
-                                                             -- directive to the solver, so we can name "expressions" that are minimized
-                                                             -- or maximized. There will be no constraints on these when we are doing
-                                                             -- the validation; in fact they will not even be used anywhere during a
-                                                             -- validation run. So, simply push a zero value that inhabits all metrics.
-                                                             mkConstCV k (0::Integer)
-                                                       else bad ("Cannot locate variable: " ++ show (nsv, k)) report
-                                              [c]  -> c
-                                              r    -> bad (   "Found multiple matching values for variable: " ++ show nsv
-                                                           ++ "\n*** " ++ show r) report
+                            cv = case [v | (nsv', v) <- env, nsv `same` nsv'] of
+                                   []    -> if isTracker
+                                            then  -- The sole purpose of a tracker variable is to send the optimization
+                                                  -- directive to the solver, so we can name "expressions" that are minimized
+                                                  -- or maximized. There will be no constraints on these when we are doing
+                                                  -- the validation; in fact they will not even be used anywhere during a
+                                                  -- validation run. So, simply push a zero value that inhabits all metrics.
+                                                  mkConstCV k (0::Integer)
+                                            else bad ("Cannot locate variable: " ++ show (nsv, k)) report
+                                   [c]  -> c
+                                   r    -> bad (   "Found multiple matching values for variable: " ++ show nsv
+                                                ++ "\n*** " ++ show r) report
 
-                                   mkC cv
+                        mkC cv
 
 -- | Introduce a new user name. We simply append a suffix if we have seen this variable before.
 introduceUserName :: State -> (Bool, Bool) -> String -> Kind -> Quantifier -> SV -> IO SVal
@@ -1876,13 +1867,12 @@
    runSymbolicInState st comp
 
 -- | Catch the catastrophic case of context mismatch
+-- NB. We're not printing _ctx1/_ctx2 here (hence the underscored variables).
+-- The reason is that they can get different values; causing test-suite failures with no helpful info.
 contextMismatchError :: SBVContext -> SBVContext -> a
-contextMismatchError ctx1 ctx2 = error $ unlines [
+contextMismatchError _ctx1 _ctx2 = error $ unlines [
                                "Data.SBV: Mismatched contexts detected."
                              , "***"
-                             , "***   Current context: " ++ show ctx1
-                             , "***   Mixed with     : " ++ show ctx2
-                             , "***"
                              , "*** This happens if you call a proof-function (prove/sat/runSMT/isSatisfiable) etc."
                              , "*** while another one is in execution, or use results from one such call in another."
                              , "*** Please avoid such nested calls, all interactions should be from the same context."
@@ -2159,26 +2149,26 @@
 
 -- | Translation tricks needed for specific capabilities afforded by each solver
 data SolverCapabilities = SolverCapabilities {
-         supportsQuantifiers        :: Bool           -- ^ Supports SMT-Lib2 style quantifiers?
-       , supportsDefineFun          :: Bool           -- ^ Supports define-fun construct?
-       , supportsDistinct           :: Bool           -- ^ Supports calls to distinct?
-       , supportsBitVectors         :: Bool           -- ^ Supports bit-vectors?
-       , supportsUninterpretedSorts :: Bool           -- ^ Supports SMT-Lib2 style uninterpreted-sorts
-       , supportsUnboundedInts      :: Bool           -- ^ Supports unbounded integers?
-       , supportsReals              :: Bool           -- ^ Supports reals?
-       , supportsApproxReals        :: Bool           -- ^ Supports printing of approximations of reals?
-       , supportsDeltaSat           :: Maybe String   -- ^ Supports delta-satisfiability? (With given precision query)
-       , supportsIEEE754            :: Bool           -- ^ Supports floating point numbers?
-       , supportsSets               :: Bool           -- ^ Supports set operations?
-       , supportsOptimization       :: Bool           -- ^ Supports optimization routines?
-       , supportsPseudoBooleans     :: Bool           -- ^ Supports pseudo-boolean operations?
-       , supportsCustomQueries      :: Bool           -- ^ Supports interactive queries per SMT-Lib?
-       , supportsGlobalDecls        :: Bool           -- ^ Supports global declarations? (Needed for push-pop.)
-       , supportsDataTypes          :: Bool           -- ^ Supports datatypes?
-       , supportsLambdas            :: Bool           -- ^ Does it support lambdas?
-       , supportsSpecialRels        :: Bool           -- ^ Does it support special relations (orders, transitive closure etc.)
-       , supportsDirectAccessors    :: Bool           -- ^ Supports data-type accessors without full ascription?
-       , supportsFlattenedModels    :: Maybe [String] -- ^ Supports flattened model output? (With given config lines.)
+         supportsQuantifiers     :: Bool           -- ^ Supports SMT-Lib2 style quantifiers?
+       , supportsDefineFun       :: Bool           -- ^ Supports define-fun construct?
+       , supportsDistinct        :: Bool           -- ^ Supports calls to distinct?
+       , supportsBitVectors      :: Bool           -- ^ Supports bit-vectors?
+       , supportsADTs            :: Bool           -- ^ Supports SMT-Lib2 style uninterpreted-sorts and ADTs
+       , supportsUnboundedInts   :: Bool           -- ^ Supports unbounded integers?
+       , supportsReals           :: Bool           -- ^ Supports reals?
+       , supportsApproxReals     :: Bool           -- ^ Supports printing of approximations of reals?
+       , supportsDeltaSat        :: Maybe String   -- ^ Supports delta-satisfiability? (With given precision query)
+       , supportsIEEE754         :: Bool           -- ^ Supports floating point numbers?
+       , supportsSets            :: Bool           -- ^ Supports set operations?
+       , supportsOptimization    :: Bool           -- ^ Supports optimization routines?
+       , supportsPseudoBooleans  :: Bool           -- ^ Supports pseudo-boolean operations?
+       , supportsCustomQueries   :: Bool           -- ^ Supports interactive queries per SMT-Lib?
+       , supportsGlobalDecls     :: Bool           -- ^ Supports global declarations? (Needed for push-pop.)
+       , supportsDataTypes       :: Bool           -- ^ Supports datatypes?
+       , supportsLambdas         :: Bool           -- ^ Does it support lambdas?
+       , supportsSpecialRels     :: Bool           -- ^ Does it support special relations (orders, transitive closure etc.)
+       , supportsDirectTesters   :: Bool           -- ^ Supports data-type testers without full ascription?
+       , supportsFlattenedModels :: Maybe [String] -- ^ Supports flattened model output? (With given config lines.)
        }
 
 -- | Solver configuration. See also 'Data.SBV.z3', 'Data.SBV.yices', 'Data.SBV.cvc4', 'Data.SBV.boolector', 'Data.SBV.mathSAT', etc.
diff --git a/Data/SBV/Either.hs b/Data/SBV/Either.hs
--- a/Data/SBV/Either.hs
+++ b/Data/SBV/Either.hs
@@ -11,15 +11,17 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE CPP                 #-}
-{-# LANGUAGE Rank2Types          #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
 {-# LANGUAGE TypeApplications    #-}
 
-{-# OPTIONS_GHC -Wall -Werror #-}
+{-# OPTIONS_GHC -Wall -Werror -fno-warn-orphans #-}
 
 module Data.SBV.Either (
     -- * Constructing sums
-      sLeft, sRight, liftEither
+      sLeft, sRight, liftEither, SEither, sEither, sEither_, sEithers
     -- * Destructing sums
     , either
     -- * Mapping functions
@@ -31,10 +33,9 @@
 import           Prelude hiding (either)
 import qualified Prelude
 
-import Data.Proxy (Proxy(Proxy))
-
+import Data.SBV.Client
 import Data.SBV.Core.Data
-import Data.SBV.Core.Model () -- instances only
+import Data.SBV.Core.Model (ite, OrdSymbolic(..))
 
 #ifdef DOCTEST
 -- $setup
@@ -42,64 +43,40 @@
 -- >>> import Data.SBV
 #endif
 
--- | Construct an @SEither a b@ from an @SBV a@
+-- | Make 'Either' symbolic.
 --
 -- >>> sLeft 3 :: SEither Integer Bool
--- Left 3 :: SEither Integer Bool
-sLeft :: forall a b. (SymVal a, SymVal b) => SBV a -> SEither a b
-sLeft sa
-  | Just a <- unliteral sa
-  = literal (Left a)
-  | True
-  = SBV $ SVal k $ Right $ cache res
-  where k1 = kindOf (Proxy @a)
-        k2 = kindOf (Proxy @b)
-        k  = KEither k1 k2
-
-        res st = do asv <- sbvToSV st sa
-                    newExpr st k $ SBVApp (EitherConstructor k1 k2 False) [asv]
-
--- | Return 'sTrue' if the given symbolic value is 'Left', 'sFalse' otherwise
---
+-- Left 3 :: Either Integer Bool
 -- >>> isLeft (sLeft 3 :: SEither Integer Bool)
 -- True
 -- >>> isLeft (sRight sTrue :: SEither Integer Bool)
 -- False
-isLeft :: (SymVal a, SymVal b) => SEither a b -> SBV Bool
-isLeft = either (const sTrue) (const sFalse)
-
--- | Construct an @SEither a b@ from an @SBV b@
---
 -- >>> sRight sFalse :: SEither Integer Bool
--- Right False :: SEither Integer Bool
-sRight :: forall a b. (SymVal a, SymVal b) => SBV b -> SEither a b
-sRight sb
-  | Just b <- unliteral sb
-  = literal (Right b)
-  | True
-  = SBV $ SVal k $ Right $ cache res
-  where k1 = kindOf (Proxy @a)
-        k2 = kindOf (Proxy @b)
-        k  = KEither k1 k2
-
-        res st = do bsv <- sbvToSV st sb
-                    newExpr st k $ SBVApp (EitherConstructor k1 k2 True) [bsv]
-
--- | Return 'sTrue' if the given symbolic value is 'Right', 'sFalse' otherwise
---
+-- Right False :: Either Integer Bool
 -- >>> isRight (sLeft 3 :: SEither Integer Bool)
 -- False
 -- >>> isRight (sRight sTrue :: SEither Integer Bool)
 -- True
-isRight :: (SymVal a, SymVal b) => SEither a b -> SBV Bool
-isRight = either (const sFalse) (const sTrue)
+mkSymbolic [''Either]
 
+-- | Declare a symbolic maybe.
+sEither :: (SymVal a, SymVal b) => String -> Symbolic (SEither a b)
+sEither = free
+
+-- | Declare a symbolic maybe, unnamed.
+sEither_ :: (SymVal a, SymVal b) => Symbolic (SEither a b)
+sEither_ = free_
+
+-- | Declare a list of symbolic maybes.
+sEithers :: (SymVal a, SymVal b) => [String] -> Symbolic [SEither a b]
+sEithers = symbolics
+
 -- | Construct an @SEither a b@ from an @Either (SBV a) (SBV b)@
 --
 -- >>> liftEither (Left 3 :: Either SInteger SBool)
--- Left 3 :: SEither Integer Bool
+-- Left 3 :: Either Integer Bool
 -- >>> liftEither (Right sTrue :: Either SInteger SBool)
--- Right True :: SEither Integer Bool
+-- Right True :: Either Integer Bool
 liftEither :: (SymVal a, SymVal b) => Either (SBV a) (SBV b) -> SEither a b
 liftEither = Prelude.either sLeft sRight
 
@@ -121,31 +98,7 @@
        -> (SBV b -> SBV c)
        -> SEither a b
        -> SBV c
-either brA brB sab
-  | Just (Left  a) <- unliteral sab
-  = brA $ literal a
-  | Just (Right b) <- unliteral sab
-  = brB $ literal b
-  | True
-  = SBV $ SVal kc $ Right $ cache res
-  where ka = kindOf (Proxy @a)
-        kb = kindOf (Proxy @b)
-        kc = kindOf (Proxy @c)
-
-        res st = do abv <- sbvToSV st sab
-
-                    let leftVal  = SBV $ SVal ka $ Right $ cache $ \_ -> newExpr st ka $ SBVApp (EitherAccess False) [abv]
-                        rightVal = SBV $ SVal kb $ Right $ cache $ \_ -> newExpr st kb $ SBVApp (EitherAccess True)  [abv]
-
-                        leftRes  = brA leftVal
-                        rightRes = brB rightVal
-
-                    br1 <- sbvToSV st leftRes
-                    br2 <- sbvToSV st rightRes
-
-                    --  Which branch are we in? Return the appropriate value:
-                    onLeft <- newExpr st KBool $ SBVApp (EitherIs ka kb False) [abv]
-                    newExpr st kc $ SBVApp Ite [onLeft, br1, br2]
+either brA brB sab = ite (isLeft sab) (brA (fromLeft sab)) (brB (fromRight sab))
 
 -- | Map over both sides of a symbolic 'Either' at the same time
 --
@@ -197,14 +150,7 @@
 -- is unspecified, thus the SMT solver picks whatever satisfies the
 -- constraints, if there is one.
 fromLeft :: forall a b. (SymVal a, SymVal b) => SEither a b -> SBV a
-fromLeft sab
-  | Just (Left a) <- unliteral sab
-  = literal a
-  | True
-  = SBV $ SVal ka $ Right $ cache res
-  where ka      = kindOf (Proxy @a)
-        res st = do ms <- sbvToSV st sab
-                    newExpr st ka (SBVApp (EitherAccess False) [ms])
+fromLeft = getLeft_1
 
 -- | Return the value from the right component. The behavior is undefined if
 -- passed a left value, i.e., it can return any value.
@@ -221,13 +167,12 @@
 -- is unspecified, thus the SMT solver picks whatever satisfies the
 -- constraints, if there is one.
 fromRight :: forall a b. (SymVal a, SymVal b) => SEither a b -> SBV b
-fromRight sab
-  | Just (Right b) <- unliteral sab
-  = literal b
-  | True
-  = SBV $ SVal kb $ Right $ cache res
-  where kb      = kindOf (Proxy @b)
-        res st = do ms <- sbvToSV st sab
-                    newExpr st kb (SBVApp (EitherAccess True) [ms])
+fromRight = getRight_1
+
+-- | Custom 'OrdSymbolic' instance over 'SEither'.
+instance (OrdSymbolic (SBV a), OrdSymbolic (SBV b), SymVal a, SymVal b) => OrdSymbolic (SBV (Either a b)) where
+  eab .< ecd = either (\a -> either (a .<)         (const sTrue) ecd)
+                      (\b -> either (const sFalse) (b .<)        ecd)
+                      eab
 
 {- HLint ignore module "Reduce duplication" -}
diff --git a/Data/SBV/Internals.hs b/Data/SBV/Internals.hs
--- a/Data/SBV/Internals.hs
+++ b/Data/SBV/Internals.hs
@@ -68,8 +68,11 @@
   -- * Generalized floats
   , svFloatingPointAsSWord
 
-  -- * lambdas and axioms
+  -- * Lambdas and axioms
   , lambda, lambdaStr, constraint, constraintStr, Lambda(..), Constraint(..), LambdaScope(..)
+
+  -- * TP induction extras
+  , HasInductionSchema(..), internalAxiom
   ) where
 
 import Control.Monad.IO.Class (MonadIO)
@@ -102,6 +105,8 @@
 import qualified Data.SBV.Control.Utils as Query
 
 import Data.SBV.Lambda
+
+import Data.SBV.TP.Kernel
 
 #ifdef DOCTEST
 --- $setup
diff --git a/Data/SBV/Lambda.hs b/Data/SBV/Lambda.hs
--- a/Data/SBV/Lambda.hs
+++ b/Data/SBV/Lambda.hs
@@ -10,13 +10,11 @@
 -- higher-order function support in SBV.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE FlexibleContexts      #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE NamedFieldPuns        #-}
-{-# LANGUAGE ScopedTypeVariables   #-}
-{-# LANGUAGE TupleSections         #-}
-{-# LANGUAGE UndecidableInstances  #-}
+{-# LANGUAGE FlexibleContexts     #-}
+{-# LANGUAGE FlexibleInstances    #-}
+{-# LANGUAGE NamedFieldPuns       #-}
+{-# LANGUAGE TupleSections        #-}
+{-# LANGUAGE UndecidableInstances #-}
 
 {-# OPTIONS_GHC -Wall -Werror -fno-warn-orphans #-}
 
diff --git a/Data/SBV/List.hs b/Data/SBV/List.hs
--- a/Data/SBV/List.hs
+++ b/Data/SBV/List.hs
@@ -22,7 +22,6 @@
 {-# LANGUAGE FunctionalDependencies #-}
 {-# LANGUAGE NamedFieldPuns         #-}
 {-# LANGUAGE OverloadedLists        #-}
-{-# LANGUAGE Rank2Types             #-}
 {-# LANGUAGE ScopedTypeVariables    #-}
 {-# LANGUAGE TypeApplications       #-}
 {-# LANGUAGE TypeFamilies           #-}
diff --git a/Data/SBV/Maybe.hs b/Data/SBV/Maybe.hs
--- a/Data/SBV/Maybe.hs
+++ b/Data/SBV/Maybe.hs
@@ -13,15 +13,16 @@
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE FlexibleInstances   #-}
-{-# LANGUAGE Rank2Types          #-}
+{-# LANGUAGE QuasiQuotes         #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
 {-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror -fno-warn-orphans #-}
 
 module Data.SBV.Maybe (
   -- * Constructing optional values
-    sJust, sNothing, liftMaybe
+    sJust, sNothing, liftMaybe, SMaybe, sMaybe, sMaybe_, sMaybes
   -- * Destructing optionals
   , maybe
   -- * Mapping functions
@@ -33,10 +34,9 @@
 import           Prelude hiding (maybe, map)
 import qualified Prelude
 
-import Data.Proxy (Proxy(Proxy))
-
+import Data.SBV.Client
 import Data.SBV.Core.Data
-import Data.SBV.Core.Model (ite)
+import Data.SBV.Core.Model (ite, OrdSymbolic(..))
 
 #ifdef DOCTEST
 -- $setup
@@ -44,56 +44,43 @@
 -- >>> import Data.SBV
 #endif
 
--- | The symbolic 'Nothing'.
+-- | Make 'Maybe' symbolic.
 --
 -- >>> sNothing :: SMaybe Integer
--- Nothing :: SMaybe Integer
-sNothing :: forall a. SymVal a => SMaybe a
-sNothing = SBV $ SVal k $ Left $ CV k $ CMaybe Nothing
-  where k = kindOf (Proxy @(Maybe a))
-
--- | Check if the symbolic value is nothing.
---
+-- Nothing :: Maybe Integer
 -- >>> isNothing (sNothing :: SMaybe Integer)
 -- True
 -- >>> isNothing (sJust (literal "nope"))
 -- False
-isNothing :: SymVal a => SMaybe a -> SBool
-isNothing = maybe sTrue (const sFalse)
-
--- | Construct an @SMaybe a@ from an @SBV a@.
---
 -- >>> sJust (3 :: SInteger)
--- Just 3 :: SMaybe Integer
-sJust :: forall a. SymVal a => SBV a -> SMaybe a
-sJust sa
-  | Just a <- unliteral sa
-  = literal (Just a)
-  | True
-  = SBV $ SVal kMaybe $ Right $ cache res
-  where ka     = kindOf (Proxy @a)
-        kMaybe = KMaybe ka
-
-        res st = do asv <- sbvToSV st sa
-                    newExpr st kMaybe $ SBVApp (MaybeConstructor ka True) [asv]
-
--- | Check if the symbolic value is not nothing.
---
+-- Just 3 :: Maybe Integer
 -- >>> isJust (sNothing :: SMaybe Integer)
 -- False
 -- >>> isJust (sJust (literal "yep"))
 -- True
 -- >>> prove $ \x -> isJust (sJust (x :: SInteger))
 -- Q.E.D.
-isJust :: SymVal a => SMaybe a -> SBool
-isJust = maybe sFalse (const sTrue)
+mkSymbolic [''Maybe]
 
+-- | Declare a symbolic maybe.
+sMaybe :: SymVal a => String -> Symbolic (SMaybe a)
+sMaybe = free
+
+-- | Declare a symbolic maybe, unnamed.
+sMaybe_ :: SymVal a => Symbolic (SMaybe a)
+sMaybe_ = free_
+
+-- | Declare a list of symbolic maybes.
+sMaybes :: SymVal a => [String] -> Symbolic [SMaybe a]
+sMaybes = symbolics
+
 -- | Return the value of an optional value. The default is returned if Nothing. Compare to 'fromJust'.
 --
 -- >>> fromMaybe 2 (sNothing :: SMaybe Integer)
 -- 2 :: SInteger
--- >>> fromMaybe 2 (sJust 5 :: SMaybe Integer)
--- 5 :: SInteger
+-- >>> sat $ \x -> fromMaybe 2 (sJust 5 :: SMaybe Integer) .== x
+-- Satisfiable. Model:
+--   s0 = 5 :: Integer
 -- >>> prove $ \x -> fromMaybe x (sNothing :: SMaybe Integer) .== x
 -- Q.E.D.
 -- >>> prove $ \x -> fromMaybe (x+1) (sJust x :: SMaybe Integer) .== x
@@ -104,8 +91,9 @@
 -- | Return the value of an optional value. The behavior is undefined if
 -- passed Nothing, i.e., it can return any value. Compare to 'fromMaybe'.
 --
--- >>> fromJust (sJust (literal 'a'))
--- 'a' :: SChar
+-- >>> sat $ \x -> fromJust (sJust (literal 'a')) .== x
+-- Satisfiable. Model:
+--   s0 = 'a' :: Char
 -- >>> prove $ \x -> fromJust (sJust x) .== (x :: SChar)
 -- Q.E.D.
 -- >>> sat $ \x -> x .== (fromJust sNothing :: SChar)
@@ -116,21 +104,14 @@
 -- is unspecified, thus the SMT solver picks whatever satisfies the
 -- constraints, if there is one.
 fromJust :: forall a. SymVal a => SMaybe a -> SBV a
-fromJust ma
-  | Just (Just x) <- unliteral ma
-  = literal x
-  | True
-  = SBV $ SVal ka $ Right $ cache res
-  where ka     = kindOf (Proxy @a)
-        res st = do ms <- sbvToSV st ma
-                    newExpr st ka (SBVApp MaybeAccess [ms])
+fromJust = getJust_1
 
 -- | Construct an @SMaybe a@ from a @Maybe (SBV a)@.
 --
 -- >>> liftMaybe (Just (3 :: SInteger))
--- Just 3 :: SMaybe Integer
+-- Just 3 :: Maybe Integer
 -- >>> liftMaybe (Nothing :: Maybe SInteger)
--- Nothing :: SMaybe Integer
+-- Nothing :: Maybe Integer
 liftMaybe :: SymVal a => Maybe (SBV a) -> SMaybe a
 liftMaybe = Prelude.maybe (literal Nothing) sJust
 
@@ -158,10 +139,12 @@
 -- | Case analysis for symbolic 'Maybe's. If the value 'isNothing', return the
 -- default value; if it 'isJust', apply the function.
 --
--- >>> maybe 0 (`sMod` 2) (sJust (3 :: SInteger))
--- 1 :: SInteger
--- >>> maybe 0 (`sMod` 2) (sNothing :: SMaybe Integer)
--- 0 :: SInteger
+-- >>> sat $ \x -> x .== maybe 0 (`sMod` 2) (sJust (3 :: SInteger))
+-- Satisfiable. Model:
+--   s0 = 1 :: Integer
+-- >>> sat $ \x -> x .== maybe 0 (`sMod` 2) (sNothing :: SMaybe Integer)
+-- Satisfiable. Model:
+--   s0 = 0 :: Integer
 -- >>> let f = uninterpret "f" :: SInteger -> SBool
 -- >>> prove $ \x d -> maybe d f (sJust x) .== f x
 -- Q.E.D.
@@ -172,28 +155,7 @@
       -> (SBV a -> SBV b)
       -> SMaybe a
       -> SBV b
-maybe brNothing brJust ma
-  | Just (Just a) <- unliteral ma
-  = brJust (literal a)
-  | Just Nothing  <- unliteral ma
-  = brNothing
-  | True
-  = SBV $ SVal kb $ Right $ cache res
-  where ka = kindOf (Proxy @a)
-        kb = kindOf (Proxy @b)
-
-        res st = do mav <- sbvToSV st ma
-
-                    let justVal = SBV $ SVal ka $ Right $ cache $ \_ -> newExpr st ka $ SBVApp MaybeAccess [mav]
-
-                        justRes = brJust justVal
-
-                    br1 <- sbvToSV st brNothing
-                    br2 <- sbvToSV st justRes
-
-                    -- Do we have a value?
-                    noVal <- newExpr st KBool $ SBVApp (MaybeIs ka False) [mav]
-                    newExpr st kb $ SBVApp Ite [noVal, br1, br2]
+maybe brNothing brJust ma = ite (isNothing ma) brNothing (brJust (fromJust ma))
 
 -- | Custom 'Num' instance over 'SMaybe'
 instance (Ord a, SymVal a, Num a, Num (SBV a)) => Num (SBV (Maybe a)) where
@@ -203,3 +165,7 @@
   abs         = map  abs
   signum      = map  signum
   fromInteger = sJust . fromInteger
+
+-- | Custom 'OrdSymbolic' instance over 'SMaybe'.
+instance (OrdSymbolic (SBV a), SymVal a) => OrdSymbolic (SBV (Maybe a)) where
+  ma .< mb = maybe sFalse (\b -> maybe sTrue (.< b) ma) mb
diff --git a/Data/SBV/Provers/ABC.hs b/Data/SBV/Provers/ABC.hs
--- a/Data/SBV/Provers/ABC.hs
+++ b/Data/SBV/Provers/ABC.hs
@@ -29,25 +29,25 @@
          , options      = const ["-S", "%blast; &sweep -C 5000; &syn4; &cec -s -m -C 2000"]
          , engine       = standardEngine "SBV_ABC" "SBV_ABC_OPTIONS"
          , capabilities = SolverCapabilities {
-                                supportsQuantifiers        = False
-                              , supportsDefineFun          = True
-                              , supportsDistinct           = True
-                              , supportsBitVectors         = True
-                              , supportsUninterpretedSorts = False
-                              , supportsUnboundedInts      = False
-                              , supportsReals              = False
-                              , supportsApproxReals        = False
-                              , supportsDeltaSat           = Nothing
-                              , supportsIEEE754            = False
-                              , supportsSets               = False
-                              , supportsOptimization       = False
-                              , supportsPseudoBooleans     = False
-                              , supportsCustomQueries      = False
-                              , supportsGlobalDecls        = False
-                              , supportsDataTypes          = False
-                              , supportsLambdas            = False
-                              , supportsSpecialRels        = False
-                              , supportsDirectAccessors    = False
-                              , supportsFlattenedModels    = Nothing
+                                supportsQuantifiers     = False
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = False
+                              , supportsUnboundedInts   = False
+                              , supportsReals           = False
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = False
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = False
+                              , supportsGlobalDecls     = False
+                              , supportsDataTypes       = False
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = False
+                              , supportsFlattenedModels = Nothing
                               }
          }
diff --git a/Data/SBV/Provers/Bitwuzla.hs b/Data/SBV/Provers/Bitwuzla.hs
--- a/Data/SBV/Provers/Bitwuzla.hs
+++ b/Data/SBV/Provers/Bitwuzla.hs
@@ -27,25 +27,25 @@
          , options      = const ["--produce-models"]
          , engine       = standardEngine "SBV_BITWUZLA" "SBV_BITWUZLA_OPTIONS"
          , capabilities = SolverCapabilities {
-                                supportsQuantifiers        = False
-                              , supportsDefineFun          = True
-                              , supportsDistinct           = True
-                              , supportsBitVectors         = True
-                              , supportsUninterpretedSorts = True
-                              , supportsUnboundedInts      = False
-                              , supportsReals              = False
-                              , supportsApproxReals        = False
-                              , supportsDeltaSat           = Nothing
-                              , supportsIEEE754            = True
-                              , supportsSets               = False
-                              , supportsOptimization       = False
-                              , supportsPseudoBooleans     = False
-                              , supportsCustomQueries      = True
-                              , supportsGlobalDecls        = True
-                              , supportsDataTypes          = False
-                              , supportsLambdas            = False
-                              , supportsSpecialRels        = False
-                              , supportsDirectAccessors    = False
-                              , supportsFlattenedModels    = Nothing
+                                supportsQuantifiers     = False
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = False
+                              , supportsReals           = False
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = True
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = False
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = False
+                              , supportsFlattenedModels = Nothing
                               }
          }
diff --git a/Data/SBV/Provers/Boolector.hs b/Data/SBV/Provers/Boolector.hs
--- a/Data/SBV/Provers/Boolector.hs
+++ b/Data/SBV/Provers/Boolector.hs
@@ -27,25 +27,25 @@
          , options      = const ["--smt2", "-m", "--output-format=smt2", "--no-exit-codes", "--incremental"]
          , engine       = standardEngine "SBV_BOOLECTOR" "SBV_BOOLECTOR_OPTIONS"
          , capabilities = SolverCapabilities {
-                                supportsQuantifiers        = False
-                              , supportsDefineFun          = True
-                              , supportsDistinct           = True
-                              , supportsBitVectors         = True
-                              , supportsUninterpretedSorts = False
-                              , supportsUnboundedInts      = False
-                              , supportsReals              = False
-                              , supportsApproxReals        = False
-                              , supportsDeltaSat           = Nothing
-                              , supportsIEEE754            = False
-                              , supportsSets               = False
-                              , supportsOptimization       = False
-                              , supportsPseudoBooleans     = False
-                              , supportsCustomQueries      = True
-                              , supportsGlobalDecls        = True
-                              , supportsDataTypes          = False
-                              , supportsLambdas            = False
-                              , supportsSpecialRels        = False
-                              , supportsDirectAccessors    = False
-                              , supportsFlattenedModels    = Nothing
+                                supportsQuantifiers     = False
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = False
+                              , supportsUnboundedInts   = False
+                              , supportsReals           = False
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = False
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = False
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = False
+                              , supportsFlattenedModels = Nothing
                               }
          }
diff --git a/Data/SBV/Provers/CVC4.hs b/Data/SBV/Provers/CVC4.hs
--- a/Data/SBV/Provers/CVC4.hs
+++ b/Data/SBV/Provers/CVC4.hs
@@ -9,8 +9,6 @@
 -- The connection to the CVC4 SMT solver
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
-
 {-# OPTIONS_GHC -Wall -Werror #-}
 
 module Data.SBV.Provers.CVC4(cvc4) where
@@ -31,26 +29,26 @@
          , options      = const ["--lang", "smt", "--incremental", "--interactive", "--no-interactive-prompt", "--model-witness-value"]
          , engine       = standardEngine "SBV_CVC4" "SBV_CVC4_OPTIONS"
          , capabilities = SolverCapabilities {
-                                supportsQuantifiers        = True
-                              , supportsDefineFun          = True
-                              , supportsDistinct           = True
-                              , supportsBitVectors         = True
-                              , supportsUninterpretedSorts = True
-                              , supportsUnboundedInts      = True
-                              , supportsReals              = True  -- Not quite the same capability as Z3; but works more or less..
-                              , supportsApproxReals        = False
-                              , supportsDeltaSat           = Nothing
-                              , supportsIEEE754            = True
-                              , supportsSets               = False
-                              , supportsOptimization       = False
-                              , supportsPseudoBooleans     = False
-                              , supportsCustomQueries      = True
-                              , supportsGlobalDecls        = True
-                              , supportsDataTypes          = True
-                              , supportsLambdas            = False
-                              , supportsSpecialRels        = False
-                              , supportsDirectAccessors    = True
-                              , supportsFlattenedModels    = Nothing
+                                supportsQuantifiers     = True
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True  -- Not quite the same capability as Z3; but works more or less..
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = True
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = True
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = True
+                              , supportsFlattenedModels = Nothing
                               }
          }
   where -- CVC4 wants all input on one line
diff --git a/Data/SBV/Provers/CVC5.hs b/Data/SBV/Provers/CVC5.hs
--- a/Data/SBV/Provers/CVC5.hs
+++ b/Data/SBV/Provers/CVC5.hs
@@ -9,8 +9,6 @@
 -- The connection to the CVC5 SMT solver
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
-
 {-# OPTIONS_GHC -Wall -Werror #-}
 
 module Data.SBV.Provers.CVC5(cvc5) where
@@ -31,26 +29,26 @@
          , options      = const ["--lang", "smt", "--incremental", "--nl-cov"]
          , engine       = standardEngine "SBV_CVC5" "SBV_CVC5_OPTIONS"
          , capabilities = SolverCapabilities {
-                                supportsQuantifiers        = True
-                              , supportsDefineFun          = True
-                              , supportsDistinct           = True
-                              , supportsBitVectors         = True
-                              , supportsUninterpretedSorts = True
-                              , supportsUnboundedInts      = True
-                              , supportsReals              = True  -- Not quite the same capability as Z3; but works more or less..
-                              , supportsApproxReals        = False
-                              , supportsDeltaSat           = Nothing
-                              , supportsIEEE754            = True
-                              , supportsSets               = False
-                              , supportsOptimization       = False
-                              , supportsPseudoBooleans     = False
-                              , supportsCustomQueries      = True
-                              , supportsGlobalDecls        = True
-                              , supportsDataTypes          = True
-                              , supportsLambdas            = True
-                              , supportsSpecialRels        = False
-                              , supportsDirectAccessors    = True
-                              , supportsFlattenedModels    = Nothing
+                                supportsQuantifiers     = True
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True  -- Not quite the same capability as Z3; but works more or less..
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = True
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = True
+                              , supportsLambdas         = True
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = True
+                              , supportsFlattenedModels = Nothing
                               }
          }
   where -- CVC5 wants all input on one line
diff --git a/Data/SBV/Provers/DReal.hs b/Data/SBV/Provers/DReal.hs
--- a/Data/SBV/Provers/DReal.hs
+++ b/Data/SBV/Provers/DReal.hs
@@ -9,8 +9,6 @@
 -- The connection to the dReal SMT solver
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
-
 {-# OPTIONS_GHC -Wall -Werror #-}
 
 module Data.SBV.Provers.DReal(dReal) where
@@ -31,26 +29,26 @@
          , options      = modConfig ["--in", "--format", "smt2"]
          , engine       = standardEngine "SBV_DREAL" "SBV_DREAL_OPTIONS"
          , capabilities = SolverCapabilities {
-                                supportsQuantifiers        = False
-                              , supportsDefineFun          = True
-                              , supportsDistinct           = False
-                              , supportsBitVectors         = False
-                              , supportsUninterpretedSorts = False
-                              , supportsUnboundedInts      = True
-                              , supportsReals              = True
-                              , supportsApproxReals        = False
-                              , supportsDeltaSat           = Just "(get-option :precision)"
-                              , supportsIEEE754            = False
-                              , supportsSets               = False
-                              , supportsOptimization       = False
-                              , supportsPseudoBooleans     = False
-                              , supportsCustomQueries      = False
-                              , supportsGlobalDecls        = False
-                              , supportsDataTypes          = False
-                              , supportsLambdas            = False
-                              , supportsSpecialRels        = False
-                              , supportsDirectAccessors    = False
-                              , supportsFlattenedModels    = Nothing
+                                supportsQuantifiers     = False
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = False
+                              , supportsBitVectors      = False
+                              , supportsADTs            = False
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Just "(get-option :precision)"
+                              , supportsIEEE754         = False
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = False
+                              , supportsGlobalDecls     = False
+                              , supportsDataTypes       = False
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = False
+                              , supportsFlattenedModels = Nothing
                               }
          }
   where -- If dsat precision is given, pass that as an argument
diff --git a/Data/SBV/Provers/MathSAT.hs b/Data/SBV/Provers/MathSAT.hs
--- a/Data/SBV/Provers/MathSAT.hs
+++ b/Data/SBV/Provers/MathSAT.hs
@@ -9,8 +9,6 @@
 -- The connection to the MathSAT SMT solver
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
-
 {-# OPTIONS_GHC -Wall -Werror #-}
 
 module Data.SBV.Provers.MathSAT(mathSAT) where
@@ -31,26 +29,26 @@
          , options      = modConfig ["-input=smt2", "-theory.fp.minmax_zero_mode=4"]
          , engine       = standardEngine "SBV_MATHSAT" "SBV_MATHSAT_OPTIONS"
          , capabilities = SolverCapabilities {
-                                supportsQuantifiers        = True
-                              , supportsDefineFun          = True
-                              , supportsDistinct           = True
-                              , supportsBitVectors         = True
-                              , supportsUninterpretedSorts = True
-                              , supportsUnboundedInts      = True
-                              , supportsReals              = True
-                              , supportsApproxReals        = False
-                              , supportsDeltaSat           = Nothing
-                              , supportsIEEE754            = True
-                              , supportsSets               = False
-                              , supportsOptimization       = False
-                              , supportsPseudoBooleans     = False
-                              , supportsCustomQueries      = True
-                              , supportsGlobalDecls        = True
-                              , supportsDataTypes          = True
-                              , supportsLambdas            = False
-                              , supportsSpecialRels        = False
-                              , supportsDirectAccessors    = True
-                              , supportsFlattenedModels    = Nothing
+                                supportsQuantifiers     = True
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = True
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = True
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = True
+                              , supportsFlattenedModels = Nothing
                               }
          }
 
diff --git a/Data/SBV/Provers/OpenSMT.hs b/Data/SBV/Provers/OpenSMT.hs
--- a/Data/SBV/Provers/OpenSMT.hs
+++ b/Data/SBV/Provers/OpenSMT.hs
@@ -27,26 +27,26 @@
          , options      = modConfig []
          , engine       = standardEngine "SBV_OpenSMT" "SBV_OpenSMT_OPTIONS"
          , capabilities = SolverCapabilities {
-                                supportsQuantifiers        = False
-                              , supportsDefineFun          = True
-                              , supportsDistinct           = True
-                              , supportsBitVectors         = False
-                              , supportsUninterpretedSorts = True
-                              , supportsUnboundedInts      = True
-                              , supportsReals              = True
-                              , supportsApproxReals        = False
-                              , supportsDeltaSat           = Nothing
-                              , supportsIEEE754            = False
-                              , supportsSets               = False
-                              , supportsOptimization       = False
-                              , supportsPseudoBooleans     = False
-                              , supportsCustomQueries      = True
-                              , supportsGlobalDecls        = True
-                              , supportsDataTypes          = False
-                              , supportsLambdas            = False
-                              , supportsSpecialRels        = False
-                              , supportsDirectAccessors    = False
-                              , supportsFlattenedModels    = Nothing
+                                supportsQuantifiers     = False
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = False
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = False
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = False
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = False
+                              , supportsFlattenedModels = Nothing
                               }
          }
 
diff --git a/Data/SBV/Provers/Prover.hs b/Data/SBV/Provers/Prover.hs
--- a/Data/SBV/Provers/Prover.hs
+++ b/Data/SBV/Provers/Prover.hs
@@ -9,7 +9,6 @@
 -- Provable abstraction and the connection to SMT solvers
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE CPP                   #-}
 {-# LANGUAGE ConstraintKinds       #-}
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE FlexibleInstances     #-}
@@ -17,7 +16,6 @@
 {-# LANGUAGE NamedFieldPuns        #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
 {-# LANGUAGE TupleSections         #-}
-{-# LANGUAGE UndecidableInstances  #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -29,7 +27,7 @@
        , SExecutable(..), isSafe
        , runSMT, runSMTWith
        , SatModel(..), Modelable(..), displayModels, extractModels
-       , getModelDictionaries, getModelValues, getModelUninterpretedValues
+       , getModelDictionaries, getModelValues
        , abc, boolector, bitwuzla, cvc4, cvc5, dReal, mathSAT, yices, z3, openSMT, defaultSMTCfg, defaultDeltaSMTCfg
        , proveWithAny, proveWithAll, proveConcurrentWithAny, proveConcurrentWithAll
        , satWithAny,   satWithAll,   satConcurrentWithAny,   satConcurrentWithAll
@@ -513,11 +511,13 @@
                                       why s = case s `lookup` S.toList (pgmAssignments (resAsgns result)) of
                                                 Nothing            -> Nothing
                                                 Just (SBVApp o as) -> case o of
-                                                                        Uninterpreted v  -> Just $ "The value depends on the uninterpreted constant " ++ show v ++ "."
                                                                         QuantifiedBool{} -> Just "The value depends on a quantified variable."
                                                                         IEEEFP FP_FMA    -> Just "Floating point FMA operation is not supported concretely."
                                                                         IEEEFP _         -> Just "Not all floating point operations are supported concretely."
                                                                         OverflowOp _     -> Just "Overflow-checking is not done concretely."
+                                                                        Uninterpreted v
+                                                                          | any isADT as -> Just "Models containing ADTs are currently only partially supported."
+                                                                          | True         -> Just $ "The value depends on the uninterpreted constant " ++ show v ++ "."
                                                                         _                -> listToMaybe $ mapMaybe why as
 
                            cstrs = S.toList $ resConstraints result
diff --git a/Data/SBV/Provers/Yices.hs b/Data/SBV/Provers/Yices.hs
--- a/Data/SBV/Provers/Yices.hs
+++ b/Data/SBV/Provers/Yices.hs
@@ -9,8 +9,6 @@
 -- The connection to the Yices SMT solver
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
-
 {-# OPTIONS_GHC -Wall -Werror #-}
 
 module Data.SBV.Provers.Yices(yices) where
@@ -29,25 +27,25 @@
          , options      = const ["--incremental"]
          , engine       = standardEngine "SBV_YICES" "SBV_YICES_OPTIONS"
          , capabilities = SolverCapabilities {
-                                supportsQuantifiers        = False
-                              , supportsDefineFun          = True
-                              , supportsDistinct           = True
-                              , supportsBitVectors         = True
-                              , supportsUninterpretedSorts = True
-                              , supportsUnboundedInts      = True
-                              , supportsReals              = True
-                              , supportsApproxReals        = False
-                              , supportsDeltaSat           = Nothing
-                              , supportsIEEE754            = False
-                              , supportsSets               = False
-                              , supportsOptimization       = False
-                              , supportsPseudoBooleans     = False
-                              , supportsCustomQueries      = True
-                              , supportsGlobalDecls        = True
-                              , supportsDataTypes          = False
-                              , supportsLambdas            = False
-                              , supportsSpecialRels        = False
-                              , supportsDirectAccessors    = False
-                              , supportsFlattenedModels    = Nothing
+                                supportsQuantifiers     = False
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = False
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = False
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = False
+                              , supportsFlattenedModels = Nothing
                               }
          }
diff --git a/Data/SBV/Provers/Z3.hs b/Data/SBV/Provers/Z3.hs
--- a/Data/SBV/Provers/Z3.hs
+++ b/Data/SBV/Provers/Z3.hs
@@ -9,8 +9,6 @@
 -- The connection to the Z3 SMT solver
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
-
 {-# OPTIONS_GHC -Wall -Werror #-}
 
 module Data.SBV.Provers.Z3(z3) where
@@ -29,29 +27,29 @@
          , options      = modConfig ["-nw", "-in", "-smt2"]
          , engine       = standardEngine "SBV_Z3" "SBV_Z3_OPTIONS"
          , capabilities = SolverCapabilities {
-                                supportsQuantifiers        = True
-                              , supportsDefineFun          = True
-                              , supportsDistinct           = True
-                              , supportsBitVectors         = True
-                              , supportsUninterpretedSorts = True
-                              , supportsUnboundedInts      = True
-                              , supportsReals              = True
-                              , supportsApproxReals        = True
-                              , supportsDeltaSat           = Nothing
-                              , supportsIEEE754            = True
-                              , supportsSets               = True
-                              , supportsOptimization       = True
-                              , supportsPseudoBooleans     = True
-                              , supportsCustomQueries      = True
-                              , supportsGlobalDecls        = True
-                              , supportsDataTypes          = True
-                              , supportsLambdas            = True
-                              , supportsSpecialRels        = True
-                              , supportsDirectAccessors    = False -- Needs ascriptions. (See the CVC4 version of this)
-                              , supportsFlattenedModels    = Just [ "(set-option :pp.max_depth      4294967295)"
-                                                                  , "(set-option :pp.min_alias_size 4294967295)"
-                                                                  , "(set-option :model.inline_def  true      )"
-                                                                  ]
+                                supportsQuantifiers     = True
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True
+                              , supportsApproxReals     = True
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = True
+                              , supportsSets            = True
+                              , supportsOptimization    = True
+                              , supportsPseudoBooleans  = True
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = True
+                              , supportsLambdas         = True
+                              , supportsSpecialRels     = True
+                              , supportsDirectTesters   = False -- Needs ascriptions. (See the CVC4 version of this)
+                              , supportsFlattenedModels = Just [ "(set-option :pp.max_depth      4294967295)"
+                                                               , "(set-option :pp.min_alias_size 4294967295)"
+                                                               , "(set-option :model.inline_def  true      )"
+                                                               ]
                               }
          }
 
diff --git a/Data/SBV/RegExp.hs b/Data/SBV/RegExp.hs
--- a/Data/SBV/RegExp.hs
+++ b/Data/SBV/RegExp.hs
@@ -17,7 +17,6 @@
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE OverloadedStrings   #-}
-{-# LANGUAGE Rank2Types          #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications    #-}
 
diff --git a/Data/SBV/SCase.hs b/Data/SBV/SCase.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/SCase.hs
@@ -0,0 +1,476 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.SCase
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Add support for symbolic case expressions. Constructed with the help of ChatGPT,
+-- which was remarkably good at giving me the basic structure.
+--
+-- Provides a quasiquoter  `[sCase|Expr expr of ... |]` for symbolic cases
+-- where @Expr@ is the underlying type.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE LambdaCase            #-}
+{-# LANGUAGE TemplateHaskellQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.SCase (sCase) where
+
+import Language.Haskell.TH
+import Language.Haskell.TH.Quote
+import qualified Language.Haskell.Meta.Parse as Meta
+
+import qualified Language.Haskell.Exts as E
+
+import Control.Monad (unless, when, zipWithM)
+
+import Data.SBV.Client (getConstructors)
+import Data.SBV.Core.Model (ite, sym)
+import Data.SBV.Core.Data  (sTrue, (.&&))
+
+import Data.Char  (isSpace, isDigit)
+import Data.List  (intercalate)
+import Data.Maybe (isJust, fromMaybe)
+
+import Prelude hiding (fail)
+import qualified Prelude as P(fail)
+
+import Data.Generics
+import qualified Data.Set as Set
+import Data.Set (Set)
+
+import System.FilePath
+
+-- | TH parse trees don't have location. Let's have a simple mechanism to keep track of them for our use case
+data Offset = Unknown | OffBy Int Int Int
+ deriving Show
+
+-- | Better fail method, keeping track of offsets
+fail :: Offset -> String -> Q a
+fail Unknown     s = P.fail s
+fail off@OffBy{} s = do loc <- location
+                        P.fail (fmtLoc loc off ++ ": " ++  s)
+
+-- | Format a given location by the offset
+fmtLoc :: Loc -> Offset -> String
+fmtLoc loc@Loc{loc_start = (sl, _)} off = takeFileName (loc_filename newLoc) ++ ":" ++ sh (loc_start newLoc) (loc_end newLoc)
+  where sh ab@(a, b) cd@(c, d) | a == c = show a ++ ":" ++ show b ++ if b == d then "" else '-' : show d
+                               | True   = show ab ++ "-" ++ show cd
+
+        newLoc = case off of
+                   Unknown       -> loc
+                   OffBy lo co w -> loc {loc_start = (sl + lo, co + 1), loc_end = (sl + lo, co + w)}
+
+-- | What kind of case-match are we given. In each case, the last maybe exp is the possible guard.
+data Case = CMatch Offset          -- regular match
+                   Name            -- name of the constructor
+                   (Maybe [Pat])   -- [a, b, c] in C a b c. Or Nothing if C{}
+                   (Maybe Exp)     -- guard
+                   Exp             -- rhs
+                   (Set Name)      -- All variables used all RHSs and All guards
+          | CWild  Offset          -- wild card
+                   (Maybe Exp)     -- guard
+                   Exp             -- rhs
+
+-- | What's the offset?
+caseOffset :: Case -> Offset
+caseOffset (CMatch o _ _ _ _ _) = o
+caseOffset (CWild  o       _ _) = o
+
+-- | Show a case nicely
+showCase :: Case -> String
+showCase = showCaseGen Nothing
+
+-- | Show a case nicely, with location
+showCaseGen :: Maybe Loc -> Case -> String
+showCaseGen mbLoc sc = case sc of
+                         CMatch _ c (Just ps) mbG _ _ -> loc ++ unwords (nameBase c : map pprint ps ++ shGuard mbG)
+                         CMatch _ c Nothing   mbG _ _ -> loc ++ unwords (nameBase c : "{}"           : shGuard mbG)
+                         CWild  _             mbG _   -> loc ++ unwords ("_"                         : shGuard mbG)
+ where shGuard Nothing  = []
+       shGuard (Just e) = ["|", pprint e]
+
+       loc = case mbLoc of
+               Nothing -> ""
+               Just l  -> fmtLoc l (caseOffset sc) ++ ": "
+
+-- | Get the name of the constructor, if any
+getCaseConstructor :: Case -> Maybe Name
+getCaseConstructor (CMatch _ nm _ _ _ _) = Just nm
+getCaseConstructor CWild{}               = Nothing
+
+-- | Get the guard, if any
+getCaseGuard :: Case -> Maybe Exp
+getCaseGuard (CMatch _ _ _ mbg _ _) = mbg
+getCaseGuard (CWild  _     mbg _  ) = mbg
+
+-- | Is there a guard?
+isGuarded :: Case -> Bool
+isGuarded = isJust . getCaseGuard
+
+-- | Find offset of each successive match. This isn't perfect, but it does the job
+findOffsets :: String -> [Offset]
+findOffsets s = analyze $ E.parseExpWithMode E.defaultParseMode $ "case ()" ++ tab ++ rest
+  where rest = relevant s
+        -- there's a chance the replication below might yield a negative value, which can make our
+        -- offset calculation slightly off. But this should be exceedingly rare because it'd have to be that
+        -- matches are on the same line and the "Type expr" part of the original must be shorter than 7 chars.
+        -- Let's ignore that possibility.
+        tab  = replicate (length s - length rest - 7) ' '
+        relevant r@(' ':'o':'f':_) = r
+        relevant ""                = ""
+        relevant (_:cs)            = relevant cs
+
+        analyze E.ParseFailed{} = [] -- Just ignore
+        analyze (E.ParseOk e)   = case e of
+                                   E.Case _ _ alts -> map getOff alts
+                                   _               -> []
+          where getOff (E.Alt l p _ _) = OffBy (E.srcSpanStartLine as - 1) (E.srcSpanStartColumn as - 1) w
+                   where as = E.srcInfoSpan l
+                         cs = E.srcInfoSpan (E.ann p)
+                         w  = E.srcSpanEndColumn cs - E.srcSpanStartColumn cs
+
+-- | Quasi-quoter for symbolic case expressions.
+sCase :: QuasiQuoter
+sCase = QuasiQuoter
+  { quoteExp  = extract
+  , quotePat  = bad "pattern"
+  , quoteType = bad "type"
+  , quoteDec  = bad "declaration"
+  }
+  where
+    bad ctx _ = fail Unknown $ "sCase: not usable in " <> ctx <> " context"
+
+    extract :: String -> ExpQ
+    extract src =
+      case parts src of
+        Nothing -> fail Unknown $ unlines [ "sCase: Failed to parse a symbolic case-expression."
+                                          , ""
+                                          , "           Instead of:   case      expr of alts"
+                                          , "           Write     : [sCase|Type expr of alts|]"
+                                          , ""
+                                          , "        where Type is the underlying concrete type of the expression."
+                                          ]
+        Just ((typ, scrutStr), altsStr) -> do
+          let fnTok    = "sCase" <> typ
+              fullCase = "case " <> scrutStr <> " of " <> altsStr
+              offsets  = findOffsets src
+          case Meta.parseExp fullCase of
+            Right (CaseE scrut matches) -> do
+              fnName <- lookupValueName fnTok >>= \case
+                Just n  -> pure (VarE n)
+                Nothing -> fail Unknown $ unlines [ "sCase: Unknown symbolic ADT: " <> typ
+                                                  , ""
+                                                  , "        To use a symbolic case expression, declare your ADT, and then:"
+                                                  , "             mkSymbolic [''" <> typ <> "]"
+                                                  , "        In a template-haskell context."
+                                                  ]
+              cases <- zipWithM matchToPair (offsets ++ repeat Unknown) matches >>= checkCase scrut typ . concat
+              buildCase typ fnName scrut cases
+            Right _  -> fail Unknown "sCase: Parse error, cannot extract a case-expression."
+            Left err -> case lines err of
+                          (_:loc:res) | ["SrcLoc", _, l, c] <- words loc, all isDigit l, all isDigit c
+                             -> fail (OffBy (read l - 1) (read c - 1) 1) (unlines res)
+                          _  -> fail Unknown $ "sCase parse error: " <> err
+
+    buildCase _    caseFunc  scrut (Left  cases) = pure $ foldl AppE (caseFunc `AppE` scrut) cases
+    buildCase typ _caseFunc _scrut (Right cases) = iteChain cases
+      where iteChain []              = pure $ AppE (VarE 'sym) (LitE (StringL ("unmatched_sCase|" ++ typ)))
+            iteChain ((t, e) : rest) = do r <- iteChain rest
+                                          pure $ foldl AppE (VarE 'ite) [t, e, r]
+
+    getGuards :: Body -> [Dec] -> Q [(Maybe Exp, Exp)]
+    getGuards (NormalB  rhs)  locals = pure [(Nothing, addLocals locals rhs)]
+    getGuards (GuardedB exps) locals = mapM get exps
+      where get (NormalG e,  rhs)
+              | isSTrue e
+              = pure (Nothing, addLocals locals rhs)
+              | True
+              = pure (Just e, addLocals locals rhs)
+            get (PatG stmts, _)   = fail Unknown $ unlines $  "sCase: Pattern guards are not supported: "
+                                                           : ["        " ++ pprint s | s <- stmts]
+
+            -- Is this literally sTrue? This is a bit dangerous since
+            -- we just look at the base-name, but good enough
+            isSTrue (VarE nm) = nameBase nm == nameBase 'sTrue
+            isSTrue _         = False
+
+    -- Turn where clause into simple let
+    addLocals :: [Dec] -> Exp -> Exp
+    addLocals [] e = e
+    addLocals ds e = LetE ds e
+
+    -- Given an occurrence of a name, find what it refers to
+    getReference :: Offset -> Name -> Q Name
+    getReference off refName = do mbN <- lookupValueName (nameBase refName)
+                                  case mbN of
+                                    Nothing -> fail off $ "sCase: Not in scope: data constructor: " <> pprint refName
+                                    Just n  -> pure n
+
+    matchToPair :: Offset -> Match -> Q [Case]
+    matchToPair off (Match pat grhs locals) = do
+      rhss <- getGuards grhs locals
+      let allUsed = Set.unions (map (\(mbG, e) -> maybe Set.empty freeVars mbG `Set.union` freeVars e) rhss)
+
+      case pat of
+        ConP conName _ subpats -> do ps  <- traverse (patToVar off) subpats
+                                     con <- getReference off conName
+                                     pure [CMatch off con (Just ps) mbG rhs allUsed | (mbG, rhs) <- rhss]
+
+        RecP conName []        -> do con <- getReference off conName
+                                     pure [CMatch off con Nothing   mbG rhs allUsed | (mbG, rhs) <- rhss]
+
+        WildP                  ->    pure [CWild  off               mbG rhs         | (mbG, rhs) <- rhss]
+
+        _ -> fail Unknown $ unlines [ "sCase: Unsupported pattern:"
+                                    , "            Saw: " <> pprint pat
+                                    , ""
+                                    , "        Only constructors with variables (i.e., Cstr a b _ d)"
+                                    , "        Empty record matches (i.e., Cstr{})"
+                                    , "        And wildcards (i.e., _) for default"
+                                    , "        are supported."
+                                    ]
+
+    -- Make sure things are in good-shape and decide if we have guards
+    checkCase :: Exp -> String -> [Case] -> Q (Either [Exp] [(Exp, Exp)])
+    checkCase scrut typ cases = do
+        loc   <- location
+
+        cstrs <- -- We don't need the field names if user supplied them; so drop them here
+                 let dropFieldNames (c, nts) = (c, map snd nts)
+                 in map dropFieldNames . snd <$> getConstructors (mkName typ)
+
+        -- Is there a catch all clause?
+        let hasCatchAll = or [True | CWild _ Nothing _ <- cases]
+
+        -- Step 0: If there's an unguarded wild-card, make sure nothing else follows it.
+        -- Note that this also handles wild-card being present twice.
+        let checkWild []                         = pure ()
+            checkWild (CMatch{}          : rest) = checkWild rest
+            checkWild (CWild _ Just{}  _ : rest) = checkWild rest
+            checkWild (CWild o Nothing _ : rest) =
+                  case rest of
+                    []  -> pure ()
+                    red  -> fail o $ unlines $ "sCase: Wildcard makes the remaining matches redundant:"
+                                             : ["        " ++ showCaseGen (Just loc) r | r <- red]
+        checkWild cases
+
+        -- Step 2: Make sure every constructor listed actually exists and matches in arity.
+        let chk1 :: Case -> Q ()
+            chk1 c = case c of
+                       CMatch o nm ps _ _ _ -> isSafe o nm (length <$> ps)
+                       CWild  {}            -> pure ()
+              where isSafe :: Offset -> Name -> Maybe Int -> Q ()
+                    isSafe o nm mbLen
+                      | Just ts <- nm `lookup` cstrs
+                      = case mbLen of
+                           Nothing  -> pure ()
+                           Just cnt -> unless (length ts == cnt)
+                                            $ fail o $ unlines [ "sCase: Arity mismatch."
+                                                               , "        Type       : " ++ typ
+                                                               , "        Constructor: " ++ nameBase nm
+                                                               , "        Expected   : " ++ show (length ts)
+                                                               , "        Given      : " ++ show cnt
+                                                               ]
+                      | True
+                      = fail o $ unlines [ "sCase: Unknown constructor:"
+                                         , "        Type          : " ++ typ
+                                         , "        Saw           : " ++ pprint nm
+                                         , "        Must be one of: " ++ intercalate ", " (map (pprint . fst) cstrs)
+                                         ]
+
+        mapM_ chk1 cases
+
+        -- Step 2: Make sure constructor matches are not overlapping
+        let problem w extras x = fail (caseOffset x) $ unlines $ [ "sCase: " ++ w ++ ":"
+                                                                 , "        Type       : " ++ typ
+                                                                 , "        Constructor: " ++ showCase x
+                                                                 ]
+                                                              ++ [ "      " ++ e | e <- extras]
+
+            overlap x xs = problem "Overlapping case constructors" extras x
+              where extras = "Overlaps with:" : ["  " ++ p | p <- map (showCaseGen (Just loc)) xs]
+
+            unmatched x
+             | isGuarded x = problem "Non-exhaustive match" ["NB. Guarded match might fail."] x
+             | True        = problem "Non-exhaustive match" []                                x
+
+            nonExhaustive o cstr = fail o $ unlines [ "sCase: Pattern match(es) are non-exhaustive."
+                                                    , "        Not matched     : " ++ nameBase cstr
+                                                    , "        Patterns of type: " ++ typ
+                                                    , "        Must match each : " ++ intercalate ", " (map (nameBase . fst) cstrs)
+                                                    , ""
+                                                    , "      You can use a '_' to match multiple cases."
+                                                    ]
+            -- We're done
+            chk2 [] = pure ()
+
+            -- If we have a non-guarded match, then there must be no matches for this constructor later on. If so, they're redundant.
+            chk2 (c@(CMatch _ nm _ Nothing _ _) : rest)
+              = case filter (\oc -> getCaseConstructor oc == Just nm) rest of
+                  [] -> chk2 rest
+                  os -> overlap (last os) (c : init os)
+
+            -- If we have a guarded match, then this guard can fail. So either there must be a match
+            -- for it later on, or there must be a catch-all. Note that if it exists later, we don't
+            -- care if that occurrence is guarded or not; because if it is guarded, we'll fail on the last one.
+            chk2 (c@(CMatch _ nm _ Just{} _ _) : rest)
+              | hasCatchAll || Just nm `elem` map getCaseConstructor rest
+              = chk2 rest
+              | True
+              = unmatched c
+
+            -- If there's a guarded wildcard, must make sure there's a catch all afterwards
+            chk2 (c@(CWild _ Just{} _) : rest)
+              | hasCatchAll
+              = chk2 rest
+              | True
+              = unmatched c
+
+            -- No need to worry about anything following catch-all, since we already covered that before
+            chk2 (CWild _ Nothing _ : rest) = chk2 rest
+
+        chk2 cases
+
+        -- At this point, we either have a simple case with no guards, in which case
+        -- we translate this to an sCase for that type. So find all alternatives.
+        -- Otherwise, this will become an ite-chain
+        let hasGuards = any isGuarded cases
+
+        if not hasGuards
+           then do defaultCase <- case [((e, mbg), c) | c@(CWild _ mbg e) <- cases] of
+                                    []                  -> pure Nothing
+                                    [((e, Nothing), c)] -> pure $ Just (caseOffset c, e)
+                                    cs@((_, c):_)       -> fail (caseOffset c)
+                                                         $ unlines $   "sCase: Impossible happened; found unexpected cases:"
+                                                                   :  [ "        " ++ showCase curc | curc <- map snd cs]
+                                                                   ++ [ ""
+                                                                      , "      Please report this as a bug."
+                                                                      ]
+                   let find _ []     = Nothing
+                       find w (c:cs)
+                         | matches = Just c
+                         | True    = find w cs
+                         where matches = case c of
+                                           CMatch _ nm _ _ _ _ -> nm == w
+                                           CWild  {}           -> False
+
+                       case2rhs :: Case -> [Type] -> (Maybe Exp, Exp)
+                       case2rhs cs ts = (LamE pats <$> mbGuard, LamE pats e)
+                         where (mbGuard, e, pats) = case cs of
+                                                      CMatch _ _ (Just ps) mbG rhs _ -> (mbG, rhs, ps)
+                                                      CMatch _ _ Nothing   mbG rhs _ -> (mbG, rhs, map (const WildP) ts)
+                                                      CWild  _             mbG rhs   -> (mbG, rhs, map (const WildP) ts)
+
+                       collect (cstr, ts)
+                         | Just e <- find cstr cases
+                         = pure $ case2rhs e ts
+                         | True
+                         = case defaultCase of
+                             Nothing -> nonExhaustive Unknown cstr
+                             Just (_, de) -> do let ps = map (const WildP) ts
+                                                pure (Nothing, LamE ps de)
+
+                   res <- mapM collect cstrs
+
+                   -- If we reached here, all is well; except we might have an extra wildcard that we did not use
+                   when (length cases > length cstrs) $
+                     case defaultCase of
+                       Nothing     -> pure ()
+                       Just (o, _) -> fail o "sCase: Wildcard match is redundant"
+
+                   -- Double check that we had no guards and return the cases
+                   case [r | (Just{}, r) <- res] of
+                     [] -> pure $ Left $ map snd res
+                     rs -> fail Unknown $ unlines $    "sCase: Impossible happened; found a guard in no-guard case."
+                                                  :  [ "        " ++ pprint r | r <- rs]
+                                                  ++ [ ""
+                                                    , "      Please report this as a bug."
+                                                    ]
+
+           else do -- We have guards.
+                   defaultCase <- case [(c, e) | c@(CWild _ Nothing e) <- cases] of
+                                    []         -> pure Nothing
+                                    ((c, e):_) -> pure $ Just (caseOffset c, e)
+
+                   -- Collect, for each constructor, the corresponding cases:
+                   let cstrMatches :: [(Name, ([Type], [Case]))]
+                       cstrMatches = map (\(cstr, ts) -> (cstr, (ts, concatMap (matches cstr) cases))) cstrs
+                         where matches cstr c | Just n <- getCaseConstructor c, n == cstr = [c]
+                                              | True                                      = []
+
+                   -- Make sure we have a match for every constructor or a catch-all
+                   unless hasCatchAll $ case [nm | (nm, (_, [])) <- cstrMatches] of
+                                          []    -> pure ()
+                                          (x:_) -> nonExhaustive Unknown x
+
+                   -- If every constructor have a full match, then catch-all, if exists, is redundant:
+                   case defaultCase of
+                     Nothing     -> pure ()
+                     Just (o, _)
+                       | map fst cstrs == [nm | (nm, (_, cs)) <- cstrMatches, not (all isGuarded cs)]
+                       -> fail o "sCase: Wildcard match is redundant"
+                       | True
+                       -> pure ()
+
+                   let collect :: Case -> Q (Exp, Exp)
+                       collect (CWild  _        mbG rhs        ) = pure (fromMaybe (VarE 'sTrue) mbG, rhs)
+                       collect (CMatch o nm mbp mbG rhs allUsed) = do
+                           case nm `lookup` cstrs of
+                             Nothing -> fail o $ unlines [ "sCase: Impossible happened."
+                                                         , "        Unable to determine params for: " <> pprint nm
+                                                         ]
+                             Just ts -> do let pats = fromMaybe (map (const WildP) ts) mbp
+                                               args = [ AppE (VarE (mkName ("get" ++ nameBase nm ++ "_" ++ show i))) scrut
+                                                      | (i, _) <- zip [(1 :: Int) ..] ts]
+                                               rec  = VarE $ mkName $ "is" ++ nameBase nm
+
+                                               -- What are the free variables in the guard and the rhs that we bind?
+                                               used    = Set.fromList [n | VarP n <- pats] `Set.intersection` allUsed
+                                               close e = foldr1 (AppE . AppE (VarE 'const)) (e:extras)
+                                                 where extras = map VarE $ Set.toList (used Set.\\ freeVars e)
+
+                                               mkApp f | null pats = f
+                                                       | True      = foldl AppE (LamE pats f) args
+
+                                               grd :: Exp
+                                               grd = case mbG of
+                                                       Nothing -> AppE rec scrut
+                                                       Just g  -> foldl1 AppE [VarE '(.&&), AppE rec scrut, mkApp (close g)]
+
+                                           pure (grd, mkApp (close rhs))
+
+                   Right <$> mapM collect cases
+
+    patToVar :: Offset -> Pat -> Q Pat
+    patToVar _ p@VarP{} = pure p
+    patToVar _ p@WildP  = pure p
+    patToVar o p        = fail o $ unlines [ "sCase: Unsupported complex pattern match."
+                                           , "        Saw: " <> pprint p
+                                           , ""
+                                           , "      Only variables and wild-card are supported."
+                                           ]
+    parts = go ""
+      where go _     ""             = Nothing
+            go sofar ('o':'f':rest) = Just (break isSpace (dropWhile isSpace (reverse sofar)), rest)
+            go sofar (c:cs)         = go (c:sofar) cs
+
+-- | Free variables = used – bound
+freeVars :: Exp -> Set Name
+freeVars e = usedVars e Set.\\ boundVars e
+ where boundVars :: Exp -> Set Name
+       boundVars = everything Set.union (mkQ Set.empty f)
+         where f :: Pat -> Set Name
+               f (VarP n)  = Set.singleton n
+               f (AsP n _) = Set.singleton n
+               f _         = Set.empty
+
+       usedVars :: Exp -> Set Name
+       usedVars = everything Set.union (mkQ Set.empty f)
+         where f :: Exp -> Set Name
+               f (VarE n) = Set.singleton n
+               f _        = Set.empty
diff --git a/Data/SBV/SMT/SMT.hs b/Data/SBV/SMT/SMT.hs
--- a/Data/SBV/SMT/SMT.hs
+++ b/Data/SBV/SMT/SMT.hs
@@ -9,11 +9,9 @@
 -- Abstraction of SMT solvers
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DefaultSignatures          #-}
 {-# LANGUAGE FlexibleInstances          #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE NamedFieldPuns             #-}
-{-# LANGUAGE OverloadedStrings          #-}
 {-# LANGUAGE Rank2Types                 #-}
 {-# LANGUAGE ScopedTypeVariables        #-}
 {-# LANGUAGE TypeApplications           #-}
@@ -27,7 +25,7 @@
          Modelable(..)
        , SatModel(..), genParse
        , extractModels, getModelValues
-       , getModelDictionaries, getModelUninterpretedValues
+       , getModelDictionaries
        , displayModels, showModel, shCV, showModelDictionary
 
        -- * Standard prover engine
@@ -234,14 +232,13 @@
   -- the remaining elements untouched. If the next element is not what's expected for this
   -- type you should return 'Nothing'
   parseCVs  :: [CV] -> Maybe (a, [CV])
+
   -- | Given a parsed model instance, transform it using @f@, and return the result.
   -- The default definition for this method should be sufficient in most use cases.
   cvtModel  :: (a -> Maybe b) -> Maybe (a, [CV]) -> Maybe (b, [CV])
   cvtModel f x = x >>= \(a, r) -> f a >>= \b -> return (b, r)
 
-  default parseCVs :: Read a => [CV] -> Maybe (a, [CV])
-  parseCVs (CV _ (CUserSort (_, s)) : r) = Just (read s, r)
-  parseCVs _                             = Nothing
+  {-# MINIMAL parseCVs #-}
 
 -- | Parse a signed/sized value from a sequence of CVs
 genParse :: Integral a => Kind -> [CV] -> Maybe (a, [CV])
@@ -328,7 +325,12 @@
   parseCVs []       = Nothing
 
 -- | A rounding mode, extracted from a model. (Default definition suffices)
-instance SatModel RoundingMode
+instance SatModel RoundingMode where
+  parseCVs (CV k (CADT (s, [])) : r)
+    | isRoundingMode k
+    , Just mode <- s `lookup` [(show m, m) | m <- [minBound .. maxBound :: RoundingMode]]
+    = Just (mode, r)
+  parseCVs _ = Nothing
 
 -- | 'String' as extracted from a model
 instance {-# OVERLAPS #-} SatModel [Char] where
@@ -404,14 +406,6 @@
   getModelValue :: SymVal b => String -> a -> Maybe b
   getModelValue v r = fromCV `fmap` (v `M.lookup` getModelDictionary r)
 
-  -- | Extract a representative name for the model value of an uninterpreted kind.
-  -- This is supposed to correspond to the value as computed internally by the
-  -- SMT solver; and is unportable from solver to solver. Also see `getModelUninterpretedValues`.
-  getModelUninterpretedValue :: String -> a -> Maybe String
-  getModelUninterpretedValue v r = case v `M.lookup` getModelDictionary r of
-                                     Just (CV _ (CUserSort (_, s))) -> Just s
-                                     _                              -> Nothing
-
   -- | A simpler variant of 'getModelAssignment' to get a model out without the fuss.
   extractModel :: SatModel b => a -> Maybe b
   extractModel a = case getModelAssignment a of
@@ -444,10 +438,6 @@
 -- | Extract value of a variable from an all-sat call. Similar to `getModelValue`.
 getModelValues :: SymVal b => String -> AllSatResult -> [Maybe b]
 getModelValues s AllSatResult{allSatResults = xs} =  map (s `getModelValue`) xs
-
--- | Extract value of an uninterpreted variable from an all-sat call. Similar to `getModelUninterpretedValue`.
-getModelUninterpretedValues :: String -> AllSatResult -> [Maybe String]
-getModelUninterpretedValues s AllSatResult{allSatResults = xs} =  map (s `getModelUninterpretedValue`) xs
 
 -- | t'ThmResult' as a generic model provider
 instance Modelable ThmResult where
diff --git a/Data/SBV/SMT/SMTLib2.hs b/Data/SBV/SMT/SMTLib2.hs
--- a/Data/SBV/SMT/SMTLib2.hs
+++ b/Data/SBV/SMT/SMTLib2.hs
@@ -10,7 +10,6 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE NamedFieldPuns      #-}
-{-# LANGUAGE PatternGuards       #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE ViewPatterns        #-}
 
@@ -28,13 +27,13 @@
 import qualified Data.Set             as Set
 
 import Data.SBV.Core.Data
-import Data.SBV.Core.Kind (smtType, needsFlattening, expandKinds)
+import Data.SBV.Core.Kind (smtType, needsFlattening, expandKinds, substituteADTVars)
 import Data.SBV.Control.Types
 
 import Data.SBV.SMT.Utils
 
 import Data.SBV.Core.Symbolic ( QueryContext(..), SetOp(..), getUserName', getSV, regExpToSMTString, NROp(..)
-                              , SMTDef(..), ResultInp(..), ProgInfo(..), SpecialRelOp(..)
+                              , SMTDef(..), ResultInp(..), ProgInfo(..), SpecialRelOp(..), ADTOp(..)
                               )
 
 import Data.SBV.Utils.PrettyNum (smtRoundingMode, cvToSMTLib)
@@ -43,9 +42,58 @@
 
 import qualified Data.Graph as DG
 
+
+-- Check that all ADT subkinds are registered. If not, tell the user to do so
+-- NB. This should not be the case as we "automatically" register the subkinds
+-- as we encounter them. But this is mostly a if-something-goes-wrong check.
+checkKinds :: [Kind] -> Maybe String
+checkKinds ks = case [m | m@(n, _) <- apps, n `notElem` defs] of
+                  []       -> Nothing
+                  xs@(f:_) -> let (h, cnt) = case [p | p@(_, i) <- xs, i > 0] of
+                                               (p:_) -> p
+                                               _     -> f
+                                  plu | length xs > 1 = "s are"
+                                      | True          = " is"
+                              in Just $ unlines $ [
+                                    "Data.SBV.mkSymbolic: Impossible happened! Unregistered subkinds."
+                                  , "***"
+                                  , "*** The following kind" ++ plu ++ " not registered: " ++ unwords (map fst xs)
+                                  , "***"
+                                  , "*** Please report this as a bug."
+                                  , "***"
+                                  , "*** As a workaround, you can try registering each ADT subfield, using: "
+                                  , "***"
+                                  , "***    {-# LANGUAGE TypeApplications #-}"
+                                  , "***"
+                                  , "***    import Data.Proxy"
+                                  , "***    registerType (Proxy @" ++ mkProxy h cnt ++ ")"
+                                  ]
+                               ++ extras cnt
+                               ++ [ "***"
+                                  , "*** Even if the workaround does the trick for you, it should not"
+                                  , "*** be needed. Please report this as a bug!"
+                                  ]
+
+
+  where apps = nub [(n, length as) | KApp n as <- concatMap expandKinds ks]
+        defs = nub [n | KADT n _ _ <- ks]
+        mkProxy h 0 = h
+        mkProxy h n = '(' : unwords (h : replicate n "Integer") ++ ")"
+
+        extras 0 = []
+        extras _ = [ "***"
+                   , "*** NB. You can use any base type as arguments, not just 'Integer'."
+                   , "*** It does not need to match the actual use cases, just one instance"
+                   , "*** at some base type is sufficent."
+                   ]
+
 -- | Translate a problem into an SMTLib2 script
 cvt :: SMTLibConverter ([String], [String])
-cvt ctx curProgInfo kindInfo isSat comments allInputs (_, consts) tbls uis defs (SBVPgm asgnsSeq) cstrs out cfg = (pgm, exportedDefs)
+cvt ctx curProgInfo kindInfo isSat comments allInputs (_, consts) tbls uis defs (SBVPgm asgnsSeq) cstrs out cfg
+   | Just s <- checkKinds allKinds
+   = error s
+   | True
+   = (pgm, exportedDefs)
   where allKinds       = Set.toList kindInfo
 
         -- Below can simply be defined as: nub (sort (G.universeBi asgnsSeq))
@@ -62,19 +110,17 @@
         hasString      = KString     `Set.member` kindInfo
         hasRegExp      = (not . null) [() | (_ :: RegExOp) <- G.universeBi allTopOps]
         hasChar        = KChar      `Set.member` kindInfo
-        hasRounding    = not $ null [s | (s, _) <- usorts, s == "RoundingMode"]
+        hasRounding    = any isRoundingMode allKinds
         hasBVs         = not (null [() | KBounded{} <- allKinds])
-        usorts         = [(s, dt) | KUserSort s dt <- allKinds]
-        trueUSorts     = [s | (s, _) <- usorts, s /= "RoundingMode"]
+        adtsNoRM       = [(s, ps, cs) | k@(KADT s ps cs) <- allKinds, not (isRoundingMode k)]
         tupleArities   = findTupleArities kindInfo
         hasOverflows   = (not . null) [() | (_ :: OvOp) <- G.universeBi allTopOps]
         hasQuantBools  = (not . null) [() | QuantifiedBool{} <- G.universeBi allTopOps]
         hasList        = any isList kindInfo
         hasSets        = any isSet kindInfo
         hasTuples      = not . null $ tupleArities
-        hasEither      = any isEither kindInfo
-        hasMaybe       = any isMaybe  kindInfo
         hasRational    = any isRational kindInfo
+        hasADTs        = not . null $ adtsNoRM
         rm             = roundingMode cfg
         solverCaps     = capabilities (solver cfg)
 
@@ -84,7 +130,7 @@
         -- Is there a reason why we can't handle this problem?
         -- NB. There's probably a lot more checking we can do here, but this is a start:
         doesntHandle = listToMaybe [nope w | (w, have, need) <- checks, need && not (have solverCaps)]
-           where checks = [ ("data types",             supportsDataTypes,          hasTuples || hasEither || hasMaybe)
+           where checks = [ ("data types",             supportsDataTypes,          hasTuples || hasADTs)
                           , ("set operations",         supportsSets,               hasSets)
                           , ("bit vectors",            supportsBitVectors,         hasBVs)
                           , ("special relations",      supportsSpecialRels,        needsSpecialRels)
@@ -92,7 +138,7 @@
                           , ("unbounded integers",     supportsUnboundedInts,      hasInteger)
                           , ("algebraic reals",        supportsReals,              hasReal)
                           , ("floating-point numbers", supportsIEEE754,            hasFP)
-                          , ("uninterpreted sorts",    supportsUninterpretedSorts, not (null trueUSorts))
+                          , ("has data-types/sorts",   supportsADTs,               not (null adtsNoRM))
                           ]
 
                  nope w = [ "***     Given problem requires support for " ++ w
@@ -146,11 +192,9 @@
            | hasInteger            = setAll "has unbounded values"
            | hasRational           = setAll "has rational values"
            | hasReal               = setAll "has algebraic reals"
-           | not (null trueUSorts) = setAll "has user-defined sorts"
+           | hasADTs               = setAll "has user-defined data-types"
            | hasNonBVArrays        = setAll "has non-bitvector arrays"
            | hasTuples             = setAll "has tuples"
-           | hasEither             = setAll "has either type"
-           | hasMaybe              = setAll "has maybe type"
            | hasSets               = setAll "has sets"
            | hasList               = setAll "has lists"
            | hasChar               = setAll "has chars"
@@ -216,14 +260,12 @@
 
         pgm  =  map ("; " ++) comments
              ++ settings
-             ++ [ "; --- uninterpreted sorts ---" ]
-             ++ concatMap declSort usorts
              ++ [ "; --- tuples ---" ]
              ++ concatMap declTuple tupleArities
              ++ [ "; --- sums ---" ]
-             ++ (if containsSum       kindInfo then declSum       else [])
-             ++ (if containsMaybe     kindInfo then declMaybe     else [])
              ++ (if containsRationals kindInfo then declRationals else [])
+             ++ [ "; --- ADTs  --- " | not (null adtsNoRM)]
+             ++ declADT adtsNoRM
              ++ [ "; --- literal constants ---" ]
              ++ concatMap (declConst cfg) consts
              ++ [ "; --- top level inputs ---"]
@@ -299,21 +341,49 @@
                         Just u  | show s /= u -> Just $ "tracks user variable " ++ show u
                         _                     -> Nothing
 
--- | Declare new sorts
-declSort :: (String, Maybe [String]) -> [String]
-declSort (s, _)
-  | s == "RoundingMode" -- built-in-sort; so don't declare.
-  = []
-declSort (s, Nothing) = [ "(declare-sort " ++ s ++ " 0)  ; N.B. Uninterpreted sort."
-                        , "(declare-fun " ++ witnessName s ++ " () " ++ s ++ ")"
-                        ]
-declSort (s, Just fs) = [ "(declare-datatypes ((" ++ s ++ " 0)) ((" ++ unwords (map (\c -> "(" ++ c ++ ")") fs) ++ ")))"
-                        , "(define-fun " ++ s ++ "_constrIndex ((x " ++ s ++ ")) Int"
-                        ] ++ ["   " ++ body fs (0::Int)] ++ [")"]
-        where body []     _ = ""
-              body [_]    i = show i
-              body (c:cs) i = "(ite (= x " ++ c ++ ") " ++ show i ++ " " ++ body cs (i+1) ++ ")"
+-- | Declare ADTs
+declADT :: [(String, [(String, Kind)], [(String, [Kind])])] -> [String]
+declADT = concatMap declGroup . DG.stronglyConnComp . map mkNode
+  where mkNode adt@(n, pks, cstrs) = (adt, n, [s | KApp s _ <- concatMap expandKinds (map snd pks ++ concatMap snd cstrs)])
 
+        declGroup (DG.AcyclicSCC d )  = singleADT d
+        declGroup (DG.CyclicSCC  ds)
+            = case ds of
+                []  -> error "Data.SBV.declADT: Impossible happened: an empty cyclic group was returned!"
+                [d] -> singleADT d
+                _   -> multiADT ds
+
+        parParens :: [(String, Kind)] -> (String, String)
+        parParens [] = ("", "")
+        parParens ps = (" (par (" ++ unwords (map fst ps) ++ ")", ")")
+
+        mkC (nm, []) = nm
+        mkC (nm, ts) = nm ++ " " ++ unwords ['(' : mkF (nm ++ "_" ++ show i) t ++ ")" | (i, t) <- zip [(1::Int)..] ts]
+          where mkF a t  = "get" ++ a ++ " " ++ smtType t
+
+        singleADT :: (String, [(String, Kind)], [(String, [Kind])]) -> [String]
+        singleADT (tName, [], []) = ["(declare-sort " ++ tName ++ " 0) ; N.B. Uninterpreted sort."]
+        singleADT (tName, pks, cstrs) = ("; User defined ADT: " ++ tName) : decl
+          where decl =  ("(declare-datatype " ++ tName ++ parOpen ++ " (")
+                     :  ["    (" ++ mkC c ++ ")" | c <- cstrs]
+                     ++ ["))" ++ parClose]
+
+                (parOpen, parClose) = parParens pks
+
+        multiADT :: [(String, [(String, Kind)], [(String, [Kind])])] -> [String]
+        multiADT adts = ("; User defined mutually-recursive ADTs: " ++ intercalate ", " (map (\(a, _, _) -> a) adts)) : decl
+          where decl = ("(declare-datatypes (" ++ typeDecls ++ ") (")
+                     : concatMap adtBody adts
+                    ++ ["))"]
+
+                typeDecls = unwords ['(' : name ++ " " ++ show (length pks) ++ ")" | (name, pks, _) <- adts]
+
+                adtBody (_, pks, cstrs) = body
+                  where (parOpen, parClose) = parParens pks
+                        body =  ("    " ++ parOpen ++ " (")
+                             :  ["        (" ++ mkC c ++ ")" | c <- cstrs]
+                             ++ ["     )" ++ parClose]
+
 -- | Declare tuple datatypes
 --
 -- eg:
@@ -351,30 +421,10 @@
                     $ Set.map length
                     $ Set.fromList [ tupKs | KTuple tupKs <- Set.toList ks ]
 
--- | Is @Either@ being used?
-containsSum :: Set Kind -> Bool
-containsSum = not . Set.null . Set.filter isEither
-
--- | Is @Maybe@ being used?
-containsMaybe :: Set Kind -> Bool
-containsMaybe = not . Set.null . Set.filter isMaybe
-
 -- | Is @Rational@ being used?
 containsRationals :: Set Kind -> Bool
 containsRationals = not . Set.null . Set.filter isRational
 
-declSum :: [String]
-declSum = [ "(declare-datatypes ((SBVEither 2)) ((par (T1 T2)"
-          , "                                    ((left_SBVEither  (get_left_SBVEither  T1))"
-          , "                                     (right_SBVEither (get_right_SBVEither T2))))))"
-          ]
-
-declMaybe :: [String]
-declMaybe = [ "(declare-datatypes ((SBVMaybe 1)) ((par (T)"
-            , "                                    ((nothing_SBVMaybe)"
-            , "                                     (just_SBVMaybe (get_just_SBVMaybe T))))))"
-            ]
-
 -- Internally, we do *not* keep the rationals in reduced form! So, the boolean operators explicitly do the math
 -- to make sure equivalent values are treated correctly.
 declRationals :: [String]
@@ -400,12 +450,9 @@
             -- any new settings?
                settings
             -- sorts
-            ++ concatMap declSort [(s, dt) | KUserSort s dt <- newKinds]
+            ++ declADT [(s, pks, cs) | k@(KADT s pks cs) <- newKinds, not (isRoundingMode k)]
             -- tuples. NB. Only declare the new sizes, old sizes persist.
             ++ concatMap declTuple (findTupleArities newKs)
-            -- sums
-            ++ (if containsSum   newKs then declSum   else [])
-            ++ (if containsMaybe newKs then declMaybe else [])
             -- constants
             ++ concatMap (declConst cfg) consts
             -- inputs
@@ -714,11 +761,6 @@
         lift2Cmp o fo | fpOp = lift2 fo
                       | True = lift2 o
 
-        unintComp o [a, b]
-          | KUserSort s (Just _) <- kindOf (hd "unintComp" arguments)
-          = let idx v = "(" ++ s ++ "_constrIndex " ++ v ++ ")" in "(" ++ o ++ " " ++ idx a ++ " " ++ idx b ++ ")"
-        unintComp o sbvs = error $ "SBV.SMT.SMTLib2.sh.unintComp: Unexpected arguments: "   ++ show (o, sbvs, map kindOf arguments)
-
         stringOrChar KString = True
         stringOrChar KChar   = True
         stringOrChar _       = False
@@ -740,49 +782,30 @@
         lift1  o _ [x]    = "(" ++ o ++ " " ++ x ++ ")"
         lift1  o _ sbvs   = error $ "SBV.SMT.SMTLib2.sh.lift1: Unexpected arguments: "   ++ show (o, sbvs)
 
-        -- We fully qualify the constructor with their types to work around type checking issues
-        -- Note that this is rather bizarre, as we're tagging the constructor with its *result* type,
-        -- not its full function type as one would expect. But this is per the spec: Pg. 27 of SMTLib 2.6 spec
-        -- says:
-        --
-        --    To simplify sort checking, a function symbol in a term can be annotated with one of its result sorts sigma.
-        --
-        -- I wish it was the full type here not just the result, but we go with the spec. Also see: <http://github.com/Z3Prover/z3/issues/2135>
-        -- and in particular <http://github.com/Z3Prover/z3/issues/2135#issuecomment-477636435>
-        dtConstructor fld args res = "((as " ++ fld ++ " " ++ smtType res ++ ") " ++ unwords (map cvtSV args) ++ ")"
-
-        -- Similarly, we fully qualify the accessors with their types to work around type checking issues
-        -- Unfortunately, z3 and CVC4 are behaving differently, so we tie this ascription to a solver capability.
-        dtAccessor fld params res
-           | supportsDirectAccessors caps = dResult
-           | True                         = aResult
-          where dResult = "(_ is " ++ fld ++ ")"
-                ps      = " (" ++ unwords (map smtType params) ++ ") "
-                aResult = "(_ is (" ++ fld ++ ps ++ smtType res ++ "))"
-
         sh (SBVApp Ite [a, b, c]) = "(ite " ++ cvtSV a ++ " " ++ cvtSV b ++ " " ++ cvtSV c ++ ")"
 
         sh (SBVApp (LkUp (t, aKnd, _, l) i e) [])
           | needsCheck = "(ite " ++ cond ++ cvtSV e ++ " " ++ lkUp ++ ")"
           | True       = lkUp
-          where needsCheck = case aKnd of
+          where unexpected = error $ "SBV.SMT.SMTLib2.cvtExp: Unexpected: " ++ show aKnd
+                needsCheck = case aKnd of
+                              KVar{}        -> unexpected
                               KBool         -> (2::Integer) > fromIntegral l
                               KBounded _ n  -> (2::Integer)^n > fromIntegral l
                               KUnbounded    -> True
-                              KUserSort s _ -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected uninterpreted valued index: " ++ s
-                              KReal         -> error "SBV.SMT.SMTLib2.cvtExp: unexpected real valued index"
-                              KFloat        -> error "SBV.SMT.SMTLib2.cvtExp: unexpected float valued index"
-                              KDouble       -> error "SBV.SMT.SMTLib2.cvtExp: unexpected double valued index"
-                              KFP{}         -> error "SBV.SMT.SMTLib2.cvtExp: unexpected arbitrary float valued index"
-                              KRational{}   -> error "SBV.SMT.SMTLib2.cvtExp: unexpected rational valued index"
-                              KChar         -> error "SBV.SMT.SMTLib2.cvtExp: unexpected char valued index"
-                              KString       -> error "SBV.SMT.SMTLib2.cvtExp: unexpected string valued index"
-                              KList k       -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected list valued: " ++ show k
-                              KSet  k       -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected set valued: " ++ show k
-                              KTuple k      -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected tuple valued: " ++ show k
-                              KMaybe k      -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected maybe valued: " ++ show k
-                              KEither k1 k2 -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected sum valued: " ++ show (k1, k2)
-                              KArray  k1 k2 -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected array valued: " ++ show (k1, k2)
+                              KApp _ _      -> unexpected
+                              KADT _ _ _    -> unexpected
+                              KReal         -> unexpected
+                              KFloat        -> unexpected
+                              KDouble       -> unexpected
+                              KFP _ _       -> unexpected
+                              KRational     -> unexpected
+                              KChar         -> unexpected
+                              KString       -> unexpected
+                              KList _       -> unexpected
+                              KSet  _       -> unexpected
+                              KTuple _      -> unexpected
+                              KArray  _ _   -> unexpected
 
                 lkUp = "(" ++ getTable tableMap t ++ " " ++ cvtSV i ++ ")"
 
@@ -791,6 +814,7 @@
                  | True      = gtl ++ " "
 
                 (less, leq) = case aKnd of
+                                KVar{}        -> error "SBV.SMT.SMTLib2.cvtExp: unexpected variable index"
                                 KBool         -> error "SBV.SMT.SMTLib2.cvtExp: unexpected boolean valued index"
                                 KBounded{}    -> if hasSign i then ("bvslt", "bvsle") else ("bvult", "bvule")
                                 KUnbounded    -> ("<", "<=")
@@ -801,12 +825,11 @@
                                 KFP{}         -> ("fp.lt", "fp.leq")
                                 KChar         -> error "SBV.SMT.SMTLib2.cvtExp: unexpected string valued index"
                                 KString       -> error "SBV.SMT.SMTLib2.cvtExp: unexpected string valued index"
-                                KUserSort s _ -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected uninterpreted valued index: " ++ s
+                                KApp  s _     -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected ADT applied index: " ++ s
+                                KADT  s _ _   -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected ADT valued index: " ++ s
                                 KList k       -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected sequence valued index: " ++ show k
                                 KSet  k       -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected set valued index: " ++ show k
                                 KTuple k      -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected tuple valued index: " ++ show k
-                                KMaybe k      -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected maybe valued index: " ++ show k
-                                KEither k1 k2 -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected sum valued index: " ++ show (k1, k2)
                                 KArray  k1 k2 -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected array valued index: " ++ show (k1, k2)
 
                 mkCnst = cvtCV rm . mkConstCV (kindOf i)
@@ -822,6 +845,8 @@
         sh (SBVApp (Uninterpreted nm) [])   = nm
         sh (SBVApp (Uninterpreted nm) args) = "(" ++ nm ++ " " ++ unwords (map cvtSV args) ++ ")"
 
+        sh (SBVApp (ADTOp aop) args) = handleADT caps aop args
+
         sh (SBVApp (QuantifiedBool i) [])   = i
         sh (SBVApp (QuantifiedBool i) args) = error $ "SBV.SMT.SMTLib2.cvtExp: unexpected arguments to quantified boolean: " ++ show (i, args)
 
@@ -904,7 +929,7 @@
         sh (SBVApp (OverflowOp op) args) = "(" ++ show op ++ " " ++ unwords (map cvtSV args) ++ ")"
 
         -- Note the unfortunate reversal in StrInRe..
-        sh (SBVApp (StrOp (StrInRe r)) args) = "(str.in.re " ++ unwords (map cvtSV args) ++ " " ++ regExpToSMTString r ++ ")"
+        sh (SBVApp (StrOp (StrInRe r)) args) = "(str.in_re " ++ unwords (map cvtSV args) ++ " " ++ regExpToSMTString r ++ ")"
         sh (SBVApp (StrOp op)          args) = "(" ++ show op ++ " " ++ unwords (map cvtSV args) ++ ")"
 
         sh (SBVApp (RegExOp o@RegExEq{})  []) = show o
@@ -929,21 +954,8 @@
         sh (SBVApp (TupleConstructor n)   args)  = "((as mkSBVTuple" ++ show n ++ " " ++ smtType (KTuple (map kindOf args)) ++ ") " ++ unwords (map cvtSV args) ++ ")"
         sh (SBVApp (TupleAccess      i n) [tup]) = "(proj_" ++ show i ++ "_SBVTuple" ++ show n ++ " " ++ cvtSV tup ++ ")"
 
-        sh (SBVApp (EitherConstructor k1 k2 False) [arg]) =       dtConstructor "left_SBVEither"  [arg] (KEither k1 k2)
-        sh (SBVApp (EitherConstructor k1 k2 True ) [arg]) =       dtConstructor "right_SBVEither" [arg] (KEither k1 k2)
-        sh (SBVApp (EitherIs          k1 k2 False) [arg]) = '(' : dtAccessor    "left_SBVEither"  [k1]  (KEither k1 k2) ++ " " ++ cvtSV arg ++ ")"
-        sh (SBVApp (EitherIs          k1 k2 True ) [arg]) = '(' : dtAccessor    "right_SBVEither" [k2]  (KEither k1 k2) ++ " " ++ cvtSV arg ++ ")"
-        sh (SBVApp (EitherAccess            False) [arg]) = "(get_left_SBVEither "  ++ cvtSV arg ++ ")"
-        sh (SBVApp (EitherAccess            True ) [arg]) = "(get_right_SBVEither " ++ cvtSV arg ++ ")"
-
         sh (SBVApp  RationalConstructor    [t, b]) = "(SBV.Rational " ++ cvtSV t ++ " " ++ cvtSV b ++ ")"
 
-        sh (SBVApp (MaybeConstructor k False) [])    =       dtConstructor "nothing_SBVMaybe" []    (KMaybe k)
-        sh (SBVApp (MaybeConstructor k True)  [arg]) =       dtConstructor "just_SBVMaybe"    [arg] (KMaybe k)
-        sh (SBVApp (MaybeIs          k False) [arg]) = '(' : dtAccessor    "nothing_SBVMaybe" []    (KMaybe k) ++ " " ++ cvtSV arg ++ ")"
-        sh (SBVApp (MaybeIs          k True ) [arg]) = '(' : dtAccessor    "just_SBVMaybe"    [k]   (KMaybe k) ++ " " ++ cvtSV arg ++ ")"
-        sh (SBVApp MaybeAccess                [arg]) = "(get_just_SBVMaybe " ++ cvtSV arg ++ ")"
-
         sh (SBVApp Implies [a, b]) = "(=> " ++ cvtSV a ++ " " ++ cvtSV b ++ ")"
 
         sh inp@(SBVApp op args)
@@ -966,25 +978,16 @@
           | Just f <- lookup op uninterpretedTable
           = f (map cvtSV args)
           | True
-          = if not (null args) && isUserSort (hd "isUserSort" args)
-            then error $ unlines [ ""
-                                 , "*** Cannot translate operator        : " ++ show op
-                                 , "*** When applied to arguments of kind: " ++ intercalate ", " (nub (map (show . kindOf) args))
-                                 , "*** Found as part of the expression  : " ++ show inp
-                                 , "***"
-                                 , "*** Note that uninterpreted kinds only support equality."
-                                 , "*** If you believe this is in error, please report!"
-                                 ]
-            else error $ unlines [ ""
-                                 , "*** SBV.SMT.SMTLib2.cvtExp.sh: impossible happened; can't translate: " ++ show inp
-                                 , "***"
-                                 , "*** Applied to arguments of type: " ++ intercalate ", " (nub (map (show . kindOf) args))
-                                 , "***"
-                                 , "*** This can happen if the Num instance isn't properly defined for a lifted kind."
-                                 , "*** (See https://github.com/LeventErkok/sbv/issues/698 for a discussion.)"
-                                 , "***"
-                                 , "*** If you believe this is in error, please report!"
-                                 ]
+          = error $ unlines [ ""
+                            , "*** SBV.SMT.SMTLib2.cvtExp.sh: impossible happened; can't translate: " ++ show inp
+                            , "***"
+                            , "*** Applied to arguments of type: " ++ intercalate ", " (nub (map (show . kindOf) args))
+                            , "***"
+                            , "*** This can happen if the Num instance isn't properly defined for a lifted kind."
+                            , "*** (See https://github.com/LeventErkok/sbv/issues/698 for a discussion.)"
+                            , "***"
+                            , "*** If you believe this is in error, please report!"
+                            ]
           where smtOpBVTable  = [ (Plus,          lift2   "bvadd")
                                 , (Minus,         lift2   "bvsub")
                                 , (Times,         lift2   "bvmul")
@@ -1051,10 +1054,6 @@
                 uninterpretedTable = [ (Equal True,  lift2S "="        "="        True)
                                      , (Equal False, lift2S "="        "="        True)
                                      , (NotEqual,    liftNS "distinct" "distinct" True)
-                                     , (LessThan,    unintComp "<")
-                                     , (GreaterThan, unintComp ">")
-                                     , (LessEq,      unintComp "<=")
-                                     , (GreaterEq,   unintComp ">=")
                                      ]
 
                 -- For strings, equality and comparisons are the only operators
@@ -1085,7 +1084,7 @@
 -- Otherwise, we just declare the name
 declareName :: String -> SBVType -> Maybe String -> [String]
 declareName s t@(SBVType inputKS) mbCmnt = decl : restrict
-  where decl        = "(declare-fun " ++ s ++ " " ++ cvtType t ++ ")" ++ maybe "" (" ; " ++) mbCmnt
+  where decl = "(declare-fun " ++ s ++ " " ++ cvtType t ++ ")" ++ maybe "" (" ; " ++) mbCmnt
 
         (args, result) = case inputKS of
                           [] -> error $ "SBV.declareName: Unexpected empty type for: " ++ show s
@@ -1135,11 +1134,12 @@
         mkAnd cs  context = context $ "(and " ++ unwords cs ++ ")"
 
         walk :: Int -> String -> (Kind -> String -> [String]) -> Kind -> [String]
+        walk _d nm f k@KVar      {}         = f k nm
         walk _d nm f k@KBool     {}         = f k nm
         walk _d nm f k@KBounded  {}         = f k nm
         walk _d nm f k@KUnbounded{}         = f k nm
         walk _d nm f k@KReal     {}         = f k nm
-        walk _d nm f k@KUserSort {}         = f k nm
+        walk _d nm f k@KApp      {}         = f k nm
         walk _d nm f k@KFloat    {}         = f k nm
         walk _d nm f k@KDouble   {}         = f k nm
         walk _d nm f k@KRational {}         = f k nm
@@ -1160,18 +1160,14 @@
                                                 project i = "(proj_" ++ show i ++ "_" ++ tt ++ " " ++ nm ++ ")"
                                                 nmks      = [(project i, k) | (i, k) <- zip [1::Int ..] ks]
                                             in concatMap (\(n, k) -> walk (d+1) n f k) nmks
-        walk  d  nm  f km@(KMaybe k)      = let n = "(get_just_SBVMaybe " ++ nm ++ ")"
-                                            in  ["(=> " ++ "((_ is (just_SBVMaybe (" ++ smtType k ++ ") " ++ smtType km ++ ")) " ++ nm ++ ") " ++ c ++ ")" | c <- walk (d+1) n f k]
-        walk  d  nm  f ke@(KEither k1 k2) = let n1 = "(get_left_SBVEither "  ++ nm ++ ")"
-                                                n2 = "(get_right_SBVEither " ++ nm ++ ")"
-                                                c1 = ["(=> " ++ "((_ is (left_SBVEither ("  ++ smtType k1 ++ ") " ++ smtType ke ++ ")) " ++ nm ++ ") " ++ c ++ ")" | c <- walk (d+1) n1 f k1]
-                                                c2 = ["(=> " ++ "((_ is (right_SBVEither (" ++ smtType k2 ++ ") " ++ smtType ke ++ ")) " ++ nm ++ ") " ++ c ++ ")" | c <- walk (d+1) n2 f k2]
-                                            in c1 ++ c2
         walk d  nm f  (KArray k1 k2)
           | all charRatFree [k1, k2]      = []
           | True                          = let fnm   = "array" ++ show d
                                                 cstrs = walk (d+1) ("(select " ++ nm ++ " " ++ fnm ++ ")") f k2
                                             in mkAnd cstrs $ \hole -> ["(forall ((" ++ fnm ++ " " ++ smtType k1 ++ ")) " ++ hole ++ ")"]
+        walk d nm f (KADT ty dict pureFS) = let fs = [(c, map (substituteADTVars ty dict) ks) | (c, ks) <- pureFS]
+                                                nmks  = [("(get" ++ c ++ "_" ++ show i ++ " " ++ nm ++ ")", k) | (c, ks) <- fs, (i, k) <- zip [(1::Int)..] ks]
+                                            in concatMap (\(n, k) -> walk (d+1) n f k) nmks
 
 -----------------------------------------------------------------------------------------------
 -- Casts supported by SMTLib. (From: <https://smt-lib.org/theories-FloatingPoint.shtml>)
@@ -1241,6 +1237,20 @@
 shft oW oS x c = "(" ++ o ++ " " ++ cvtSV x ++ " " ++ cvtSV c ++ ")"
    where o = if hasSign x then oS else oW
 
+-- ADT operations
+handleADT :: SolverCapabilities -> ADTOp -> [SV] -> String
+handleADT caps op args = case args of
+                          [] -> f
+                          _  -> "(" ++ f ++ " " ++ unwords (map cvtSV args) ++ ")"
+  where f = case op of
+              ADTConstructor nm k -> ascribe nm k
+              ADTTester      nm k -> if supportsDirectTesters caps
+                                     then nm
+                                     else ascribe nm k
+              ADTAccessor    nm _ -> nm
+
+        ascribe nm k = "(as " ++ nm ++ " " ++ smtType k ++ ")"
+
 -- Various casts
 handleKindCast :: Kind -> Kind -> String -> String
 handleKindCast kFrom kTo a
@@ -1340,3 +1350,5 @@
         smtBool :: Bool -> String
         smtBool True  = "true"
         smtBool False = "false"
+
+{- HLint ignore module "Use record patterns" -}
diff --git a/Data/SBV/SMT/Utils.hs b/Data/SBV/SMT/Utils.hs
--- a/Data/SBV/SMT/Utils.hs
+++ b/Data/SBV/SMT/Utils.hs
@@ -16,7 +16,6 @@
 module Data.SBV.SMT.Utils (
           SMTLibConverter
         , SMTLibIncConverter
-        , witnessName
         , addAnnotations
         , showTimeoutValue
         , alignDiagnostic
@@ -85,11 +84,6 @@
                           -> S.Seq (Bool, [(String, String)], SV)        -- ^ extra constraints
                           -> SMTConfig                                   -- ^ configuration
                           -> a
-
--- | The name of a witness for a type. We should make sure this doesn't conflict any reserved names, but I think the chances of that is
--- pretty low anyhow.
-witnessName :: String -> String
-witnessName = (++ "_witness")
 
 -- | Create an annotated term
 addAnnotations :: [(String, String)] -> String -> String
diff --git a/Data/SBV/Set.hs b/Data/SBV/Set.hs
--- a/Data/SBV/Set.hs
+++ b/Data/SBV/Set.hs
@@ -62,6 +62,7 @@
 -- >>> -- For doctest purposes only:
 -- >>> import Prelude hiding(null)
 -- >>> import Data.SBV hiding(complement)
+-- >>> import Data.SBV.Maybe
 -- >>> :set -XScopedTypeVariables
 #endif
 
diff --git a/Data/SBV/TP.hs b/Data/SBV/TP.hs
--- a/Data/SBV/TP.hs
+++ b/Data/SBV/TP.hs
@@ -29,13 +29,16 @@
        -- * Basic proofs
        , lemma, lemmaWith
 
+       -- * Basic proofs, with induction schema
+       , inductiveLemma, inductiveLemmaWith
+
        -- * Reasoning via calculation
        , calc, calcWith
 
-       -- * Reasoning via regular induction
+       -- * Reasoning via explicit regular induction
        , induct, inductWith
 
-       -- * Reasoning via measure-based strong induction
+       -- * Reasoning via explicit measure-based strong induction
        , sInduct, sInductWith
 
        -- * Creating instances of proofs
diff --git a/Data/SBV/TP/Kernel.hs b/Data/SBV/TP/Kernel.hs
--- a/Data/SBV/TP/Kernel.hs
+++ b/Data/SBV/TP/Kernel.hs
@@ -9,23 +9,22 @@
 -- Kernel of the TP prover API.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ConstraintKinds      #-}
-{-# LANGUAGE DataKinds            #-}
-{-# LANGUAGE FlexibleContexts     #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE NamedFieldPuns       #-}
-{-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE TypeAbstractions     #-}
+{-# LANGUAGE ConstraintKinds     #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE NamedFieldPuns      #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
 module Data.SBV.TP.Kernel (
          Proposition,  Proof(..)
        , axiom
-       , lemma
-       , lemmaWith
+       , lemma,          lemmaWith
+       , inductiveLemma, inductiveLemmaWith
        , internalAxiom
-       , TPProofContext (..), smtProofStep
+       , TPProofContext (..), smtProofStep, HasInductionSchema(..)
        ) where
 
 import Control.Monad.Trans  (liftIO, MonadIO)
@@ -48,6 +47,10 @@
 
 import Data.Dynamic
 
+import Type.Reflection (typeRep)
+
+import qualified Data.SBV.List as SL (nil, (.:))
+
 -- | A proposition is something SBV is capable of proving/disproving in TP.
 type Proposition a = ( QNot a
                      , QuantifiedBool a
@@ -58,6 +61,109 @@
                      , Typeable a
                      )
 
+-- | An inductive proposition is a proposition that has an induction scheme associated with it.
+type Inductive a = (HasInductionSchema a, Proposition a)
+
+-- | A class of values that has an associated induction schema. SBV manages this internally.
+class HasInductionSchema a where
+  inductionSchema :: a -> ProofObj
+
+-- | Induction schema for integers. Note that this is good for proving properties over naturals really.
+-- There are other instances that would apply to all integers, but this one is really the most useful
+-- in practice.
+instance HasInductionSchema (Forall nm Integer -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom "inductInteger" ax
+     where pf = p . Forall
+           ax =   sAnd [pf 0, quantifiedBool (\(Forall i) -> (i .>= 0 .=> pf i) .=> pf (i + 1))]
+              .=> quantifiedBool (\(Forall i) -> pf i)
+
+-- | Induction schema for integers with one extra argument
+instance SymVal at => HasInductionSchema (Forall nm Integer -> Forall an at -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom "inductInteger1" ax
+     where pf i a = p (Forall i) (Forall a)
+           ax     = sAnd [ quantifiedBool (\           (Forall a) -> pf 0 a)
+                         , quantifiedBool (\(Forall i) (Forall a) -> (i .>= 0 .=> pf i a) .=> pf (i + 1) a)]
+                    .=>    quantifiedBool (\(Forall i) (Forall a) -> pf i a)
+
+-- | Induction schema for integers with two extra arguments
+instance (SymVal at, SymVal bt) => HasInductionSchema (Forall nm Integer -> Forall an at -> Forall bn bt -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom "inductInteger2" ax
+     where pf i a b = p (Forall i) (Forall a) (Forall b)
+           ax       = sAnd [ quantifiedBool (\           (Forall a) (Forall b) -> pf 0 a b)
+                           , quantifiedBool (\(Forall i) (Forall a) (Forall b) -> (i .>= 0 .=> pf i a b) .=> pf (i + 1) a b)]
+                      .=>    quantifiedBool (\(Forall i) (Forall a) (Forall b) -> pf i a b)
+
+-- | Induction schema for integers with three extra arguments
+instance (SymVal at, SymVal bt, SymVal ct) => HasInductionSchema (Forall nm Integer -> Forall an at -> Forall bn bt -> Forall cn ct -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom "inductInteger3" ax
+     where pf i a b c = p (Forall i) (Forall a) (Forall b) (Forall c)
+           ax         = sAnd [ quantifiedBool (\           (Forall a) (Forall b) (Forall c) -> pf 0 a b c)
+                             , quantifiedBool (\(Forall i) (Forall a) (Forall b) (Forall c) -> (i .>= 0 .=> pf i a b c) .=> pf (i + 1) a b c)]
+                        .=>    quantifiedBool (\(Forall i) (Forall a) (Forall b) (Forall c) -> pf i a b c)
+
+-- | Induction schema for integers with four extra arguments
+instance (SymVal at, SymVal bt, SymVal ct, SymVal dt) => HasInductionSchema (Forall nm Integer -> Forall an at -> Forall bn bt -> Forall cn ct -> Forall dn dt -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom "inductInteger4" ax
+     where pf i a b c d = p (Forall i) (Forall a) (Forall b) (Forall c) (Forall d)
+           ax           = sAnd [ quantifiedBool (\           (Forall a) (Forall b) (Forall c) (Forall d) -> pf 0 a b c d)
+                               , quantifiedBool (\(Forall i) (Forall a) (Forall b) (Forall c) (Forall d) -> (i .>= 0 .=> pf i a b c d) .=> pf (i + 1) a b c d)]
+                          .=>    quantifiedBool (\(Forall i) (Forall a) (Forall b) (Forall c) (Forall d) -> pf i a b c d)
+
+-- | Induction schema for integers with five extra arguments
+instance (SymVal at, SymVal bt, SymVal ct, SymVal dt, SymVal et) => HasInductionSchema (Forall nm Integer -> Forall an at -> Forall bn bt -> Forall cn ct -> Forall dn dt -> Forall en et -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom "inductInteger5" ax
+     where pf i a b c d e = p (Forall i) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e)
+           ax             = sAnd [ quantifiedBool (\           (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) -> pf 0 a b c d e)
+                                 , quantifiedBool (\(Forall i) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) -> (i .>= 0 .=> pf i a b c d e) .=> pf (i + 1) a b c d e)]
+                            .=>    quantifiedBool (\(Forall i) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) -> pf i a b c d e)
+
+-- | Induction schema for lists.
+instance SymVal x => HasInductionSchema (Forall nm [x] -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom ("induct" ++ show (typeRep @[x])) ax
+     where pf = p . Forall
+           ax =   sAnd [pf SL.nil, quantifiedBool (\(Forall x) (Forall xs) -> pf xs .=> pf (x SL..: xs))]
+              .=> quantifiedBool (\(Forall xs) -> pf xs)
+
+-- | Induction schema for lists with one extra argument
+instance (SymVal x, SymVal at) => HasInductionSchema (Forall nm [x] -> Forall an at -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom ("induct" ++ show (typeRep @[x]) ++ "1") ax
+     where pf xs a = p (Forall xs) (Forall a)
+           ax      = sAnd [ quantifiedBool (\                       (Forall a) -> pf SL.nil a)
+                          , quantifiedBool (\(Forall x) (Forall xs) (Forall a) -> pf xs a .=> pf (x SL..: xs) a)]
+                     .=>    quantifiedBool (\(Forall xs) (Forall a) -> pf xs a)
+
+-- | Induction schema for lists with two extra arguments
+instance (SymVal x, SymVal at, SymVal bt) => HasInductionSchema (Forall nm [x] -> Forall an at -> Forall bn bt -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom ("induct" ++ show (typeRep @[x]) ++ "2") ax
+     where pf xs a b = p (Forall xs) (Forall a) (Forall b)
+           ax        = sAnd [ quantifiedBool (\                       (Forall a) (Forall b) -> pf SL.nil a b)
+                            , quantifiedBool (\(Forall x) (Forall xs) (Forall a) (Forall b) -> pf xs a b .=> pf (x SL..: xs) a b)]
+                       .=>    quantifiedBool (\(Forall xs) (Forall a) (Forall b) -> pf xs a b)
+
+-- | Induction schema for lists with three extra arguments
+instance (SymVal x, SymVal at, SymVal bt, SymVal ct) => HasInductionSchema (Forall nm [x] -> Forall an at -> Forall bn bt -> Forall cn ct -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom ("induct" ++ show (typeRep @[x]) ++ "3") ax
+     where pf xs a b c = p (Forall xs) (Forall a) (Forall b) (Forall c)
+           ax          = sAnd [ quantifiedBool (\                       (Forall a) (Forall b) (Forall c) -> pf SL.nil a b c)
+                              , quantifiedBool (\(Forall x) (Forall xs) (Forall a) (Forall b) (Forall c) -> pf xs a b c .=> pf (x SL..: xs) a b c)]
+                         .=>    quantifiedBool (\(Forall xs) (Forall a) (Forall b) (Forall c) -> pf xs a b c)
+
+-- | Induction schema for lists with four extra arguments
+instance (SymVal x, SymVal at, SymVal bt, SymVal ct, SymVal dt) => HasInductionSchema (Forall nm [x] -> Forall an at -> Forall bn bt -> Forall cn ct -> Forall dn dt -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom ("induct" ++ show (typeRep @[x]) ++ "4") ax
+     where pf xs a b c d = p (Forall xs) (Forall a) (Forall b) (Forall c) (Forall d)
+           ax            = sAnd [ quantifiedBool (\                       (Forall a) (Forall b) (Forall c) (Forall d) -> pf SL.nil a b c d)
+                                , quantifiedBool (\(Forall x) (Forall xs) (Forall a) (Forall b) (Forall c) (Forall d) -> pf xs a b c d .=> pf (x SL..: xs) a b c d)]
+                           .=>    quantifiedBool (\(Forall xs) (Forall a) (Forall b) (Forall c) (Forall d) -> pf xs a b c d)
+
+-- | Induction schema for lists with five extra arguments
+instance (SymVal x, SymVal at, SymVal bt, SymVal ct, SymVal dt, SymVal et) => HasInductionSchema (Forall nm [x] -> Forall an at -> Forall bn bt -> Forall cn ct -> Forall dn dt -> Forall en et -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom ("induct" ++ show (typeRep @[x]) ++ "5") ax
+     where pf xs a b c d e = p (Forall xs) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e)
+           ax              = sAnd [ quantifiedBool (\                       (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) -> pf SL.nil a b c d e)
+                                  , quantifiedBool (\(Forall x) (Forall xs) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) -> pf xs a b c d e .=> pf (x SL..: xs) a b c d e)]
+                             .=>    quantifiedBool (\(Forall xs) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) -> pf xs a b c d e)
+
 -- | Accept the given definition as a fact. Usually used to introduce definitial axioms,
 -- giving meaning to uninterpreted symbols. Note that we perform no checks on these propositions,
 -- if you assert nonsense, then you get nonsense back. So, calls to 'axiom' should be limited to
@@ -106,6 +212,15 @@
 lemma :: Proposition a => String -> a -> [ProofObj] -> TP (Proof a)
 lemma nm f by = do cfg <- getTPConfig
                    lemmaWith cfg nm f by
+
+-- | Prove a given statement, using the induction schema for the proposition. Using the default solver.
+inductiveLemma :: Inductive a => String -> a -> [ProofObj] -> TP (Proof a)
+inductiveLemma nm f by = do cfg <- getTPConfig
+                            inductiveLemmaWith cfg nm f by
+
+-- | Prove a given statement, using the induction schema for the proposition. Using the default solver.
+inductiveLemmaWith :: Inductive a => SMTConfig -> String -> a -> [ProofObj] -> TP (Proof a)
+inductiveLemmaWith cfg nm f by = lemmaWith cfg nm f (inductionSchema f : by)
 
 -- | Capture the general flow of a proof-step. Note that this is the only point where we call the backend solver
 -- in a TP proof.
diff --git a/Data/SBV/TP/List.hs b/Data/SBV/TP/List.hs
--- a/Data/SBV/TP/List.hs
+++ b/Data/SBV/TP/List.hs
@@ -14,9 +14,8 @@
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE OverloadedLists     #-}
-{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE QuasiQuotes         #-}
-{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
@@ -139,7 +138,7 @@
 initsLength =
    sInduct "initsLength"
            (\(Forall xs) -> length (inits xs) .== 1 + length xs)
-           (length @a) $
+           (length @a, []) $
            \ih xs -> [] |- length (inits xs)
                         ?? ih
                         =: 1 + length xs
@@ -372,7 +371,7 @@
 enumLen =
   sInduct "enumLen"
           (\(Forall n) (Forall m) -> length [sEnum|n .. m|] .== 0 `smax` (m - n + 1))
-          (\n m -> abs (m - n)) $
+          (\n m -> abs (m - n), []) $
           \ih n m -> [] |- length [sEnum|n+1 .. m|]
                         =: cases [ n+1 .>  m ==> trivial
                                  , n+1 .<= m ==> length (n+1 .: [sEnum|n+2 .. m|])
@@ -411,7 +410,7 @@
   helper <- sInduct "helper"
                     (\(Forall @"m" (m :: SInteger)) (Forall @"n" n) ->
                           n .< m .=> [sEnum|m, m-1 .. n+1|] ++ [n] .== [sEnum|m, m-1 .. n|])
-                    (\m n -> abs (m - n)) $
+                    (\m n -> abs (m - n), []) $
                     \ih m n -> [n .< m] |- [sEnum|m, m-1 .. n+1|] ++ [n]
                                         =: m .: [sEnum|m-1, m-2 .. n+1|] ++ [n]
                                         ?? ih
@@ -421,7 +420,7 @@
 
   sInduct "revNM"
           (\(Forall n) (Forall m) -> reverse [sEnum|n .. m|] .== [sEnum|m, m-1 .. n|])
-          (\n m -> abs (m - n)) $
+          (\n m -> abs (m - n), []) $
           \ih n m -> [] |- reverse [sEnum|n .. m|]
                         =: cases [ n .>  m ==> trivial
                                  , n .<= m ==> reverse (n .: [sEnum|(n+1) .. m|])
@@ -1140,7 +1139,7 @@
    -- Helper: prove that noAdd is true for the result of destutter
    helper3 <- sInductWith cvc5 "helper3"
                   (\(Forall @"xs" (xs :: SList a)) -> noAdd (destutter xs))
-                  length $
+                  (length, []) $
                   \ih xs -> []
                          |- noAdd (destutter xs)
                          =: split xs
@@ -1693,7 +1692,7 @@
 interleaveLen :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
 interleaveLen = sInduct "interleaveLen"
                         (\(Forall xs) (Forall ys) -> length xs + length ys .== length (interleave xs ys))
-                        (\xs ys -> length xs + length ys) $
+                        (\xs ys -> length xs + length ys, []) $
                         \ih xs ys -> [] |- length xs + length ys .== length (interleave xs ys)
                                         =: split xs
                                                  trivial
@@ -1752,7 +1751,7 @@
          (\(Forall @"xs" xs) (Forall @"ys" ys) (Forall @"alts" alts) ->
                length xs .== length ys .=> let (es, os) = untuple alts
                                            in uninterleaveGen (interleave xs ys) alts .== tuple (reverse es ++ xs, reverse os ++ ys))
-         (\xs ys _alts -> length xs + length ys) $
+         (\xs ys _alts -> length xs + length ys, []) $
          \ih xs ys alts -> [length xs .== length ys]
                         |- let (es, os) = untuple alts
                         in uninterleaveGen (interleave xs ys) alts
diff --git a/Data/SBV/TP/TP.hs b/Data/SBV/TP/TP.hs
--- a/Data/SBV/TP/TP.hs
+++ b/Data/SBV/TP/TP.hs
@@ -7,19 +7,16 @@
 -- Stability : experimental
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ConstraintKinds            #-}
-{-# LANGUAGE DataKinds                  #-}
-{-# LANGUAGE DerivingStrategies         #-}
-{-# LANGUAGE FlexibleContexts           #-}
-{-# LANGUAGE FlexibleInstances          #-}
-{-# LANGUAGE MultiParamTypeClasses      #-}
-{-# LANGUAGE NamedFieldPuns             #-}
-{-# LANGUAGE ScopedTypeVariables        #-}
-{-# LANGUAGE TupleSections              #-}
-{-# LANGUAGE TypeAbstractions           #-}
-{-# LANGUAGE TypeApplications           #-}
-{-# LANGUAGE TypeFamilyDependencies     #-}
-{-# LANGUAGE TypeOperators              #-}
+{-# LANGUAGE DataKinds              #-}
+{-# LANGUAGE FlexibleContexts       #-}
+{-# LANGUAGE FlexibleInstances      #-}
+{-# LANGUAGE MultiParamTypeClasses  #-}
+{-# LANGUAGE NamedFieldPuns         #-}
+{-# LANGUAGE ScopedTypeVariables    #-}
+{-# LANGUAGE TupleSections          #-}
+{-# LANGUAGE TypeApplications       #-}
+{-# LANGUAGE TypeFamilyDependencies #-}
+{-# LANGUAGE TypeOperators          #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -27,10 +24,11 @@
          Proposition, Proof, proofOf, assumptionFromProof, Instantiatable(..), Inst(..)
        , rootOfTrust, RootOfTrust(..), ProofTree(..), showProofTree, showProofTreeHTML
        ,   axiom
-       ,   lemma,   lemmaWith
-       ,    calc,    calcWith
-       ,  induct,  inductWith
-       , sInduct, sInductWith
+       ,            lemma,          lemmaWith
+       ,   inductiveLemma, inductiveLemmaWith
+       ,             calc,           calcWith
+       ,           induct,         inductWith
+       ,          sInduct,        sInductWith
        , sorry
        , TP, runTP, runTPWith, tpQuiet, tpRibbon, tpStats, tpAsms, tpCache
        , (|-), (|->), (⊢), (=:), (≡), (??), (∵), split, split2, cases, (==>), (⟹), qed, trivial, contradiction
@@ -501,7 +499,7 @@
 
 -- | Captures the schema for an inductive proof. Base case might be nothing, to cover strong induction.
 data InductionStrategy = InductionStrategy { inductionIntros     :: SBool
-                                           , inductionMeasure    :: Maybe SBool
+                                           , inductionMeasure    :: Maybe (SBool, [ProofObj])
                                            , inductionBaseCase   :: Maybe SBool
                                            , inductionProofTree  :: TPProof
                                            , inductiveStep       :: SBool
@@ -518,7 +516,15 @@
                                                     inductionProofSteps
                                                     inductiveStep
                                                     _inductiveQCInstance)
-  = inductionIntros : inductiveStep : proofTreeSaturatables inductionProofSteps ++ maybeToList inductionBaseCase ++ maybeToList inductionMeasure
+  = inductionIntros
+  : inductiveStep
+  : proofTreeSaturatables inductionProofSteps
+  ++ measureDs
+  ++ maybeToList inductionBaseCase
+  where objDeps p = getObjProof p : concatMap objDeps (dependencies p)
+        measureDs = case inductionMeasure of
+                      Nothing      -> []
+                      Just (a, ps) -> a : concatMap objDeps ps
 
 -- | A class for doing regular inductive proofs.
 class Inductive a where
@@ -570,19 +576,19 @@
    -- | Inductively prove a lemma, using measure based induction, using the default config.
    -- Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only
    -- partial correctness is guaranteed if non-terminating functions are involved.
-   sInduct :: (Proposition a, Zero m, SymVal t, EqSymbolic (SBV t)) => String -> a -> MeasureArgs a m -> (Proof a -> StepArgs a t) -> TP (Proof a)
+   sInduct :: (Proposition a, Zero m, SymVal t, EqSymbolic (SBV t)) => String -> a -> (MeasureArgs a m, [ProofObj]) -> (Proof a -> StepArgs a t) -> TP (Proof a)
 
    -- | Same as 'sInduct', but with the given solver configuration.
    -- Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only
    -- partial correctness is guaranteed if non-terminating functions are involved.
-   sInductWith :: (Proposition a, Zero m, SymVal t, EqSymbolic (SBV t)) => SMTConfig -> String -> a -> MeasureArgs a m -> (Proof a -> StepArgs a t) -> TP (Proof a)
+   sInductWith :: (Proposition a, Zero m, SymVal t, EqSymbolic (SBV t)) => SMTConfig -> String -> a -> (MeasureArgs a m, [ProofObj]) -> (Proof a -> StepArgs a t) -> TP (Proof a)
 
-   sInduct         nm p m steps = getTPConfig >>= \cfg  -> sInductWith                            cfg                   nm p m steps
-   sInductWith cfg nm p m steps = getTPConfig >>= \cfg' -> inductionEngine GeneralInduction False (tpMergeCfg cfg cfg') nm p (sInductionStrategy p m steps)
+   sInduct         nm p mhs steps = getTPConfig >>= \cfg  -> sInductWith                            cfg                   nm p mhs steps
+   sInductWith cfg nm p mhs steps = getTPConfig >>= \cfg' -> inductionEngine GeneralInduction False (tpMergeCfg cfg cfg') nm p (sInductionStrategy p mhs steps)
 
    -- | Internal, shouldn't be needed outside the library
    {-# MINIMAL sInductionStrategy #-}
-   sInductionStrategy :: (Proposition a, Zero m, SymVal t, EqSymbolic (SBV t)) => a -> MeasureArgs a m -> (Proof a -> StepArgs a t) -> Symbolic InductionStrategy
+   sInductionStrategy :: (Proposition a, Zero m, SymVal t, EqSymbolic (SBV t)) => a -> (MeasureArgs a m, [ProofObj]) -> (Proof a -> StepArgs a t) -> Symbolic InductionStrategy
 
 -- | Do an inductive proof, based on the given strategy
 inductionEngine :: Proposition a => InductionStyle -> Bool -> SMTConfig -> String -> a -> Symbolic InductionStrategy -> TP (Proof a)
@@ -613,14 +619,14 @@
       query $ do
 
        case inductionMeasure of
-          Nothing -> queryDebug [nm ++ ": Induction" ++ qual ++ ", there is no custom measure to show non-negativeness."]
-          Just ms -> do queryDebug [nm ++ ": Induction, proving measure is always non-negative:"]
-                        smtProofStep cfg tpSt "Step" 1
-                                              (TPProofStep False nm [] ["Measure is non-negative"])
-                                              (Just inductionIntros)
-                                              ms
-                                              []
-                                              (\d -> finishTP cfg "Q.E.D." d [])
+          Nothing      -> queryDebug [nm ++ ": Induction" ++ qual ++ ", there is no custom measure to show non-negativeness."]
+          Just (m, hs) -> do queryDebug [nm ++ ": Induction, proving measure is always non-negative:"]
+                             smtProofStep cfg tpSt "Step" 1
+                                                   (TPProofStep False nm [] ["Measure is non-negative"])
+                                                   (Just (sAnd (inductionIntros : map getObjProof hs)))
+                                                   m
+                                                   []
+                                                   (\d -> finishTP cfg "Q.E.D." d [])
        case inductionBaseCase of
           Nothing -> queryDebug [nm ++ ": Induction" ++ qual ++ ", there is no base case to prove."]
           Just bc -> do queryDebug [nm ++ ": Induction, proving base case:"]
@@ -634,7 +640,7 @@
        proveProofTree cfg tpSt nm (result, inductiveStep) inductionIntros inductionProofTree u inductiveQCInstance
 
 -- Induction strategy helper
-mkIndStrategy :: (SymVal a, EqSymbolic (SBV a)) => Maybe SBool -> Maybe SBool -> (SBool, TPProofRaw (SBV a)) -> SBool -> ([Int] -> Symbolic SBool) -> Symbolic InductionStrategy
+mkIndStrategy :: (SymVal a, EqSymbolic (SBV a)) => Maybe (SBool, [ProofObj]) -> Maybe SBool -> (SBool, TPProofRaw (SBV a)) -> SBool -> ([Int] -> Symbolic SBool) -> Symbolic InductionStrategy
 mkIndStrategy mbMeasure mbBaseCase indSteps step indQCInstance = do
         CalcStrategy { calcIntros, calcProofTree, calcQCInstance } <- mkCalcSteps indSteps indQCInstance
         pure $ InductionStrategy { inductionIntros     = calcIntros
@@ -1031,13 +1037,13 @@
 
 -- | Generalized induction with one parameter
 instance (KnownSymbol na, SymVal a) => SInductive (Forall na a -> SBool) where
-  sInductionStrategy result measure steps = do
+  sInductionStrategy result (measure, helpers) steps = do
       (a, na) <- mkVar (Proxy @na)
 
       let ih   = internalAxiom "IH" (\(Forall a' :: Forall na a) -> measure a' .< measure a .=> result (Forall a'))
           conc = result (Forall a)
 
-      mkIndStrategy (Just (measure a .>= zero))
+      mkIndStrategy (Just (measure a .>= zero, helpers))
                     Nothing
                     (steps ih a)
                     (indResult [na] conc)
@@ -1045,14 +1051,14 @@
 
 -- | Generalized induction with two parameters
 instance (KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b) => SInductive (Forall na a -> Forall nb b -> SBool) where
-  sInductionStrategy result measure steps = do
+  sInductionStrategy result (measure, helpers) steps = do
       (a, na) <- mkVar (Proxy @na)
       (b, nb) <- mkVar (Proxy @nb)
 
       let ih   = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) -> measure a' b' .< measure a b .=> result (Forall a') (Forall b'))
           conc = result (Forall a) (Forall b)
 
-      mkIndStrategy (Just (measure a b .>= zero))
+      mkIndStrategy (Just (measure a b .>= zero, helpers))
                     Nothing
                     (steps ih a b)
                     (indResult [na, nb] conc)
@@ -1060,7 +1066,7 @@
 
 -- | Generalized induction with three parameters
 instance (KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c) => SInductive (Forall na a -> Forall nb b -> Forall nc c -> SBool) where
-  sInductionStrategy result measure steps = do
+  sInductionStrategy result (measure, helpers) steps = do
       (a, na) <- mkVar (Proxy @na)
       (b, nb) <- mkVar (Proxy @nb)
       (c, nc) <- mkVar (Proxy @nc)
@@ -1068,7 +1074,7 @@
       let ih   = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) -> measure a' b' c' .< measure a b c .=> result (Forall a') (Forall b') (Forall c'))
           conc = result (Forall a) (Forall b) (Forall c)
 
-      mkIndStrategy (Just (measure a b c .>= zero))
+      mkIndStrategy (Just (measure a b c .>= zero, helpers))
                     Nothing
                     (steps ih a b c)
                     (indResult [na, nb, nc] conc)
@@ -1076,7 +1082,7 @@
 
 -- | Generalized induction with four parameters
 instance (KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c, KnownSymbol nd, SymVal d) => SInductive (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) where
-  sInductionStrategy result measure steps = do
+  sInductionStrategy result (measure, helpers) steps = do
       (a, na) <- mkVar (Proxy @na)
       (b, nb) <- mkVar (Proxy @nb)
       (c, nc) <- mkVar (Proxy @nc)
@@ -1085,7 +1091,7 @@
       let ih   = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) (Forall d' :: Forall nd d) -> measure a' b' c' d' .< measure a b c d .=> result (Forall a') (Forall b') (Forall c') (Forall d'))
           conc = result (Forall a) (Forall b) (Forall c) (Forall d)
 
-      mkIndStrategy (Just (measure a b c d .>= zero))
+      mkIndStrategy (Just (measure a b c d .>= zero, helpers))
                     Nothing
                     (steps ih a b c d)
                     (indResult [na, nb, nc, nd] conc)
@@ -1093,7 +1099,7 @@
 
 -- | Generalized induction with five parameters
 instance (KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c, KnownSymbol nd, SymVal d, KnownSymbol ne, SymVal e) => SInductive (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) where
-  sInductionStrategy result measure steps = do
+  sInductionStrategy result (measure, helpers) steps = do
       (a, na) <- mkVar (Proxy @na)
       (b, nb) <- mkVar (Proxy @nb)
       (c, nc) <- mkVar (Proxy @nc)
@@ -1103,7 +1109,7 @@
       let ih   = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) (Forall d' :: Forall nd d) (Forall e' :: Forall ne e) -> measure a' b' c' d' e' .< measure a b c d e .=> result (Forall a') (Forall b') (Forall c') (Forall d') (Forall e'))
           conc = result (Forall a) (Forall b) (Forall c) (Forall d) (Forall e)
 
-      mkIndStrategy (Just (measure a b c d e .>= zero))
+      mkIndStrategy (Just (measure a b c d e .>= zero, helpers))
                     Nothing
                     (steps ih a b c d e)
                     (indResult [na, nb, nc, nd, ne] conc)
diff --git a/Data/SBV/TP/Utils.hs b/Data/SBV/TP/Utils.hs
--- a/Data/SBV/TP/Utils.hs
+++ b/Data/SBV/TP/Utils.hs
@@ -17,7 +17,6 @@
 {-# LANGUAGE NamedFieldPuns             #-}
 {-# LANGUAGE ScopedTypeVariables        #-}
 {-# LANGUAGE TupleSections              #-}
-{-# LANGUAGE TypeAbstractions           #-}
 {-# LANGUAGE TypeApplications           #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
diff --git a/Data/SBV/Tools/BMC.hs b/Data/SBV/Tools/BMC.hs
--- a/Data/SBV/Tools/BMC.hs
+++ b/Data/SBV/Tools/BMC.hs
@@ -11,7 +11,6 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE TypeFamilies     #-}
 {-# LANGUAGE TypeOperators    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
diff --git a/Data/SBV/Tools/BVOptimize.hs b/Data/SBV/Tools/BVOptimize.hs
--- a/Data/SBV/Tools/BVOptimize.hs
+++ b/Data/SBV/Tools/BVOptimize.hs
@@ -97,7 +97,7 @@
 minMaxBV :: SFiniteBits a => Bool -> SMTConfig -> Bool -> SBV a -> Symbolic SatResult
 minMaxBV isMax cfg getUC v
  | hasSign v
- = error $ "minMaxBV works on unsigned bitvectors, received: " ++ show (kindOf v)
+ = error $ "minMaxBV works on unsigned bit-vectors, received: " ++ show (kindOf v)
  | True
  = do when getUC $ setOption $ ProduceUnsatCores True
       query $ go (blastBE v)
diff --git a/Data/SBV/Tools/GenTest.hs b/Data/SBV/Tools/GenTest.hs
--- a/Data/SBV/Tools/GenTest.hs
+++ b/Data/SBV/Tools/GenTest.hs
@@ -141,10 +141,10 @@
                  KReal             -> error $ "SBV.renderTest: Unsupported real valued test value: " ++ show cv
                  KList es          -> error $ "SBV.renderTest: Unsupported list valued test: [" ++ show es ++ "]"
                  KSet  es          -> error $ "SBV.renderTest: Unsupported set valued test: {" ++ show es ++ "}"
-                 KUserSort us _    -> error $ "SBV.renderTest: Unsupported uninterpreted sort: " ++ us
                  _                 -> error $ "SBV.renderTest: Unexpected CV: " ++ show cv
 
         s cv = case kindOf cv of
+                  KVar{}            -> error $ "SBV.renderTest: Unexpected: " ++ show (kindOf cv)
                   KBool             -> take 5 (show (cvToBool cv) ++ repeat ' ')
                   KBounded sgn   sz -> let CInteger w = cvVal cv in shex  False True (sgn, sz) w
                   KUnbounded        -> let CInteger w = cvVal cv in shexI False True           w
@@ -157,11 +157,10 @@
                   KReal             -> let CAlgReal w = cvVal cv in algRealToHaskell w
                   KList es          -> error $ "SBV.renderTest: Unsupported list valued sort: [" ++ show es ++ "]"
                   KSet  es          -> error $ "SBV.renderTest: Unsupported set valued sort: {" ++ show es ++ "}"
-                  KUserSort us _    -> error $ "SBV.renderTest: Unsupported uninterpreted sort: " ++ us
-                  k@KTuple{}        -> error $ "SBV.renderTest: Unsupported tuple: " ++ show k
-                  k@KMaybe{}        -> error $ "SBV.renderTest: Unsupported maybe: " ++ show k
-                  k@KEither{}       -> error $ "SBV.renderTest: Unsupported sum: "   ++ show k
-                  k@KArray{}        -> error $ "SBV.renderTest: Unsupported array: " ++ show k
+                  k@KApp{}          -> error $ "SBV.renderTest: Unsupported adt app: " ++ show k
+                  k@KADT{}          -> error $ "SBV.renderTest: Unsupported adt: "     ++ show k
+                  k@KTuple{}        -> error $ "SBV.renderTest: Unsupported tuple: "   ++ show k
+                  k@KArray{}        -> error $ "SBV.renderTest: Unsupported array: "   ++ show k
 
 c :: String -> [([CV], [CV])] -> String
 c n vs = intercalate "\n" $
@@ -231,6 +230,7 @@
               ]
   where mkField p cv i = "    " ++ t ++ " " ++ p ++ show i ++ ";"
             where t = case kindOf cv of
+                        KVar{}            -> error $ "SBV.renderTest: Unexpected: " ++ show (kindOf cv)
                         KBool             -> "SBool"
                         KBounded False 8  -> "SWord8"
                         KBounded False 16 -> "SWord16"
@@ -249,35 +249,33 @@
                         KString           -> error "SBV.renderTest: Unsupported string"
                         KUnbounded        -> error "SBV.renderTest: Unbounded integers are not supported when generating C test-cases."
                         KReal             -> error "SBV.renderTest: Real values are not supported when generating C test-cases."
-                        KUserSort us _    -> error $ "SBV.renderTest: Unsupported uninterpreted sort: " ++ us
+                        k@KApp{}          -> error $ "SBV.renderTest: Unsupported adt app: "     ++ show k
+                        k@KADT{}          -> error $ "SBV.renderTest: Unsupported adt: "         ++ show k
                         k@KList{}         -> error $ "SBV.renderTest: Unsupported list sort: "   ++ show k
                         k@KSet{}          -> error $ "SBV.renderTest: Unsupported set sort: "    ++ show k
                         k@KTuple{}        -> error $ "SBV.renderTest: Unsupported tuple sort: "  ++ show k
-                        k@KMaybe{}        -> error $ "SBV.renderTest: Unsupported maybe sort: "  ++ show k
-                        k@KEither{}       -> error $ "SBV.renderTest: Unsupported either sort: " ++ show k
                         k@KArray{}        -> error $ "SBV.renderTest: Unsupported array sort: "  ++ show k
 
-
         mkLine (is, os) = "{{" ++ intercalate ", " (map v is) ++ "}, {" ++ intercalate ", " (map v os) ++ "}}"
 
         v cv = case kindOf cv of
-                  KBool            -> if cvToBool cv then "true " else "false"
-                  KBounded sgn sz  -> let CInteger w = cvVal cv in chex  False True (sgn, sz) w
-                  KUnbounded       -> let CInteger w = cvVal cv in shexI False True           w
-                  KFloat           -> let CFloat w   = cvVal cv in showCFloat w
-                  KDouble          -> let CDouble w  = cvVal cv in showCDouble w
-                  KRational        -> error "SBV.renderTest: Unsupported rational number"
-                  KFP{}            -> error "SBV.renderTest: Unsupported arbitrary float"
-                  KChar            -> error "SBV.renderTest: Unsupported char"
-                  KString          -> error "SBV.renderTest: Unsupported string"
-                  k@KList{}        -> error $ "SBV.renderTest: Unsupported list sort!" ++ show k
-                  k@KSet{}         -> error $ "SBV.renderTest: Unsupported set sort!" ++ show k
-                  KUserSort us _   -> error $ "SBV.renderTest: Unsupported uninterpreted sort: " ++ us
-                  KReal            -> error "SBV.renderTest: Real values are not supported when generating C test-cases."
-                  k@KTuple{}       -> error $ "SBV.renderTest: Unsupported tuple sort: " ++ show k
-                  k@KMaybe{}       -> error $ "SBV.renderTest: Unsupported maybe sort: " ++ show k
-                  k@KEither{}      -> error $ "SBV.renderTest: Unsupported sum sort: "   ++ show k
-                  k@KArray{}       -> error $ "SBV.renderTest: Unsupported sum sort: "   ++ show k
+                  KVar{}          -> error $ "SBV.renderTest: Unexpected: " ++ show (kindOf cv)
+                  KBool           -> if cvToBool cv then "true " else "false"
+                  KBounded sgn sz -> let CInteger w = cvVal cv in chex  False True (sgn, sz) w
+                  KUnbounded      -> let CInteger w = cvVal cv in shexI False True           w
+                  KFloat          -> let CFloat w   = cvVal cv in showCFloat w
+                  KDouble         -> let CDouble w  = cvVal cv in showCDouble w
+                  KRational       -> error "SBV.renderTest: Unsupported rational number"
+                  KFP{}           -> error "SBV.renderTest: Unsupported arbitrary float"
+                  KChar           -> error "SBV.renderTest: Unsupported char"
+                  KString         -> error "SBV.renderTest: Unsupported string"
+                  KReal           -> error "SBV.renderTest: Real values are not supported when generating C test-cases."
+                  k@KList{}       -> error $ "SBV.renderTest: Unsupported list sort!"           ++ show k
+                  k@KSet{}        -> error $ "SBV.renderTest: Unsupported set sort!"            ++ show k
+                  k@KApp{}        -> error $ "SBV.renderTest: Unsupported adt app: "            ++ show k
+                  k@KADT{}        -> error $ "SBV.renderTest: Unsupported adt: "                ++ show k
+                  k@KTuple{}      -> error $ "SBV.renderTest: Unsupported tuple sort: "         ++ show k
+                  k@KArray{}      -> error $ "SBV.renderTest: Unsupported sum sort: "           ++ show k
 
         outLine
           | null vs = "printf(\"\");"
@@ -352,7 +350,6 @@
                         KList ek          -> noForte $ "List of " ++ show ek
                         KSet  ek          -> noForte $ "Set of " ++ show ek
                         KUnbounded        -> noForte "Unbounded integers"
-                        KUserSort s _     -> noForte $ "Uninterpreted kind " ++ show s
                         _                 -> error $ "SBV.renderTest: Unexpected CV: " ++ show cv
 
         xlt s (CInteger  v)  = [toF (testBit v i) | i <- [s-1, s-2 .. 0]]
@@ -363,13 +360,11 @@
         xlt _ (CChar     r)  = error $ "SBV.renderTest.Forte: Unexpected char value: "             ++ show r
         xlt _ (CString   r)  = error $ "SBV.renderTest.Forte: Unexpected string value: "           ++ show r
         xlt _ (CAlgReal  r)  = error $ "SBV.renderTest.Forte: Unexpected real value: "             ++ show r
-        xlt _ (CUserSort r)  = error $ "SBV.renderTest.Forte: Unexpected uninterpreted value: "    ++ show r
+        xlt _ (CADT (k, _))  = error $ "SBV.renderTest.Forte: Unexpected ADT value: "              ++ show k
         xlt _ CList{}        = error   "SBV.renderTest.Forte: Unexpected list value!"
         xlt _ CSet{}         = error   "SBV.renderTest.Forte: Unexpected set value!"
         xlt _ CTuple{}       = error   "SBV.renderTest.Forte: Unexpected list value!"
-        xlt _ CMaybe{}       = error   "SBV.renderTest.Forte: Unexpected maybe value!"
-        xlt _ CEither{}      = error   "SBV.renderTest.Forte: Unexpected sum value!"
-        xlt _  CArray{}      = error   "SBV.renderTest.Forte: Unexpected array value!"
+        xlt _ CArray{}       = error   "SBV.renderTest.Forte: Unexpected array value!"
 
         mkLine  (i, o) = "("  ++ mkTuple (form (fst ss) (concatMap blast i)) ++ ", " ++ mkTuple (form (snd ss) (concatMap blast o)) ++ ")"
         mkTuple []  = "()"
diff --git a/Data/SBV/Tools/Overflow.hs b/Data/SBV/Tools/Overflow.hs
--- a/Data/SBV/Tools/Overflow.hs
+++ b/Data/SBV/Tools/Overflow.hs
@@ -15,7 +15,6 @@
 {-# LANGUAGE FlexibleContexts     #-}
 {-# LANGUAGE FlexibleInstances    #-}
 {-# LANGUAGE ImplicitParams       #-}
-{-# LANGUAGE Rank2Types           #-}
 {-# LANGUAGE ScopedTypeVariables  #-}
 {-# LANGUAGE TypeApplications     #-}
 {-# LANGUAGE TypeOperators        #-}
diff --git a/Data/SBV/Tools/Polynomial.hs b/Data/SBV/Tools/Polynomial.hs
--- a/Data/SBV/Tools/Polynomial.hs
+++ b/Data/SBV/Tools/Polynomial.hs
@@ -9,11 +9,7 @@
 -- Implementation of polynomial arithmetic
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DataKinds            #-}
-{-# LANGUAGE FlexibleContexts     #-}
 {-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE PatternGuards        #-}
-{-# LANGUAGE TypeFamilies         #-}
 {-# LANGUAGE UndecidableInstances #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
diff --git a/Data/SBV/Tools/WeakestPreconditions.hs b/Data/SBV/Tools/WeakestPreconditions.hs
--- a/Data/SBV/Tools/WeakestPreconditions.hs
+++ b/Data/SBV/Tools/WeakestPreconditions.hs
@@ -13,12 +13,10 @@
 -- several example proofs.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE FlexibleContexts       #-}
-{-# LANGUAGE MultiParamTypeClasses  #-}
-{-# LANGUAGE NamedFieldPuns         #-}
-{-# LANGUAGE ScopedTypeVariables    #-}
-{-# LANGUAGE TypeFamilies           #-}
-{-# LANGUAGE TypeOperators          #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE NamedFieldPuns      #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeOperators       #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
diff --git a/Data/SBV/Trans.hs b/Data/SBV/Trans.hs
--- a/Data/SBV/Trans.hs
+++ b/Data/SBV/Trans.hs
@@ -26,7 +26,7 @@
   , SWord8, SWord16, SWord32, SWord64, SWord, WordN
   -- *** Signed bit-vectors
   , SInt8, SInt16, SInt32, SInt64, SInt, IntN
-  -- *** Converting between fixed-size and arbitrary bitvectors
+  -- *** Converting between fixed-size and arbitrary bit-vectors
   , BVIsNonZero, FromSized, ToSized, fromSized, toSized
   -- ** Unbounded integers
   , SInteger
@@ -85,11 +85,8 @@
   , blastSDouble
   , blastSFloatingPoint
 
-  -- * Enumerations
-  , mkSymbolicEnumeration
-
-  -- * Uninterpreted sorts, axioms, constants, and functions
-  , mkUninterpretedSort, SMTDefinable(..)
+  -- * Symbolic types
+  , mkSymbolic, SMTDefinable(..)
 
   -- * Properties, proofs, and satisfiability
   , Predicate, ConstraintSet, ProvableM(..), Provable, SatisfiableM(..), Satisfiable
@@ -137,7 +134,7 @@
 
   -- ** Programmable model extraction
   , SatModel(..), Modelable(..), displayModels, extractModels
-  , getModelDictionaries, getModelValues, getModelUninterpretedValues
+  , getModelDictionaries, getModelValues
 
   -- * SMT Interface
   , SMTConfig(..), Timing(..), SMTLibVersion(..), Solver(..), SMTSolver(..)
diff --git a/Data/SBV/Trans/Control.hs b/Data/SBV/Trans/Control.hs
--- a/Data/SBV/Trans/Control.hs
+++ b/Data/SBV/Trans/Control.hs
@@ -22,7 +22,7 @@
 
      -- * Querying the solver
      -- ** Extracting values
-     , getValue, getFunction, getUninterpretedValue, getModel, getAssignment, getSMTResult, getUnknownReason, getObservables
+     , getValue, getFunction, getModel, getAssignment, getSMTResult, getUnknownReason, getObservables
 
      -- ** Extracting the unsat core
      , getUnsatCore
diff --git a/Data/SBV/Tuple.hs b/Data/SBV/Tuple.hs
--- a/Data/SBV/Tuple.hs
+++ b/Data/SBV/Tuple.hs
@@ -16,8 +16,6 @@
 {-# LANGUAGE FlexibleInstances      #-}
 {-# LANGUAGE FunctionalDependencies #-}
 {-# LANGUAGE KindSignatures         #-}
-{-# LANGUAGE Rank2Types             #-}
-{-# LANGUAGE ScopedTypeVariables    #-}
 {-# LANGUAGE TypeApplications       #-}
 
 {-# OPTIONS_GHC -Wall -Werror -fno-warn-orphans #-}
diff --git a/Data/SBV/Utils/CrackNum.hs b/Data/SBV/Utils/CrackNum.hs
--- a/Data/SBV/Utils/CrackNum.hs
+++ b/Data/SBV/Utils/CrackNum.hs
@@ -42,17 +42,17 @@
   crackNum cv verbose mbIV = case kindOf cv of
                                -- Maybe one day we'll have a use for these, currently cracking them
                                -- any further seems overkill
+                               KVar       {}  -> Nothing
                                KBool      {}  -> Nothing
                                KUnbounded {}  -> Nothing
                                KReal      {}  -> Nothing
-                               KUserSort  {}  -> Nothing
+                               KApp       {}  -> Nothing
+                               KADT       {}  -> Nothing
                                KChar      {}  -> Nothing
                                KString    {}  -> Nothing
                                KList      {}  -> Nothing
                                KSet       {}  -> Nothing
                                KTuple     {}  -> Nothing
-                               KMaybe     {}  -> Nothing
-                               KEither    {}  -> Nothing
                                KRational  {}  -> Nothing
                                KArray     {}  -> Nothing
 
diff --git a/Data/SBV/Utils/Lib.hs b/Data/SBV/Utils/Lib.hs
--- a/Data/SBV/Utils/Lib.hs
+++ b/Data/SBV/Utils/Lib.hs
@@ -9,7 +9,6 @@
 -- Misc helpers
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE RankNTypes          #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications    #-}
 
diff --git a/Data/SBV/Utils/Numeric.hs b/Data/SBV/Utils/Numeric.hs
--- a/Data/SBV/Utils/Numeric.hs
+++ b/Data/SBV/Utils/Numeric.hs
@@ -16,6 +16,7 @@
 module Data.SBV.Utils.Numeric (
            fpMaxH, fpMinH, fp2fp, fpRemH, fpRoundToIntegralH, fpIsEqualObjectH, fpCompareObjectH, fpIsNormalizedH
          , floatToWord, wordToFloat, doubleToWord, wordToDouble
+         , RoundingMode(..), smtRoundingMode
          ) where
 
 import Data.Word
@@ -23,6 +24,8 @@
 import Data.Array.Unsafe (castSTUArray)
 import GHC.ST            (runST, ST)
 
+import Test.QuickCheck  (Arbitrary(..), elements)
+
 -- | The SMT-Lib (in particular Z3) implementation for min/max for floats does not agree with
 -- Haskell's; and also it does not agree with what the hardware does. Sigh.. See:
 --      <https://gitlab.haskell.org/ghc/ghc/-/issues/10378>
@@ -152,3 +155,30 @@
 {-# INLINE cast #-}
 cast :: (MArray (STUArray s) a (ST s), MArray (STUArray s) b (ST s)) => a -> ST s b
 cast x = newArray (0 :: Int, 0) x >>= castSTUArray >>= flip readArray 0
+
+-- | Rounding mode to be used for the IEEE floating-point operations.
+-- Note that Haskell's default is 'RoundNearestTiesToEven'. If you use
+-- a different rounding mode, then the counter-examples you get may not
+-- match what you observe in Haskell.
+data RoundingMode = RoundNearestTiesToEven  -- ^ Round to nearest representable floating point value.
+                                            -- If precisely at half-way, pick the even number.
+                                            -- (In this context, /even/ means the lowest-order bit is zero.)
+                  | RoundNearestTiesToAway  -- ^ Round to nearest representable floating point value.
+                                            -- If precisely at half-way, pick the number further away from 0.
+                                            -- (That is, for positive values, pick the greater; for negative values, pick the smaller.)
+                  | RoundTowardPositive     -- ^ Round towards positive infinity. (Also known as rounding-up or ceiling.)
+                  | RoundTowardNegative     -- ^ Round towards negative infinity. (Also known as rounding-down or floor.)
+                  | RoundTowardZero         -- ^ Round towards zero. (Also known as truncation.)
+                  deriving (Show, Enum, Bounded)
+
+-- | Arbitrary instance for 'RoundingMode'
+instance Arbitrary RoundingMode where
+  arbitrary = elements [minBound .. maxBound]
+
+-- | Convert a rounding mode to the format SMT-Lib2 understands.
+smtRoundingMode :: RoundingMode -> String
+smtRoundingMode RoundNearestTiesToEven = "roundNearestTiesToEven"
+smtRoundingMode RoundNearestTiesToAway = "roundNearestTiesToAway"
+smtRoundingMode RoundTowardPositive    = "roundTowardPositive"
+smtRoundingMode RoundTowardNegative    = "roundTowardNegative"
+smtRoundingMode RoundTowardZero        = "roundTowardZero"
diff --git a/Data/SBV/Utils/PrettyNum.hs b/Data/SBV/Utils/PrettyNum.hs
--- a/Data/SBV/Utils/PrettyNum.hs
+++ b/Data/SBV/Utils/PrettyNum.hs
@@ -35,12 +35,13 @@
 import qualified Numeric as N (showHFloat)
 
 import Data.SBV.Core.Data
-import Data.SBV.Core.Kind (smtType, smtRoundingMode, showBaseKind)
+import Data.SBV.Core.Kind (smtType, showBaseKind)
 
 import Data.SBV.Core.AlgReals    (algRealToSMTLib2)
 import Data.SBV.Core.SizedFloats (fprToSMTLib2, bfToString)
 
-import Data.SBV.Utils.Lib (stringToQFS)
+import Data.SBV.Utils.Lib     (stringToQFS)
+import Data.SBV.Utils.Numeric (smtRoundingMode)
 
 -- | PrettyNum class captures printing of numbers in hex and binary formats; also supporting negative numbers.
 class PrettyNum a where
@@ -168,7 +169,7 @@
 shBKind a = " :: " ++ showBaseKind (kindOf a)
 
 instance PrettyNum CV where
-  hexS cv | isUserSort      cv = shows cv                                               $  shBKind cv
+  hexS cv | isADT           cv = shows cv                                               $  shBKind cv
           | isBoolean       cv = hexS (cvToBool cv)                                     ++ shBKind cv
           | isFloat         cv = let CFloat   f = cvVal cv in N.showHFloat f            $  shBKind cv
           | isDouble        cv = let CDouble  d = cvVal cv in N.showHFloat d            $  shBKind cv
@@ -178,7 +179,7 @@
           | not (isBounded cv) = let CInteger i = cvVal cv in shexI True True i
           | True               = let CInteger i = cvVal cv in shex  True True (hasSign cv, intSizeOf cv) i
 
-  binS cv | isUserSort      cv = shows cv                                              $  shBKind cv
+  binS cv | isADT           cv = shows cv                                              $  shBKind cv
           | isBoolean       cv = binS (cvToBool cv)                                    ++ shBKind cv
           | isFloat         cv = let CFloat   f = cvVal cv in showBFloat f             $  shBKind cv
           | isDouble        cv = let CDouble  d = cvVal cv in showBFloat d             $  shBKind cv
@@ -188,7 +189,7 @@
           | not (isBounded cv) = let CInteger i = cvVal cv in sbinI True True i
           | True               = let CInteger i = cvVal cv in sbin  True True (hasSign cv, intSizeOf cv) i
 
-  hexP cv | isUserSort      cv = show cv
+  hexP cv | isADT           cv = show cv
           | isBoolean       cv = hexS (cvToBool cv)
           | isFloat         cv = let CFloat   f = cvVal cv in show f
           | isDouble        cv = let CDouble  d = cvVal cv in show d
@@ -198,7 +199,7 @@
           | not (isBounded cv) = let CInteger i = cvVal cv in shexI False True i
           | True               = let CInteger i = cvVal cv in shex  False True (hasSign cv, intSizeOf cv) i
 
-  binP cv | isUserSort      cv = show cv
+  binP cv | isADT           cv = show cv
           | isBoolean       cv = binS (cvToBool cv)
           | isFloat         cv = let CFloat   f = cvVal cv in show f
           | isDouble        cv = let CDouble  d = cvVal cv in show d
@@ -208,7 +209,7 @@
           | not (isBounded cv) = let CInteger i = cvVal cv in sbinI False True i
           | True               = let CInteger i = cvVal cv in sbin  False True (hasSign cv, intSizeOf cv) i
 
-  hex cv  | isUserSort      cv = show cv
+  hex cv  | isADT           cv = show cv
           | isBoolean       cv = hexS (cvToBool cv)
           | isFloat         cv = let CFloat   f = cvVal cv in show f
           | isDouble        cv = let CDouble  d = cvVal cv in show d
@@ -218,7 +219,7 @@
           | not (isBounded cv) = let CInteger i = cvVal cv in shexI False False i
           | True               = let CInteger i = cvVal cv in shex  False False (hasSign cv, intSizeOf cv) i
 
-  bin cv  | isUserSort      cv = show cv
+  bin cv  | isADT           cv = show cv
           | isBoolean       cv = binS (cvToBool cv)
           | isFloat         cv = let CFloat   f = cvVal cv in show f
           | isDouble        cv = let CDouble  d = cvVal cv in show d
@@ -415,7 +416,7 @@
 cvToSMTLib :: RoundingMode -> CV -> String
 cvToSMTLib rm x
   | isBoolean       x, CInteger  w      <- cvVal x = if w == 0 then "false" else "true"
-  | isUserSort      x, CUserSort (_, s) <- cvVal x = roundModeConvert s
+  | isRoundingMode  x, CADT (s, [])     <- cvVal x = roundModeConvert s
   | isReal          x, CAlgReal  r      <- cvVal x = algRealToSMTLib2 r
   | isFloat         x, CFloat    f      <- cvVal x = showSMTFloat  rm f
   | isDouble        x, CDouble   d      <- cvVal x = showSMTDouble rm d
@@ -434,12 +435,13 @@
   | isList x         , CList xs         <- cvVal x = smtLibSeq (kindOf x) xs
   | isSet x          , CSet s           <- cvVal x = smtLibSet (kindOf x) s
   | isTuple x        , CTuple xs        <- cvVal x = smtLibTup (kindOf x) xs
-  | isMaybe x        , CMaybe mc        <- cvVal x = smtLibMaybe  (kindOf x) mc
-  | isEither x       , CEither ec       <- cvVal x = smtLibEither (kindOf x) ec
 
   -- Arrays become sequence of stores
-  | isArray x        , CArray ac       <- cvVal x = smtLibArray (kindOf x) ac
+  | isArray x        , CArray ac       <- cvVal x  = smtLibArray (kindOf x) ac
 
+  -- ADTs
+  | isADT x          , CADT c          <- cvVal x = smtLibADT (cvKind x) c
+
   | True = error $ "SBV.cvtCV: Impossible happened: Kind/Value disagreement on: " ++ show (kindOf x, x)
   where roundModeConvert s = fromMaybe s (listToMaybe [smtRoundingMode m | m <- [minBound .. maxBound] :: [RoundingMode], show m == s])
         -- Carefully code hex numbers, SMTLib is picky about lengths of hex constants. For the time
@@ -480,19 +482,6 @@
         smtLibTup (KTuple ks) xs = "(mkSBVTuple" ++ show (length ks) ++ " " ++ unwords (zipWith (\ek e -> cvToSMTLib rm (CV ek e)) ks xs) ++ ")"
         smtLibTup k           _  = error $ "SBV.cvToSMTLib: Impossible case (smtLibTup), received kind: " ++ show k
 
-        dtConstructor fld []   res =  "(as " ++ fld ++ " " ++ smtType res ++ ")"
-        dtConstructor fld args res = "((as " ++ fld ++ " " ++ smtType res ++ ") " ++ unwords args ++ ")"
-
-        smtLibMaybe :: Kind -> Maybe CVal -> String
-        smtLibMaybe km@KMaybe{}   Nothing   = dtConstructor "nothing_SBVMaybe" []                       km
-        smtLibMaybe km@(KMaybe k) (Just  c) = dtConstructor "just_SBVMaybe"    [cvToSMTLib rm (CV k c)] km
-        smtLibMaybe k             _         = error $ "SBV.cvToSMTLib: Impossible case (smtLibMaybe), received kind: " ++ show k
-
-        smtLibEither :: Kind -> Either CVal CVal -> String
-        smtLibEither ke@(KEither  k _) (Left c)  = dtConstructor "left_SBVEither"  [cvToSMTLib rm (CV k c)] ke
-        smtLibEither ke@(KEither  _ k) (Right c) = dtConstructor "right_SBVEither" [cvToSMTLib rm (CV k c)] ke
-        smtLibEither k                 _         = error $ "SBV.cvToSMTLib: Impossible case (smtLibEither), received kind: " ++ show k
-
         -- Remember that in an ArrayModel we keep a history; i.e., the earlier elements are written later. So, we reverse the assocs
         smtLibArray :: Kind -> ArrayModel CVal CVal -> String
         smtLibArray k@(KArray k1 k2) (ArrayModel assocs def) = mkStoreChain k k1 k2 (reverse assocs) def
@@ -510,6 +499,12 @@
         -- as there is no positive value we can provide to make the bvneg work.. (see above)
         mkMinBound :: Int -> String
         mkMinBound i = "#b1" ++ replicate (i-1) '0'
+
+        -- ADTs
+        smtLibADT :: Kind -> (String,  [(Kind, CVal)]) -> String
+        smtLibADT knd (c, [])  = ascribe c knd
+        smtLibADT knd (c, kvs) = '(' : ascribe c knd ++ " " ++ unwords (map (\(k, v) -> cvToSMTLib rm (CV  k v)) kvs) ++ ")"
+        ascribe nm k = "(as " ++ nm ++ " " ++ smtType k ++ ")"
 
 -- | Show a float as a binary
 showBFloat :: (Show a, RealFloat a) => a -> ShowS
diff --git a/Data/SBV/Utils/SExpr.hs b/Data/SBV/Utils/SExpr.hs
--- a/Data/SBV/Utils/SExpr.hs
+++ b/Data/SBV/Utils/SExpr.hs
@@ -40,7 +40,8 @@
 
 -- | ADT S-Expression format, suitable for representing get-model output of SMT-Lib
 data SExpr = ECon           String
-           | ENum           (Integer, Maybe Int)  -- Second argument is how wide the field was in bits, if known. Useful in FP parsing.
+           | ENum           (Integer, Maybe Int, Bool)  -- Second argument is how wide the field was in bits, if known. Useful in FP parsing.
+                                                        -- Third argument is true, if this was a boolean constant
            | EReal          AlgReal
            | EFloat         Float
            | EFloatingPoint FP
@@ -127,8 +128,8 @@
         parseApp (tok:toks) sofar = do t <- pTok tok
                                        parseApp toks (t : sofar)
 
-        pTok "false" = return $ ENum (0, Nothing)
-        pTok "true"  = return $ ENum (1, Nothing)
+        pTok "false" = return $ ENum (0, Nothing, True)
+        pTok "true"  = return $ ENum (1, Nothing, True)
 
         pTok ('0':'b':r)                                 = mkNum (Just (length r))     $ readInt 2 (`elem` "01") (\c -> ord c - ord '0') r
         pTok ('b':'v':r) | not (null r) && all isDigit r = mkNum Nothing               $ readDec (takeWhile (/= '[') r)
@@ -146,7 +147,7 @@
 
         intChar c = c == '-' || isDigit c
 
-        mkNum l [(n, "")] = return $ ENum (n, l)
+        mkNum l [(n, "")] = return $ ENum (n, l, False)
         mkNum _ _         = die "cannot read number"
 
         getReal n = return $ EReal $ mkPolyReal (Left (exact, n'))
@@ -154,42 +155,46 @@
                 n' | exact = n
                    | True  = init n
 
+        fst3 (a, _, _) = a
+        snd3 (_, b, _) = b
+        thd3 (_, _, c) = c
+
         -- simplify numbers and root-obj values
         cvt (EApp [ECon "to_int",  EReal a])                       = return $ EReal a   -- ignore the "casting"
         cvt (EApp [ECon "to_real", EReal a])                       = return $ EReal a   -- ignore the "casting"
         cvt (EApp [ECon "/", EReal a, EReal b])                    = return $ EReal (a / b)
-        cvt (EApp [ECon "/", EReal a, ENum  b])                    = return $ EReal (a                   / fromInteger (fst b))
-        cvt (EApp [ECon "/", ENum  a, EReal b])                    = return $ EReal (fromInteger (fst a) /             b      )
-        cvt (EApp [ECon "/", ENum  a, ENum  b])                    = return $ EReal (fromInteger (fst a) / fromInteger (fst b))
+        cvt (EApp [ECon "/", EReal a, ENum  b])                    = return $ EReal (a                    / fromInteger (fst3 b))
+        cvt (EApp [ECon "/", ENum  a, EReal b])                    = return $ EReal (fromInteger (fst3 a) /             b      )
+        cvt (EApp [ECon "/", ENum  a, ENum  b])                    = return $ EReal (fromInteger (fst3 a) / fromInteger (fst3 b))
         cvt (EApp [ECon "-", EReal a])                             = return $ EReal (-a)
-        cvt (EApp [ECon "-", ENum a])                              = return $ ENum  (-(fst a), snd a)
+        cvt (EApp [ECon "-", ENum a])                              = return $ ENum  (-(fst3 a), snd3 a, thd3 a)
 
         -- bit-vector value as CVC4 prints: (_ bv0 16) for instance
         cvt (EApp [ECon "_", ENum a, ENum _b])                     = return $ ENum a
         cvt (EApp [ECon "root-obj", EApp (ECon "+":trms), ENum k]) = do ts <- mapM getCoeff trms
-                                                                        return $ EReal $ mkPolyReal (Right (fst k, ts))
-        cvt (EApp [ECon "as", n, EApp [ECon "_", ECon "FloatingPoint", ENum (11, _), ENum (53, _)]]) = getDouble n
-        cvt (EApp [ECon "as", n, EApp [ECon "_", ECon "FloatingPoint", ENum ( 8, _), ENum (24, _)]]) = getFloat  n
-        cvt (EApp [ECon "as", n, ECon "Float64"])                                                    = getDouble n
-        cvt (EApp [ECon "as", n, ECon "Float32"])                                                    = getFloat  n
+                                                                        return $ EReal $ mkPolyReal (Right (fst3 k, ts))
+        cvt (EApp [ECon "as", n, EApp [ECon "_", ECon "FloatingPoint", ENum (11, _, _), ENum (53, _, _)]]) = getDouble n
+        cvt (EApp [ECon "as", n, EApp [ECon "_", ECon "FloatingPoint", ENum ( 8, _, _), ENum (24, _, _)]]) = getFloat  n
+        cvt (EApp [ECon "as", n, ECon "Float64"])                                                          = getDouble n
+        cvt (EApp [ECon "as", n, ECon "Float32"])                                                          = getFloat  n
 
         -- Deal with CVC4's approximate reals
         cvt x@(EApp [ECon "witness", EApp [EApp [ECon v, ECon "Real"]]
                                    , EApp [ECon "or", EApp [ECon "=", ECon v', val], _]]) | v == v'   = do
                                                 approx <- cvt val
                                                 case approx of
-                                                  ENum (s, _) -> return $ EReal $ mkPolyReal (Left (False, show s))
-                                                  EReal aval  -> case aval of
-                                                                   AlgRational _ r -> return $ EReal $ AlgRational False r
-                                                                   _               -> return $ EReal aval
-                                                  _           -> die $ "Cannot parse a CVC4 approximate value from: " ++ show x
+                                                  ENum (s, _, _) -> return $ EReal $ mkPolyReal (Left (False, show s))
+                                                  EReal aval     -> case aval of
+                                                                      AlgRational _ r -> return $ EReal $ AlgRational False r
+                                                                      _               -> return $ EReal aval
+                                                  _              -> die $ "Cannot parse a CVC4 approximate value from: " ++ show x
 
         -- Deal with CVC5's algebraic reals. This is very crude!
         cvt x@(EApp (ECon "_" : ECon "real_algebraic_number" : rest)) =
             let isComma (ECon ",") = True
                 isComma _          = False
 
-                get (ENum    (n, _))               = return $ fromIntegral n
+                get (ENum    (n, _, _))            = return $ fromIntegral n
                 get (EReal   (AlgRational True r)) = return r
                 get (EFloat  f)                    = return $ toRational f
                 get (EDouble d)                    = return $ toRational d
@@ -202,37 +207,37 @@
                 _                  -> die $ "Cannot parse a CVC5 real-algebraic number from: " ++ show x
 
         -- NB. Note the lengths on the mantissa for the following two are 23/52; not 24/53!
-        cvt (EApp [ECon "fp",    ENum (s, Just 1), ENum ( e, Just 8),  ENum (m, Just 23)])           = return $ EFloat         $ getTripleFloat  s e m
-        cvt (EApp [ECon "fp",    ENum (s, Just 1), ENum ( e, Just 11), ENum (m, Just 52)])           = return $ EDouble        $ getTripleDouble s e m
-        cvt (EApp [ECon "fp",    ENum (s, Just 1), ENum ( e, Just eb), ENum (m, Just sb)])           = return $ EFloatingPoint $ fpFromRawRep (s == 1) (e, eb) (m, sb+1)
+        cvt (EApp [ECon "fp",    ENum (s, Just 1, _), ENum ( e, Just  8, _), ENum (m, Just 23, _)]) = return $ EFloat         $ getTripleFloat  s e m
+        cvt (EApp [ECon "fp",    ENum (s, Just 1, _), ENum ( e, Just 11, _), ENum (m, Just 52, _)]) = return $ EDouble        $ getTripleDouble s e m
+        cvt (EApp [ECon "fp",    ENum (s, Just 1, _), ENum ( e, Just eb, _), ENum (m, Just sb, _)]) = return $ EFloatingPoint $ fpFromRawRep (s == 1) (e, eb) (m, sb+1)
 
-        cvt (EApp [ECon "_",     ECon "NaN",       ENum ( 8, _),       ENum (24,      _)])           = return $ EFloat           nan
-        cvt (EApp [ECon "_",     ECon "NaN",       ENum (11, _),       ENum (53,      _)])           = return $ EDouble          nan
-        cvt (EApp [ECon "_",     ECon "NaN",       ENum (eb, _),       ENum (sb,      _)])           = return $ EFloatingPoint $ fpNaN (fromIntegral eb) (fromIntegral sb)
+        cvt (EApp [ECon "_",     ECon "NaN",       ENum ( 8, _, _),       ENum (24, _, _)])         = return $ EFloat           nan
+        cvt (EApp [ECon "_",     ECon "NaN",       ENum (11, _, _),       ENum (53, _, _)])         = return $ EDouble          nan
+        cvt (EApp [ECon "_",     ECon "NaN",       ENum (eb, _, _),       ENum (sb, _, _)])         = return $ EFloatingPoint $ fpNaN (fromIntegral eb) (fromIntegral sb)
 
-        cvt (EApp [ECon "_",     ECon "+oo",       ENum ( 8, _),       ENum (24,      _)])           = return $ EFloat           infinity
-        cvt (EApp [ECon "_",     ECon "+oo",       ENum (11, _),       ENum (53,      _)])           = return $ EDouble          infinity
-        cvt (EApp [ECon "_",     ECon "+oo",       ENum (eb, _),       ENum (sb,      _)])           = return $ EFloatingPoint $ fpInf False (fromIntegral eb) (fromIntegral sb)
+        cvt (EApp [ECon "_",     ECon "+oo",       ENum ( 8, _, _),       ENum (24, _, _)])         = return $ EFloat           infinity
+        cvt (EApp [ECon "_",     ECon "+oo",       ENum (11, _, _),       ENum (53, _, _)])         = return $ EDouble          infinity
+        cvt (EApp [ECon "_",     ECon "+oo",       ENum (eb, _, _),       ENum (sb, _, _)])         = return $ EFloatingPoint $ fpInf False (fromIntegral eb) (fromIntegral sb)
 
-        cvt (EApp [ECon "_",     ECon "-oo",       ENum ( 8, _),       ENum (24,      _)])           = return $ EFloat         $ -infinity
-        cvt (EApp [ECon "_",     ECon "-oo",       ENum (11, _),       ENum (53,      _)])           = return $ EDouble        $ -infinity
-        cvt (EApp [ECon "_",     ECon "-oo",       ENum (eb, _),       ENum (sb,      _)])           = return $ EFloatingPoint $ fpInf True (fromIntegral eb) (fromIntegral sb)
+        cvt (EApp [ECon "_",     ECon "-oo",       ENum ( 8, _, _),       ENum (24, _, _)])         = return $ EFloat         $ -infinity
+        cvt (EApp [ECon "_",     ECon "-oo",       ENum (11, _, _),       ENum (53, _, _)])         = return $ EDouble        $ -infinity
+        cvt (EApp [ECon "_",     ECon "-oo",       ENum (eb, _, _),       ENum (sb, _, _)])         = return $ EFloatingPoint $ fpInf True (fromIntegral eb) (fromIntegral sb)
 
-        cvt (EApp [ECon "_",     ECon "+zero",     ENum ( 8, _),       ENum (24,      _)])           = return $ EFloat  0
-        cvt (EApp [ECon "_",     ECon "+zero",     ENum (11, _),       ENum (53,      _)])           = return $ EDouble 0
-        cvt (EApp [ECon "_",     ECon "+zero",     ENum (eb, _),       ENum (sb,      _)])           = return $ EFloatingPoint $ fpZero False (fromIntegral eb) (fromIntegral sb)
+        cvt (EApp [ECon "_",     ECon "+zero",     ENum ( 8, _, _),       ENum (24, _, _)])         = return $ EFloat  0
+        cvt (EApp [ECon "_",     ECon "+zero",     ENum (11, _, _),       ENum (53, _, _)])         = return $ EDouble 0
+        cvt (EApp [ECon "_",     ECon "+zero",     ENum (eb, _, _),       ENum (sb, _, _)])         = return $ EFloatingPoint $ fpZero False (fromIntegral eb) (fromIntegral sb)
 
-        cvt (EApp [ECon "_",     ECon "-zero",     ENum ( 8, _),       ENum (24,      _)])           = return $ EFloat         $ -0
-        cvt (EApp [ECon "_",     ECon "-zero",     ENum (11, _),       ENum (53,      _)])           = return $ EDouble        $ -0
-        cvt (EApp [ECon "_",     ECon "-zero",     ENum (eb, _),       ENum (sb,      _)])           = return $ EFloatingPoint $ fpZero True (fromIntegral eb) (fromIntegral sb)
+        cvt (EApp [ECon "_",     ECon "-zero",     ENum ( 8, _, _),       ENum (24, _, _)])         = return $ EFloat         $ -0
+        cvt (EApp [ECon "_",     ECon "-zero",     ENum (11, _, _),       ENum (53, _, _)])         = return $ EDouble        $ -0
+        cvt (EApp [ECon "_",     ECon "-zero",     ENum (eb, _, _),       ENum (sb, _, _)])         = return $ EFloatingPoint $ fpZero True (fromIntegral eb) (fromIntegral sb)
 
-        cvt x                                                                                        = return x
+        cvt x                                                                                       = return x
 
-        getCoeff (EApp [ECon "*", ENum k, EApp [ECon "^", ECon "x", ENum p]]) = return (fst k, fst p)  -- kx^p
-        getCoeff (EApp [ECon "*", ENum k,                 ECon "x"        ] ) = return (fst k,     1)  -- kx
-        getCoeff (                        EApp [ECon "^", ECon "x", ENum p] ) = return (    1, fst p)  --  x^p
-        getCoeff (                                        ECon "x"          ) = return (    1,     1)  --  x
-        getCoeff (                ENum k                                    ) = return (fst k,     0)  -- k
+        getCoeff (EApp [ECon "*", ENum k, EApp [ECon "^", ECon "x", ENum p]]) = return (fst3 k, fst3 p)  -- kx^p
+        getCoeff (EApp [ECon "*", ENum k,                 ECon "x"        ] ) = return (fst3 k,      1)  -- kx
+        getCoeff (                        EApp [ECon "^", ECon "x", ENum p] ) = return (     1, fst3 p)  --  x^p
+        getCoeff (                                        ECon "x"          ) = return (     1,      1)  --  x
+        getCoeff (                ENum k                                    ) = return (fst3 k,      0)  -- k
         getCoeff x = die $ "Cannot parse a root-obj,\nProcessing term: " ++ show x
         getDouble (ECon s)  = case (s, rdFP (dropWhile (== '+') s)) of
                                 ("plusInfinity",  _     ) -> return $ EDouble infinity
@@ -317,7 +322,7 @@
 --              (= x!1 "l")
 --              (= x!1 "e")
 --              (= x!1 "h")))
---   For this, we do a little bit of an interpretative dance to see if we can "construct" the necesary expression.
+--   For this, we do a little bit of an interpretative dance to see if we can "construct" the necessary expression.
 --
 --   In parsed form:
 --      EApp [ECon "lambda",EApp [EApp [ECon "x!1",ECon "String"]],EApp [ECon "not",EApp [ECon "or",EApp [ECon "=",ECon "x!1",ECon "\"e\""],EApp [ECon "=",ECon "x!1",ECon "\"l\""]]]]
@@ -337,20 +342,20 @@
         foldM1 _ []     = error "Data.SBV.parseSetLambda: Impossible happened; empty arg to foldM1"
         foldM1 f (x:xs) = foldM f x xs
 
-        checkBool (ENum (1, Nothing)) = True
-        checkBool (ENum (0, Nothing)) = True
-        checkBool _                   = False
+        checkBool (ENum (1, Nothing, True)) = True
+        checkBool (ENum (0, Nothing, True)) = True
+        checkBool _                         = False
 
-        negBool (ENum (1, Nothing)) = ENum (0, Nothing)
-        negBool _                   = ENum (1, Nothing)
+        negBool (ENum (1, Nothing, _)) = ENum (0, Nothing, True)
+        negBool _                      = ENum (1, Nothing, True)
 
-        orBool t@(ENum (1, Nothing)) _                      = t
-        orBool _                     t@(ENum (1, Nothing))  = t
-        orBool _ _                                          = ENum (0, Nothing)
+        orBool t@(ENum (1, Nothing, _)) _                        = t
+        orBool _                        t@(ENum (1, Nothing, _)) = t
+        orBool _ _                                               = ENum (0, Nothing, True)
 
-        andBool f@(ENum (0, Nothing)) _                     = f
-        andBool _                     f@(ENum (0, Nothing)) = f
-        andBool _ _                                         = ENum (1, Nothing)
+        andBool f@(ENum (0, Nothing, _)) _                        = f
+        andBool _                        f@(ENum (0, Nothing, _)) = f
+        andBool _ _                                               = ENum (1, Nothing, True)
 
         neg :: ([([SExpr], SExpr)], SExpr) -> Maybe ([([SExpr], SExpr)], SExpr)
         neg (rows, dflt)
@@ -405,8 +410,8 @@
         lambda :: [(String, Bool)]  -- Bool is True if this is a boolean variable. Otherwise we don't keep track of the type
                -> SExpr -> Maybe [Either ([SExpr], SExpr) SExpr]
         lambda params body = reverse <$> go [] body
-          where true  = ENum (1, Nothing)
-                false = ENum (0, Nothing)
+          where true  = ENum (1, Nothing, True)
+                false = ENum (0, Nothing, True)
 
                 go :: [Either ([SExpr], SExpr) SExpr] -> SExpr -> Maybe [Either ([SExpr], SExpr) SExpr]
                 go sofar (EApp [ECon "ite", selector, thenBranch, elseBranch])
@@ -534,7 +539,7 @@
         same :: SExpr -> SExpr -> Bool
         same x y = case (x, y) of
                      (ECon a,            ECon b)            -> a == b
-                     (ENum (i, _),       ENum (j, _))       -> i == j
+                     (ENum (i, _, _),    ENum (j, _, _))    -> i == j
                      (EReal a,           EReal b)           -> algRealStructuralEqual a b
                      (EFloat  f1,        EFloat  f2)        -> fpIsEqualObjectH f1 f2
                      (EDouble d1,        EDouble d2)        -> fpIsEqualObjectH d1 d2
@@ -600,7 +605,9 @@
   where go p e = case e of
                    ECon n | Just a <- n `lookup` env -> a
                           | True                     -> simplifyECon n
-                   ENum (i, _)       -> cnst i
+                   ENum (1, _, True) -> "True"
+                   ENum (0, _, True) -> "False"
+                   ENum (i, _, _)    -> cnst i
                    EReal  a          -> cnst a
                    EFloat f          -> cnst f
                    EFloatingPoint f  -> cnst f
@@ -621,13 +628,13 @@
                    EApp [ECon "not", EApp [ECon ">",  a, b]] -> go p $ EApp [ECon "<=", a, b]
 
                    -- Handle x + -y that z3 is fond of producing
-                   EApp [ECon a, x, EApp [ECon m, ENum (-1, _), y]] | isPlus a && isTimes m -> go p $ EApp [ECon "-", x, y]
+                   EApp [ECon a, x, EApp [ECon m, ENum (-1, _, _), y]] | isPlus a && isTimes m -> go p $ EApp [ECon "-", x, y]
 
                    -- Handle x + -NUM that z3 is also fond of producing
-                   EApp [ECon a, x, ENum (i, mw)] | isPlus a && i < 0 -> go p $ EApp [ECon "-", x, ENum (-i, mw)]
+                   EApp [ECon a, x, ENum (i, mw, bool)] | isPlus a && i < 0 -> go p $ EApp [ECon "-", x, ENum (-i, mw, bool)]
 
                    -- Handle -1 * x
-                   EApp [ECon o, ENum (-1, _), b] | isTimes o -> parenIf (p >= 8) (neg (go 8 b))
+                   EApp [ECon o, ENum (-1, _, _), b] | isTimes o -> parenIf (p >= 8) (neg (go 8 b))
 
                    -- Move additive constants to the right, multiplicative constants to the left
                    EApp [ECon o, x, y] | isPlus  o && isConst x && not (isConst y) -> go p $ EApp [ECon o, y, x]
diff --git a/Data/SBV/Utils/TDiff.hs b/Data/SBV/Utils/TDiff.hs
--- a/Data/SBV/Utils/TDiff.hs
+++ b/Data/SBV/Utils/TDiff.hs
@@ -77,7 +77,7 @@
                             r `seq` do mbElapsed <- getElapsedTime mbStart
                                        pure (mbElapsed, r)
 
--- | Same as 'timeIf', except we fully evaluate the result, via its the NFData instance.
+-- | Same as 'timeIf', except we fully evaluate the result, via its NFData instance.
 timeIfRNF :: (NFData a, MonadIO m) => Bool -> m a -> m (Maybe NominalDiffTime, a)
 timeIfRNF measureTime act = timeIf measureTime (act >>= \r -> rnf r `seq` pure r)
 
diff --git a/Documentation/SBV/Examples/ADT/Expr.hs b/Documentation/SBV/Examples/ADT/Expr.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/ADT/Expr.hs
@@ -0,0 +1,164 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.ADT.Expr
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A basic expression ADT example.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.ADT.Expr where
+
+import Data.SBV
+import Data.SBV.Control
+import Data.SBV.RegExp
+import Data.SBV.Tuple
+import qualified Data.SBV.List as SL
+
+-- | A basic arithmetic expression type.
+data Expr = Val Integer
+          | Var String
+          | Add Expr Expr
+          | Mul Expr Expr
+          | Let String Expr Expr
+
+-- | Create a symbolic version of expressions.
+mkSymbolic [''Expr]
+
+-- | Show instance for 'Expr'.
+instance Show Expr where
+  show (Val i)     = show i
+  show (Var a)     = a
+  show (Add l r)   = "(" ++ show l ++ " + " ++ show r ++ ")"
+  show (Mul l r)   = "(" ++ show l ++ " * " ++ show r ++ ")"
+  show (Let s a b) = "(let " ++ s ++ " = " ++ show a ++ " in " ++ show b ++ ")"
+
+-- | Num instance, simplifies construction of values
+instance Num Expr where
+  fromInteger = Val
+  (+)         = Add
+  (*)         = Mul
+  abs         = error "Num Expr: undefined abs"
+  signum      = error "Num Expr: undefined signum"
+  negate      = error "Num Expr: undefined negate"
+
+-- | Num instance for the symbolic version
+instance Num SExpr where
+  fromInteger = sVal . literal
+  (+)         = sAdd
+  (*)         = sMul
+  abs         = error "Num SExpr: undefined abs"
+  signum      = error "Num SExpr: undefined signum"
+  negate      = error "Num SExpr: undefined negate"
+
+-- | Validity: We require each variable appearing to be an identifier (lowercase letter followed by
+-- any number of upper-lower case letters and digits), and all expressions are closed; i.e., any
+-- variable referenced is introduced by an enclosing let expression.
+isValid :: SExpr -> SBool
+isValid = go SL.nil
+  where isId s = s `match` (asciiLower * KStar (asciiLetter + digit))
+        go :: SList String -> SExpr -> SBool
+        go = smtFunction "valid" $ \env expr -> [sCase|Expr expr of
+                                                   Var s     -> isId s .&& s `SL.elem` env
+                                                   Val _     -> sTrue
+                                                   Add l r   -> go env l .&& go env r
+                                                   Mul l r   -> go env l .&& go env r
+                                                   Let s a b -> isId s .&& go env a .&& go (s SL..: env) b
+                                                |]
+
+-- | Evaluate an expression.
+eval :: SExpr -> SInteger
+eval = go SL.nil
+ where go :: SList (String, Integer) -> SExpr -> SInteger
+       go = smtFunction "eval" $ \env expr -> [sCase|Expr expr of
+                                                 Val i     -> i
+                                                 Var s     -> get env s
+                                                 Add l r   -> go env l + go env r
+                                                 Mul l r   -> go env l * go env r
+                                                 Let s e r -> go (tuple (s, go env e) SL..: env) r
+                                              |]
+
+       get :: SList (String, Integer) -> SString -> SInteger
+       get = smtFunction "get" $ \env s -> ite (SL.null env) 0
+                                         $ let (k, v) = untuple (SL.head env)
+                                           in ite (s .== k) v (get (SL.tail env) s)
+
+-- | A basic theorem about 'eval'.
+-- >>> evalPlus5
+-- Q.E.D.
+evalPlus5 :: IO ThmResult
+evalPlus5 = prove $ do e :: SExpr <- free "e"
+                       pure $ eval (e + 5) .== 5 + eval e
+
+-- | A simple sat result example.
+--
+-- >>> evalSat
+-- Satisfiable. Model:
+--   e = Let "k" (Val 1) (Var "k") :: Expr
+--   a =                         9 :: Integer
+--   b =                        10 :: Integer
+evalSat :: IO SatResult
+evalSat = sat $ do e :: SExpr    <- free "e"
+                   constrain $ isValid e
+                   constrain $ isLet   e
+
+                   a :: SInteger <- free "a"
+                   b :: SInteger <- free "b"
+                   constrain $ a .>= 4
+                   constrain $ b .>= 10
+
+                   pure $ eval (e + sVal a) .== b * eval e
+
+-- | Another test, generating some (mildly) interesting examples.
+--
+-- >>> genE
+-- Satisfiable. Model:
+--   e1 = Let "p" (Val 5) (Val 3) :: Expr
+--   e2 =                Val (-2) :: Expr
+genE :: IO SatResult
+genE = sat $ do e1 :: SExpr <- free "e1"
+                e2 :: SExpr <- free "e2"
+
+                constrain $ isValid e1
+                constrain $ isValid e2
+
+                constrain $ e1 ./== e2
+                constrain $ isLet e1
+                constrain $ eval e1 .== 3
+                constrain $ eval e1 .== eval e2 + 5
+
+-- | Query mode example.
+--
+-- >>> queryE
+-- e1: (let p = 5 in 3)
+-- e2: -2
+queryE :: IO ()
+queryE = runSMT $ do
+           e1 :: SExpr <- free "e1"
+           e2 :: SExpr <- free "e2"
+
+           constrain $ isValid e1
+           constrain $ isValid e2
+
+           constrain $ e1 ./== e2
+           constrain $ isLet e1
+           constrain $ eval e1 .== 3
+           constrain $ eval e1 .== eval e2 + 5
+
+           query $ do cs <- checkSat
+                      case cs of
+                        Sat -> do e1v <- getValue e1
+                                  e2v <- getValue e2
+                                  io $ putStrLn $ "e1: " ++ show e1v
+                                  io $ putStrLn $ "e2: " ++ show e2v
+                        _   -> error $ "Unexpected result: " ++ show cs
diff --git a/Documentation/SBV/Examples/ADT/Param.hs b/Documentation/SBV/Examples/ADT/Param.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/ADT/Param.hs
@@ -0,0 +1,183 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.ADT.Param
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A basic parameterized expression ADT example.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.ADT.Param where
+
+import Data.SBV
+import Data.SBV.Control
+import Data.SBV.RegExp
+import Data.SBV.Tuple
+import qualified Data.SBV.List as SL
+
+-- | A basic arithmetic expression type.
+data Expr nm val = Val val
+                 | Var nm
+                 | Add (Expr nm val) (Expr nm val)
+                 | Mul (Expr nm val) (Expr nm val)
+                 | Let nm (Expr nm val) (Expr nm val)
+
+-- | Create a symbolic version of expressions.
+mkSymbolic [''Expr]
+
+-- | Show instance for 'Expr'.
+instance (Show nm, Show val) => Show (Expr nm val) where
+  show (Val i)     = show i
+  show (Var a)     = show a
+  show (Add l r)   = "(" ++ show l ++ " + " ++ show r ++ ")"
+  show (Mul l r)   = "(" ++ show l ++ " * " ++ show r ++ ")"
+  show (Let s a b) = "(let " ++ show s ++ " = " ++ show a ++ " in " ++ show b ++ ")"
+
+-- | Show instance for 'Expr', specialized when name is string.
+instance {-# OVERLAPPING #-} Show val => Show (Expr String val) where
+  show (Val i)     = show i
+  show (Var a)     = a
+  show (Add l r)   = "(" ++ show l ++ " + " ++ show r ++ ")"
+  show (Mul l r)   = "(" ++ show l ++ " * " ++ show r ++ ")"
+  show (Let s a b) = "(let " ++ s ++ " = " ++ show a ++ " in " ++ show b ++ ")"
+
+-- | Num instance, simplifies construction of values
+instance Integral val => Num (Expr nm val) where
+  fromInteger = Val . fromIntegral
+  (+)         = Add
+  (*)         = Mul
+  abs         = error "Num Expr: undefined abs"
+  signum      = error "Num Expr: undefined signum"
+  negate      = error "Num Expr: undefined negate"
+
+-- | Num instance for the symbolic version
+instance (SymVal nm, SymVal val, Integral val) => Num (SExpr nm val) where
+  fromInteger = sVal . literal . fromIntegral
+  (+)         = sAdd
+  (*)         = sMul
+  abs         = error "Num SExpr: undefined abs"
+  signum      = error "Num SExpr: undefined signum"
+  negate      = error "Num SExpr: undefined negate"
+
+-- | Validity: We require each variable appearing to be an identifier to satisfy the predicate given.
+-- any number of upper-lower case letters and digits), and all expressions are closed; i.e., any
+-- variable referenced is introduced by an enclosing let expression.
+isValid :: (SymVal nm, Eq nm, SymVal val) => (SBV nm -> SBool) -> SExpr nm val -> SBool
+isValid nmChk = go SL.nil
+  where go = smtFunction "valid" $ \env expr -> [sCase|Expr expr of
+                                                   Var s     -> nmChk s  .&& s `SL.elem` env
+                                                   Val _     -> sTrue
+                                                   Add l r   -> go env l .&& go env r
+                                                   Mul l r   -> go env l .&& go env r
+                                                   Let s a b -> nmChk s  .&& go env a .&& go (s SL..: env) b
+                                                |]
+
+-- | Evaluate an expression.
+eval :: (SymVal nm, SymVal val, Num (SBV val)) => SExpr nm val -> SBV val
+eval = go SL.nil
+ where go = smtFunction "eval" $ \env expr -> [sCase|Expr expr of
+                                                 Val i     -> i
+                                                 Var s     -> get env s
+                                                 Add l r   -> go env l + go env r
+                                                 Mul l r   -> go env l * go env r
+                                                 Let s e r -> go (tuple (s, go env e) SL..: env) r
+                                              |]
+
+       get = smtFunction "get" $ \env s -> ite (SL.null env) 0
+                                         $ let (k, v) = untuple (SL.head env)
+                                           in ite (s .== k) v (get (SL.tail env) s)
+
+-- | A basic theorem about 'eval'.
+-- >>> evalPlus5
+-- Q.E.D.
+evalPlus5 :: IO ThmResult
+evalPlus5 = prove $ do e :: SExpr String Integer <- free "e"
+                       pure $ eval (e + 5) .== 5 + eval e
+
+-- | Is this a string identifier? Lowercase letter followed by any number of upeer-lower case letters nd digits.
+isId :: SString -> SBool
+isId s = s `match` (asciiLower * KStar (asciiLetter + digit))
+
+-- | A simple sat result example.
+--
+-- >>> evalSat
+-- Satisfiable. Model:
+--   e = Let "h" (Val 1) (Var "h") :: Expr String Integer
+--   a =                         9 :: Integer
+--   b =                        10 :: Integer
+evalSat :: IO SatResult
+evalSat = sat $ do e :: SExpr String Integer  <- free "e"
+                   constrain $ isValid isId e
+                   constrain $ isLet   e
+
+                   a :: SInteger <- free "a"
+                   b :: SInteger <- free "b"
+                   constrain $ a .>= 4
+                   constrain $ b .>= 10
+
+                   pure $ eval (e + sVal a) .== b * eval e
+
+-- | Another test, generating some (mildly) interesting examples.
+--
+-- >>> genE
+-- Satisfiable. Model:
+--   e1 =                      Let "s" (Val 6) (Val 3) :: Expr String Integer
+--   e2 = Let "h" (Val (-1)) (Add (Var "h") (Var "h")) :: Expr String Integer
+genE :: IO SatResult
+genE = sat $ do e1 :: SExpr String Integer <- free "e1"
+                e2 :: SExpr String Integer <- free "e2"
+
+                constrain $ isValid isId e1
+                constrain $ isValid isId e2
+
+                constrain $ e1 ./== e2
+                constrain $ isLet e1
+                constrain $ eval e1 .== 3
+                constrain $ eval e1 .== eval e2 + 5
+
+-- | Query mode example.
+--
+-- >>> queryE
+-- e1: (let p = (-3 * -1) in (1 * p))
+-- e2: -2
+-- e3: (let q = 96 % 97 in q)
+queryE :: IO ()
+queryE = runSMT $ do
+           e1 :: SExpr String Integer <- free "e1"
+           e2 :: SExpr String Integer <- free "e2"
+
+           e3 :: SExpr String Rational <- free "e3"
+
+           constrain $ isValid isId e1
+           constrain $ isValid isId e2
+           constrain $ isValid isId e3
+
+           constrain $ e1 ./== e2
+           constrain $ isLet e1
+           constrain $ eval e1 .== 3
+           constrain $ eval e1 .== eval e2 + 5
+
+           constrain $ isLet e3
+           constrain $ isMul (getLet_2 e1)
+           constrain $ isMul (getLet_3 e1)
+
+           query $ do cs <- checkSat
+                      case cs of
+                        Sat -> do e1v <- getValue e1
+                                  e2v <- getValue e2
+                                  e3v <- getValue e3
+                                  io $ putStrLn $ "e1: " ++ show e1v
+                                  io $ putStrLn $ "e2: " ++ show e2v
+                                  io $ putStrLn $ "e3: " ++ show e3v
+                        _   -> error $ "Unexpected result: " ++ show cs
diff --git a/Documentation/SBV/Examples/ADT/Types.hs b/Documentation/SBV/Examples/ADT/Types.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/ADT/Types.hs
@@ -0,0 +1,132 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.ADT.Types
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- An encoding of the simple type-checking via constraints, following
+-- <https://microsoft.github.io/z3guide/docs/theories/Datatypes/#using-datatypes-for-solving-type-constraints>
+-----------------------------------------------------------------------------
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+module Documentation.SBV.Examples.ADT.Types where
+
+import Data.SBV
+
+-- | Simple encoding of untyped lambda terms
+data M = Var { var   :: String }     -- ^ Variables: @x@
+       | Lam { bound :: String       -- ^ Abstraction: @\x. M@
+             , body :: M
+             }
+       | App { fn  :: M              -- ^ Application: @M M@
+             , arg :: M
+             }
+
+-- | Types.
+data T = TInt                        -- ^ Integers
+       | TStr                        -- ^ Strings
+       | TArr { dom :: T, rng :: T } -- ^ Functions: @t -> t@
+
+-- | Make terms and types symbolic
+mkSymbolic [''M]
+mkSymbolic [''T]
+
+-- | Instead of modeling environments for mapping variables to their
+-- types, we'll simply use an uninterpreted function. Note that
+-- this also implies we consider all terms to be given so that variables
+-- do not shadow each other; i.e., all variables are unique. This is
+-- a simplification, but it is not without justification: One can 
+-- always alpha-rename bound variables so all bound variables are unique.
+env :: SString -> ST
+env = uninterpret "env"
+
+-- | Use an uninterpreted function to also magically find the type of a term.
+typeOf :: SM -> ST
+typeOf = uninterpret "typeOf"
+
+-- | Given a term and a type, check that the term has that type.
+tc :: SM -> ST -> SBool
+tc = smtFunction "constraints" $ \m t ->
+        [sCase|M m of
+
+          -- Var case. The environment must match the type we expect.
+          Var s -> env s .== t
+
+          -- Abstraction case. Type must be a function, whose domain matches the variable.
+          -- And body much match the range. Note that we can't do a nested scase
+          -- here, unfortunately, since custom quasi-quoters do not nest.
+          Lam v b
+            | isTArr t .&& env v .== sdom t
+            -> tc b (srng t)
+
+          -- Application case. In this case, we ask the solver to give us the type of the
+          -- function, and then ensure the whole thing is well-formedvx
+          App f a -> let tf = typeOf f
+                     in   isTArr tf      -- f must have an arrow type
+                      .&& tc f tf        -- The function must type-check with that type
+                      .&& tc a (sdom tf) -- Argument must have the type of this function
+                      .&& t .== srng tf  -- Final result must match the type we're looking for
+
+          -- Otherwise, ill-typed.
+          _ -> sFalse
+        |]
+
+-- | Well typedness: If what the 'typeOf' function returns type-checks the term,
+-- then a term is well-typed.
+wellTyped :: SM -> SBool
+wellTyped m = tc m (typeOf m)
+
+-- | Make sure the identity function can be typed.
+--
+-- >>> idWF
+-- Satisfiable. Model:
+--   env :: String -> T
+--   env _ = TStr
+-- <BLANKLINE>
+--   typeOf :: M -> T
+--   typeOf _ = TArr TStr TStr
+--
+-- The model is rather uninteresting, but it shows that identity can have the type String to String, where
+-- all variables are mapped to Strings.
+idWF :: IO SatResult
+idWF = sat $ wellTyped $ sLam x vx
+  where x  = literal "x"
+        vx = sVar x
+
+-- | Check that if we apply a function that takes n integer to a string is not well-typed.
+--
+-- >>> intFuncAppString
+-- Unsatisfiable
+--
+-- As expected, the solver says that there's no way to type-check such an expression.
+intFuncAppString :: IO SatResult
+intFuncAppString = sat $ do
+        -- Introduce the constant @plus1 :: Int -> Int@
+        plus1 <- free "plus1"
+        constrain $ tc plus1 (literal (TInt `TArr` TInt))
+
+        -- Introduce the constant @str :: String@
+        str <- free "str"
+        constrain $ tc str sTStr
+
+        -- Check if the application of plus1 to str can be well-typed
+        pure $ wellTyped $ sApp plus1 str
+
+-- | Make sure self-application cannot be typed.
+--
+-- >>> selfAppNotWellTyped
+-- Unsatisfiable
+--
+-- We get unsatisfiable, indicating there's no way to come up with an environment that will
+-- successfully assign a type to the term @\x -> x x@.
+selfAppNotWellTyped :: IO SatResult
+selfAppNotWellTyped = sat $ wellTyped $ sLam x (sApp vx vx)
+  where x  = literal "x"
+        vx = sVar x
diff --git a/Documentation/SBV/Examples/BitPrecise/PEXT_PDEP.hs b/Documentation/SBV/Examples/BitPrecise/PEXT_PDEP.hs
--- a/Documentation/SBV/Examples/BitPrecise/PEXT_PDEP.hs
+++ b/Documentation/SBV/Examples/BitPrecise/PEXT_PDEP.hs
@@ -37,7 +37,6 @@
 
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE DataKinds           #-}
-{-# LANGUAGE Rank2Types          #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications    #-}
 
diff --git a/Documentation/SBV/Examples/Crypto/RC4.hs b/Documentation/SBV/Examples/Crypto/RC4.hs
--- a/Documentation/SBV/Examples/Crypto/RC4.hs
+++ b/Documentation/SBV/Examples/Crypto/RC4.hs
@@ -15,8 +15,6 @@
 -- functional implementation.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
-
 {-# OPTIONS_GHC -Wall -Werror #-}
 
 module Documentation.SBV.Examples.Crypto.RC4 where
diff --git a/Documentation/SBV/Examples/Crypto/SHA.hs b/Documentation/SBV/Examples/Crypto/SHA.hs
--- a/Documentation/SBV/Examples/Crypto/SHA.hs
+++ b/Documentation/SBV/Examples/Crypto/SHA.hs
@@ -17,7 +17,6 @@
 
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE NamedFieldPuns      #-}
-{-# LANGUAGE Rank2Types          #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications    #-}
 
diff --git a/Documentation/SBV/Examples/Lists/BoundedMutex.hs b/Documentation/SBV/Examples/Lists/BoundedMutex.hs
--- a/Documentation/SBV/Examples/Lists/BoundedMutex.hs
+++ b/Documentation/SBV/Examples/Lists/BoundedMutex.hs
@@ -9,14 +9,10 @@
 -- Proves a simple mutex algorithm correct up to a given bound.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
-{-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE FlexibleInstances   #-}
-{-# LANGUAGE OverloadedLists     #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -29,10 +25,10 @@
 data State = Idle     -- ^ Regular work
            | Ready    -- ^ Intention to enter critical state
            | Critical -- ^ In the critical state
-           deriving (Enum, Bounded)
+           deriving Show
 
 -- | Make 'State' a symbolic enumeration
-mkSymbolicEnumeration ''State
+mkSymbolic [''State]
 
 -- | The mutex property holds for two sequences of state transitions, if they are not in
 -- their critical section at the same time.
diff --git a/Documentation/SBV/Examples/Misc/Auxiliary.hs b/Documentation/SBV/Examples/Misc/Auxiliary.hs
--- a/Documentation/SBV/Examples/Misc/Auxiliary.hs
+++ b/Documentation/SBV/Examples/Misc/Auxiliary.hs
@@ -15,8 +15,6 @@
 -- considering them explicitly in model construction.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE OverloadedStrings #-}
-
 {-# OPTIONS_GHC -Wall -Werror #-}
 
 module Documentation.SBV.Examples.Misc.Auxiliary where
diff --git a/Documentation/SBV/Examples/Misc/Definitions.hs b/Documentation/SBV/Examples/Misc/Definitions.hs
--- a/Documentation/SBV/Examples/Misc/Definitions.hs
+++ b/Documentation/SBV/Examples/Misc/Definitions.hs
@@ -11,7 +11,7 @@
 -- for recursive definitions.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE OverloadedLists  #-}
+{-# LANGUAGE OverloadedLists #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
diff --git a/Documentation/SBV/Examples/Misc/Enumerate.hs b/Documentation/SBV/Examples/Misc/Enumerate.hs
--- a/Documentation/SBV/Examples/Misc/Enumerate.hs
+++ b/Documentation/SBV/Examples/Misc/Enumerate.hs
@@ -12,12 +12,10 @@
 -- example involving enumerations.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -28,15 +26,10 @@
 -- | A simple enumerated type, that we'd like to translate to SMT-Lib intact;
 -- i.e., this type will not be uninterpreted but rather preserved and will
 -- be just like any other symbolic type SBV provides.
---
--- Also note that we need to have the following @LANGUAGE@ options defined:
--- @TemplateHaskell@, @StandaloneDeriving@, @DeriveDataTypeable@, @DeriveAnyClass@ for
--- this to work.
 data E = A | B | C
-       deriving (Enum, Bounded, Eq, Ord)
 
 -- | Make 'E' a symbolic value.
-mkSymbolicEnumeration ''E
+mkSymbolic [''E]
 
 -- | Have the SMT solver enumerate the elements of the domain. We have:
 --
diff --git a/Documentation/SBV/Examples/Misc/FirstOrderLogic.hs b/Documentation/SBV/Examples/Misc/FirstOrderLogic.hs
--- a/Documentation/SBV/Examples/Misc/FirstOrderLogic.hs
+++ b/Documentation/SBV/Examples/Misc/FirstOrderLogic.hs
@@ -12,11 +12,8 @@
 
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE DataKinds           #-}
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
 {-# LANGUAGE TypeApplications    #-}
 
@@ -38,17 +35,16 @@
 
 -- | An uninterpreted sort for demo purposes, named 'U'
 data U
-mkUninterpretedSort ''U
+mkSymbolic [''U]
 
 -- | An uninterpreted sort for demo purposes, named 'V'
 data V
-mkUninterpretedSort ''V
+mkSymbolic [''V]
 
 -- | An enumerated type for demo purposes, named 'E'
 data E = A | B | C
-       deriving (Enum, Bounded, Ord, Eq)
 
-mkSymbolicEnumeration ''E
+mkSymbolic [''E]
 
 -- | Helper to turn quantified formula to a regular boolean. We
 -- can think of this as quantifier elimination, hence the name 'qe'.
diff --git a/Documentation/SBV/Examples/Optimization/Enumerate.hs b/Documentation/SBV/Examples/Optimization/Enumerate.hs
--- a/Documentation/SBV/Examples/Optimization/Enumerate.hs
+++ b/Documentation/SBV/Examples/Optimization/Enumerate.hs
@@ -10,13 +10,10 @@
 -- by properly defining your metric values.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
-{-# LANGUAGE FlexibleInstances   #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
-{-# LANGUAGE TemplateHaskell     #-}
-{-# LANGUAGE TypeFamilies        #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+{-# LANGUAGE TypeFamilies      #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -26,10 +23,9 @@
 
 -- | A simple enumeration
 data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun
-         deriving (Enum, Bounded)
 
 -- | Make 'Day' a symbolic value.
-mkSymbolicEnumeration ''Day
+mkSymbolic [''Day]
 
 -- | Make day an optimizable value, by mapping it to 'Word8' in the most
 -- obvious way. We can map it to any value the underlying solver can optimize,
diff --git a/Documentation/SBV/Examples/Optimization/ExtField.hs b/Documentation/SBV/Examples/Optimization/ExtField.hs
--- a/Documentation/SBV/Examples/Optimization/ExtField.hs
+++ b/Documentation/SBV/Examples/Optimization/ExtField.hs
@@ -10,6 +10,7 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE CPP #-}
+
 {-# OPTIONS_GHC -Wall -Werror #-}
 
 module Documentation.SBV.Examples.Optimization.ExtField where
diff --git a/Documentation/SBV/Examples/Puzzles/Birthday.hs b/Documentation/SBV/Examples/Puzzles/Birthday.hs
--- a/Documentation/SBV/Examples/Puzzles/Birthday.hs
+++ b/Documentation/SBV/Examples/Puzzles/Birthday.hs
@@ -35,11 +35,9 @@
 -- NB. Thanks to Amit Goel for suggesting the formalization strategy used in here.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
-{-# LANGUAGE FlexibleInstances   #-}
-{-# LANGUAGE StandaloneDeriving  #-}
-{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -53,14 +51,12 @@
 
 -- | Months. We only put in the months involved in the puzzle for simplicity
 data Month = May | Jun | Jul | Aug
-           deriving (Enum, Bounded)
 
 -- | Days. Again, only the ones mentioned in the puzzle.
 data Day = D14 | D15 | D16 | D17 | D18 | D19
-         deriving (Enum, Bounded)
 
-mkSymbolicEnumeration ''Month
-mkSymbolicEnumeration ''Day
+mkSymbolic [''Month]
+mkSymbolic [''Day]
 
 -- | Represent the birthday as a record
 data Birthday = BD SMonth SDay
diff --git a/Documentation/SBV/Examples/Puzzles/DieHard.hs b/Documentation/SBV/Examples/Puzzles/DieHard.hs
--- a/Documentation/SBV/Examples/Puzzles/DieHard.hs
+++ b/Documentation/SBV/Examples/Puzzles/DieHard.hs
@@ -11,14 +11,12 @@
 -- We use a bounded-model-checking style search to find a solution.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass        #-}
-{-# LANGUAGE DeriveDataTypeable    #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NamedFieldPuns        #-}
-{-# LANGUAGE StandaloneDeriving    #-}
 {-# LANGUAGE OverloadedRecordDot   #-}
 {-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeApplications      #-}
 {-# LANGUAGE TypeFamilies          #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
@@ -30,9 +28,9 @@
 
 -- | Possible actions
 data Action = Initial | FillBig | FillSmall | EmptyBig | EmptySmall | BigToSmall | SmallToBig
-            deriving (Enum, Bounded)
+             deriving Show
 
-mkSymbolicEnumeration ''Action
+mkSymbolic [''Action]
 
 -- | We represent the state with two quantities, the amount of water in each jug. The
 -- action is how we got into this state.
diff --git a/Documentation/SBV/Examples/Puzzles/Drinker.hs b/Documentation/SBV/Examples/Puzzles/Drinker.hs
--- a/Documentation/SBV/Examples/Puzzles/Drinker.hs
+++ b/Documentation/SBV/Examples/Puzzles/Drinker.hs
@@ -16,10 +16,7 @@
 -- @
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass     #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE TemplateHaskell    #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -31,7 +28,7 @@
 data P
 
 -- | Make 'P' an uninterpreted sort, introducing the type 'SP' for its symbolic version
-mkUninterpretedSort ''P
+mkSymbolic [''P]
 
 -- | Declare the uninterpret function 'd', standing for drinking. For each person, this function
 -- assigns whether they are drinking; but is otherwise completely uninterpreted. (i.e., our theorem
diff --git a/Documentation/SBV/Examples/Puzzles/Fish.hs b/Documentation/SBV/Examples/Puzzles/Fish.hs
--- a/Documentation/SBV/Examples/Puzzles/Fish.hs
+++ b/Documentation/SBV/Examples/Puzzles/Fish.hs
@@ -27,53 +27,47 @@
 -- Who owns the fish?
 ------------------------------------------------------------------------------
 
-{-# OPTIONS_GHC -Wall -Werror #-}
-
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
 
+{-# OPTIONS_GHC -Wall -Werror #-}
+
 module Documentation.SBV.Examples.Puzzles.Fish where
 
 import Data.SBV
 
 -- | Colors of houses
 data Color = Red | Green | White | Yellow | Blue
-           deriving (Enum, Bounded)
 
 -- | Make 'Color' a symbolic value.
-mkSymbolicEnumeration ''Color
+mkSymbolic [''Color]
 
 -- | Nationalities of the occupants
 data Nationality = Briton | Dane | Swede | Norwegian | German
-                 deriving (Enum, Bounded)
+                 deriving Show
 
 -- | Make 'Nationality' a symbolic value.
-mkSymbolicEnumeration ''Nationality
+mkSymbolic [''Nationality]
 
 -- | Beverage choices
 data Beverage = Tea | Coffee | Milk | Beer | Water
-              deriving (Enum, Bounded)
 
 -- | Make 'Beverage' a symbolic value.
-mkSymbolicEnumeration ''Beverage
+mkSymbolic [''Beverage]
 
 -- | Pets they keep
 data Pet = Dog | Horse | Cat | Bird | Fish
-         deriving (Enum, Bounded)
 
 -- | Make 'Pet' a symbolic value.
-mkSymbolicEnumeration ''Pet
+mkSymbolic [''Pet]
 
 -- | Sports they engage in
 data Sport = Football | Baseball | Volleyball | Hockey | Tennis
-           deriving (Enum, Bounded)
 
 -- | Make 'Sport' a symbolic value.
-mkSymbolicEnumeration ''Sport
+mkSymbolic [''Sport]
 
 -- | We have:
 --
diff --git a/Documentation/SBV/Examples/Puzzles/Garden.hs b/Documentation/SBV/Examples/Puzzles/Garden.hs
--- a/Documentation/SBV/Examples/Puzzles/Garden.hs
+++ b/Documentation/SBV/Examples/Puzzles/Garden.hs
@@ -28,12 +28,9 @@
 -- case, the second student would be right.
 ------------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
-{-# LANGUAGE FlexibleInstances   #-}
-{-# LANGUAGE OverloadedStrings   #-}
-{-# LANGUAGE StandaloneDeriving  #-}
-{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE FlexibleInstances  #-}
+{-# LANGUAGE TemplateHaskell    #-}
+{-# LANGUAGE TypeApplications   #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -43,10 +40,9 @@
 
 -- | Colors of the flowers
 data Color = Red | Yellow | Blue
-          deriving (Enum, Bounded)
 
 -- | Make 'Color' a symbolic value.
-mkSymbolicEnumeration ''Color
+mkSymbolic [''Color]
 
 -- | Represent flowers by symbolic integers
 type Flower = SInteger
diff --git a/Documentation/SBV/Examples/Puzzles/HexPuzzle.hs b/Documentation/SBV/Examples/Puzzles/HexPuzzle.hs
--- a/Documentation/SBV/Examples/Puzzles/HexPuzzle.hs
+++ b/Documentation/SBV/Examples/Puzzles/HexPuzzle.hs
@@ -36,13 +36,9 @@
 -- to the final one.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
-{-# LANGUAGE FlexibleInstances   #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
-{-# LANGUAGE TemplateHaskell     #-}
-{-# LANGUAGE TypeApplications    #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -55,10 +51,9 @@
 
 -- | Colors we're allowed
 data Color = Black | Blue | Green | Red
-          deriving (Enum, Bounded)
 
 -- | Make 'Color' a symbolic value.
-mkSymbolicEnumeration ''Color
+mkSymbolic [''Color]
 
 -- | Use 8-bit words for button numbers, even though we only have 1 to 19.
 type Button  = Word8
diff --git a/Documentation/SBV/Examples/Puzzles/KnightsAndKnaves.hs b/Documentation/SBV/Examples/Puzzles/KnightsAndKnaves.hs
--- a/Documentation/SBV/Examples/Puzzles/KnightsAndKnaves.hs
+++ b/Documentation/SBV/Examples/Puzzles/KnightsAndKnaves.hs
@@ -12,11 +12,9 @@
 -- Determine which one is a knave or a knight, depending on their answers.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass     #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE FlexibleInstances  #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE TemplateHaskell    #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
 
 module Documentation.SBV.Examples.Puzzles.KnightsAndKnaves where
 
@@ -27,19 +25,17 @@
 
 -- | Inhabitants of the island, as an uninterpreted sort
 data Inhabitant
-mkUninterpretedSort ''Inhabitant
+mkSymbolic [''Inhabitant]
 
 -- | Each inhabitant is either a knave or a knight
 data Identity = Knave | Knight
-              deriving (Enum, Bounded)
 
-mkSymbolicEnumeration ''Identity
+mkSymbolic [''Identity]
 
 -- | Statements are utterances which are either true or false
 data Statement = Truth | Falsity
-               deriving (Enum, Bounded)
 
-mkSymbolicEnumeration ''Statement
+mkSymbolic [''Statement]
 
 -- | John is an inhabitant of the island.
 john :: SInhabitant
diff --git a/Documentation/SBV/Examples/Puzzles/Murder.hs b/Documentation/SBV/Examples/Puzzles/Murder.hs
--- a/Documentation/SBV/Examples/Puzzles/Murder.hs
+++ b/Documentation/SBV/Examples/Puzzles/Murder.hs
@@ -20,12 +20,10 @@
 -- @
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass     #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE FlexibleInstances  #-}
-{-# LANGUAGE NamedFieldPuns     #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE TemplateHaskell    #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE NamedFieldPuns    #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
 
 {-# OPTIONS_GHC -Wall -Werror   #-}
 
@@ -39,19 +37,19 @@
 
 -- | Locations
 data Location = Bar | Beach | Alone
-              deriving (Enum, Bounded)
+              deriving Show
 
 -- | Sexes
-data Sex  = Male | Female
-          deriving (Enum, Bounded)
+data Sex = Male | Female
+         deriving Show
 
 -- | Roles
 data Role = Victim | Killer | Bystander
-          deriving (Enum, Bounded)
+          deriving Show
 
-mkSymbolicEnumeration ''Location
-mkSymbolicEnumeration ''Sex
-mkSymbolicEnumeration ''Role
+mkSymbolic [''Location]
+mkSymbolic [''Sex]
+mkSymbolic [''Role]
 
 -- | A person has a name, age, together with location and sex.
 -- We parameterize over a function so we can use this struct
@@ -89,10 +87,10 @@
 -- | Solve the puzzle. We have:
 --
 -- >>> killer
--- Alice     47  Bar    Female  Bystander
--- Husband   46  Beach  Male    Killer
--- Brother   47  Beach  Male    Victim
--- Daughter  20  Alone  Female  Bystander
+-- Alice     48  Bar    Female  Bystander
+-- Husband   47  Beach  Male    Killer
+-- Brother   48  Beach  Male    Victim
+-- Daughter  21  Alone  Female  Bystander
 -- Son       20  Bar    Male    Bystander
 --
 -- That is, Alice's brother was the victim and Alice's husband was the killer.
diff --git a/Documentation/SBV/Examples/Puzzles/Orangutans.hs b/Documentation/SBV/Examples/Puzzles/Orangutans.hs
--- a/Documentation/SBV/Examples/Puzzles/Orangutans.hs
+++ b/Documentation/SBV/Examples/Puzzles/Orangutans.hs
@@ -11,12 +11,11 @@
 
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE DeriveGeneric       #-}
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE TemplateHaskell     #-}
-{-# LANGUAGE StandaloneDeriving  #-}
+{-# LANGUAGE TypeApplications    #-}
 {-# LANGUAGE OverloadedRecordDot #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
@@ -33,19 +32,17 @@
 
 -- | Orangutans in the puzzle.
 data Orangutan = Merah | Ofallo | Quirrel | Shamir
-               deriving (Enum, Bounded)
+               deriving (Show, Enum, Bounded)
 
 -- | Handlers for each orangutan.
 data Handler = Dolly | Eva | Francine | Gracie
-             deriving (Enum, Bounded)
 
 -- | Location for each orangutan.
 data Location = Ambalat | Basahan | Kendisi | Tarakan
-             deriving (Enum, Bounded)
 
-mkSymbolicEnumeration ''Orangutan
-mkSymbolicEnumeration ''Handler
-mkSymbolicEnumeration ''Location
+mkSymbolic [''Orangutan]
+mkSymbolic [''Handler]
+mkSymbolic [''Location]
 
 -- | An assignment is solution to the puzzle
 data Assignment = MkAssignment { orangutan :: SOrangutan
diff --git a/Documentation/SBV/Examples/Puzzles/Rabbits.hs b/Documentation/SBV/Examples/Puzzles/Rabbits.hs
--- a/Documentation/SBV/Examples/Puzzles/Rabbits.hs
+++ b/Documentation/SBV/Examples/Puzzles/Rabbits.hs
@@ -15,11 +15,9 @@
 -- What's implicit here is that there is a rabbit that must be not-greedy;
 -- which we add to our constraints.
 -----------------------------------------------------------------------------
-{-# LANGUAGE DeriveAnyClass     #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE TemplateHaskell    #-}
 
+{-# LANGUAGE TemplateHaskell #-}
+
 {-# OPTIONS_GHC -Wall -Werror #-}
 
 module Documentation.SBV.Examples.Puzzles.Rabbits where
@@ -30,7 +28,7 @@
 data Rabbit
 
 -- | Make rabbits symbolically available.
-mkUninterpretedSort ''Rabbit
+mkSymbolic [''Rabbit]
 
 -- | Identify those rabbits that are greedy. Note that we leave the predicate uninterpreted.
 greedy :: SRabbit -> SBool
diff --git a/Documentation/SBV/Examples/Puzzles/U2Bridge.hs b/Documentation/SBV/Examples/Puzzles/U2Bridge.hs
--- a/Documentation/SBV/Examples/Puzzles/U2Bridge.hs
+++ b/Documentation/SBV/Examples/Puzzles/U2Bridge.hs
@@ -9,12 +9,11 @@
 -- The famous U2 bridge crossing puzzle: <http://www.braingle.com/brainteasers/515/u2.html>
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass       #-}
-{-# LANGUAGE DeriveDataTypeable   #-}
-{-# LANGUAGE DeriveGeneric        #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE StandaloneDeriving   #-}
-{-# LANGUAGE TemplateHaskell      #-}
+{-# LANGUAGE DeriveAnyClass    #-}
+{-# LANGUAGE DeriveGeneric     #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
 
 {-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-uni-patterns #-}
 
@@ -33,13 +32,12 @@
 -- * Modeling the puzzle
 -------------------------------------------------------------
 
--- | U2 band members. We want to translate this to SMT-Lib as a data-type, and hence the
--- call to mkSymbolicEnumeration.
+-- | U2 band members.
 data U2Member = Bono | Edge | Adam | Larry
-              deriving (Enum, Bounded, Eq, Ord)
+              deriving Show
 
 -- | Make 'U2Member' a symbolic value.
-mkSymbolicEnumeration ''U2Member
+mkSymbolic [''U2Member]
 
 -- | Model time using 32 bits
 type Time  = Word32
@@ -63,10 +61,10 @@
 
 -- | Location of the flash
 data Location = Here | There
-              deriving (Enum, Bounded)
+              deriving (Eq, Show, Enum, Bounded)
 
 -- | Make 'Location' a symbolic value.
-mkSymbolicEnumeration ''Location
+mkSymbolic [''Location]
 
 -- | The status of the puzzle after each move
 --
@@ -197,9 +195,12 @@
 -- | Check if a given sequence of actions is valid, i.e., they must all
 -- cross the bridge according to the rules and in less than 17 seconds
 isValid :: Actions -> SBool
-isValid as = time end .<= 17 .&& sAll check as .&& zigZag (cycle [sThere, sHere]) (map flash states) .&& sAll (.== sThere) [lBono end, lEdge end, lAdam end, lLarry end]
-  where check (s, p1, p2) =   (sNot s .=> p1 .> p2)       -- for two person moves, ensure first person is "larger"
-                          .&& (s      .=> p2 .== sBono)   -- for one person moves, ensure second person is always "bono"
+isValid as =   time end .<= 17
+           .&& sAll check as
+           .&& zigZag (cycle [sThere, sHere]) (map flash states)
+           .&& sAll (.== sThere) [lBono end, lEdge end, lAdam end, lLarry end]
+  where check (s, p1, p2) =   (sNot s .=> p1 .>  p2)    -- for two person moves, ensure first person is "larger"
+                          .&& (s      .=> p2 .== sBono) -- for one person moves, ensure second person is always "bono"
         states = evalState (run as) start
         end = last states
         zigZag reqs locs = sAnd $ zipWith (.==) locs reqs
diff --git a/Documentation/SBV/Examples/Queries/Enums.hs b/Documentation/SBV/Examples/Queries/Enums.hs
--- a/Documentation/SBV/Examples/Queries/Enums.hs
+++ b/Documentation/SBV/Examples/Queries/Enums.hs
@@ -9,12 +9,10 @@
 -- Demonstrates the use of enumeration values during queries.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -23,12 +21,12 @@
 import Data.SBV
 import Data.SBV.Control
 
--- | Days of the week. We make it symbolic using the 'mkSymbolicEnumeration' splice.
+-- | Days of the week. We make it symbolic using the 'mkSymbolic' splice.
 data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday
-         deriving (Eq, Ord, Bounded, Enum)
+         deriving Show
 
 -- | Make 'Day' a symbolic value.
-mkSymbolicEnumeration ''Day
+mkSymbolic [''Day]
 
 -- | A trivial query to find three consecutive days that's all before 'Thursday'. The point
 -- here is that we can perform queries on such enumerated values and use 'getValue' on them
diff --git a/Documentation/SBV/Examples/Queries/FourFours.hs b/Documentation/SBV/Examples/Queries/FourFours.hs
--- a/Documentation/SBV/Examples/Queries/FourFours.hs
+++ b/Documentation/SBV/Examples/Queries/FourFours.hs
@@ -19,12 +19,9 @@
 -- and ask the SMT solver to find the appropriate fillings.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
-{-# LANGUAGE FlexibleInstances  #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
-{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -40,20 +37,20 @@
 -- and exponentiation will only be to the power @0@. This does restrict the search space, but is sufficient to
 -- solve all the instances.
 data BinOp = Plus | Minus | Times | Divide | Expt
-           deriving (Eq, Enum, Bounded)
+           deriving (Eq, Show)
 
 -- | Make 'BinOp' a symbolic value.
-mkSymbolicEnumeration ''BinOp
+mkSymbolic [''BinOp]
 
 -- | Supported unary operators. Similar to 'BinOp' case, we will restrict square-root and factorial to
 -- be only applied to the value @4.
 data UnOp  = Negate | Sqrt | Factorial
-           deriving (Eq, Enum, Bounded)
+           deriving Eq
 
 -- | Make 'UnOp' a symbolic value.
-mkSymbolicEnumeration ''UnOp
+mkSymbolic [''UnOp]
 
--- | The shape of a tree, either a binary node, or a unary node, or the number @4@, represented hear by
+-- | The shape of a tree, either a binary node, or a unary node, or the number @4@, represented here by
 -- the constructor @F@. We parameterize by the operator type: When doing symbolic computations, we'll fill
 -- those with 'SBinOp' and 'SUnOp'. When finding the shapes, we will simply put unit values, i.e., holes.
 data T b u = B b (T b u) (T b u)
@@ -98,9 +95,9 @@
 
 -- | Minor helper for writing "symbolic" case statements. Simply walks down a list
 -- of values to match against a symbolic version of the key.
-sCase :: (Eq a, SymVal a, Mergeable v) => SBV a -> [(a, v)] -> v
-sCase k = walk
-  where walk []              = error "sCase: Expected a non-empty list of cases!"
+cases :: (Eq a, SymVal a, Mergeable v) => SBV a -> [(a, v)] -> v
+cases k = walk
+  where walk []              = error "cases: Expected a non-empty list of cases!"
         walk [(_, v)]        = v
         walk ((k1, v1):rest) = ite (k .== literal k1) v1 (walk rest)
 
@@ -117,7 +114,7 @@
   where binOp :: SBinOp -> SInteger -> SInteger -> Symbolic SInteger
         binOp o l r = do constrain $ o .== sDivide .=> r .== 4 .|| r .== 2
                          constrain $ o .== sExpt   .=> r .== 0
-                         return $ sCase o
+                         return $ cases o
                                     [ (Plus,    l+r)
                                     , (Minus,   l-r)
                                     , (Times,   l*r)
@@ -128,7 +125,7 @@
         uOp :: SUnOp -> SInteger -> Symbolic SInteger
         uOp o v = do constrain $ o .== sSqrt      .=> v .== 4
                      constrain $ o .== sFactorial .=> v .== 4
-                     return $ sCase o
+                     return $ cases o
                                 [ (Negate,    -v)
                                 , (Sqrt,       2)  -- argument is restricted to 4, so the value is 2
                                 , (Factorial, 24)  -- argument is restricted to 4, so the value is 24
diff --git a/Documentation/SBV/Examples/TP/Basics.hs b/Documentation/SBV/Examples/TP/Basics.hs
--- a/Documentation/SBV/Examples/TP/Basics.hs
+++ b/Documentation/SBV/Examples/TP/Basics.hs
@@ -11,7 +11,6 @@
 
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE DataKinds           #-}
-{-# LANGUAGE TypeAbstractions    #-}
 {-# LANGUAGE TypeApplications    #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
diff --git a/Documentation/SBV/Examples/TP/BinarySearch.hs b/Documentation/SBV/Examples/TP/BinarySearch.hs
--- a/Documentation/SBV/Examples/TP/BinarySearch.hs
+++ b/Documentation/SBV/Examples/TP/BinarySearch.hs
@@ -9,10 +9,8 @@
 -- Proving binary search correct.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DataKinds           #-}
-{-# LANGUAGE TypeAbstractions    #-}
-{-# LANGUAGE TypeApplications    #-}
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE TypeApplications #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -142,7 +140,7 @@
   bsearchAbsent <- sInduct "bsearchAbsent"
         (\(Forall arr) (Forall lo) (Forall hi) (Forall x) ->
             nonDecreasing arr (lo, hi) .&& sNot (inArray arr (lo, hi) x) .=> isNothing (bsearch arr (lo, hi) x))
-        (\_arr lo hi _x -> abs (hi - lo + 1)) $
+        (\_arr lo hi _x -> abs (hi - lo + 1), []) $
         \ih arr lo hi x ->
               [nonDecreasing arr (lo, hi), sNot (inArray arr (lo, hi) x)]
            |- isNothing (bsearch arr (lo, hi) x)
@@ -195,7 +193,7 @@
   bsearchPresent <- sInduct "bsearchPresent"
         (\(Forall arr) (Forall lo) (Forall hi) (Forall x) ->
             nonDecreasing arr (lo, hi) .&& inArray arr (lo, hi) x .=> arr `readArray` fromJust (bsearch arr (lo, hi) x) .== x)
-        (\_arr lo hi _x -> abs (hi - lo + 1)) $
+        (\_arr lo hi _x -> abs (hi - lo + 1), []) $
         \ih arr lo hi x ->
              [nonDecreasing arr (lo, hi), inArray arr (lo, hi) x]
           |- x .== arr `readArray` fromJust (bsearch arr (lo, hi) x)
diff --git a/Documentation/SBV/Examples/TP/CaseSplit.hs b/Documentation/SBV/Examples/TP/CaseSplit.hs
--- a/Documentation/SBV/Examples/TP/CaseSplit.hs
+++ b/Documentation/SBV/Examples/TP/CaseSplit.hs
@@ -9,8 +9,7 @@
 -- Use TP to prove @2n^2 + n + 1@ is never divisible by @3@.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DataKinds        #-}
-{-# LANGUAGE TypeAbstractions #-}
+{-# LANGUAGE DataKinds #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
diff --git a/Documentation/SBV/Examples/TP/Fibonacci.hs b/Documentation/SBV/Examples/TP/Fibonacci.hs
--- a/Documentation/SBV/Examples/TP/Fibonacci.hs
+++ b/Documentation/SBV/Examples/TP/Fibonacci.hs
@@ -10,10 +10,8 @@
 -- version are equivalent.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DataKinds           #-}
-{-# LANGUAGE TypeAbstractions    #-}
-{-# LANGUAGE TypeApplications    #-}
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE TypeApplications #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -40,7 +38,7 @@
 
 -- * Correctness
 
--- | Proving the the tail version of fibonacci is equivalent to the textbook version.
+-- | Proving the tail recursive version of fibonacci is equivalent to the textbook version.
 --
 -- We have:
 --
diff --git a/Documentation/SBV/Examples/TP/GCD.hs b/Documentation/SBV/Examples/TP/GCD.hs
--- a/Documentation/SBV/Examples/TP/GCD.hs
+++ b/Documentation/SBV/Examples/TP/GCD.hs
@@ -71,7 +71,7 @@
      -- We first prove over nGCD, using strong induction with the measure @a+b@.
      nn <- sInduct "nonNegativeNGCD"
                    (\(Forall a) (Forall b) -> a .>= 0 .&& b .>= 0 .=> nGCD a b .>= 0)
-                   (\_a b -> b) $
+                   (\_a b -> b, []) $
                    \ih a b -> [a .>= 0, b .>= 0]
                            |- cases [ b .== 0 ==> trivial
                                     , b ./= 0 ==> nGCD a b .>= 0
@@ -106,7 +106,7 @@
   nGCDZero <-
     sInduct "nGCDZero"
             (\(Forall @"a" a) (Forall @"b" b) -> a .>= 0 .&& b .>= 0 .&& nGCD a b .== 0 .=> a .== 0 .&& b .== 0)
-            (\_a b -> b) $
+            (\_a b -> b, []) $
             \ih a b -> [a .>= 0, b .>= 0]
                     |- (nGCD a b .== 0 .=> a .== 0 .&& b .== 0)
                     =: cases [ b .== 0 ==> trivial
@@ -129,6 +129,7 @@
 --   Result:                               Q.E.D.
 -- Lemma: commutative
 --   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
 --   Result:                               Q.E.D.
 -- [Proven] commutative :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
 commutative :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
@@ -148,7 +149,8 @@
     calc "commutative"
           (\(Forall a) (Forall b) -> gcd a b .== gcd b a) $
           \a b -> [] |- gcd a b
-                     ?? nGCDComm
+                     =: nGCD (abs a) (abs b)
+                     ?? nGCDComm `at` (Inst @"a" (abs a), Inst @"b" (abs b))
                      =: gcd b a
                      =: qed
 
@@ -293,7 +295,7 @@
 dvdEvenWhenOdd = calc "dvdEvenWhenOdd"
                       (\(Forall d) (Forall a) -> isOdd d .&& d `dvd` (2*a) .=> d `dvd` a) $
                       \d a ->  [isOdd d, d `dvd` (2*a)]
-                           |-> let t = (d - 1) `sEDiv` 2
+                           |-  let t = (d - 1) `sEDiv` 2
                                    m = (2*a)   `sEDiv` d
                             in sTrue
 
@@ -422,7 +424,7 @@
    -- Use strong induction to prove divisibility over non-negative numbers.
    dNGCD <- sInduct "dvdNGCD"
                      (\(Forall @"a" a) (Forall @"b" b) -> a .>= 0 .&& b .>= 0 .=> nGCD a b `dvd` a .&& nGCD a b `dvd` b)
-                     (\_a b -> b) $
+                     (\_a b -> b, []) $
                      \ih a b -> [a .>= 0, b .>= 0]
                              |- let g = nGCD a b
                              in g `dvd` a .&& g `dvd` b
@@ -447,6 +449,7 @@
 -- ==== __Proof__
 -- >>> runTP gcdMaximal
 -- Lemma: dvdAbs                           Q.E.D.
+-- Lemma: gcdComm                          Q.E.D.
 -- Lemma: eDiv                             Q.E.D.
 -- Lemma: helper
 --   Step: 1 (x `dvd` a && x `dvd` b)      Q.E.D.
@@ -467,13 +470,16 @@
 --     Step: 1.1.2                         Q.E.D.
 --     Step: 1.2.1                         Q.E.D.
 --     Step: 1.2.2                         Q.E.D.
+--     Step: 1.2.3                         Q.E.D.
+--     Step: 1.2.4                         Q.E.D.
 --     Step: 1.Completeness                Q.E.D.
 --   Result:                               Q.E.D.
 -- [Proven] gcdMaximal :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐx ∷ Integer → Bool
 gcdMaximal :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "x" Integer -> SBool))
 gcdMaximal = do
 
-   dAbs  <- recall "dvdAbs" dvdAbs
+   dAbs <- recall "dvdAbs" dvdAbs
+   comm <- recall "gcdComm" commutative
 
    eDiv <- lemma "eDiv"
                  (\(Forall @"x" x) (Forall @"y" y) -> y ./= 0 .=> x .== (x `sEDiv` y) * y + x `sEMod` y)
@@ -501,7 +507,7 @@
    mNGCD <- sInduct "mNGCD"
                     (\(Forall @"a" a) (Forall @"b" b) (Forall @"x" x) ->
                           a .>= 0 .&& b .>= 0 .&& x `dvd` a .&& x `dvd` b .=> x `dvd` nGCD a b)
-                    (\_a b _x -> b) $
+                    (\_a b _x -> b, []) $
                     \ih a b x -> let g = nGCD a b
                               in [a .>= 0, b .>= 0, x `dvd` a .&& x `dvd` b]
                               |- x `dvd` g
@@ -524,7 +530,10 @@
                                            ?? dAbs     `at` (Inst @"a" x, Inst @"b" b)
                                            =: sTrue
                                            =: qed
-                        , abs a .<  abs b ==> x `dvd` nGCD (abs b) (abs a)
+                        , abs a .<  abs b ==> x `dvd` gcd a b
+                                           ?? comm `at` (Inst @"a" a, Inst @"b" b)
+                                           =: x `dvd` gcd b a
+                                           =: x `dvd` nGCD (abs b) (abs a)
                                            ?? mNGCD    `at` (Inst @"a" (abs b), Inst @"b" (abs a), Inst @"x" x)
                                            ?? dAbs     `at` (Inst @"a" x, Inst @"b" a)
                                            ?? dAbs     `at` (Inst @"a" x, Inst @"b" b)
@@ -694,7 +703,7 @@
 
    nGCDEvenEven <- sInduct "nGCDEvenEven"
                            (\(Forall @"a" a) (Forall @"b" b) -> a .>= 0 .&& b .>= 0 .=> nGCD (2*a) (2*b) .== 2 * nGCD a b)
-                           (\_a b -> b) $
+                           (\_a b -> b, []) $
                            \ih a b -> [a .>= 0, b .>= 0]
                                    |- nGCD (2*a) (2*b)
                                    =: cases [ b .== 0 ==> trivial
@@ -841,7 +850,7 @@
    -- First prove over the non-negative numbers:
    nEq <- sInduct "nGCDSubEquiv"
                   (\(Forall @"a" a) (Forall @"b" b) -> a .>= 0 .&& b .>= 0 .=> nGCDSub a b .== nGCD a b)
-                  (\a b -> a + b) $
+                  (\a b -> a + b, []) $
                   \ih a b -> [a .>= 0, b .>= 0]
                           |- nGCDSub a b
                           =: cases [ a .== b             ==> nGCD a b =: qed
@@ -942,7 +951,7 @@
    -- First prove over the non-negative numbers:
    nEq <- sInduct "nGCDBinEquiv"
                   (\(Forall @"a" a) (Forall @"b" b) -> a .>= 0 .&& b .>= 0 .=> nGCDBin a b .== nGCD a b)
-                  (\a b -> tuple (a, b)) $
+                  (\a b -> tuple (a, b), []) $
                   \ih a b -> [a .>= 0, b .>= 0]
                           |- nGCDBin a b
                           =: cases [ a .== 0               ==> trivial
diff --git a/Documentation/SBV/Examples/TP/InsertionSort.hs b/Documentation/SBV/Examples/TP/InsertionSort.hs
--- a/Documentation/SBV/Examples/TP/InsertionSort.hs
+++ b/Documentation/SBV/Examples/TP/InsertionSort.hs
@@ -13,9 +13,8 @@
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE OverloadedLists     #-}
-{-# LANGUAGE TypeAbstractions    #-}
-{-# LANGUAGE TypeApplications    #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
diff --git a/Documentation/SBV/Examples/TP/Kleene.hs b/Documentation/SBV/Examples/TP/Kleene.hs
--- a/Documentation/SBV/Examples/TP/Kleene.hs
+++ b/Documentation/SBV/Examples/TP/Kleene.hs
@@ -11,14 +11,11 @@
 -- Based on <http://www.philipzucker.com/bryzzowski_kat/>
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DataKinds            #-}
-{-# LANGUAGE DeriveAnyClass       #-}
-{-# LANGUAGE DeriveDataTypeable   #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE StandaloneDeriving   #-}
-{-# LANGUAGE TemplateHaskell      #-}
-{-# LANGUAGE TypeAbstractions     #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeAbstractions    #-}
 
 {-# OPTIONS_GHC -Wall -Werror -Wno-unused-matches #-}
 
@@ -31,7 +28,7 @@
 
 -- | An uninterpreted sort, corresponding to the type of Kleene algebra strings.
 data Kleene
-mkUninterpretedSort ''Kleene
+mkSymbolic [''Kleene]
 
 -- | Star operator over kleene algebras. We're leaving this uninterpreted.
 star :: SKleene -> SKleene
diff --git a/Documentation/SBV/Examples/TP/Majority.hs b/Documentation/SBV/Examples/TP/Majority.hs
--- a/Documentation/SBV/Examples/TP/Majority.hs
+++ b/Documentation/SBV/Examples/TP/Majority.hs
@@ -10,7 +10,6 @@
 -- closely, which you can find at <https://github.com/acl2/acl2/blob/master/books/demos/majority-vote.lisp>.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE CPP                 #-}
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeAbstractions    #-}
diff --git a/Documentation/SBV/Examples/TP/McCarthy91.hs b/Documentation/SBV/Examples/TP/McCarthy91.hs
--- a/Documentation/SBV/Examples/TP/McCarthy91.hs
+++ b/Documentation/SBV/Examples/TP/McCarthy91.hs
@@ -9,10 +9,9 @@
 -- Proving McCarthy's 91 function correct.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DataKinds           #-}
-{-# LANGUAGE TypeAbstractions    #-}
-{-# LANGUAGE TypeApplications    #-}
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE TypeAbstractions #-}
+{-# LANGUAGE TypeApplications #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -65,7 +64,7 @@
    -- Case 3. When @n < 90@. The crucial point here is the measure, which makes sure 101 < 100 < 99 < ...
    case3 <- sInduct "case3"
                     (\(Forall n) -> n .< 90 .=> mcCarthy91 n .== spec91 n)
-                    (\n -> abs (101 - n)) $
+                    (\n -> abs (101 - n), []) $
                     \ih n -> [n .< 90] |- mcCarthy91 n
                                        ?? "unfold"
                                        =: mcCarthy91 (mcCarthy91 (n + 11))
diff --git a/Documentation/SBV/Examples/TP/MergeSort.hs b/Documentation/SBV/Examples/TP/MergeSort.hs
--- a/Documentation/SBV/Examples/TP/MergeSort.hs
+++ b/Documentation/SBV/Examples/TP/MergeSort.hs
@@ -13,9 +13,8 @@
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE OverloadedLists     #-}
-{-# LANGUAGE TypeAbstractions    #-}
-{-# LANGUAGE TypeApplications    #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -142,7 +141,7 @@
     mergeKeepsSort <-
         sInductWith cvc5 "mergeKeepsSort"
            (\(Forall xs) (Forall ys) -> nonDecreasing xs .&& nonDecreasing ys .=> nonDecreasing (merge xs ys))
-           (\xs ys -> tuple (length xs, length ys)) $
+           (\xs ys -> tuple (length xs, length ys), []) $
            \ih xs ys -> [nonDecreasing xs, nonDecreasing ys]
                      |- split2 (xs, ys)
                                trivial           -- when both xs and ys are empty.  Trivial.
@@ -170,7 +169,7 @@
     sortNonDecreasing <-
         sInduct "sortNonDecreasing"
                 (\(Forall xs) -> nonDecreasing (mergeSort xs))
-                length $
+                (length, []) $
                 \ih xs -> [] |- split xs
                                       qed
                                       (\e es -> nonDecreasing (mergeSort (e .: es))
@@ -199,7 +198,7 @@
     mergeCount <-
         sInduct "mergeCount"
                 (\(Forall xs) (Forall ys) (Forall e) -> count e (merge xs ys) .== count e xs + count e ys)
-                (\xs ys _e -> tuple (length xs, length ys)) $
+                (\xs ys _e -> tuple (length xs, length ys), []) $
                 \ih as bs e -> [] |- split2 (as, bs)
                                             trivial
                                             trivial
@@ -236,7 +235,7 @@
     sortIsPermutation <-
         sInductWith cvc5 "sortIsPermutation"
                 (\(Forall xs) (Forall e) -> count e xs .== count e (mergeSort xs))
-                (\xs _e -> length xs) $
+                (\xs _e -> length xs, []) $
                 \ih as e -> [] |- split as
                                         trivial
                                         (\x xs -> count e (mergeSort (x .: xs))
diff --git a/Documentation/SBV/Examples/TP/Peano.hs b/Documentation/SBV/Examples/TP/Peano.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Peano.hs
@@ -0,0 +1,891 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Peano
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Modeling Peano arithmetic in SBV and proving various properties using TP.
+-- Most of the properties we prove come from <https://en.wikipedia.org/wiki/Peano_axioms>.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Peano where
+
+import Data.SBV
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.TP
+#endif
+
+-- | Natural numbers. (If you are looking at the haddock documents, note the plethora of definitions
+-- the call to 'mkSymbolic' generates. You can mostly ignore these, except for the case analyzer,
+-- the testers and accessors.)
+data Nat = Zero
+         | Succ { prev :: Nat }
+
+-- | Create a symbolic version of naturals.
+mkSymbolic [''Nat]
+
+-- | Numeric instance. Choices: We clamp everything at 'Zero'. Negation is identity.
+instance Num Nat where
+  fromInteger i | i <= 0 = Zero
+                | True   = Succ (fromInteger (i - 1))
+
+  a + Zero   = a
+  a + Succ b = Succ (a + b)
+
+  (-) = error "Nat: No support for subtraction"
+
+  _ * Zero   = Zero
+  a * Succ b = a + a * b
+
+  abs = id
+
+  signum Zero = 0
+  signum _    = 1
+
+  negate = id
+
+-- Symbolic numeric instance, mirroring the above
+instance Num SNat where
+  fromInteger = literal . fromInteger
+
+  (+) = plus
+      where plus = smtFunction "sNatPlus" $
+                     \m n -> [sCase|Nat m of
+                               Zero   -> n
+                               Succ p -> sSucc (p + n)
+                             |]
+
+  (-) = error "SNat: No support for subtraction"
+
+  (*) = times
+      where times = smtFunction "sNatTimes" $
+                      \m n -> [sCase|Nat m of
+                                Zero   -> 0
+                                Succ p -> n + p * n
+                              |]
+
+  abs = id
+
+  signum m = [sCase|Nat m of
+               Zero -> 0
+               _    -> 1
+             |]
+
+-- | Symbolic ordering. We only define less-than, other methods use the defaults.
+instance OrdSymbolic SNat where
+   m .< n = quantifiedBool (\(Exists k) -> n .== m + sSucc k)
+
+-- * Conversion to and from integers
+
+-- | Convert from 'Nat' to 'Integer'.
+--
+-- NB. When writing the properties below, we use the notation \(\overline{n}\) to mean @n2i n@.
+n2i :: SNat -> SInteger
+n2i = smtFunction "n2i" $ \n -> [sCase|Nat n of
+                                   Zero   -> 0
+                                   Succ p -> 1 + n2i p
+                                |]
+
+-- | Convert Non-negative integers to 'Nat'. Negative numbers become 'Zero'.
+--
+-- NB. When writing the properties below, we use the notation \(\underline{i}\) to mean @i2n i@.
+i2n :: SInteger -> SNat
+i2n = smtFunction "i2n" $ \i -> ite (i .<= 0) 0 (sSucc (i2n (i - 1)))
+
+-- | \(\overline{n} \geq 0\)
+--
+-- >>> runTP n2iNonNeg
+-- Lemma: n2iNonNeg                        Q.E.D.
+-- [Proven] n2iNonNeg :: Ɐn ∷ Nat → Bool
+n2iNonNeg  :: TP (Proof (Forall "n" Nat -> SBool))
+n2iNonNeg = inductiveLemma "n2iNonNeg" (\(Forall n) -> n2i n .>= 0) []
+
+-- | \(\overline{\underline{i}} = \max(i, 0)\).
+--
+-- >>> runTP i2n2i
+-- Lemma: i2n2i                            Q.E.D.
+-- [Proven] i2n2i :: Ɐi ∷ Integer → Bool
+i2n2i :: TP (Proof (Forall "i" Integer -> SBool))
+i2n2i = inductiveLemma "i2n2i" (\(Forall i) -> n2i (i2n i) .== i `smax` 0) []
+
+-- | \(\underline{\overline{n}} = n\)
+--
+-- >>> runTP n2i2n
+-- Lemma: n2i2n                            Q.E.D.
+-- [Proven] n2i2n :: Ɐn ∷ Nat → Bool
+n2i2n :: TP (Proof (Forall "n" Nat -> SBool))
+n2i2n = inductiveLemma "n2i2n" (\(Forall n) -> i2n (n2i n) .== n) []
+
+-- | \(\overline{m + n} = \overline{m} + \overline{n}\)
+--
+-- >>> runTP n2iAdd
+-- Lemma: n2iAdd                           Q.E.D.
+-- [Proven] n2iAdd :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+n2iAdd :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+n2iAdd = inductiveLemma "n2iAdd" (\(Forall m) (Forall n) -> n2i (m + n) .== n2i m + n2i n) []
+
+-- * Addition
+
+-- ** Correctness
+
+-- | \(\overline{m + n} = \overline{m} + \overline{n}\)
+--
+-- >>> runTP addCorrect
+-- Lemma: addCorrect                       Q.E.D.
+-- [Proven] addCorrect :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+addCorrect :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+addCorrect = inductiveLemma
+               "addCorrect"
+               (\(Forall m) (Forall n) -> n2i (m + n) .== n2i m + n2i n)
+               []
+
+-- ** Left and right unit
+
+-- | \(0 + m = m\)
+--
+-- >>> runTP addLeftUnit
+-- Lemma: addLeftUnit                      Q.E.D.
+-- [Proven] addLeftUnit :: Ɐm ∷ Nat → Bool
+addLeftUnit :: TP (Proof (Forall "m" Nat -> SBool))
+addLeftUnit = lemma "addLeftUnit" (\(Forall m) -> 0 + m .== m) []
+
+-- | \(m + 0 = m\)
+--
+-- >>> runTP addRightUnit
+-- Lemma: addRightUnit                     Q.E.D.
+-- [Proven] addRightUnit :: Ɐm ∷ Nat → Bool
+addRightUnit :: TP (Proof (Forall "m" Nat -> SBool))
+addRightUnit = inductiveLemma "addRightUnit" (\(Forall m) -> m + 0 .== m) []
+
+-- ** Addition with non-zero values
+
+-- | \(m + \mathrm{Succ}\,n = \mathrm{Succ}\,(m + n)\)
+--
+-- >>> runTP addSucc
+-- Lemma: caseZero                         Q.E.D.
+-- Lemma: caseSucc
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Result:                               Q.E.D.
+-- Lemma: addSucc                          Q.E.D.
+-- [Proven] addSucc :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+addSucc :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+addSucc = do
+   caseZero <- lemma "caseZero"
+                      (\(Forall @"n" n) -> 0 + sSucc n .== sSucc (0 + n))
+                      []
+
+   caseSucc <- calc "caseSucc"
+                    (\(Forall @"m" m) (Forall @"n" n) ->
+                        m + sSucc n .== sSucc (m + n) .=> sSucc m + sSucc n .== sSucc (sSucc m + n)) $
+                    \m n -> let ih = m + sSucc n .== sSucc (m + n)
+                         in [ih] |- sSucc m + sSucc n
+                                 =: sSucc (m + sSucc n)
+                                 ?? ih
+                                 =: sSucc (sSucc (m + n))
+                                 =: sSucc (sSucc m + n)
+                                 =: qed
+
+   inductiveLemma
+      "addSucc"
+      (\(Forall @"m" m) (Forall @"n" n) -> m + sSucc n .== sSucc (m + n))
+      [proofOf caseZero, proofOf caseSucc]
+
+-- ** Associativity
+
+-- | \(m + (n + o) = (m + n) + o\)
+--
+-- >>> runTP addAssoc
+-- Lemma: addAssoc                         Q.E.D.
+-- [Proven] addAssoc :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+addAssoc :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+addAssoc = inductiveLemma
+             "addAssoc"
+             (\(Forall m) (Forall n) (Forall o) -> m + (n + o) .== (m + n) + o)
+             []
+
+-- ** Commutativity
+
+-- | \(m + n = n + m\)
+--
+-- >>> runTP addComm
+-- Lemma: addLeftUnit                      Q.E.D.
+-- Lemma: addRightUnit                     Q.E.D.
+-- Lemma: caseZero                         Q.E.D.
+-- Lemma: addSucc                          Q.E.D.
+-- Lemma: caseSucc
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Result:                               Q.E.D.
+-- Lemma: addComm                          Q.E.D.
+-- [Proven] addComm :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+addComm :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+addComm = do
+    alu <- recall "addLeftUnit"  addLeftUnit
+    aru <- recall "addRightUnit" addRightUnit
+
+    caseZero <- lemma "caseZero"
+                      (\(Forall @"n" (n :: SNat)) -> 0 + n .== n + 0)
+                      [proofOf alu, proofOf aru]
+
+    as <- recall "addSucc" addSucc
+
+    caseSucc <- calc "caseSucc"
+                     (\(Forall @"m" m) (Forall @"n" n) -> m + n .== n + m .=> sSucc m + n .== n + sSucc m) $
+                     \m n -> let ih = m + n .== n + m
+                          in [ih] |- sSucc m + n
+                                  =: sSucc (m + n)
+                                  ?? ih
+                                  =: sSucc (n + m)
+                                  ?? as `at` (Inst @"m" n, Inst @"n" m)
+                                  =: n + sSucc m
+                                  =: qed
+
+    inductiveLemma "addComm"
+                   (\(Forall m) (Forall n) -> m + n .== n + m)
+                   [proofOf caseZero, proofOf caseSucc]
+
+-- * Multiplication
+
+-- ** Correctness
+
+-- | \(\overline{m * n} = \overline{m} * \overline{n}\)
+--
+-- >>> runTP mulCorrect
+-- Lemma: caseZero                         Q.E.D.
+-- Lemma: addCorrect                       Q.E.D.
+-- Lemma: caseSucc
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Step: 4                               Q.E.D.
+--   Step: 5                               Q.E.D.
+--   Result:                               Q.E.D.
+-- Lemma: mullCorrect                      Q.E.D.
+-- [Proven] mullCorrect :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+mulCorrect :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+mulCorrect = do
+   caseZero <- lemma "caseZero"
+                     (\(Forall @"n" n) -> n2i (0 * n) .== n2i 0 * n2i n)
+                     []
+
+   addC <- recall "addCorrect" addCorrect
+
+   caseSucc <- calc "caseSucc"
+                    (\(Forall @"m" m) (Forall @"n" n) ->
+                          n2i (m * n) .== n2i m * n2i n .=> n2i (sSucc m * n) .== n2i (sSucc m) * n2i n) $
+                    \m n -> let ih = n2i (m * n) .== n2i m * n2i n
+                         in [ih] |- n2i (sSucc m * n)
+                                 =: n2i (n + m * n)
+                                 ?? addC `at` (Inst @"m" n, Inst @"n" (m * n))
+                                 =: n2i n + n2i (m * n)
+                                 ?? ih
+                                 =: n2i n + n2i m * n2i n
+                                 =: n2i n * (1 + n2i m)
+                                 =: n2i n * n2i (sSucc m)
+                                 =: qed
+
+   inductiveLemma
+       "mullCorrect"
+       (\(Forall @"m" m) (Forall @"n" n) -> n2i (m * n) .== n2i m * n2i n)
+       [proofOf caseZero, proofOf caseSucc]
+
+-- ** Left and right absorption
+
+-- | \(0 * m = 0\)
+--
+-- >>> runTP mulLeftAbsorb
+-- Lemma: mulLeftAbsorb                    Q.E.D.
+-- [Proven] mulLeftAbsorb :: Ɐm ∷ Nat → Bool
+mulLeftAbsorb :: TP (Proof (Forall "m" Nat -> SBool))
+mulLeftAbsorb = lemma "mulLeftAbsorb" (\(Forall m) -> 0 * m .== 0) []
+
+-- | \(m * 0 = 0\)
+--
+-- >>> runTP mulRightAbsorb
+-- Lemma: mulRightAbsorb                   Q.E.D.
+-- [Proven] mulRightAbsorb :: Ɐm ∷ Nat → Bool
+mulRightAbsorb :: TP (Proof (Forall "m" Nat -> SBool))
+mulRightAbsorb = inductiveLemma "mulRightAbsorb" (\(Forall m) -> m * 0 .== 0) []
+
+-- ** Left and right unit
+
+-- | \(\mathrm{Succ\,0} * m = m\)
+--
+-- >>> runTP mulLeftUnit
+-- Lemma: mulLeftUnit                      Q.E.D.
+-- [Proven] mulLeftUnit :: Ɐm ∷ Nat → Bool
+mulLeftUnit :: TP (Proof (Forall "m" Nat -> SBool))
+mulLeftUnit = inductiveLemma "mulLeftUnit" (\(Forall m) -> sSucc 0 * m .== m) []
+
+-- | \(m * \mathrm{Succ\,0} = m\)
+--
+-- >>> runTP mulRightUnit
+-- Lemma: mulRightUnit                     Q.E.D.
+-- [Proven] mulRightUnit :: Ɐm ∷ Nat → Bool
+mulRightUnit :: TP (Proof (Forall "m" Nat -> SBool))
+mulRightUnit = inductiveLemma "mulRightUnit" (\(Forall m) -> m * sSucc 0 .== m) []
+
+-- ** Distribution over addition
+
+-- | \(m * (n + o) = m * n + m * o\)
+--
+-- >>> runTP distribLeft
+-- Lemma: caseZero                         Q.E.D.
+-- Lemma: addAssoc                         Q.E.D.
+-- Lemma: addComm                          Q.E.D.
+-- Lemma: caseSucc
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Step: 4                               Q.E.D.
+--   Step: 5                               Q.E.D.
+--   Step: 6                               Q.E.D.
+--   Step: 7                               Q.E.D.
+--   Step: 8                               Q.E.D.
+--   Step: 9                               Q.E.D.
+--   Result:                               Q.E.D.
+-- Lemma: distribLeft                      Q.E.D.
+-- [Proven] distribLeft :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+distribLeft :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+distribLeft = do
+   caseZero <- lemma "caseZero" (\(Forall @"n" n) (Forall @"o" (o :: SNat)) -> 0 * (n + o) .== 0 * n + 0 * o) []
+
+   addAsc <- recall "addAssoc" addAssoc
+   addCom <- recall "addComm"  addComm
+
+   caseSucc <- calc "caseSucc"
+                    (\(Forall @"m" m) (Forall @"n" n) (Forall @"o" o) ->
+                        m * (n + o) .== m * n + m * o .=> sSucc m * (n + o) .== sSucc m * n + sSucc m * o) $
+               \m n o -> let ih = m * (n + o) .== m * n + m * o
+                      in [ih] |- sSucc m * (n + o)
+                              =: (n + o) + m * (n + o)
+                              ?? ih
+                              =: (n + o) + (m * n + m * o)
+                              ?? addAsc `at` (Inst @"m" n, Inst @"n" o, Inst @"o" (m * n + m * o))
+                              =: n + (o + (m * n + m * o))
+                              ?? addCom `at` (Inst @"m" (m * n), Inst @"n" (m * o))
+                              =: n + (o + (m * o + m * n))
+                              ?? addAsc `at` (Inst @"m" o, Inst @"n" (m * o), Inst @"o" (m * n))
+                              =: n + ((o + m * o) + m * n)
+                              =: n + (sSucc m * o + m * n)
+                              ?? addCom `at` (Inst @"m" (sSucc m * o), Inst @"n" (m * n))
+                              =: n + (m * n + sSucc m * o)
+                              ?? addAsc `at` (Inst @"m" n, Inst @"n" (m * n), Inst @"o" (sSucc m * o))
+                              =: (n + m * n) + sSucc m * o
+                              =: sSucc m * n + sSucc m * o
+                              =: qed
+
+   inductiveLemma
+     "distribLeft"
+     (\(Forall m) (Forall n) (Forall o) -> m * (n + o) .== m * n + m * o)
+     [proofOf caseZero, proofOf caseSucc]
+
+-- | \((m + n) * o = m * o + n * o\)
+--
+-- >>> runTP distribRight
+-- Lemma: caseZero                         Q.E.D.
+-- Lemma: addAssoc                         Q.E.D.
+-- Lemma: addComm                          Q.E.D.
+-- Lemma: addSucc                          Q.E.D.
+-- Lemma: caseSucc
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Step: 4                               Q.E.D.
+--   Step: 5                               Q.E.D.
+--   Step: 6                               Q.E.D.
+--   Step: 7                               Q.E.D.
+--   Result:                               Q.E.D.
+-- Lemma: distribRight                     Q.E.D.
+-- [Proven] distribRight :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+distribRight :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+distribRight = do
+   caseZero <- lemma "caseZero" (\(Forall @"n" n) (Forall @"o" (o :: SNat)) -> (0 + n) * o .== 0 * o + n * o) []
+
+   pAddAssoc <- recall "addAssoc" addAssoc
+   pAddCom   <- recall "addComm"  addComm
+   pAddSucc  <- recall "addSucc"  addSucc
+
+   caseSucc <- calc "caseSucc"
+                    (\(Forall @"m" m) (Forall @"n" n) (Forall @"o" o) ->
+                        (m + n) * o .== m * o + n * o .=> (sSucc m + n) * o .== sSucc m * o + n * o) $
+               \m n o -> let ih = (m + n) * o .== m * o + n * o
+                      in [ih] |- (sSucc m + n) * o
+                              ?? pAddCom `at` (Inst @"m" (sSucc m), Inst @"n" n)
+                              =: (n + sSucc m) * o
+                              ?? pAddSucc `at` (Inst @"m" n, Inst @"n" m)
+                              =: sSucc (n + m) * o
+                              ?? pAddCom `at` (Inst @"m" n, Inst @"n" m)
+                              =: sSucc (m + n) * o
+                              =: o + (m + n) * o
+                              ?? ih
+                              =: o + (m * o + n *o)
+                              ?? pAddAssoc `at` (Inst @"m" o, Inst @"n" (m * o), Inst @"o" (n * o))
+                              =: (o + m * o) + n * o
+                              =: sSucc m * o + n * o
+                              =: qed
+
+   inductiveLemma
+     "distribRight"
+     (\(Forall m) (Forall n) (Forall o) -> (m + n) * o .== m * o + n * o)
+     [proofOf caseZero, proofOf caseSucc]
+
+-- ** Multiplication with non-zero values
+
+-- | \(m * \mathrm{Succ}\,n = m * n + m\)
+--
+-- >>> runTP mulSucc
+-- Lemma: addLeftUnit                      Q.E.D.
+-- Lemma: distribLeft                      Q.E.D.
+-- Lemma: mulRightUnit                     Q.E.D.
+-- Lemma: addComm                          Q.E.D.
+-- Lemma: mulSucc
+--   Step: 1                               Q.E.D.
+--   Step: 2 (defn of +)                   Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Step: 4                               Q.E.D.
+--   Step: 5                               Q.E.D.
+--   Result:                               Q.E.D.
+-- [Proven] mulSucc :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+mulSucc :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+mulSucc = do
+   alu <- recall "addLeftUnit"    addLeftUnit
+   dL  <- recall "distribLeft"    distribLeft
+   mru <- recall "mulRightUnit"   mulRightUnit
+   ac  <- recall "addComm"        addComm
+
+   calc "mulSucc"
+        (\(Forall @"m" m) (Forall @"n" n) -> m * sSucc n .== m * n + m) $
+        \m n -> [] |- m * sSucc n
+                   ?? alu
+                   =: m * sSucc (0 + n)
+                   ?? "defn of +"
+                   =: m * (sSucc 0 + n)
+                   ?? dL `at` (Inst @"m" m, Inst @"n" (sSucc 0), Inst @"o" n)
+                   =: m * sSucc 0 + m * n
+                   ?? mru
+                   =: m + m * n
+                   ?? ac `at` (Inst @"m" m, Inst @"n" (m * n))
+                   =: m * n + m
+                   =: qed
+
+-- ** Associativity
+
+-- | \(m * (n * o) = (m * n) * o\)
+--
+-- >>> runTP mulAssoc
+-- Lemma: caseZero                         Q.E.D.
+-- Lemma: distribRight                     Q.E.D.
+-- Lemma: caseSucc
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Step: 4                               Q.E.D.
+--   Result:                               Q.E.D.
+-- Lemma: mulAssoc                         Q.E.D.
+-- [Proven] mulAssoc :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+mulAssoc :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+mulAssoc = do
+   caseZero <- lemma "caseZero"
+                     (\(Forall @"n" n) (Forall @"o" (o :: SNat)) -> 0 * (n * o) .== (0 * n) * o)
+                     []
+
+   distR <- recall "distribRight" distribRight
+
+   caseSucc <- calc "caseSucc"
+                    (\(Forall @"m" m) (Forall @"n" n) (Forall @"o" o) ->
+                       m * (n * o) .== (m * n) * o .=> sSucc m * (n * o) .== (sSucc m * n) * o) $
+                    \m n o -> let ih = m * (n * o) .== (m * n) * o
+                              in [ih] |- sSucc m * (n * o)
+                                      =: (n * o) + m * (n * o)
+                                      ?? ih
+                                      =: (n * o) + (m * n) * o
+                                      ?? distR `at` (Inst @"m" n, Inst @"n" (m * n), Inst @"o" o)
+                                      =: (n + m * n) * o
+                                      =: (sSucc m * n) * o
+                                      =: qed
+
+   inductiveLemma
+     "mulAssoc"
+     (\(Forall m) (Forall n) (Forall o) -> m * (n * o) .== (m * n) * o)
+     [proofOf caseZero, proofOf caseSucc]
+
+-- ** Commutativity
+
+-- | \(m * n = n * m\)
+--
+-- >>> runTP mulComm
+-- Lemma: mulRightAbsorb                   Q.E.D.
+-- Lemma: caseZero                         Q.E.D.
+-- Lemma: mulRightUnit                     Q.E.D.
+-- Lemma: distribLeft                      Q.E.D.
+-- Lemma: caseSucc
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Step: 4                               Q.E.D.
+--   Step: 5                               Q.E.D.
+--   Step: 6                               Q.E.D.
+--   Result:                               Q.E.D.
+-- Lemma: mulComm                          Q.E.D.
+-- [Proven] mulComm :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+mulComm :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+mulComm = do
+  mra <- recall "mulRightAbsorb" mulRightAbsorb
+
+  caseZero <- lemma "caseZero"
+                    (\(Forall @"m" (m :: SNat)) -> 0 * m .== m * 0)
+                    [proofOf mra]
+
+  mru <- recall "mulRightUnit" mulRightUnit
+  dL  <- recall "distribLeft"  distribLeft
+
+  caseSucc <- calc "caseSucc"
+                   (\(Forall @"m" m) (Forall @"n" n) -> m * n .== n * m .=> sSucc m * n .== n * sSucc m) $
+                   \m n -> let ih = m * n .== n * m
+                        in [ih] |- sSucc m * n
+                                =: n + m * n
+                                ?? ih
+                                =: n + n * m
+                                ?? mru
+                                =: n * sSucc 0 + n * m
+                                ?? dL `at` (Inst @"m" n, Inst @"n" (sSucc 0), Inst @"o" m)
+                                =: n * (sSucc 0 + m)
+                                =: n * sSucc (0 + m)
+                                =: n * sSucc m
+                                =: qed
+
+  inductiveLemma
+    "mulComm"
+    (\(Forall @"m" m) (Forall @"n" n) -> m * n .== n * m)
+    [proofOf caseZero, proofOf caseSucc]
+
+-- * Ordering
+
+-- ** Transitivity of @<@
+
+-- | \(m < n \;\wedge\; n < o \;\rightarrow\; m < o\)
+--
+-- >>> runTP ltTrans
+-- Lemma: addAssoc                         Q.E.D.
+-- Lemma: ltTrans
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Step: 4                               Q.E.D.
+--   Step: 5                               Q.E.D.
+--   Step: 6                               Q.E.D.
+--   Result:                               Q.E.D.
+-- [Proven] ltTrans :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+ltTrans :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+ltTrans = do
+  aa <- recall "addAssoc" addAssoc
+
+  calc "ltTrans"
+       (\(Forall @"m" m) (Forall @"n" n) (Forall @"o" o) -> m .< n .&& n .< o .=> m .< o) $
+       \m n o ->  [m .< n, n .< o]
+              |-> let k1 = some "k1" (\k -> n .== m + sSucc k)
+                      k2 = some "k2" (\k -> o .== n + sSucc k)
+               in n .== m + sSucc k1
+               =: o .== n + sSucc k2
+               =: o .== (m + sSucc k1) + sSucc k2
+               ?? aa `at` (Inst @"m" m, Inst @"n" (sSucc k1), Inst @"o" (sSucc k2))
+               =: o .== m + (sSucc k1 + sSucc k2)
+               =: o .== m + sSucc (k1 + sSucc k2)
+               =: m .< o
+               =: sTrue
+               =: qed
+
+-- ** Irreflexivity of @<@
+
+-- | \(\neg(m < m)\)
+--
+-- >>> runTP ltIrreflexive
+-- Lemma: cancel                           Q.E.D.
+-- Lemma: ltIrreflexive
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Result:                               Q.E.D.
+-- [Proven] ltIrreflexive :: Ɐm ∷ Nat → Bool
+ltIrreflexive :: TP (Proof (Forall "m" Nat -> SBool))
+ltIrreflexive = do
+  cancel <- inductiveLemma
+              "cancel"
+              (\(Forall @"m" m) (Forall @"n" n) -> m + n .== m .=> n .== 0)
+              []
+
+  calc "ltIrreflexive"
+       (\(Forall @"m" m) -> sNot (m .< m)) $
+       \m -> [m .< m] |-> let k = some "k" (\d -> m .== m + sSucc d)
+                      in m .== m + sSucc k
+                      ?? cancel `at` (Inst @"m" m, Inst @"n" (sSucc k))
+                      =: sSucc k .== 0
+                      =: contradiction
+
+-- ** Trichotomy
+
+-- | \(m \geq n = \overline{m} \geq \overline{n}\)
+--
+-- >>> runTP lteEquiv
+-- Lemma: n2iAdd                           Q.E.D.
+-- Lemma: n2iNonNeg                        Q.E.D.
+-- Lemma: n2i2n                            Q.E.D.
+-- Lemma: i2n2i                            Q.E.D.
+-- Lemma: addRightUnit                     Q.E.D.
+-- Lemma: lteEquiv_ltr
+--   Step: 1 (2 way case split)
+--     Step: 1.1                           Q.E.D.
+--     Step: 1.2.1                         Q.E.D.
+--     Step: 1.2.2                         Q.E.D.
+--     Step: 1.2.3                         Q.E.D.
+--     Step: 1.2.4                         Q.E.D.
+--     Step: 1.Completeness                Q.E.D.
+--   Result:                               Q.E.D.
+-- Lemma: lteEquiv_rtl
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Step: 4                               Q.E.D.
+--   Step: 5                               Q.E.D.
+--   Step: 6                               Q.E.D.
+--   Step: 7 (2 way case split)
+--     Step: 7.1                           Q.E.D.
+--     Step: 7.2.1                         Q.E.D.
+--     Step: 7.2.2                         Q.E.D.
+--     Step: 7.2.3                         Q.E.D.
+--     Step: 7.2.4                         Q.E.D.
+--     Step: 7.2.5                         Q.E.D.
+--     Step: 7.Completeness                Q.E.D.
+--   Result:                               Q.E.D.
+-- Lemma: lteEquiv                         Q.E.D.
+-- [Proven] lteEquiv :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+lteEquiv :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+lteEquiv = do
+    n2ia    <- recall "n2iAdd"       n2iAdd
+    nn      <- recall "n2iNonNeg"    n2iNonNeg
+    n2i2nId <- recall "n2i2n"        n2i2n
+    i2n2iId <- recall "i2n2i"        i2n2i
+    aru     <- recall "addRightUnit" addRightUnit
+
+    ltr <- calcWith cvc5 "lteEquiv_ltr"
+              (\(Forall @"m" m) (Forall @"n" n) -> (m .>= n) .=> (n2i m .>= n2i n)) $
+              \m n -> [m .>= n]
+                   |- n2i m .>= n2i n
+                    =: cases [ m .== n ==> trivial
+                             , m .>  n ==> let k = some "k" (\d -> m .== n + sSucc d)
+                                        in n2i m .>= n2i n
+                                        ?? m .> n
+                                        =: n2i (n + sSucc k) .>= n2i n
+                                        ?? n2ia `at` (Inst @"m" n, Inst @"n" (sSucc k))
+                                        =: n2i n + n2i (sSucc k) .>= n2i n
+                                        ?? nn `at` Inst @"n" (sSucc k)
+                                        =: sTrue
+                                        =: qed
+                             ]
+
+    rtl <- calc "lteEquiv_rtl"
+                (\(Forall @"m" m) (Forall @"n" n) -> (n2i m .>= n2i n) .=> (m .>= n)) $
+                \m n -> [n2i m .>= n2i n]
+                     |-> let k = n2i m - n2i n
+                     in k .>= 0
+                     =: n2i m .== n2i n + k
+                     ?? i2n2iId `at` Inst @"i" k
+                     =: n2i m .== n2i n + n2i (i2n k)
+                     ?? n2ia `at` (Inst @"m" n, Inst @"n" (i2n k))
+                     =: n2i m .== n2i (n + i2n k)
+                     =: i2n (n2i m) .== i2n (n2i (n + i2n k))
+                     ?? n2i2nId `at` Inst @"n" m
+                     =: m .== i2n (n2i (n + i2n k))
+                     ?? n2i2nId `at` Inst @"n" (n + i2n k)
+                     =: m .== n + i2n k
+                     =: cases [ k .>  0 ==> trivial
+                              , k .<= 0 ==> m .== n + i2n k
+                                         ?? i2n k .== 0
+                                         =: m .== n + 0
+                                         ?? aru
+                                         =: m .== n
+                                         =: m .== n .|| m .> n
+                                         =: m .>= n
+                                         =: qed
+                              ]
+
+    lemma "lteEquiv"
+          (\(Forall m) (Forall n) -> (n2i m .>= n2i n) .== (m .>= n))
+          [proofOf ltr, proofOf rtl]
+
+-- | \(m \geq n \;\lor\; n \geq m\)
+--
+-- >>> runTP ordered
+-- Lemma: lteEquiv                         Q.E.D.
+-- Lemma: ordered
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Result:                               Q.E.D.
+-- [Proven] ordered :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+ordered :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+ordered = do
+   lteEq <- recall "lteEquiv" lteEquiv
+
+   calcWith cvc5 "ordered"
+        (\(Forall m) (Forall n) -> m .>= n .|| n .>= m) $
+        \m n -> [] |- (m .>= n .|| n .>= m)
+                   ?? lteEq `at` (Inst @"m" m, Inst @"n" n)
+                   =: (n2i m .>= n2i n .|| n .>= m)
+                   ?? lteEq `at` (Inst @"m" n, Inst @"n" m)
+                   =: (n2i m .>= n2i n .|| n2i n .>= n2i m)
+                   =: qed
+
+-- | \(m < n \;\lor\; m = n \;\lor\; n < m\)
+--
+-- >>> runTP trichotomy
+-- Lemma: ordered                          Q.E.D.
+-- Lemma: trichotomy                       Q.E.D.
+-- [Proven] trichotomy :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+trichotomy :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+trichotomy = do
+   pOrdered <- recall "ordered" ordered
+
+   lemma "trichotomy"
+         (\(Forall m) (Forall n) -> m .< n .|| m .== n .|| n .< m)
+         [proofOf pOrdered]
+
+-- ** Addition and ordering
+
+-- | \(m < n \;\rightarrow\; m + o < n + o\)
+--
+-- >>> runTP addOrder
+-- Lemma: addAssoc                         Q.E.D.
+-- Lemma: addComm                          Q.E.D.
+-- Lemma: addOrder
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Step: 4                               Q.E.D.
+--   Step: 5                               Q.E.D.
+--   Result:                               Q.E.D.
+-- [Proven] addOrder :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+addOrder :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+addOrder = do
+  pAddAssoc <- recall "addAssoc" addAssoc
+  pAddComm  <- recall "addComm"  addComm
+
+  calc "addOrder"
+       (\(Forall m) (Forall n) (Forall o) -> m .< n .=> m + o .< n + o) $
+       \m n o -> [m .< n]
+              |-> let k = some "k" (\d -> n .== m + sSucc d)
+               in n .== m + sSucc k
+               =: n + o .== (m + sSucc k) + o
+               ?? pAddAssoc `at` (Inst @"m" m, Inst @"n" (sSucc k), Inst @"o" o)
+               =: n + o .== m + (sSucc k + o)
+               ?? pAddComm `at` (Inst @"m" (sSucc k), Inst @"n" o)
+               =: n + o .== m + (o + sSucc k)
+               ?? pAddAssoc `at` (Inst @"m" m, Inst @"n" o, Inst @"o" (sSucc k))
+               =: n + o .== (m + o) + sSucc k
+               =: m + o .<= n + o
+               =: qed
+
+-- ** Multiplication and ordering
+
+-- | \(o > 0 \;\wedge\; m < n \;\rightarrow\; m * o < n * o\)
+--
+-- >>> runTP mulOrder
+-- Lemma: distribRight                     Q.E.D.
+-- Lemma: mulOrder
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Step: 4                               Q.E.D.
+--   Step: 5                               Q.E.D.
+--   Step: 6                               Q.E.D.
+--   Result:                               Q.E.D.
+-- [Proven] mulOrder :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+mulOrder :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+mulOrder = do
+  pDistribRight <- recall "distribRight" distribRight
+
+  calc "mulOrder"
+       (\(Forall m) (Forall n) (Forall o) -> 0 .< o .&& m .< n .=> m * o .< n * o) $
+       \m n o -> [0 .< o, m .< n]
+              |-> let k = some "k" (\d -> n .== m + sSucc d)
+               in n .== m + sSucc k
+               =: n * o .== (m + sSucc k) * o
+               ?? pDistribRight `at` (Inst @"m" m, Inst @"n" (sSucc k), Inst @"o" o)
+               =: n * o .== m * o + sSucc k * o
+               ?? 0 .< o
+               =: n * o .== m * o + sSucc k * sSucc (sprev o)
+               =: n * o .== m * o + (sSucc (sprev o) + k * sSucc (sprev o))
+               =: n * o .== m * o + sSucc (sprev o + k * sSucc (sprev o))
+               =: m * o .< n * o
+               =: qed
+
+-- ** Order and sum
+
+-- | \(m < n \;\rightarrow\; \exists o.\; m + o = n\)
+--
+-- >>> runTP orderSum
+-- Lemma: orderSum                         Q.E.D.
+-- [Proven] orderSum :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+orderSum :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+orderSum = lemma "orderSum"
+                 (\(Forall m) (Forall n) -> m .< n .=> quantifiedBool (\(Exists o) -> m + o .== n))
+                 []
+
+-- ** 0 and 1 relationship
+
+-- | \(0 < 1\)
+--
+-- >>> runTP zeroLtOne
+-- Lemma: zeroLtOne                        Q.E.D.
+-- [Proven] zeroLtOne :: Bool
+zeroLtOne :: TP (Proof SBool)
+zeroLtOne = lemma "zeroLtOne" (0 .< (1 :: SNat)) []
+
+-- | \(m > 0 \;\rightarrow\; m \geq 1\)
+--
+-- >>> runTP nothingBetweenZeroAndOne
+-- Lemma: nothingBetweenZeroAndOne         Q.E.D.
+-- [Proven] nothingBetweenZeroAndOne :: Ɐm ∷ Nat → Bool
+nothingBetweenZeroAndOne :: TP (Proof (Forall "m" Nat -> SBool))
+nothingBetweenZeroAndOne = lemma "nothingBetweenZeroAndOne"
+                                 (\(Forall m) -> m .> 0 .=> m .>= 1)
+                                 []
+
+-- ** 0 is the minimum
+
+-- | \(m \geq 0\)
+--
+-- >>> runTP minimumElt
+-- Lemma: minimumElt                       Q.E.D.
+-- [Proven] minimumElt :: Ɐm ∷ Nat → Bool
+minimumElt :: TP (Proof (Forall "m" Nat -> SBool))
+minimumElt = lemma "minimumElt" (\(Forall m) -> m .>= 0) []
+
+-- ** There is no maximum element
+
+-- | \(\forall m \;\exists n \;.\; m < n\)
+--
+-- >>> runTP noMaximumElt
+-- Lemma: noMaximumElt                     Q.E.D.
+-- [Proven] noMaximumElt :: Ɐm ∷ Nat → ∃n ∷ Nat → Bool
+noMaximumElt :: TP (Proof (Forall "m" Nat -> Exists "n" Nat -> SBool))
+noMaximumElt = lemma "noMaximumElt" (\(Forall m) (Exists n) -> m .< n) []
diff --git a/Documentation/SBV/Examples/TP/PowerMod.hs b/Documentation/SBV/Examples/TP/PowerMod.hs
--- a/Documentation/SBV/Examples/TP/PowerMod.hs
+++ b/Documentation/SBV/Examples/TP/PowerMod.hs
@@ -12,10 +12,9 @@
 -- We also demonstrate the proof-caching features of TP.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DataKinds           #-}
-{-# LANGUAGE TypeAbstractions    #-}
-{-# LANGUAGE TypeApplications    #-}
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE TypeAbstractions #-}
+{-# LANGUAGE TypeApplications #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -137,9 +136,10 @@
    mAddMul <- modAddMultiple
    calc "modSubRight"
       (\(Forall a) (Forall b) (Forall m) -> m .> 0 .=>  (a-b) `sEMod` m .== (a - b `sEMod` m) `sEMod` m) $
-      \a b m -> [m .> 0] |- (a-b) `sEMod` m
+      \a b m -> [m .> 0] |- (a - b) `sEMod` m
+                         ?? b .== b `sEMod` m + m * b `sEDiv` m
                          =: (a - (b `sEMod` m + m * b `sEDiv` m)) `sEMod` m
-                         =: ((a - b `sEMod` m) + m*(- (b `sEDiv` m))) `sEMod` m
+                         =: ((a - b `sEMod` m) + m * (- (b `sEDiv` m))) `sEMod` m
                          ?? mAddMul `at` (Inst @"k" (- (b `sEDiv` m)), Inst @"n" (a - b `sEMod` m), Inst @"m" m)
                          =: (a - b `sEMod` m) `sEMod` m
                          =: qed
diff --git a/Documentation/SBV/Examples/TP/QuickSort.hs b/Documentation/SBV/Examples/TP/QuickSort.hs
--- a/Documentation/SBV/Examples/TP/QuickSort.hs
+++ b/Documentation/SBV/Examples/TP/QuickSort.hs
@@ -17,7 +17,6 @@
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE OverloadedLists     #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeAbstractions    #-}
 {-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
@@ -406,7 +405,7 @@
   -- The first element of partition does not increase in size
   partitionNotLongerFst <- sInduct "partitionNotLongerFst"
      (\(Forall l) (Forall pivot) -> length (fst (partition @a pivot l)) .<= length l)
-     (\l _ -> length l) $
+     (\l _ -> length l, []) $
      \ih l pivot -> [] |- length (fst (partition @a pivot l)) .<= length l
                        =: split l trivial
                                 (\a as -> let lo = fst (partition pivot as)
@@ -424,7 +423,7 @@
   -- The second element of partition does not increase in size
   partitionNotLongerSnd <- sInduct "partitionNotLongerSnd"
      (\(Forall l) (Forall pivot) -> length (snd (partition @a pivot l)) .<= length l)
-     (\l _ -> length l) $
+     (\l _ -> length l, []) $
      \ih l pivot -> [] |- length (snd (partition @a pivot l)) .<= length l
                        =: split l trivial
                                 (\a as -> let hi = snd (partition pivot as)
@@ -487,7 +486,7 @@
   sortCountsMatch <-
      sInduct "sortCountsMatch"
              (\(Forall xs) (Forall e) -> count e xs .== count e (quickSort xs))
-             (\xs _ -> length xs) $
+             (\xs _ -> length xs, []) $
              \ih xs e ->
                 [] |- count e (quickSort xs)
                    =: split xs trivial
@@ -546,7 +545,7 @@
   sortIsNonDecreasing <-
      sInductWith cvc5 "sortIsNonDecreasing"
              (\(Forall xs) -> nonDecreasing (quickSort xs))
-             (length @a) $
+             (length @a, []) $
              \ih xs ->
                 [] |- nonDecreasing (quickSort xs)
                    =: split xs trivial
diff --git a/Documentation/SBV/Examples/TP/Reverse.hs b/Documentation/SBV/Examples/TP/Reverse.hs
--- a/Documentation/SBV/Examples/TP/Reverse.hs
+++ b/Documentation/SBV/Examples/TP/Reverse.hs
@@ -18,7 +18,6 @@
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE OverloadedLists     #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeAbstractions    #-}
 {-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
@@ -93,7 +92,7 @@
 
   sInductWith cvc5 "revCorrect"
     (\(Forall xs) -> rev xs .== reverse xs)
-    length $
+    (length, []) $
     \ih xs -> [] |- rev xs
                  =: split xs trivial
                           (\a as -> split as trivial
diff --git a/Documentation/SBV/Examples/TP/ShefferStroke.hs b/Documentation/SBV/Examples/TP/ShefferStroke.hs
--- a/Documentation/SBV/Examples/TP/ShefferStroke.hs
+++ b/Documentation/SBV/Examples/TP/ShefferStroke.hs
@@ -11,15 +11,12 @@
 -- logic), imply it is a boolean algebra.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DataKinds            #-}
-{-# LANGUAGE DeriveDataTypeable   #-}
-{-# LANGUAGE DeriveAnyClass       #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE NamedFieldPuns       #-}
-{-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE StandaloneDeriving   #-}
-{-# LANGUAGE TemplateHaskell      #-}
-{-# LANGUAGE TypeAbstractions     #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE NamedFieldPuns      #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeAbstractions    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -101,7 +98,7 @@
 
 -- | The abstract type for the domain.
 data Stroke
-mkUninterpretedSort ''Stroke
+mkSymbolic [''Stroke]
 
 -- | The sheffer stroke operator.
 (⏐) :: SStroke -> SStroke -> SStroke
diff --git a/Documentation/SBV/Examples/TP/SortHelpers.hs b/Documentation/SBV/Examples/TP/SortHelpers.hs
--- a/Documentation/SBV/Examples/TP/SortHelpers.hs
+++ b/Documentation/SBV/Examples/TP/SortHelpers.hs
@@ -12,9 +12,9 @@
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeAbstractions    #-}
 {-# LANGUAGE TypeApplications    #-}
-{-# LANGUAGE ScopedTypeVariables #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
diff --git a/Documentation/SBV/Examples/TP/Sqrt2IsIrrational.hs b/Documentation/SBV/Examples/TP/Sqrt2IsIrrational.hs
--- a/Documentation/SBV/Examples/TP/Sqrt2IsIrrational.hs
+++ b/Documentation/SBV/Examples/TP/Sqrt2IsIrrational.hs
@@ -9,9 +9,8 @@
 -- Prove that square-root of 2 is irrational.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DataKinds           #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE TypeAbstractions #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -84,7 +83,7 @@
                                            =: 4*k*k + 4*k + 1
                                            =: qed
 
-    -- Prove that if a perfect square is even, then it be the square of an even number. For z3, the above proof
+    -- Prove that if a perfect square is even, then it has to be the square of an even number. For z3, the above proof
     -- is enough to establish this.
     squareEvenImpliesEven <- lemma "squareEvenImpliesEven"
                                    (\(Forall @"a" a) -> even (sq a) .=> even a)
diff --git a/Documentation/SBV/Examples/TP/StrongInduction.hs b/Documentation/SBV/Examples/TP/StrongInduction.hs
--- a/Documentation/SBV/Examples/TP/StrongInduction.hs
+++ b/Documentation/SBV/Examples/TP/StrongInduction.hs
@@ -61,7 +61,7 @@
   -- the negation of the goal leads to falsehood.
   sInductWith cvc5 "oddSequence1"
           (\(Forall n) -> n .>= 0 .=> sNot (2 `sDivides` s n))
-          abs $
+          (abs, []) $
           \ih n -> [n .>= 0] |- 2 `sDivides` s n
                              =: cases [ n .== 0 ==> contradiction
                                       , n .== 1 ==> contradiction
@@ -108,7 +108,7 @@
 
   sNp2 <- sInduct "oddSequence_sNp2"
                   (\(Forall n) -> n .>= 2 .=> s n .== 2 * n + 1)
-                  abs $
+                  (abs, []) $
                   \ih n -> [n .>= 2] |- s n
                                      =: 2 * s (n-1) - s (n-2)
                                      ?? ih `at` Inst @"n" (n-1)
@@ -154,7 +154,7 @@
    -- Run it for 5 seconds, as otherwise z3 will hang as it can't prove make the inductive step
    _ <- sInductWith z3{extraArgs = ["-t:5000"]} "lengthGood"
                 (\(Forall xs) -> len xs .== length xs)
-                length $
+                (length, []) $
                 \ih xs -> [] |- len xs
                              -- incorrectly instantiate the IH at xs!
                              ?? ih `at` Inst @"xs" xs
@@ -183,7 +183,7 @@
 
    _ <- sInduct "badLength"
                 (\(Forall xs) -> len xs .== length xs)
-                length $
+                (length, []) $
                 \ih xs -> [] |- len xs
                              ?? ih `at` Inst @"xs" xs
                              =: length xs
@@ -204,7 +204,7 @@
 won'tProve3 = runTP $ do
    _ <- sInduct "badMeasure"
                 (\(Forall @"x" (x :: SInteger)) -> x .== x)
-                id $
+                (id, []) $
                 \_ih x -> [] |- x
                              =: x
                              =: qed
@@ -235,7 +235,7 @@
                 (\(Forall x) (Forall y) -> x .>= 0 .=> weirdSum x y .== x + y)
                 -- This measure is not good, since it remains the same. Note that we do not get a
                 -- failure, but the proof will never converge either; so we put a time bound
-                (\x y -> abs x + abs y) $
+                (\x y -> abs x + abs y, []) $
                 \ih x y -> [x .>= 0] |- ite (x .<= 0) y (weirdSum (x - 1) (y + 1))
                                      =: cases [ x .<= 0 ==> trivial
                                               , x .>  0 ==> weirdSum (x - 1) (y + 1)
@@ -294,7 +294,7 @@
     -- Use strong induction to prove the theorem. CVC5 solves this with ease, but z3 struggles.
     sInductWith cvc5 "sumHalves"
       (\(Forall xs) -> halvingSum xs .== sum xs)
-      length $
+      (length, []) $
       \ih xs -> [] |- halvingSum xs
                    =: split xs qed
                             (\a as -> split as qed
diff --git a/Documentation/SBV/Examples/TP/SumReverse.hs b/Documentation/SBV/Examples/TP/SumReverse.hs
--- a/Documentation/SBV/Examples/TP/SumReverse.hs
+++ b/Documentation/SBV/Examples/TP/SumReverse.hs
@@ -13,7 +13,6 @@
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeAbstractions    #-}
 {-# LANGUAGE TypeApplications    #-}
 {-# LANGUAGE OverloadedLists     #-}
 
diff --git a/Documentation/SBV/Examples/TP/Tao.hs b/Documentation/SBV/Examples/TP/Tao.hs
--- a/Documentation/SBV/Examples/TP/Tao.hs
+++ b/Documentation/SBV/Examples/TP/Tao.hs
@@ -18,12 +18,7 @@
 
 
 {-# LANGUAGE CPP                 #-}
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
-{-# LANGUAGE DataKinds           #-}
-{-# LANGUAGE TypeAbstractions    #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
@@ -41,7 +36,7 @@
 
 -- | Create an uninterpreted type to do the proofs over.
 data T
-mkUninterpretedSort ''T
+mkSymbolic [''T]
 
 -- | Prove that:
 --
diff --git a/Documentation/SBV/Examples/TP/VM.hs b/Documentation/SBV/Examples/TP/VM.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/VM.hs
@@ -0,0 +1,443 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.VM
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Correctness of a simple interpreter vs virtual-machine interpretation of a language.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.VM
+#ifndef DOCTEST
+ (   -- * Language
+     Expr(..), SExpr, size
+
+     -- * Environment and the stack
+   , Env, Stack
+
+     -- * Interpretation
+   , interpInEnv, interp
+
+     -- * Virtual machine
+   , Instr(..), SInstr
+
+     -- * Compilation
+   , compile, compileAndRun
+
+     -- * Correctness of the compiler
+   , correctness)
+#endif
+where
+
+import Data.SBV
+import Data.SBV.Tuple as ST
+import Data.SBV.List  as SL
+
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV.TP
+-- >>> :set -XTypeApplications
+#endif
+
+-- * Language
+
+-- | Basic expression language.
+data Expr nm val = Var nm                             -- ^ Variables
+                 | Con val                            -- ^ Constants
+                 | Sqr (Expr nm val)                  -- ^ Squaring
+                 | Inc (Expr nm val)                  -- ^ Increment
+                 | Add (Expr nm val) (Expr nm val)    -- ^ Addition
+                 | Mul (Expr nm val) (Expr nm val)    -- ^ Multiplication
+                 | Let nm (Expr nm val) (Expr nm val) -- ^ Let expression
+
+-- | Create symbolic version of expressions
+mkSymbolic [''Expr]
+
+-- | Size of an expression. Used in strong induction.
+size :: (SymVal nm, SymVal val) => SExpr nm val -> SInteger
+size = smtFunction "exprSize" $ \expr -> [sCase|Expr expr of
+                                            Var _     -> 0
+                                            Con _     -> 0
+                                            Sqr a     -> 1 + size a
+                                            Inc a     -> 1 + size a
+                                            Add a b   -> 1 + size a `smax` size b
+                                            Mul a b   -> 1 + size a `smax` size b
+                                            Let _ a b -> 1 + size a `smax` size b
+                                         |]
+
+-- | Environment, binding names to values
+type Env nm val = SList (nm, val)
+
+-- * Functional interpretation
+
+-- | Interpreter, in the usual functional style, taking an arbitrary environment.
+interpInEnv :: (SymVal nm, SymVal val, Num (SBV val)) => Env nm val -> SExpr nm val -> SBV val
+interpInEnv = smtFunction "interpInEnv" $ \env expr ->
+                 [sCase|Expr expr of
+                    Var nm    -> nm `SL.lookup` env
+                    Con v     -> v
+                    Sqr a     -> let av = interpInEnv env a in av * av
+                    Inc a     -> let av = interpInEnv env a in av + 1
+                    Add a b   -> let av = interpInEnv env a; bv = interpInEnv env b in av + bv
+                    Mul a b   -> let av = interpInEnv env a; bv = interpInEnv env b in av * bv
+                    Let v a b -> let av = interpInEnv env a in interpInEnv (tuple (v, av) .: env) b
+                 |]
+
+-- | Interpret starting from empty environment.
+interp :: (SymVal nm, SymVal val, Num (SBV val)) => SExpr nm val -> SBV val
+interp = interpInEnv []
+
+-- * Virtual machine
+
+-- | Instructions
+data Instr nm val = IPushN nm   -- ^ Push the value of nm from the environment on to the stack
+                  | IPushV val  -- ^ Push a value on to the stack
+                  | IDup        -- ^ Duplicate the top of the stack
+                  | IAdd        -- ^ Add      the top two elements and push back
+                  | IMul        -- ^ Multiply the top two elements and push back
+                  | IBind nm    -- ^ Bind the value on top of stack to name
+                  | IForget     -- ^ Pop and ignore the binding on the environment
+
+-- | Create symbolic version of instructions
+mkSymbolic [''Instr]
+
+-- | Stack of values.
+type Stack val = SList val
+
+-- | Pushing on to the stack.
+push :: SymVal val => SBV val -> Stack val  -> Stack val
+push = (SL..:)
+
+-- | Top of the stack. If the stack is empty, the result is underspecified.
+top :: SymVal val => Stack val  -> SBV val
+top = SL.head
+
+-- | Popping from the stack. If the stack is empty, the result is underspecified.
+pop :: SymVal val => Stack val  -> Stack val
+pop = SL.tail
+
+-- | A pair containing an environment and a stack
+type EnvStack nm val = SBV ([(nm, val)], [val])
+
+-- | Executing a single instruction in a given environment and the instruction stack.
+-- We produce the new environment, and the new stack.
+execute :: (SymVal nm, SymVal val, Num (SBV val)) => EnvStack nm val -> SInstr nm val -> EnvStack nm val
+execute envStk instr = let (env, stk) = untuple envStk
+                       in tuple [sCase|Instr instr of
+                                   IPushN nm   -> (env, push (nm `SL.lookup` env) stk)
+                                   IPushV val  -> (env, push val stk)
+                                   IDup        -> (env, push (top stk) stk)
+                                   IAdd        -> (env, let a = top stk; b = top (pop stk) in push (a + b) (pop (pop stk)))
+                                   IMul        -> (env, let a = top stk; b = top (pop stk) in push (a * b) (pop (pop stk)))
+                                   IBind nm    -> (push (tuple (nm, top stk)) env, pop stk)
+                                   IForget     -> (pop env, stk)
+                                |]
+
+-- | Execute a sequence of instructions, in a given stack and env. Returnsg the final environment and the stack. This is a
+-- simple fold-left.
+run :: (SymVal nm, SymVal val, Num (SBV val)) => EnvStack nm val -> SList (Instr nm val) -> EnvStack nm val
+run = SL.foldl execute
+
+-- * Compiler
+
+-- | Convert an expression to a sequence of instructions for our virtual machine.
+compile :: (SymVal nm, SymVal val, Num (SBV val)) => SExpr nm val -> SList (Instr nm val)
+compile = smtFunction "compile" $ \expr ->
+                [sCase|Expr expr of
+                   Var nm    -> [sIPushN nm]
+                   Con v     -> [sIPushV v]
+                   Sqr a     -> compile a SL.++ [sIDup,     sIMul]
+                   Inc a     -> compile a SL.++ [sIPushV 1, sIAdd]
+                   Add a b   -> compile a SL.++ compile b  SL.++ [sIAdd]
+                   Mul a b   -> compile a SL.++ compile b  SL.++ [sIMul]
+                   Let v a b -> compile a SL.++ [sIBind v] SL.++ compile b SL.++ [sIForget]
+                |]
+
+-- | Compile and run an expression.
+compileAndRun :: (SymVal nm, SymVal val, Num (SBV val)) => SExpr nm val -> SBV val
+compileAndRun = top . ST.snd . run (tuple ([], [])) . compile
+
+-- * Correctness
+
+-- | The property we're after is that interpreting an expression is the same as
+-- first compiling it to virtual-machine instructions, and then running them.
+--
+-- >>> runTP (correctness @String @Integer)
+-- Inductive lemma: runSeq
+--   Step: Base                            Q.E.D.
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Result:                               Q.E.D.
+-- Lemma: runOne                           Q.E.D.
+-- Lemma: runTwo
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Result:                               Q.E.D.
+-- Lemma: runMul                           Q.E.D.
+-- Lemma: measureNonNeg                    Q.E.D.
+-- Inductive lemma (strong): helper
+--   Step: Measure is non-negative         Q.E.D.
+--   Step: 1 (7 way case split)
+--     Step: 1.1.1 (case Var)              Q.E.D.
+--     Step: 1.1.2                         Q.E.D.
+--     Step: 1.2.1 (case Con)              Q.E.D.
+--     Step: 1.2.2                         Q.E.D.
+--     Step: 1.2.3                         Q.E.D.
+--     Step: 1.3.1 (case Sqr)              Q.E.D.
+--     Step: 1.3.2                         Q.E.D.
+--     Step: 1.3.3                         Q.E.D.
+--     Step: 1.3.4                         Q.E.D.
+--     Step: 1.3.5                         Q.E.D.
+--     Step: 1.3.6                         Q.E.D.
+--     Step: 1.3.7                         Q.E.D.
+--     Step: 1.4.1 (case Inc)              Q.E.D.
+--     Step: 1.4.2                         Q.E.D.
+--     Step: 1.4.3                         Q.E.D.
+--     Step: 1.4.4                         Q.E.D.
+--     Step: 1.4.5                         Q.E.D.
+--     Step: 1.4.6                         Q.E.D.
+--     Step: 1.4.7                         Q.E.D.
+--     Step: 1.5.1 (case sAdd)             Q.E.D.
+--     Step: 1.5.2                         Q.E.D.
+--     Step: 1.5.3                         Q.E.D.
+--     Step: 1.5.4                         Q.E.D.
+--     Step: 1.5.5                         Q.E.D.
+--     Step: 1.5.6                         Q.E.D.
+--     Step: 1.5.7                         Q.E.D.
+--     Step: 1.5.8                         Q.E.D.
+--     Step: 1.5.9                         Q.E.D.
+--     Step: 1.6.1 (case sMul)             Q.E.D.
+--     Step: 1.6.2                         Q.E.D.
+--     Step: 1.6.3                         Q.E.D.
+--     Step: 1.6.4                         Q.E.D.
+--     Step: 1.6.5                         Q.E.D.
+--     Step: 1.6.6                         Q.E.D.
+--     Step: 1.6.7                         Q.E.D.
+--     Step: 1.6.8                         Q.E.D.
+--     Step: 1.6.9                         Q.E.D.
+--     Step: 1.7.1 (case Let)              Q.E.D.
+--     Step: 1.7.2                         Q.E.D.
+--     Step: 1.7.3                         Q.E.D.
+--     Step: 1.7.4                         Q.E.D.
+--     Step: 1.7.5                         Q.E.D.
+--     Step: 1.7.6                         Q.E.D.
+--     Step: 1.7.7                         Q.E.D.
+--     Step: 1.7.8                         Q.E.D.
+--     Step: 1.7.9                         Q.E.D.
+--     Step: 1.7.10                        Q.E.D.
+--     Step: 1.7.11                        Q.E.D.
+--     Step: 1.Completeness                Q.E.D.
+--   Result:                               Q.E.D.
+-- Lemma: correctness
+--   Step: 1                               Q.E.D.
+--   Step: 2                               Q.E.D.
+--   Step: 3                               Q.E.D.
+--   Step: 4                               Q.E.D.
+--   Result:                               Q.E.D.
+-- [Proven] correctness :: Ɐexpr ∷ (Expr [Char] Integer) → Bool
+correctness :: forall nm val. (SymVal nm, SymVal val, Num (SBV val)) => TP (Proof (Forall "expr" (Expr nm val) -> SBool))
+correctness = do
+
+   -- Running a sequence of instructions that are appended is equivalent to running them in sequence:
+   runSeq <- induct "runSeq"
+                    (\(Forall @"xs" xs) (Forall @"ys" ys) (Forall @"es" (es :: EnvStack nm val))
+                         -> run es (xs SL.++ ys) .== run (run es xs) ys) $
+                    \ih (x, xs) ys es -> [] |- run es ((x .: xs) SL.++ ys)
+                                            =: run es (x .: (xs SL.++ ys))
+                                            =: run (execute es x) (xs SL.++ ys)
+                                            ?? ih `at` (Inst @"ys" ys, Inst @"es" (execute es x))
+                                            =: run (run es (x .: xs)) ys
+                                            =: qed
+
+   -- The following few lemmas make the proof go thru faster, even though they're really easy to prove themselves.
+
+   -- Running one instruction is equal to just executing it
+   runOne <- lemma "runOne"
+                   (\(Forall @"es" (es :: EnvStack nm val)) (Forall @"i" i) -> run es [i] .== execute es i)
+                   []
+
+   -- Same for two
+   runTwo <- calc "runTwo"
+                   (\(Forall @"es" (es :: EnvStack nm val)) (Forall @"i" i) (Forall @"j" j)
+                             -> run es [i, j] .== execute (execute es i) j) $
+                   \es i j -> [] |- run es [i, j]
+                                 =: run (execute es i) [j]
+                                 =: execute (execute es i) j
+                                 =: qed
+
+   -- Provers struggle with multiplication, so help them a bit here even though this is really
+   -- a trivial proof. What's hard is the correct instantiation of it, so abstracting it away helps
+   -- us speed up the solver.
+   runMul <- lemma "runMul"
+                    (\(Forall @"a" a) (Forall @"b" b) (Forall  @"env" (env :: Env nm val)) (Forall @"stk" stk)
+                                 ->   execute (tuple (env, push a (push b stk))) sIMul
+                                 .==  tuple (env, push (a * b) stk))
+                   []
+
+   -- We will use the size of the expression as the measure. We need to show that it is
+   -- always positive for the inductive proof to go thru.
+   measureNonNeg <- inductiveLemma "measureNonNeg"
+                                   (\(Forall @"e" (e :: SExpr nm val)) -> size e .>= 0)
+                                   []
+
+   -- A more general version of the theorem, starting with an arbitrary env and stack.
+   -- We prove this using the induction principle for expressions.
+   helper <- sInductWith cvc5 "helper"
+               (\(Forall @"e" e) (Forall @"env" (env :: Env nm val)) (Forall @"stk" stk) ->
+                             run (tuple (env, stk)) (compile e)
+                         .== tuple (env, push (interpInEnv env e) stk))
+               (\e _ _  -> size e, [proofOf measureNonNeg]) $
+               \ih e env stk -> []
+                 |- cases [ isVar e ==> let nm = getVar_1 e
+                                     in run (tuple (env, stk)) (compile (sVar nm))
+                                     ?? "case Var"
+                                     =: run (tuple (env, stk)) [sIPushN nm]
+                                     =: tuple (env, push (interpInEnv env (sVar nm)) stk)
+                                     =: qed
+
+                          , isCon e ==> let v = getCon_1 e
+                                     in run (tuple (env, stk)) (compile (sCon v))
+                                     ?? "case Con"
+                                     =: run (tuple (env, stk)) [sIPushV v]
+                                     =: tuple (env, push v stk)
+                                     =: tuple (env, push (interpInEnv env (sCon v)) stk)
+                                     =: qed
+
+                          , isSqr e ==> let a = getSqr_1 e
+                                     in run (tuple (env, stk)) (compile (sSqr a))
+                                     ?? "case Sqr"
+                                     =: run (tuple (env, stk)) (compile a SL.++ [sIDup, sIMul])
+                                     ?? runSeq
+                                     =: run (run (tuple (env, stk)) (compile a)) [sIDup, sIMul]
+                                     ?? ih `at` (Inst @"e" a, Inst @"env" env, Inst @"stk" stk)
+                                     =: let stk' = push (interpInEnv env a) stk
+                                     in run (tuple (env, stk')) [sIDup, sIMul]
+                                     ?? runTwo `at` (Inst @"es" (tuple (env, stk')), Inst @"i" sIDup, Inst @"j" sIMul)
+                                     =: execute (execute (tuple (env, stk')) sIDup) sIMul
+                                     =: let stk'' = push (interpInEnv env a) stk'
+                                     in execute (tuple (env, stk'')) sIMul
+                                     =: tuple (env, push (interpInEnv env a * interpInEnv env a) stk)
+                                     =: tuple (env, push (interpInEnv env (sSqr a)) stk)
+                                     =: qed
+
+                          , isInc e ==> let a = getInc_1 e
+                                     in run (tuple (env, stk)) (compile (sInc a))
+                                     ?? "case Inc"
+                                     =: run (tuple (env, stk)) (compile a SL.++ [sIPushV 1, sIAdd])
+                                     ?? runSeq
+                                     =: run (run (tuple (env, stk)) (compile a)) [sIPushV 1, sIAdd]
+                                     ?? ih `at` (Inst @"e" a, Inst @"env" env, Inst @"stk" stk)
+                                     =: let stk' = push (interpInEnv env a) stk
+                                     in run (tuple (env, stk')) [sIPushV 1, sIAdd]
+                                     ?? runTwo `at` (Inst @"es" (tuple (env, stk')), Inst @"i" (sIPushV 1), Inst @"j" sIAdd)
+                                     =: execute (execute (tuple (env, stk')) (sIPushV 1)) sIAdd
+                                     =: let stk'' = push 1 stk'
+                                     in execute (tuple (env, stk'')) sIAdd
+                                     =: tuple (env, push (1 + interpInEnv env a) stk)
+                                     =: tuple (env, push (interpInEnv env (sInc a)) stk)
+                                     =: qed
+
+                          , isAdd e ==> let a = getAdd_1 e
+                                            b = getAdd_2 e
+                                     in run (tuple (env, stk)) (compile (sAdd a b))
+                                     ?? "case sAdd"
+                                     =: run (tuple (env, stk)) (compile a SL.++ compile b SL.++ [sIAdd])
+                                     ?? runSeq
+                                     =: run (run (tuple (env, stk)) (compile a)) (compile b SL.++ [sIAdd])
+                                     ?? ih `at` (Inst @"e" a, Inst @"env" env, Inst @"stk" stk)
+                                     =: let stk' = push (interpInEnv env a) stk
+                                     in run (tuple (env, stk')) (compile b SL.++ [sIAdd])
+                                     ?? runSeq
+                                     =: run (run (tuple (env, stk')) (compile b)) [sIAdd]
+                                     ?? ih `at` (Inst @"e" b, Inst @"env" env, Inst @"stk" stk')
+                                     =: let stk'' = push (interpInEnv env b) stk'
+                                     in run (tuple (env, stk'')) [sIAdd]
+                                     ?? runOne `at` (Inst @"es" (tuple (env, stk'')), Inst @"i" sIAdd)
+                                     =: execute (tuple (env, stk'')) sIAdd
+                                     =: tuple (env, push (interpInEnv env b + interpInEnv env a) stk)
+                                     =: tuple (env, push (interpInEnv env a + interpInEnv env b) stk)
+                                     =: tuple (env, push (interpInEnv env (sAdd a b)) stk)
+                                     =: qed
+
+                          , isMul e ==> let a = getMul_1 e
+                                            b = getMul_2 e
+                                     in run (tuple (env, stk)) (compile (sMul a b))
+                                     ?? "case sMul"
+                                     =: run (tuple (env, stk)) (compile a SL.++ compile b SL.++ [sIMul])
+                                     ?? runSeq
+                                     =: run (run (tuple (env, stk)) (compile a)) (compile b SL.++ [sIMul])
+                                     ?? ih `at` (Inst @"e" a, Inst @"env" env, Inst @"stk" stk)
+                                     =: let stk' = push (interpInEnv env a) stk
+                                     in run (tuple (env, stk')) (compile b SL.++ [sIMul])
+                                     ?? runSeq
+                                     =: run (run (tuple (env, stk')) (compile b)) [sIMul]
+                                     ?? ih `at` (Inst @"e" b, Inst @"env" env, Inst @"stk" stk')
+                                     =: let stk'' = push (interpInEnv env b) stk'
+                                     in run (tuple (env, stk'')) [sIMul]
+                                     ?? runOne `at` (Inst @"es" (tuple (env, stk'')), Inst @"i" sIMul)
+                                     =: execute (tuple (env, stk'')) sIMul
+                                     ?? runMul `at` ( Inst @"a"   (interpInEnv env b)
+                                                    , Inst @"b"   (interpInEnv env a)
+                                                    , Inst @"env" env
+                                                    , Inst @"stk" stk)
+                                     =: tuple (env, push (interpInEnv env b * interpInEnv env a) stk)
+                                     =: tuple (env, push (interpInEnv env a * interpInEnv env b) stk)
+                                     =: tuple (env, push (interpInEnv env (sMul a b)) stk)
+                                     =: qed
+
+                          , isLet e ==> let nm = getLet_1 e
+                                            a  = getLet_2 e
+                                            b  = getLet_3 e
+                                     in run (tuple (env, stk)) (compile (sLet nm a b))
+                                     ?? "case Let"
+                                     =: run (tuple (env, stk)) (compile a SL.++ [sIBind nm] SL.++ compile b SL.++ [sIForget])
+                                     ?? runSeq
+                                     =: run (run (tuple (env, stk)) (compile a)) ([sIBind nm] SL.++ compile b SL.++ [sIForget])
+                                     ?? ih `at` (Inst @"e" a, Inst @"env" env, Inst @"stk" stk)
+                                     =: let stk' = push (interpInEnv env a) stk
+                                     in run (tuple (env, stk')) ([sIBind nm] SL.++ compile b SL.++ [sIForget])
+                                     ?? runSeq
+                                     =: run (run (tuple (env, stk')) [sIBind nm]) (compile b SL.++ [sIForget])
+                                     ?? runOne
+                                     =: run (execute (tuple (env, stk')) (sIBind nm)) (compile b SL.++ [sIForget])
+                                     =: let env' = push (tuple (nm, interpInEnv env a)) env
+                                     in run (tuple (env', stk)) (compile b SL.++ [sIForget])
+                                     ?? runSeq
+                                     =: run (run (tuple (env', stk)) (compile b)) [sIForget]
+                                     ?? ih `at` (Inst @"e" b, Inst @"env" env', Inst @"stk" stk)
+                                     =: let stk'' = push (interpInEnv env' b) stk
+                                     in run (tuple (env', stk'')) [sIForget]
+                                     ?? runOne
+                                     =: execute (tuple (env', stk'')) sIForget
+                                     =: tuple (env, stk'')
+                                     =: tuple (env, push (interpInEnv env (sLet nm a b)) stk)
+                                     =: qed
+                          ]
+
+   -- We can now prove the final correctness theorem, based on the helper.
+   calc "correctness"
+        (\(Forall @"expr" (e :: SExpr nm val)) -> compileAndRun e .== interp e) $
+        \(e :: SExpr nm val) -> [] |- compileAndRun e
+                                   =: top (ST.snd (run (tuple ([], [])) (compile e)))
+                                   ?? helper `at` (Inst @"e" e, Inst @"env" [], Inst @"stk" [])
+                                   =: top (ST.snd (tuple ([] :: Env nm val, push (interpInEnv [] e) [])))
+                                   =: interpInEnv [] e
+                                   =: interp e
+                                   =: qed
diff --git a/Documentation/SBV/Examples/Uninterpreted/AUF.hs b/Documentation/SBV/Examples/Uninterpreted/AUF.hs
--- a/Documentation/SBV/Examples/Uninterpreted/AUF.hs
+++ b/Documentation/SBV/Examples/Uninterpreted/AUF.hs
@@ -27,8 +27,7 @@
 -- The function @read@ and @write@ are usual array operations.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE CPP                 #-}
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE CPP #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
diff --git a/Documentation/SBV/Examples/Uninterpreted/Deduce.hs b/Documentation/SBV/Examples/Uninterpreted/Deduce.hs
--- a/Documentation/SBV/Examples/Uninterpreted/Deduce.hs
+++ b/Documentation/SBV/Examples/Uninterpreted/Deduce.hs
@@ -9,10 +9,7 @@
 -- Demonstrates uninterpreted sorts and how they can be used for deduction.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass     #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE TemplateHaskell    #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -33,7 +30,7 @@
 
 -- | Make this sort uninterpreted. This splice will automatically introduce
 -- the type 'SB' into the environment, as a synonym for 'SBV' 'B'.
-mkUninterpretedSort ''B
+mkSymbolic [''B]
 
 -----------------------------------------------------------------------------
 -- * Uninterpreted connectives over 'B'
diff --git a/Documentation/SBV/Examples/Uninterpreted/Sort.hs b/Documentation/SBV/Examples/Uninterpreted/Sort.hs
--- a/Documentation/SBV/Examples/Uninterpreted/Sort.hs
+++ b/Documentation/SBV/Examples/Uninterpreted/Sort.hs
@@ -9,10 +9,7 @@
 -- Demonstrates uninterpreted sorts, together with axioms.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass     #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE TemplateHaskell    #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -27,7 +24,7 @@
 -- | Make 'Q' an uinterpreted sort. This will automatically introduce the
 -- type 'SQ' into our environment, which is the symbolic version of the
 -- carrier type 'Q'.
-mkUninterpretedSort ''Q
+mkSymbolic [''Q]
 
 -- | Declare an uninterpreted function that works over Q's
 f :: SQ -> SQ
diff --git a/Documentation/SBV/Examples/Uninterpreted/UISortAllSat.hs b/Documentation/SBV/Examples/Uninterpreted/UISortAllSat.hs
--- a/Documentation/SBV/Examples/Uninterpreted/UISortAllSat.hs
+++ b/Documentation/SBV/Examples/Uninterpreted/UISortAllSat.hs
@@ -10,11 +10,8 @@
 -- Thanks to Eric Seidel for the idea.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE CPP                #-}
-{-# LANGUAGE DeriveAnyClass     #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE TemplateHaskell    #-}
+{-# LANGUAGE CPP             #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -33,7 +30,7 @@
 
 -- | Make 'L' into an uninterpreted sort, automatically introducing 'SL'
 -- as a synonym for 'SBV' 'L'.
-mkUninterpretedSort ''L
+mkSymbolic [''L]
 
 -- | An uninterpreted "classify" function. Really, we only care about
 -- the fact that such a function exists, not what it does.
diff --git a/Documentation/SBV/Examples/WeakestPreconditions/Sum.hs b/Documentation/SBV/Examples/WeakestPreconditions/Sum.hs
--- a/Documentation/SBV/Examples/WeakestPreconditions/Sum.hs
+++ b/Documentation/SBV/Examples/WeakestPreconditions/Sum.hs
@@ -207,8 +207,8 @@
 Following proof obligation failed:
 ==================================
   Invariant for loop "i < n" is not maintained by the body:
-    Before: SumS {n = 3, i = 1, s = 1}
-    After : SumS {n = 3, i = 2, s = 3}
+    Before: SumS {n = 2, i = 1, s = 1}
+    After : SumS {n = 2, i = 2, s = 3}
 
 Here, we posed the extra incorrect invariant that @s <= i@ must be maintained, and SBV found us a reachable state that violates the invariant. The
 /before/ state indeed satisfies @s <= i@, but the /after/ state does not. Note that the proof fails in this case not because the program
@@ -224,8 +224,8 @@
 Following proof obligation failed:
 ==================================
   Measure for loop "i < n" is negative:
-    State  : SumS {n = 3, i = 2, s = 3}
-    Measure: -1
+    State  : SumS {n = 4, i = 3, s = 6}
+    Measure: -2
 
 The failure is pretty obvious in this case: Measure produces a negative value.
 
@@ -239,9 +239,9 @@
 Following proof obligation failed:
 ==================================
   Measure for loop "i < n" does not decrease:
-    Before : SumS {n = 2, i = -2, s = 1}
+    Before : SumS {n = 1, i = -1, s = 0}
     Measure: 0
-    After  : SumS {n = 2, i = -1, s = 0}
+    After  : SumS {n = 1, i = 0, s = 0}
     Measure: 1
 
 Clearly, as @i@ increases, so does our bogus measure @n+i@. (Note that in this case the counterexample might have @i@ and @n@ as negative values, as the SMT solver finds a counter-example to induction, not
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -89,6 +89,7 @@
  - Symbolic polynomials over GF(2^n ), polynomial arithmetic, and CRCs.
  - Uninterpreted constants and functions over symbolic values, with user defined axioms.
  - Uninterpreted sorts, and proofs over such sorts, potentially with axioms.
+ - Algebraic data types, including recursive fields.
  - Ability to define SMTLib functions, generated directly from Haskell versions, including support for recursive and mutually recursive functions.
  - Reasoning with universal and existential quantifiers, including alternating quantifiers.
    
diff --git a/SBVTestSuite/GoldFiles/adt00.gold b/SBVTestSuite/GoldFiles/adt00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt00.gold
@@ -0,0 +1,94 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "e"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool (= s0 s0))
+[GOOD] (define-fun s2 () Bool (not s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt01.gold b/SBVTestSuite/GoldFiles/adt01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt01.gold
@@ -0,0 +1,102 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () ADT ((as APair ADT) ((as AInt64 ADT) #x0000000000000004) ((as AMaybe ADT) ((as Just (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))) (mkSBVTuple3 0.0 ((_ to_fp 8 24) roundNearestTiesToEven (/ 12.0 1.0)) (mkSBVTuple2 ((as Left (Either Int (_ FloatingPoint  8 24))) 3) (seq.++ (seq.unit false) (seq.unit true))))))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "e"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (APair (AInt64 #x0000000000000004)
+              (AMaybe (Just (mkSBVTuple3 0.0
+                                         (fp #b0 #x82 #b10000000000000000000000)
+                                         (mkSBVTuple2 (Left 3)
+                                                      (seq.++ (seq.unit false)
+                                                              (seq.unit true)))))))))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("e",APair (AInt64 4) (AMaybe (Just (0.0,12.0,(Left 3,[False,True])))) :: ADT)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt02.gold b/SBVTestSuite/GoldFiles/adt02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt02.gold
@@ -0,0 +1,96 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "e"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-AList Bool) s0))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AList (seq.unit 2))))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("e",AList [2] :: ADT)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt03.gold b/SBVTestSuite/GoldFiles/adt03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt03.gold
@@ -0,0 +1,95 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "e"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-AList Bool) s0))
+[GOOD] (define-fun s2 () Bool ((as is-AFP Bool) s0))
+[GOOD] (define-fun s3 () Bool (and s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt04.gold b/SBVTestSuite/GoldFiles/adt04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt04.gold
@@ -0,0 +1,180 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 0)
+[GOOD] (define-fun s5 () Int 5)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "a"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-AInteger Bool) s0))
+[GOOD] (define-fun s2 () Int (getAInteger_1 s0))
+[GOOD] (define-fun s4 () Bool (>= s2 s3))
+[GOOD] (define-fun s6 () Bool (<= s2 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s4)
+[GOOD] (assert s6)
+*** Checking Satisfiability, all solutions..
+Fast allSat, Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AInteger 4)))
+[GOOD] (push 1)
+[GOOD] (define-fun s7 () ADT ((as AInteger ADT) 4))
+[GOOD] (define-fun s8 () Bool (= s0 s7))
+[GOOD] (define-fun s9 () Bool (not s8))
+[GOOD] (assert s9)
+Fast allSat, Looking for solution 2
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AInteger 0)))
+[GOOD] (push 1)
+[GOOD] (define-fun s10 () ADT ((as AInteger ADT) 0))
+[GOOD] (define-fun s11 () Bool (= s0 s10))
+[GOOD] (define-fun s12 () Bool (not s11))
+[GOOD] (assert s12)
+Fast allSat, Looking for solution 3
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AInteger 5)))
+[GOOD] (push 1)
+[GOOD] (define-fun s13 () ADT ((as AInteger ADT) 5))
+[GOOD] (define-fun s14 () Bool (= s0 s13))
+[GOOD] (define-fun s15 () Bool (not s14))
+[GOOD] (assert s15)
+Fast allSat, Looking for solution 4
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AInteger 2)))
+[GOOD] (push 1)
+[GOOD] (define-fun s16 () ADT ((as AInteger ADT) 2))
+[GOOD] (define-fun s17 () Bool (= s0 s16))
+[GOOD] (define-fun s18 () Bool (not s17))
+[GOOD] (assert s18)
+Fast allSat, Looking for solution 5
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AInteger 3)))
+[GOOD] (push 1)
+[GOOD] (define-fun s19 () ADT ((as AInteger ADT) 3))
+[GOOD] (define-fun s20 () Bool (= s0 s19))
+[GOOD] (define-fun s21 () Bool (not s20))
+[GOOD] (assert s21)
+Fast allSat, Looking for solution 6
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AInteger 1)))
+[GOOD] (push 1)
+[GOOD] (define-fun s22 () ADT ((as AInteger ADT) 1))
+[GOOD] (define-fun s23 () Bool (= s0 s22))
+[GOOD] (define-fun s24 () Bool (not s23))
+[GOOD] (assert s24)
+Fast allSat, Looking for solution 7
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+MODEL:Satisfiable. Model:
+  a = AInteger 1 :: ADT
+MODEL:Satisfiable. Model:
+  a = AInteger 3 :: ADT
+MODEL:Satisfiable. Model:
+  a = AInteger 2 :: ADT
+MODEL:Satisfiable. Model:
+  a = AInteger 5 :: ADT
+MODEL:Satisfiable. Model:
+  a = AInteger 0 :: ADT
+MODEL:Satisfiable. Model:
+  a = AInteger 4 :: ADT
diff --git a/SBVTestSuite/GoldFiles/adt05.gold b/SBVTestSuite/GoldFiles/adt05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt05.gold
@@ -0,0 +1,130 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic HO_ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s4 () (_ FloatingPoint  8 24) ((_ to_fp 8 24) roundNearestTiesToEven (/ 4.0 1.0)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "a"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] (declare-fun s1 () ADT) ; tracks user variable "b"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s1)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s1)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (is-AFloat s0))
+[GOOD] (define-fun s3 () (_ FloatingPoint  8 24) (getAFloat_1 s0))
+[GOOD] (define-fun s5 () Bool (fp.eq s3 s4))
+[GOOD] (define-fun s6 () Bool (and s2 s5))
+[GOOD] (define-fun s7 () Bool (is-AFloat s1))
+[GOOD] (define-fun s8 () (_ FloatingPoint  8 24) (getAFloat_1 s1))
+[GOOD] (define-fun s9 () Bool (fp.isNaN s8))
+[GOOD] (define-fun s10 () Bool (and s7 s9))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s6)
+[GOOD] (assert s10)
+*** Checking Satisfiability, all solutions..
+Fast allSat, Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AFloat (fp #b0 #b10000001 #b00000000000000000000000))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (AFloat (fp #b0 #b11111111 #b10000000000000000000000))))
+[GOOD] (push 1)
+[GOOD] (define-fun s11 () ADT ((as AFloat ADT) ((_ to_fp 8 24) roundNearestTiesToEven (/ 4.0 1.0))))
+[GOOD] (define-fun s12 () Bool (= s0 s11))
+[GOOD] (define-fun s13 () Bool (not s12))
+[GOOD] (assert s13)
+Fast allSat, Looking for solution 2
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (define-fun s14 () ADT ((as AFloat ADT) (_ NaN 8 24)))
+[GOOD] (define-fun s15 () Bool (= s1 s14))
+[GOOD] (define-fun s16 () Bool (not s15))
+[GOOD] (assert s16)
+[GOOD] (assert s12)
+Fast allSat, Looking for solution 2
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+MODEL:Satisfiable. Model:
+  a = AFloat 4.0 :: ADT
+  b = AFloat NaN :: ADT
diff --git a/SBVTestSuite/GoldFiles/adt06.gold b/SBVTestSuite/GoldFiles/adt06.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt06.gold
@@ -0,0 +1,103 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "a"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-AMaybe Bool) s0))
+[GOOD] (define-fun s2 () (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool)))) (getAMaybe_1 s0))
+[GOOD] (define-fun s3 () Bool ((as is-Just Bool) s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AMaybe (Just (mkSBVTuple3 2.0
+                                  (fp #b0 #x00 #b00000000000000000000001)
+                                  (mkSBVTuple2 (Right (fp #b0 #x01 #b00000000000010000000000))
+                                               (seq.unit true)))))))
+
+getValue: AMaybe (Just (2.0,1.0e-45,(Right 1.1756378e-38,[True])))
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_chk01.gold b/SBVTestSuite/GoldFiles/adt_chk01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_chk01.gold
@@ -0,0 +1,40 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: A
+[GOOD] (declare-datatype A (
+           (A (getA_1 Int))
+           (B (getB_1 (_ BitVec 8)))
+           (C (getC_1 A) (getC_2 A))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () A ((as A A) 13))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () A) ; tracks user variable "res"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (A 13)))
+Result: A 13
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr00.gold b/SBVTestSuite/GoldFiles/adt_expr00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr00.gold
@@ -0,0 +1,96 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Val Expr) 3))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 3)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s9 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s6 (proj_1_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s7 (= l2_s1 l2_s6)))
+                                                 (let ((l2_s8 (proj_2_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s10 (- l2_s2 l2_s9)))
+                                                 (let ((l2_s11 (seq.extract l2_s0 l2_s9 l2_s10)))
+                                                 (let ((l2_s12 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s11 l2_s1)))
+                                                 (let ((l2_s13 (ite l2_s7 l2_s8 l2_s12)))
+                                                 (let ((l2_s14 (ite l2_s4 l2_s3 l2_s13)))
+                                                 l2_s14))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr00c.gold b/SBVTestSuite/GoldFiles/adt_expr00c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr00c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr01.gold b/SBVTestSuite/GoldFiles/adt_expr01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr01.gold
@@ -0,0 +1,96 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 7)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s9 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s6 (proj_1_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s7 (= l2_s1 l2_s6)))
+                                                 (let ((l2_s8 (proj_2_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s10 (- l2_s2 l2_s9)))
+                                                 (let ((l2_s11 (seq.extract l2_s0 l2_s9 l2_s10)))
+                                                 (let ((l2_s12 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s11 l2_s1)))
+                                                 (let ((l2_s13 (ite l2_s7 l2_s8 l2_s12)))
+                                                 (let ((l2_s14 (ite l2_s4 l2_s3 l2_s13)))
+                                                 l2_s14))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr01c.gold b/SBVTestSuite/GoldFiles/adt_expr01c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr01c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr02.gold b/SBVTestSuite/GoldFiles/adt_expr02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr02.gold
@@ -0,0 +1,96 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 21)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s9 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s6 (proj_1_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s7 (= l2_s1 l2_s6)))
+                                                 (let ((l2_s8 (proj_2_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s10 (- l2_s2 l2_s9)))
+                                                 (let ((l2_s11 (seq.extract l2_s0 l2_s9 l2_s10)))
+                                                 (let ((l2_s12 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s11 l2_s1)))
+                                                 (let ((l2_s13 (ite l2_s7 l2_s8 l2_s12)))
+                                                 (let ((l2_s14 (ite l2_s4 l2_s3 l2_s13)))
+                                                 l2_s14))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr02c.gold b/SBVTestSuite/GoldFiles/adt_expr02c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr02c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr03.gold b/SBVTestSuite/GoldFiles/adt_expr03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr03.gold
@@ -0,0 +1,96 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Let Expr) "a" ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 28)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s9 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s6 (proj_1_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s7 (= l2_s1 l2_s6)))
+                                                 (let ((l2_s8 (proj_2_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s10 (- l2_s2 l2_s9)))
+                                                 (let ((l2_s11 (seq.extract l2_s0 l2_s9 l2_s10)))
+                                                 (let ((l2_s12 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s11 l2_s1)))
+                                                 (let ((l2_s13 (ite l2_s7 l2_s8 l2_s12)))
+                                                 (let ((l2_s14 (ite l2_s4 l2_s3 l2_s13)))
+                                                 l2_s14))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr03c.gold b/SBVTestSuite/GoldFiles/adt_expr03c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr03c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr04.gold b/SBVTestSuite/GoldFiles/adt_expr04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr04.gold
@@ -0,0 +1,30 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 63)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "res"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 63))
+Result: 63
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr05.gold b/SBVTestSuite/GoldFiles/adt_expr05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr05.gold
@@ -0,0 +1,30 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 3969)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "res"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3969))
+Result: 3969
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr06.gold b/SBVTestSuite/GoldFiles/adt_expr06.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr06.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Var Expr) "a"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s8 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr06c.gold b/SBVTestSuite/GoldFiles/adt_expr06c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr06c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr07.gold b/SBVTestSuite/GoldFiles/adt_expr07.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr07.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Var Expr) "b"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s15 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr07c.gold b/SBVTestSuite/GoldFiles/adt_expr07c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr07c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr08.gold b/SBVTestSuite/GoldFiles/adt_expr08.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr08.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Var Expr) "c"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s15 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr08c.gold b/SBVTestSuite/GoldFiles/adt_expr08c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr08c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr09.gold b/SBVTestSuite/GoldFiles/adt_expr09.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr09.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Var Expr) "d"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s16 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr09c.gold b/SBVTestSuite/GoldFiles/adt_expr09c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr09c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr10.gold b/SBVTestSuite/GoldFiles/adt_expr10.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr10.gold
@@ -0,0 +1,454 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s15 () Expr ((as Val Expr) (- 5)))
+[GOOD] (define-fun s17 () Expr ((as Val Expr) (- 4)))
+[GOOD] (define-fun s19 () Expr ((as Val Expr) (- 3)))
+[GOOD] (define-fun s21 () Expr ((as Val Expr) (- 2)))
+[GOOD] (define-fun s23 () Expr ((as Val Expr) (- 1)))
+[GOOD] (define-fun s25 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s27 () Expr ((as Val Expr) 1))
+[GOOD] (define-fun s29 () Expr ((as Val Expr) 2))
+[GOOD] (define-fun s31 () Expr ((as Val Expr) 3))
+[GOOD] (define-fun s33 () Expr ((as Val Expr) 4))
+[GOOD] (define-fun s35 () Expr ((as Val Expr) 5))
+[GOOD] (define-fun s37 () Expr ((as Val Expr) 6))
+[GOOD] (define-fun s39 () Expr ((as Val Expr) 7))
+[GOOD] (define-fun s41 () Expr ((as Val Expr) 8))
+[GOOD] (define-fun s43 () Expr ((as Val Expr) 9))
+[GOOD] (define-fun s61 () String "a")
+[GOOD] (define-fun s64 () Int 0)
+[GOOD] (define-fun s65 () String "b")
+[GOOD] (define-fun s67 () String "c")
+[GOOD] (define-fun s71 () Int 1)
+[GOOD] (define-fun s72 () Int 2)
+[GOOD] (define-fun s75 () Int 10)
+[GOOD] (define-fun s78 () Int 3)
+[GOOD] (define-fun s81 () Int 4)
+[GOOD] (define-fun s84 () Int 5)
+[GOOD] (define-fun s85 () Int 6)
+[GOOD] (define-fun s414 () Int 45)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] (declare-fun s1 () Expr)
+[GOOD] (declare-fun s2 () Expr)
+[GOOD] (declare-fun s3 () Expr)
+[GOOD] (declare-fun s4 () Expr)
+[GOOD] (declare-fun s5 () Expr)
+[GOOD] (declare-fun s6 () Expr)
+[GOOD] (declare-fun s7 () Expr)
+[GOOD] (declare-fun s8 () Expr)
+[GOOD] (declare-fun s9 () Expr)
+[GOOD] (declare-fun s10 () Expr)
+[GOOD] (declare-fun s11 () Expr)
+[GOOD] (declare-fun s12 () Expr)
+[GOOD] (declare-fun s13 () Expr)
+[GOOD] (declare-fun s14 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s16 () Bool (= s0 s15))
+[GOOD] (define-fun s18 () Bool (= s1 s17))
+[GOOD] (define-fun s20 () Bool (= s2 s19))
+[GOOD] (define-fun s22 () Bool (= s3 s21))
+[GOOD] (define-fun s24 () Bool (= s4 s23))
+[GOOD] (define-fun s26 () Bool (= s5 s25))
+[GOOD] (define-fun s28 () Bool (= s6 s27))
+[GOOD] (define-fun s30 () Bool (= s7 s29))
+[GOOD] (define-fun s32 () Bool (= s8 s31))
+[GOOD] (define-fun s34 () Bool (= s9 s33))
+[GOOD] (define-fun s36 () Bool (= s10 s35))
+[GOOD] (define-fun s38 () Bool (= s11 s37))
+[GOOD] (define-fun s40 () Bool (= s12 s39))
+[GOOD] (define-fun s42 () Bool (= s13 s41))
+[GOOD] (define-fun s44 () Bool (= s14 s43))
+[GOOD] (define-fun s45 () Bool (and s42 s44))
+[GOOD] (define-fun s46 () Bool (and s40 s45))
+[GOOD] (define-fun s47 () Bool (and s38 s46))
+[GOOD] (define-fun s48 () Bool (and s36 s47))
+[GOOD] (define-fun s49 () Bool (and s34 s48))
+[GOOD] (define-fun s50 () Bool (and s32 s49))
+[GOOD] (define-fun s51 () Bool (and s30 s50))
+[GOOD] (define-fun s52 () Bool (and s28 s51))
+[GOOD] (define-fun s53 () Bool (and s26 s52))
+[GOOD] (define-fun s54 () Bool (and s24 s53))
+[GOOD] (define-fun s55 () Bool (and s22 s54))
+[GOOD] (define-fun s56 () Bool (and s20 s55))
+[GOOD] (define-fun s57 () Bool (and s18 s56))
+[GOOD] (define-fun s58 () Bool (and s16 s57))
+[GOOD] (define-fun s59 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s60 () String (getVar_1 s0))
+[GOOD] (define-fun s62 () Bool (= s60 s61))
+[GOOD] (define-fun s63 () Bool (and s59 s62))
+[GOOD] (define-fun s66 () Bool (= s60 s65))
+[GOOD] (define-fun s68 () Bool (= s60 s67))
+[GOOD] (define-fun s69 () Bool (or s66 s68))
+[GOOD] (define-fun s70 () Bool (and s59 s69))
+[GOOD] (define-fun s73 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s74 () Int (getVal_1 s0))
+[GOOD] (define-fun s76 () Bool (< s74 s75))
+[GOOD] (define-fun s77 () Bool (and s73 s76))
+[GOOD] (define-fun s79 () Bool (= s74 s75))
+[GOOD] (define-fun s80 () Bool (and s73 s79))
+[GOOD] (define-fun s82 () Bool (> s74 s75))
+[GOOD] (define-fun s83 () Bool (and s73 s82))
+[GOOD] (define-fun s86 () Int (ite s83 s84 s85))
+[GOOD] (define-fun s87 () Int (ite s80 s81 s86))
+[GOOD] (define-fun s88 () Int (ite s77 s78 s87))
+[GOOD] (define-fun s89 () Int (ite s59 s72 s88))
+[GOOD] (define-fun s90 () Int (ite s70 s71 s89))
+[GOOD] (define-fun s91 () Int (ite s63 s64 s90))
+[GOOD] (define-fun s92 () Bool ((as is-Var Bool) s1))
+[GOOD] (define-fun s93 () String (getVar_1 s1))
+[GOOD] (define-fun s94 () Bool (= s61 s93))
+[GOOD] (define-fun s95 () Bool (and s92 s94))
+[GOOD] (define-fun s96 () Bool (= s65 s93))
+[GOOD] (define-fun s97 () Bool (= s67 s93))
+[GOOD] (define-fun s98 () Bool (or s96 s97))
+[GOOD] (define-fun s99 () Bool (and s92 s98))
+[GOOD] (define-fun s100 () Bool ((as is-Val Bool) s1))
+[GOOD] (define-fun s101 () Int (getVal_1 s1))
+[GOOD] (define-fun s102 () Bool (< s101 s75))
+[GOOD] (define-fun s103 () Bool (and s100 s102))
+[GOOD] (define-fun s104 () Bool (= s75 s101))
+[GOOD] (define-fun s105 () Bool (and s100 s104))
+[GOOD] (define-fun s106 () Bool (> s101 s75))
+[GOOD] (define-fun s107 () Bool (and s100 s106))
+[GOOD] (define-fun s108 () Int (ite s107 s84 s85))
+[GOOD] (define-fun s109 () Int (ite s105 s81 s108))
+[GOOD] (define-fun s110 () Int (ite s103 s78 s109))
+[GOOD] (define-fun s111 () Int (ite s92 s72 s110))
+[GOOD] (define-fun s112 () Int (ite s99 s71 s111))
+[GOOD] (define-fun s113 () Int (ite s95 s64 s112))
+[GOOD] (define-fun s114 () Int (+ s91 s113))
+[GOOD] (define-fun s115 () Bool ((as is-Var Bool) s2))
+[GOOD] (define-fun s116 () String (getVar_1 s2))
+[GOOD] (define-fun s117 () Bool (= s61 s116))
+[GOOD] (define-fun s118 () Bool (and s115 s117))
+[GOOD] (define-fun s119 () Bool (= s65 s116))
+[GOOD] (define-fun s120 () Bool (= s67 s116))
+[GOOD] (define-fun s121 () Bool (or s119 s120))
+[GOOD] (define-fun s122 () Bool (and s115 s121))
+[GOOD] (define-fun s123 () Bool ((as is-Val Bool) s2))
+[GOOD] (define-fun s124 () Int (getVal_1 s2))
+[GOOD] (define-fun s125 () Bool (< s124 s75))
+[GOOD] (define-fun s126 () Bool (and s123 s125))
+[GOOD] (define-fun s127 () Bool (= s75 s124))
+[GOOD] (define-fun s128 () Bool (and s123 s127))
+[GOOD] (define-fun s129 () Bool (> s124 s75))
+[GOOD] (define-fun s130 () Bool (and s123 s129))
+[GOOD] (define-fun s131 () Int (ite s130 s84 s85))
+[GOOD] (define-fun s132 () Int (ite s128 s81 s131))
+[GOOD] (define-fun s133 () Int (ite s126 s78 s132))
+[GOOD] (define-fun s134 () Int (ite s115 s72 s133))
+[GOOD] (define-fun s135 () Int (ite s122 s71 s134))
+[GOOD] (define-fun s136 () Int (ite s118 s64 s135))
+[GOOD] (define-fun s137 () Int (+ s114 s136))
+[GOOD] (define-fun s138 () Bool ((as is-Var Bool) s3))
+[GOOD] (define-fun s139 () String (getVar_1 s3))
+[GOOD] (define-fun s140 () Bool (= s61 s139))
+[GOOD] (define-fun s141 () Bool (and s138 s140))
+[GOOD] (define-fun s142 () Bool (= s65 s139))
+[GOOD] (define-fun s143 () Bool (= s67 s139))
+[GOOD] (define-fun s144 () Bool (or s142 s143))
+[GOOD] (define-fun s145 () Bool (and s138 s144))
+[GOOD] (define-fun s146 () Bool ((as is-Val Bool) s3))
+[GOOD] (define-fun s147 () Int (getVal_1 s3))
+[GOOD] (define-fun s148 () Bool (< s147 s75))
+[GOOD] (define-fun s149 () Bool (and s146 s148))
+[GOOD] (define-fun s150 () Bool (= s75 s147))
+[GOOD] (define-fun s151 () Bool (and s146 s150))
+[GOOD] (define-fun s152 () Bool (> s147 s75))
+[GOOD] (define-fun s153 () Bool (and s146 s152))
+[GOOD] (define-fun s154 () Int (ite s153 s84 s85))
+[GOOD] (define-fun s155 () Int (ite s151 s81 s154))
+[GOOD] (define-fun s156 () Int (ite s149 s78 s155))
+[GOOD] (define-fun s157 () Int (ite s138 s72 s156))
+[GOOD] (define-fun s158 () Int (ite s145 s71 s157))
+[GOOD] (define-fun s159 () Int (ite s141 s64 s158))
+[GOOD] (define-fun s160 () Int (+ s137 s159))
+[GOOD] (define-fun s161 () Bool ((as is-Var Bool) s4))
+[GOOD] (define-fun s162 () String (getVar_1 s4))
+[GOOD] (define-fun s163 () Bool (= s61 s162))
+[GOOD] (define-fun s164 () Bool (and s161 s163))
+[GOOD] (define-fun s165 () Bool (= s65 s162))
+[GOOD] (define-fun s166 () Bool (= s67 s162))
+[GOOD] (define-fun s167 () Bool (or s165 s166))
+[GOOD] (define-fun s168 () Bool (and s161 s167))
+[GOOD] (define-fun s169 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s170 () Int (getVal_1 s4))
+[GOOD] (define-fun s171 () Bool (< s170 s75))
+[GOOD] (define-fun s172 () Bool (and s169 s171))
+[GOOD] (define-fun s173 () Bool (= s75 s170))
+[GOOD] (define-fun s174 () Bool (and s169 s173))
+[GOOD] (define-fun s175 () Bool (> s170 s75))
+[GOOD] (define-fun s176 () Bool (and s169 s175))
+[GOOD] (define-fun s177 () Int (ite s176 s84 s85))
+[GOOD] (define-fun s178 () Int (ite s174 s81 s177))
+[GOOD] (define-fun s179 () Int (ite s172 s78 s178))
+[GOOD] (define-fun s180 () Int (ite s161 s72 s179))
+[GOOD] (define-fun s181 () Int (ite s168 s71 s180))
+[GOOD] (define-fun s182 () Int (ite s164 s64 s181))
+[GOOD] (define-fun s183 () Int (+ s160 s182))
+[GOOD] (define-fun s184 () Bool ((as is-Var Bool) s5))
+[GOOD] (define-fun s185 () String (getVar_1 s5))
+[GOOD] (define-fun s186 () Bool (= s61 s185))
+[GOOD] (define-fun s187 () Bool (and s184 s186))
+[GOOD] (define-fun s188 () Bool (= s65 s185))
+[GOOD] (define-fun s189 () Bool (= s67 s185))
+[GOOD] (define-fun s190 () Bool (or s188 s189))
+[GOOD] (define-fun s191 () Bool (and s184 s190))
+[GOOD] (define-fun s192 () Bool ((as is-Val Bool) s5))
+[GOOD] (define-fun s193 () Int (getVal_1 s5))
+[GOOD] (define-fun s194 () Bool (< s193 s75))
+[GOOD] (define-fun s195 () Bool (and s192 s194))
+[GOOD] (define-fun s196 () Bool (= s75 s193))
+[GOOD] (define-fun s197 () Bool (and s192 s196))
+[GOOD] (define-fun s198 () Bool (> s193 s75))
+[GOOD] (define-fun s199 () Bool (and s192 s198))
+[GOOD] (define-fun s200 () Int (ite s199 s84 s85))
+[GOOD] (define-fun s201 () Int (ite s197 s81 s200))
+[GOOD] (define-fun s202 () Int (ite s195 s78 s201))
+[GOOD] (define-fun s203 () Int (ite s184 s72 s202))
+[GOOD] (define-fun s204 () Int (ite s191 s71 s203))
+[GOOD] (define-fun s205 () Int (ite s187 s64 s204))
+[GOOD] (define-fun s206 () Int (+ s183 s205))
+[GOOD] (define-fun s207 () Bool ((as is-Var Bool) s6))
+[GOOD] (define-fun s208 () String (getVar_1 s6))
+[GOOD] (define-fun s209 () Bool (= s61 s208))
+[GOOD] (define-fun s210 () Bool (and s207 s209))
+[GOOD] (define-fun s211 () Bool (= s65 s208))
+[GOOD] (define-fun s212 () Bool (= s67 s208))
+[GOOD] (define-fun s213 () Bool (or s211 s212))
+[GOOD] (define-fun s214 () Bool (and s207 s213))
+[GOOD] (define-fun s215 () Bool ((as is-Val Bool) s6))
+[GOOD] (define-fun s216 () Int (getVal_1 s6))
+[GOOD] (define-fun s217 () Bool (< s216 s75))
+[GOOD] (define-fun s218 () Bool (and s215 s217))
+[GOOD] (define-fun s219 () Bool (= s75 s216))
+[GOOD] (define-fun s220 () Bool (and s215 s219))
+[GOOD] (define-fun s221 () Bool (> s216 s75))
+[GOOD] (define-fun s222 () Bool (and s215 s221))
+[GOOD] (define-fun s223 () Int (ite s222 s84 s85))
+[GOOD] (define-fun s224 () Int (ite s220 s81 s223))
+[GOOD] (define-fun s225 () Int (ite s218 s78 s224))
+[GOOD] (define-fun s226 () Int (ite s207 s72 s225))
+[GOOD] (define-fun s227 () Int (ite s214 s71 s226))
+[GOOD] (define-fun s228 () Int (ite s210 s64 s227))
+[GOOD] (define-fun s229 () Int (+ s206 s228))
+[GOOD] (define-fun s230 () Bool ((as is-Var Bool) s7))
+[GOOD] (define-fun s231 () String (getVar_1 s7))
+[GOOD] (define-fun s232 () Bool (= s61 s231))
+[GOOD] (define-fun s233 () Bool (and s230 s232))
+[GOOD] (define-fun s234 () Bool (= s65 s231))
+[GOOD] (define-fun s235 () Bool (= s67 s231))
+[GOOD] (define-fun s236 () Bool (or s234 s235))
+[GOOD] (define-fun s237 () Bool (and s230 s236))
+[GOOD] (define-fun s238 () Bool ((as is-Val Bool) s7))
+[GOOD] (define-fun s239 () Int (getVal_1 s7))
+[GOOD] (define-fun s240 () Bool (< s239 s75))
+[GOOD] (define-fun s241 () Bool (and s238 s240))
+[GOOD] (define-fun s242 () Bool (= s75 s239))
+[GOOD] (define-fun s243 () Bool (and s238 s242))
+[GOOD] (define-fun s244 () Bool (> s239 s75))
+[GOOD] (define-fun s245 () Bool (and s238 s244))
+[GOOD] (define-fun s246 () Int (ite s245 s84 s85))
+[GOOD] (define-fun s247 () Int (ite s243 s81 s246))
+[GOOD] (define-fun s248 () Int (ite s241 s78 s247))
+[GOOD] (define-fun s249 () Int (ite s230 s72 s248))
+[GOOD] (define-fun s250 () Int (ite s237 s71 s249))
+[GOOD] (define-fun s251 () Int (ite s233 s64 s250))
+[GOOD] (define-fun s252 () Int (+ s229 s251))
+[GOOD] (define-fun s253 () Bool ((as is-Var Bool) s8))
+[GOOD] (define-fun s254 () String (getVar_1 s8))
+[GOOD] (define-fun s255 () Bool (= s61 s254))
+[GOOD] (define-fun s256 () Bool (and s253 s255))
+[GOOD] (define-fun s257 () Bool (= s65 s254))
+[GOOD] (define-fun s258 () Bool (= s67 s254))
+[GOOD] (define-fun s259 () Bool (or s257 s258))
+[GOOD] (define-fun s260 () Bool (and s253 s259))
+[GOOD] (define-fun s261 () Bool ((as is-Val Bool) s8))
+[GOOD] (define-fun s262 () Int (getVal_1 s8))
+[GOOD] (define-fun s263 () Bool (< s262 s75))
+[GOOD] (define-fun s264 () Bool (and s261 s263))
+[GOOD] (define-fun s265 () Bool (= s75 s262))
+[GOOD] (define-fun s266 () Bool (and s261 s265))
+[GOOD] (define-fun s267 () Bool (> s262 s75))
+[GOOD] (define-fun s268 () Bool (and s261 s267))
+[GOOD] (define-fun s269 () Int (ite s268 s84 s85))
+[GOOD] (define-fun s270 () Int (ite s266 s81 s269))
+[GOOD] (define-fun s271 () Int (ite s264 s78 s270))
+[GOOD] (define-fun s272 () Int (ite s253 s72 s271))
+[GOOD] (define-fun s273 () Int (ite s260 s71 s272))
+[GOOD] (define-fun s274 () Int (ite s256 s64 s273))
+[GOOD] (define-fun s275 () Int (+ s252 s274))
+[GOOD] (define-fun s276 () Bool ((as is-Var Bool) s9))
+[GOOD] (define-fun s277 () String (getVar_1 s9))
+[GOOD] (define-fun s278 () Bool (= s61 s277))
+[GOOD] (define-fun s279 () Bool (and s276 s278))
+[GOOD] (define-fun s280 () Bool (= s65 s277))
+[GOOD] (define-fun s281 () Bool (= s67 s277))
+[GOOD] (define-fun s282 () Bool (or s280 s281))
+[GOOD] (define-fun s283 () Bool (and s276 s282))
+[GOOD] (define-fun s284 () Bool ((as is-Val Bool) s9))
+[GOOD] (define-fun s285 () Int (getVal_1 s9))
+[GOOD] (define-fun s286 () Bool (< s285 s75))
+[GOOD] (define-fun s287 () Bool (and s284 s286))
+[GOOD] (define-fun s288 () Bool (= s75 s285))
+[GOOD] (define-fun s289 () Bool (and s284 s288))
+[GOOD] (define-fun s290 () Bool (> s285 s75))
+[GOOD] (define-fun s291 () Bool (and s284 s290))
+[GOOD] (define-fun s292 () Int (ite s291 s84 s85))
+[GOOD] (define-fun s293 () Int (ite s289 s81 s292))
+[GOOD] (define-fun s294 () Int (ite s287 s78 s293))
+[GOOD] (define-fun s295 () Int (ite s276 s72 s294))
+[GOOD] (define-fun s296 () Int (ite s283 s71 s295))
+[GOOD] (define-fun s297 () Int (ite s279 s64 s296))
+[GOOD] (define-fun s298 () Int (+ s275 s297))
+[GOOD] (define-fun s299 () Bool ((as is-Var Bool) s10))
+[GOOD] (define-fun s300 () String (getVar_1 s10))
+[GOOD] (define-fun s301 () Bool (= s61 s300))
+[GOOD] (define-fun s302 () Bool (and s299 s301))
+[GOOD] (define-fun s303 () Bool (= s65 s300))
+[GOOD] (define-fun s304 () Bool (= s67 s300))
+[GOOD] (define-fun s305 () Bool (or s303 s304))
+[GOOD] (define-fun s306 () Bool (and s299 s305))
+[GOOD] (define-fun s307 () Bool ((as is-Val Bool) s10))
+[GOOD] (define-fun s308 () Int (getVal_1 s10))
+[GOOD] (define-fun s309 () Bool (< s308 s75))
+[GOOD] (define-fun s310 () Bool (and s307 s309))
+[GOOD] (define-fun s311 () Bool (= s75 s308))
+[GOOD] (define-fun s312 () Bool (and s307 s311))
+[GOOD] (define-fun s313 () Bool (> s308 s75))
+[GOOD] (define-fun s314 () Bool (and s307 s313))
+[GOOD] (define-fun s315 () Int (ite s314 s84 s85))
+[GOOD] (define-fun s316 () Int (ite s312 s81 s315))
+[GOOD] (define-fun s317 () Int (ite s310 s78 s316))
+[GOOD] (define-fun s318 () Int (ite s299 s72 s317))
+[GOOD] (define-fun s319 () Int (ite s306 s71 s318))
+[GOOD] (define-fun s320 () Int (ite s302 s64 s319))
+[GOOD] (define-fun s321 () Int (+ s298 s320))
+[GOOD] (define-fun s322 () Bool ((as is-Var Bool) s11))
+[GOOD] (define-fun s323 () String (getVar_1 s11))
+[GOOD] (define-fun s324 () Bool (= s61 s323))
+[GOOD] (define-fun s325 () Bool (and s322 s324))
+[GOOD] (define-fun s326 () Bool (= s65 s323))
+[GOOD] (define-fun s327 () Bool (= s67 s323))
+[GOOD] (define-fun s328 () Bool (or s326 s327))
+[GOOD] (define-fun s329 () Bool (and s322 s328))
+[GOOD] (define-fun s330 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s331 () Int (getVal_1 s11))
+[GOOD] (define-fun s332 () Bool (< s331 s75))
+[GOOD] (define-fun s333 () Bool (and s330 s332))
+[GOOD] (define-fun s334 () Bool (= s75 s331))
+[GOOD] (define-fun s335 () Bool (and s330 s334))
+[GOOD] (define-fun s336 () Bool (> s331 s75))
+[GOOD] (define-fun s337 () Bool (and s330 s336))
+[GOOD] (define-fun s338 () Int (ite s337 s84 s85))
+[GOOD] (define-fun s339 () Int (ite s335 s81 s338))
+[GOOD] (define-fun s340 () Int (ite s333 s78 s339))
+[GOOD] (define-fun s341 () Int (ite s322 s72 s340))
+[GOOD] (define-fun s342 () Int (ite s329 s71 s341))
+[GOOD] (define-fun s343 () Int (ite s325 s64 s342))
+[GOOD] (define-fun s344 () Int (+ s321 s343))
+[GOOD] (define-fun s345 () Bool ((as is-Var Bool) s12))
+[GOOD] (define-fun s346 () String (getVar_1 s12))
+[GOOD] (define-fun s347 () Bool (= s61 s346))
+[GOOD] (define-fun s348 () Bool (and s345 s347))
+[GOOD] (define-fun s349 () Bool (= s65 s346))
+[GOOD] (define-fun s350 () Bool (= s67 s346))
+[GOOD] (define-fun s351 () Bool (or s349 s350))
+[GOOD] (define-fun s352 () Bool (and s345 s351))
+[GOOD] (define-fun s353 () Bool ((as is-Val Bool) s12))
+[GOOD] (define-fun s354 () Int (getVal_1 s12))
+[GOOD] (define-fun s355 () Bool (< s354 s75))
+[GOOD] (define-fun s356 () Bool (and s353 s355))
+[GOOD] (define-fun s357 () Bool (= s75 s354))
+[GOOD] (define-fun s358 () Bool (and s353 s357))
+[GOOD] (define-fun s359 () Bool (> s354 s75))
+[GOOD] (define-fun s360 () Bool (and s353 s359))
+[GOOD] (define-fun s361 () Int (ite s360 s84 s85))
+[GOOD] (define-fun s362 () Int (ite s358 s81 s361))
+[GOOD] (define-fun s363 () Int (ite s356 s78 s362))
+[GOOD] (define-fun s364 () Int (ite s345 s72 s363))
+[GOOD] (define-fun s365 () Int (ite s352 s71 s364))
+[GOOD] (define-fun s366 () Int (ite s348 s64 s365))
+[GOOD] (define-fun s367 () Int (+ s344 s366))
+[GOOD] (define-fun s368 () Bool ((as is-Var Bool) s13))
+[GOOD] (define-fun s369 () String (getVar_1 s13))
+[GOOD] (define-fun s370 () Bool (= s61 s369))
+[GOOD] (define-fun s371 () Bool (and s368 s370))
+[GOOD] (define-fun s372 () Bool (= s65 s369))
+[GOOD] (define-fun s373 () Bool (= s67 s369))
+[GOOD] (define-fun s374 () Bool (or s372 s373))
+[GOOD] (define-fun s375 () Bool (and s368 s374))
+[GOOD] (define-fun s376 () Bool ((as is-Val Bool) s13))
+[GOOD] (define-fun s377 () Int (getVal_1 s13))
+[GOOD] (define-fun s378 () Bool (< s377 s75))
+[GOOD] (define-fun s379 () Bool (and s376 s378))
+[GOOD] (define-fun s380 () Bool (= s75 s377))
+[GOOD] (define-fun s381 () Bool (and s376 s380))
+[GOOD] (define-fun s382 () Bool (> s377 s75))
+[GOOD] (define-fun s383 () Bool (and s376 s382))
+[GOOD] (define-fun s384 () Int (ite s383 s84 s85))
+[GOOD] (define-fun s385 () Int (ite s381 s81 s384))
+[GOOD] (define-fun s386 () Int (ite s379 s78 s385))
+[GOOD] (define-fun s387 () Int (ite s368 s72 s386))
+[GOOD] (define-fun s388 () Int (ite s375 s71 s387))
+[GOOD] (define-fun s389 () Int (ite s371 s64 s388))
+[GOOD] (define-fun s390 () Int (+ s367 s389))
+[GOOD] (define-fun s391 () Bool ((as is-Var Bool) s14))
+[GOOD] (define-fun s392 () String (getVar_1 s14))
+[GOOD] (define-fun s393 () Bool (= s61 s392))
+[GOOD] (define-fun s394 () Bool (and s391 s393))
+[GOOD] (define-fun s395 () Bool (= s65 s392))
+[GOOD] (define-fun s396 () Bool (= s67 s392))
+[GOOD] (define-fun s397 () Bool (or s395 s396))
+[GOOD] (define-fun s398 () Bool (and s391 s397))
+[GOOD] (define-fun s399 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s400 () Int (getVal_1 s14))
+[GOOD] (define-fun s401 () Bool (< s400 s75))
+[GOOD] (define-fun s402 () Bool (and s399 s401))
+[GOOD] (define-fun s403 () Bool (= s75 s400))
+[GOOD] (define-fun s404 () Bool (and s399 s403))
+[GOOD] (define-fun s405 () Bool (> s400 s75))
+[GOOD] (define-fun s406 () Bool (and s399 s405))
+[GOOD] (define-fun s407 () Int (ite s406 s84 s85))
+[GOOD] (define-fun s408 () Int (ite s404 s81 s407))
+[GOOD] (define-fun s409 () Int (ite s402 s78 s408))
+[GOOD] (define-fun s410 () Int (ite s391 s72 s409))
+[GOOD] (define-fun s411 () Int (ite s398 s71 s410))
+[GOOD] (define-fun s412 () Int (ite s394 s64 s411))
+[GOOD] (define-fun s413 () Int (+ s390 s412))
+[GOOD] (define-fun s415 () Bool (distinct s413 s414))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s58)
+[GOOD] (assert s415)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr10c.gold b/SBVTestSuite/GoldFiles/adt_expr10c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr10c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr11.gold b/SBVTestSuite/GoldFiles/adt_expr11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr11.gold
@@ -0,0 +1,102 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Expr ((as Val Expr) 10))
+[GOOD] (define-fun s8 () String "a")
+[GOOD] (define-fun s11 () Int 0)
+[GOOD] (define-fun s12 () String "b")
+[GOOD] (define-fun s14 () String "c")
+[GOOD] (define-fun s18 () Int 1)
+[GOOD] (define-fun s19 () Int 2)
+[GOOD] (define-fun s22 () Int 10)
+[GOOD] (define-fun s25 () Int 3)
+[GOOD] (define-fun s28 () Int 4)
+[GOOD] (define-fun s31 () Int 5)
+[GOOD] (define-fun s32 () Int 6)
+[GOOD] (define-fun s62 () Int 8)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] (declare-fun s1 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] (define-fun s5 () Bool (and s3 s4))
+[GOOD] (define-fun s6 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s7 () String (getVar_1 s0))
+[GOOD] (define-fun s9 () Bool (= s7 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s13 () Bool (= s7 s12))
+[GOOD] (define-fun s15 () Bool (= s7 s14))
+[GOOD] (define-fun s16 () Bool (or s13 s15))
+[GOOD] (define-fun s17 () Bool (and s6 s16))
+[GOOD] (define-fun s20 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s21 () Int (getVal_1 s0))
+[GOOD] (define-fun s23 () Bool (< s21 s22))
+[GOOD] (define-fun s24 () Bool (and s20 s23))
+[GOOD] (define-fun s26 () Bool (= s21 s22))
+[GOOD] (define-fun s27 () Bool (and s20 s26))
+[GOOD] (define-fun s29 () Bool (> s21 s22))
+[GOOD] (define-fun s30 () Bool (and s20 s29))
+[GOOD] (define-fun s33 () Int (ite s30 s31 s32))
+[GOOD] (define-fun s34 () Int (ite s27 s28 s33))
+[GOOD] (define-fun s35 () Int (ite s24 s25 s34))
+[GOOD] (define-fun s36 () Int (ite s6 s19 s35))
+[GOOD] (define-fun s37 () Int (ite s17 s18 s36))
+[GOOD] (define-fun s38 () Int (ite s10 s11 s37))
+[GOOD] (define-fun s39 () Bool ((as is-Var Bool) s1))
+[GOOD] (define-fun s40 () String (getVar_1 s1))
+[GOOD] (define-fun s41 () Bool (= s8 s40))
+[GOOD] (define-fun s42 () Bool (and s39 s41))
+[GOOD] (define-fun s43 () Bool (= s12 s40))
+[GOOD] (define-fun s44 () Bool (= s14 s40))
+[GOOD] (define-fun s45 () Bool (or s43 s44))
+[GOOD] (define-fun s46 () Bool (and s39 s45))
+[GOOD] (define-fun s47 () Bool ((as is-Val Bool) s1))
+[GOOD] (define-fun s48 () Int (getVal_1 s1))
+[GOOD] (define-fun s49 () Bool (< s48 s22))
+[GOOD] (define-fun s50 () Bool (and s47 s49))
+[GOOD] (define-fun s51 () Bool (= s22 s48))
+[GOOD] (define-fun s52 () Bool (and s47 s51))
+[GOOD] (define-fun s53 () Bool (> s48 s22))
+[GOOD] (define-fun s54 () Bool (and s47 s53))
+[GOOD] (define-fun s55 () Int (ite s54 s31 s32))
+[GOOD] (define-fun s56 () Int (ite s52 s28 s55))
+[GOOD] (define-fun s57 () Int (ite s50 s25 s56))
+[GOOD] (define-fun s58 () Int (ite s39 s19 s57))
+[GOOD] (define-fun s59 () Int (ite s46 s18 s58))
+[GOOD] (define-fun s60 () Int (ite s42 s11 s59))
+[GOOD] (define-fun s61 () Int (+ s38 s60))
+[GOOD] (define-fun s63 () Bool (distinct s61 s62))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s5)
+[GOOD] (assert s63)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr11c.gold b/SBVTestSuite/GoldFiles/adt_expr11c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr11c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr12.gold b/SBVTestSuite/GoldFiles/adt_expr12.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr12.gold
@@ -0,0 +1,319 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s10 () Expr ((as Val Expr) 11))
+[GOOD] (define-fun s12 () Expr ((as Val Expr) 12))
+[GOOD] (define-fun s14 () Expr ((as Val Expr) 13))
+[GOOD] (define-fun s16 () Expr ((as Val Expr) 14))
+[GOOD] (define-fun s18 () Expr ((as Val Expr) 15))
+[GOOD] (define-fun s20 () Expr ((as Val Expr) 16))
+[GOOD] (define-fun s22 () Expr ((as Val Expr) 17))
+[GOOD] (define-fun s24 () Expr ((as Val Expr) 18))
+[GOOD] (define-fun s26 () Expr ((as Val Expr) 19))
+[GOOD] (define-fun s28 () Expr ((as Val Expr) 20))
+[GOOD] (define-fun s41 () String "a")
+[GOOD] (define-fun s44 () Int 0)
+[GOOD] (define-fun s45 () String "b")
+[GOOD] (define-fun s47 () String "c")
+[GOOD] (define-fun s51 () Int 1)
+[GOOD] (define-fun s52 () Int 2)
+[GOOD] (define-fun s55 () Int 10)
+[GOOD] (define-fun s58 () Int 3)
+[GOOD] (define-fun s61 () Int 4)
+[GOOD] (define-fun s64 () Int 5)
+[GOOD] (define-fun s65 () Int 6)
+[GOOD] (define-fun s279 () Int 50)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] (declare-fun s1 () Expr)
+[GOOD] (declare-fun s2 () Expr)
+[GOOD] (declare-fun s3 () Expr)
+[GOOD] (declare-fun s4 () Expr)
+[GOOD] (declare-fun s5 () Expr)
+[GOOD] (declare-fun s6 () Expr)
+[GOOD] (declare-fun s7 () Expr)
+[GOOD] (declare-fun s8 () Expr)
+[GOOD] (declare-fun s9 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s11 () Bool (= s0 s10))
+[GOOD] (define-fun s13 () Bool (= s1 s12))
+[GOOD] (define-fun s15 () Bool (= s2 s14))
+[GOOD] (define-fun s17 () Bool (= s3 s16))
+[GOOD] (define-fun s19 () Bool (= s4 s18))
+[GOOD] (define-fun s21 () Bool (= s5 s20))
+[GOOD] (define-fun s23 () Bool (= s6 s22))
+[GOOD] (define-fun s25 () Bool (= s7 s24))
+[GOOD] (define-fun s27 () Bool (= s8 s26))
+[GOOD] (define-fun s29 () Bool (= s9 s28))
+[GOOD] (define-fun s30 () Bool (and s27 s29))
+[GOOD] (define-fun s31 () Bool (and s25 s30))
+[GOOD] (define-fun s32 () Bool (and s23 s31))
+[GOOD] (define-fun s33 () Bool (and s21 s32))
+[GOOD] (define-fun s34 () Bool (and s19 s33))
+[GOOD] (define-fun s35 () Bool (and s17 s34))
+[GOOD] (define-fun s36 () Bool (and s15 s35))
+[GOOD] (define-fun s37 () Bool (and s13 s36))
+[GOOD] (define-fun s38 () Bool (and s11 s37))
+[GOOD] (define-fun s39 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s40 () String (getVar_1 s0))
+[GOOD] (define-fun s42 () Bool (= s40 s41))
+[GOOD] (define-fun s43 () Bool (and s39 s42))
+[GOOD] (define-fun s46 () Bool (= s40 s45))
+[GOOD] (define-fun s48 () Bool (= s40 s47))
+[GOOD] (define-fun s49 () Bool (or s46 s48))
+[GOOD] (define-fun s50 () Bool (and s39 s49))
+[GOOD] (define-fun s53 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s54 () Int (getVal_1 s0))
+[GOOD] (define-fun s56 () Bool (< s54 s55))
+[GOOD] (define-fun s57 () Bool (and s53 s56))
+[GOOD] (define-fun s59 () Bool (= s54 s55))
+[GOOD] (define-fun s60 () Bool (and s53 s59))
+[GOOD] (define-fun s62 () Bool (> s54 s55))
+[GOOD] (define-fun s63 () Bool (and s53 s62))
+[GOOD] (define-fun s66 () Int (ite s63 s64 s65))
+[GOOD] (define-fun s67 () Int (ite s60 s61 s66))
+[GOOD] (define-fun s68 () Int (ite s57 s58 s67))
+[GOOD] (define-fun s69 () Int (ite s39 s52 s68))
+[GOOD] (define-fun s70 () Int (ite s50 s51 s69))
+[GOOD] (define-fun s71 () Int (ite s43 s44 s70))
+[GOOD] (define-fun s72 () Bool ((as is-Var Bool) s1))
+[GOOD] (define-fun s73 () String (getVar_1 s1))
+[GOOD] (define-fun s74 () Bool (= s41 s73))
+[GOOD] (define-fun s75 () Bool (and s72 s74))
+[GOOD] (define-fun s76 () Bool (= s45 s73))
+[GOOD] (define-fun s77 () Bool (= s47 s73))
+[GOOD] (define-fun s78 () Bool (or s76 s77))
+[GOOD] (define-fun s79 () Bool (and s72 s78))
+[GOOD] (define-fun s80 () Bool ((as is-Val Bool) s1))
+[GOOD] (define-fun s81 () Int (getVal_1 s1))
+[GOOD] (define-fun s82 () Bool (< s81 s55))
+[GOOD] (define-fun s83 () Bool (and s80 s82))
+[GOOD] (define-fun s84 () Bool (= s55 s81))
+[GOOD] (define-fun s85 () Bool (and s80 s84))
+[GOOD] (define-fun s86 () Bool (> s81 s55))
+[GOOD] (define-fun s87 () Bool (and s80 s86))
+[GOOD] (define-fun s88 () Int (ite s87 s64 s65))
+[GOOD] (define-fun s89 () Int (ite s85 s61 s88))
+[GOOD] (define-fun s90 () Int (ite s83 s58 s89))
+[GOOD] (define-fun s91 () Int (ite s72 s52 s90))
+[GOOD] (define-fun s92 () Int (ite s79 s51 s91))
+[GOOD] (define-fun s93 () Int (ite s75 s44 s92))
+[GOOD] (define-fun s94 () Int (+ s71 s93))
+[GOOD] (define-fun s95 () Bool ((as is-Var Bool) s2))
+[GOOD] (define-fun s96 () String (getVar_1 s2))
+[GOOD] (define-fun s97 () Bool (= s41 s96))
+[GOOD] (define-fun s98 () Bool (and s95 s97))
+[GOOD] (define-fun s99 () Bool (= s45 s96))
+[GOOD] (define-fun s100 () Bool (= s47 s96))
+[GOOD] (define-fun s101 () Bool (or s99 s100))
+[GOOD] (define-fun s102 () Bool (and s95 s101))
+[GOOD] (define-fun s103 () Bool ((as is-Val Bool) s2))
+[GOOD] (define-fun s104 () Int (getVal_1 s2))
+[GOOD] (define-fun s105 () Bool (< s104 s55))
+[GOOD] (define-fun s106 () Bool (and s103 s105))
+[GOOD] (define-fun s107 () Bool (= s55 s104))
+[GOOD] (define-fun s108 () Bool (and s103 s107))
+[GOOD] (define-fun s109 () Bool (> s104 s55))
+[GOOD] (define-fun s110 () Bool (and s103 s109))
+[GOOD] (define-fun s111 () Int (ite s110 s64 s65))
+[GOOD] (define-fun s112 () Int (ite s108 s61 s111))
+[GOOD] (define-fun s113 () Int (ite s106 s58 s112))
+[GOOD] (define-fun s114 () Int (ite s95 s52 s113))
+[GOOD] (define-fun s115 () Int (ite s102 s51 s114))
+[GOOD] (define-fun s116 () Int (ite s98 s44 s115))
+[GOOD] (define-fun s117 () Int (+ s94 s116))
+[GOOD] (define-fun s118 () Bool ((as is-Var Bool) s3))
+[GOOD] (define-fun s119 () String (getVar_1 s3))
+[GOOD] (define-fun s120 () Bool (= s41 s119))
+[GOOD] (define-fun s121 () Bool (and s118 s120))
+[GOOD] (define-fun s122 () Bool (= s45 s119))
+[GOOD] (define-fun s123 () Bool (= s47 s119))
+[GOOD] (define-fun s124 () Bool (or s122 s123))
+[GOOD] (define-fun s125 () Bool (and s118 s124))
+[GOOD] (define-fun s126 () Bool ((as is-Val Bool) s3))
+[GOOD] (define-fun s127 () Int (getVal_1 s3))
+[GOOD] (define-fun s128 () Bool (< s127 s55))
+[GOOD] (define-fun s129 () Bool (and s126 s128))
+[GOOD] (define-fun s130 () Bool (= s55 s127))
+[GOOD] (define-fun s131 () Bool (and s126 s130))
+[GOOD] (define-fun s132 () Bool (> s127 s55))
+[GOOD] (define-fun s133 () Bool (and s126 s132))
+[GOOD] (define-fun s134 () Int (ite s133 s64 s65))
+[GOOD] (define-fun s135 () Int (ite s131 s61 s134))
+[GOOD] (define-fun s136 () Int (ite s129 s58 s135))
+[GOOD] (define-fun s137 () Int (ite s118 s52 s136))
+[GOOD] (define-fun s138 () Int (ite s125 s51 s137))
+[GOOD] (define-fun s139 () Int (ite s121 s44 s138))
+[GOOD] (define-fun s140 () Int (+ s117 s139))
+[GOOD] (define-fun s141 () Bool ((as is-Var Bool) s4))
+[GOOD] (define-fun s142 () String (getVar_1 s4))
+[GOOD] (define-fun s143 () Bool (= s41 s142))
+[GOOD] (define-fun s144 () Bool (and s141 s143))
+[GOOD] (define-fun s145 () Bool (= s45 s142))
+[GOOD] (define-fun s146 () Bool (= s47 s142))
+[GOOD] (define-fun s147 () Bool (or s145 s146))
+[GOOD] (define-fun s148 () Bool (and s141 s147))
+[GOOD] (define-fun s149 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s150 () Int (getVal_1 s4))
+[GOOD] (define-fun s151 () Bool (< s150 s55))
+[GOOD] (define-fun s152 () Bool (and s149 s151))
+[GOOD] (define-fun s153 () Bool (= s55 s150))
+[GOOD] (define-fun s154 () Bool (and s149 s153))
+[GOOD] (define-fun s155 () Bool (> s150 s55))
+[GOOD] (define-fun s156 () Bool (and s149 s155))
+[GOOD] (define-fun s157 () Int (ite s156 s64 s65))
+[GOOD] (define-fun s158 () Int (ite s154 s61 s157))
+[GOOD] (define-fun s159 () Int (ite s152 s58 s158))
+[GOOD] (define-fun s160 () Int (ite s141 s52 s159))
+[GOOD] (define-fun s161 () Int (ite s148 s51 s160))
+[GOOD] (define-fun s162 () Int (ite s144 s44 s161))
+[GOOD] (define-fun s163 () Int (+ s140 s162))
+[GOOD] (define-fun s164 () Bool ((as is-Var Bool) s5))
+[GOOD] (define-fun s165 () String (getVar_1 s5))
+[GOOD] (define-fun s166 () Bool (= s41 s165))
+[GOOD] (define-fun s167 () Bool (and s164 s166))
+[GOOD] (define-fun s168 () Bool (= s45 s165))
+[GOOD] (define-fun s169 () Bool (= s47 s165))
+[GOOD] (define-fun s170 () Bool (or s168 s169))
+[GOOD] (define-fun s171 () Bool (and s164 s170))
+[GOOD] (define-fun s172 () Bool ((as is-Val Bool) s5))
+[GOOD] (define-fun s173 () Int (getVal_1 s5))
+[GOOD] (define-fun s174 () Bool (< s173 s55))
+[GOOD] (define-fun s175 () Bool (and s172 s174))
+[GOOD] (define-fun s176 () Bool (= s55 s173))
+[GOOD] (define-fun s177 () Bool (and s172 s176))
+[GOOD] (define-fun s178 () Bool (> s173 s55))
+[GOOD] (define-fun s179 () Bool (and s172 s178))
+[GOOD] (define-fun s180 () Int (ite s179 s64 s65))
+[GOOD] (define-fun s181 () Int (ite s177 s61 s180))
+[GOOD] (define-fun s182 () Int (ite s175 s58 s181))
+[GOOD] (define-fun s183 () Int (ite s164 s52 s182))
+[GOOD] (define-fun s184 () Int (ite s171 s51 s183))
+[GOOD] (define-fun s185 () Int (ite s167 s44 s184))
+[GOOD] (define-fun s186 () Int (+ s163 s185))
+[GOOD] (define-fun s187 () Bool ((as is-Var Bool) s6))
+[GOOD] (define-fun s188 () String (getVar_1 s6))
+[GOOD] (define-fun s189 () Bool (= s41 s188))
+[GOOD] (define-fun s190 () Bool (and s187 s189))
+[GOOD] (define-fun s191 () Bool (= s45 s188))
+[GOOD] (define-fun s192 () Bool (= s47 s188))
+[GOOD] (define-fun s193 () Bool (or s191 s192))
+[GOOD] (define-fun s194 () Bool (and s187 s193))
+[GOOD] (define-fun s195 () Bool ((as is-Val Bool) s6))
+[GOOD] (define-fun s196 () Int (getVal_1 s6))
+[GOOD] (define-fun s197 () Bool (< s196 s55))
+[GOOD] (define-fun s198 () Bool (and s195 s197))
+[GOOD] (define-fun s199 () Bool (= s55 s196))
+[GOOD] (define-fun s200 () Bool (and s195 s199))
+[GOOD] (define-fun s201 () Bool (> s196 s55))
+[GOOD] (define-fun s202 () Bool (and s195 s201))
+[GOOD] (define-fun s203 () Int (ite s202 s64 s65))
+[GOOD] (define-fun s204 () Int (ite s200 s61 s203))
+[GOOD] (define-fun s205 () Int (ite s198 s58 s204))
+[GOOD] (define-fun s206 () Int (ite s187 s52 s205))
+[GOOD] (define-fun s207 () Int (ite s194 s51 s206))
+[GOOD] (define-fun s208 () Int (ite s190 s44 s207))
+[GOOD] (define-fun s209 () Int (+ s186 s208))
+[GOOD] (define-fun s210 () Bool ((as is-Var Bool) s7))
+[GOOD] (define-fun s211 () String (getVar_1 s7))
+[GOOD] (define-fun s212 () Bool (= s41 s211))
+[GOOD] (define-fun s213 () Bool (and s210 s212))
+[GOOD] (define-fun s214 () Bool (= s45 s211))
+[GOOD] (define-fun s215 () Bool (= s47 s211))
+[GOOD] (define-fun s216 () Bool (or s214 s215))
+[GOOD] (define-fun s217 () Bool (and s210 s216))
+[GOOD] (define-fun s218 () Bool ((as is-Val Bool) s7))
+[GOOD] (define-fun s219 () Int (getVal_1 s7))
+[GOOD] (define-fun s220 () Bool (< s219 s55))
+[GOOD] (define-fun s221 () Bool (and s218 s220))
+[GOOD] (define-fun s222 () Bool (= s55 s219))
+[GOOD] (define-fun s223 () Bool (and s218 s222))
+[GOOD] (define-fun s224 () Bool (> s219 s55))
+[GOOD] (define-fun s225 () Bool (and s218 s224))
+[GOOD] (define-fun s226 () Int (ite s225 s64 s65))
+[GOOD] (define-fun s227 () Int (ite s223 s61 s226))
+[GOOD] (define-fun s228 () Int (ite s221 s58 s227))
+[GOOD] (define-fun s229 () Int (ite s210 s52 s228))
+[GOOD] (define-fun s230 () Int (ite s217 s51 s229))
+[GOOD] (define-fun s231 () Int (ite s213 s44 s230))
+[GOOD] (define-fun s232 () Int (+ s209 s231))
+[GOOD] (define-fun s233 () Bool ((as is-Var Bool) s8))
+[GOOD] (define-fun s234 () String (getVar_1 s8))
+[GOOD] (define-fun s235 () Bool (= s41 s234))
+[GOOD] (define-fun s236 () Bool (and s233 s235))
+[GOOD] (define-fun s237 () Bool (= s45 s234))
+[GOOD] (define-fun s238 () Bool (= s47 s234))
+[GOOD] (define-fun s239 () Bool (or s237 s238))
+[GOOD] (define-fun s240 () Bool (and s233 s239))
+[GOOD] (define-fun s241 () Bool ((as is-Val Bool) s8))
+[GOOD] (define-fun s242 () Int (getVal_1 s8))
+[GOOD] (define-fun s243 () Bool (< s242 s55))
+[GOOD] (define-fun s244 () Bool (and s241 s243))
+[GOOD] (define-fun s245 () Bool (= s55 s242))
+[GOOD] (define-fun s246 () Bool (and s241 s245))
+[GOOD] (define-fun s247 () Bool (> s242 s55))
+[GOOD] (define-fun s248 () Bool (and s241 s247))
+[GOOD] (define-fun s249 () Int (ite s248 s64 s65))
+[GOOD] (define-fun s250 () Int (ite s246 s61 s249))
+[GOOD] (define-fun s251 () Int (ite s244 s58 s250))
+[GOOD] (define-fun s252 () Int (ite s233 s52 s251))
+[GOOD] (define-fun s253 () Int (ite s240 s51 s252))
+[GOOD] (define-fun s254 () Int (ite s236 s44 s253))
+[GOOD] (define-fun s255 () Int (+ s232 s254))
+[GOOD] (define-fun s256 () Bool ((as is-Var Bool) s9))
+[GOOD] (define-fun s257 () String (getVar_1 s9))
+[GOOD] (define-fun s258 () Bool (= s41 s257))
+[GOOD] (define-fun s259 () Bool (and s256 s258))
+[GOOD] (define-fun s260 () Bool (= s45 s257))
+[GOOD] (define-fun s261 () Bool (= s47 s257))
+[GOOD] (define-fun s262 () Bool (or s260 s261))
+[GOOD] (define-fun s263 () Bool (and s256 s262))
+[GOOD] (define-fun s264 () Bool ((as is-Val Bool) s9))
+[GOOD] (define-fun s265 () Int (getVal_1 s9))
+[GOOD] (define-fun s266 () Bool (< s265 s55))
+[GOOD] (define-fun s267 () Bool (and s264 s266))
+[GOOD] (define-fun s268 () Bool (= s55 s265))
+[GOOD] (define-fun s269 () Bool (and s264 s268))
+[GOOD] (define-fun s270 () Bool (> s265 s55))
+[GOOD] (define-fun s271 () Bool (and s264 s270))
+[GOOD] (define-fun s272 () Int (ite s271 s64 s65))
+[GOOD] (define-fun s273 () Int (ite s269 s61 s272))
+[GOOD] (define-fun s274 () Int (ite s267 s58 s273))
+[GOOD] (define-fun s275 () Int (ite s256 s52 s274))
+[GOOD] (define-fun s276 () Int (ite s263 s51 s275))
+[GOOD] (define-fun s277 () Int (ite s259 s44 s276))
+[GOOD] (define-fun s278 () Int (+ s255 s277))
+[GOOD] (define-fun s280 () Bool (distinct s278 s279))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s38)
+[GOOD] (assert s280)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr12c.gold b/SBVTestSuite/GoldFiles/adt_expr12c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr12c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr13.gold b/SBVTestSuite/GoldFiles/adt_expr13.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr13.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Val Expr) 3))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s22 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr13c.gold b/SBVTestSuite/GoldFiles/adt_expr13c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr13c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr14.gold b/SBVTestSuite/GoldFiles/adt_expr14.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr14.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr14c.gold b/SBVTestSuite/GoldFiles/adt_expr14c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr14c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr15.gold b/SBVTestSuite/GoldFiles/adt_expr15.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr15.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr15c.gold b/SBVTestSuite/GoldFiles/adt_expr15c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr15c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr16.gold b/SBVTestSuite/GoldFiles/adt_expr16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr16.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Let Expr) "a" ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr16c.gold b/SBVTestSuite/GoldFiles/adt_expr16c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr16c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr17.gold b/SBVTestSuite/GoldFiles/adt_expr17.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr17.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Let Expr) "a" ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))) ((as Let Expr) "a" ((as Let Expr) "a" ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr17c.gold b/SBVTestSuite/GoldFiles/adt_expr17c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr17c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr18.gold b/SBVTestSuite/GoldFiles/adt_expr18.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr18.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Let Expr) "a" ((as Add Expr) ((as Let Expr) "a" ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))) ((as Let Expr) "a" ((as Let Expr) "a" ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))))) ((as Mul Expr) ((as Var Expr) "a") ((as Var Expr) "a"))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr18c.gold b/SBVTestSuite/GoldFiles/adt_expr18c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr18c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen00.gold b/SBVTestSuite/GoldFiles/adt_gen00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen00.gold
@@ -0,0 +1,144 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Seq String) (as seq.empty (Seq String)))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 12)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| :: [SString] -> Expr -> SBool [Recursive]
+[GOOD] (define-fun-rec |valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| ((l1_s0 (Seq String)) (l1_s1 Expr)) Bool
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s4 (getVar_1 l1_s1)))
+                                 (let ((l1_s5 (str.in_re l1_s4 (re.++ (re.range "a" "z") (re.* (re.union (re.range "a" "z") (re.range "A" "Z") (re.range "0" "9")))))))
+                                 (let ((l1_s6 (seq.unit l1_s4)))
+                                 (let ((l1_s7 (seq.contains l1_s0 l1_s6)))
+                                 (let ((l1_s8 (and l1_s5 l1_s7)))
+                                 (let ((l1_s9 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s10 (getAdd_1 l1_s1)))
+                                 (let ((l1_s11 (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (getAdd_2 l1_s1)))
+                                 (let ((l1_s13 (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| l1_s0 l1_s12)))
+                                 (let ((l1_s14 (and l1_s11 l1_s13)))
+                                 (let ((l1_s15 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s16 (getMul_1 l1_s1)))
+                                 (let ((l1_s17 (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (getMul_2 l1_s1)))
+                                 (let ((l1_s19 (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| l1_s0 l1_s18)))
+                                 (let ((l1_s20 (and l1_s17 l1_s19)))
+                                 (let ((l1_s21 (getLet_1 l1_s1)))
+                                 (let ((l1_s22 (str.in_re l1_s21 (re.++ (re.range "a" "z") (re.* (re.union (re.range "a" "z") (re.range "A" "Z") (re.range "0" "9")))))))
+                                 (let ((l1_s23 (getLet_2 l1_s1)))
+                                 (let ((l1_s24 (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| l1_s0 l1_s23)))
+                                 (let ((l1_s25 (seq.unit l1_s21)))
+                                 (let ((l1_s26 (seq.++ l1_s25 l1_s0)))
+                                 (let ((l1_s27 (getLet_3 l1_s1)))
+                                 (let ((l1_s28 (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| l1_s26 l1_s27)))
+                                 (let ((l1_s29 (and l1_s24 l1_s28)))
+                                 (let ((l1_s30 (and l1_s22 l1_s29)))
+                                 (let ((l1_s31 (ite l1_s15 l1_s20 l1_s30)))
+                                 (let ((l1_s32 (ite l1_s9 l1_s14 l1_s31)))
+                                 (let ((l1_s33 (ite l1_s3 l1_s8 l1_s32)))
+                                 (let ((l1_s34 (or l1_s2 l1_s33)))
+                                 l1_s34))))))))))))))))))))))))))))))))))
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s9 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s6 (proj_1_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s7 (= l2_s1 l2_s6)))
+                                                 (let ((l2_s8 (proj_2_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s10 (- l2_s2 l2_s9)))
+                                                 (let ((l2_s11 (seq.extract l2_s0 l2_s9 l2_s10)))
+                                                 (let ((l2_s12 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s11 l2_s1)))
+                                                 (let ((l2_s13 (ite l2_s7 l2_s8 l2_s12)))
+                                                 (let ((l2_s14 (ite l2_s4 l2_s3 l2_s13)))
+                                                 l2_s14))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| s1 s0))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s8 () Expr (getLet_3 s0))
+[GOOD] (define-fun s9 () Bool ((as is-Let Bool) s8))
+[GOOD] (define-fun s10 () Expr (getLet_3 s8))
+[GOOD] (define-fun s11 () Bool ((as is-Add Bool) s10))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[GOOD] (assert s7)
+[GOOD] (assert s9)
+[GOOD] (assert s11)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Let "k" (Val 7) (Let "c" (Val 6) (Add (Var "c") (Var "c"))))))
+
+Got: (let k = 7 in (let c = 6 in (c + c)))
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen01.gold b/SBVTestSuite/GoldFiles/adt_gen01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen01.gold
@@ -0,0 +1,83 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] (define-fun s43 () Int (- 1))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s44 () Bool (= s42 s43))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s44)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen02.gold b/SBVTestSuite/GoldFiles/adt_gen02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen02.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s6 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Var "a")))
+
+Got: a
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen03.gold b/SBVTestSuite/GoldFiles/adt_gen03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen03.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s13 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Var "b")))
+
+Got: b
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen04.gold b/SBVTestSuite/GoldFiles/adt_gen04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen04.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s14 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Var "")))
+
+Got: 
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen05.gold b/SBVTestSuite/GoldFiles/adt_gen05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen05.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s20 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Val 0)))
+
+Got: 0
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen06.gold b/SBVTestSuite/GoldFiles/adt_gen06.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen06.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s23 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Val 10)))
+
+Got: 10
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen07.gold b/SBVTestSuite/GoldFiles/adt_gen07.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen07.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s26 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Val 11)))
+
+Got: 11
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen08.gold b/SBVTestSuite/GoldFiles/adt_gen08.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen08.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s28 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Add (Val 3) (Val 2))))
+
+Got: (3 + 2)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen09.gold b/SBVTestSuite/GoldFiles/adt_gen09.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen09.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s30 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Mul (Val 3) (Val 2))))
+
+Got: (3 * 2)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen10.gold b/SBVTestSuite/GoldFiles/adt_gen10.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen10.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s32 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Let "!0!" (Val 3) (Val 2))))
+
+Got: (let !0! = 3 in 2)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen11.gold b/SBVTestSuite/GoldFiles/adt_gen11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen11.gold
@@ -0,0 +1,83 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] (define-fun s43 () Int 9)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s44 () Bool (= s42 s43))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s44)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen12.gold b/SBVTestSuite/GoldFiles/adt_gen12.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen12.gold
@@ -0,0 +1,82 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s33 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_mr00.gold b/SBVTestSuite/GoldFiles/adt_mr00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_mr00.gold
@@ -0,0 +1,68 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (var val) (
+           (Con (getCon_1 val))
+           (Var (getVar_1 var))
+           (Add (getAdd_1 (Expr var val)) (getAdd_2 (Expr var val)))
+           (Mul (getMul_1 (Expr var val)) (getMul_2 (Expr var val)))
+       )))
+[GOOD] ; User defined ADT: Stmt
+[GOOD] (declare-datatype Stmt (par (var val) (
+           (Assign (getAssign_1 var) (getAssign_2 (Expr var val)))
+           (Seq (getSeq_1 (Stmt var val)) (getSeq_2 (Stmt var val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Stmt String Int)) ; tracks user variable "p"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Seq Bool) s0))
+[GOOD] (define-fun s2 () (Stmt String Int) (getSeq_2 s0))
+[GOOD] (define-fun s3 () Bool ((as is-Seq Bool) s2))
+[GOOD] (define-fun s4 () (Stmt String Int) (getSeq_2 s2))
+[GOOD] (define-fun s5 () Bool ((as is-Seq Bool) s4))
+[GOOD] (define-fun s6 () (Stmt String Int) (getSeq_2 s4))
+[GOOD] (define-fun s7 () Bool ((as is-Assign Bool) s6))
+[GOOD] (define-fun s8 () (Expr String Int) (getAssign_2 s6))
+[GOOD] (define-fun s9 () Bool ((as is-Add Bool) s8))
+[GOOD] (define-fun s10 () (Expr String Int) (getAdd_1 s8))
+[GOOD] (define-fun s11 () Bool ((as is-Var Bool) s10))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[GOOD] (assert s7)
+[GOOD] (assert s9)
+[GOOD] (assert s11)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Seq (Assign "!2!" (Con 3))
+            (Seq (Assign "!4!" (Con 5))
+                 (Seq (Assign "!3!" (Con 4)) (Assign "!0!" (Add (Var "!1!") (Con 2))))))))
+
+Got:
+!2! := 3;
+!4! := 5;
+!3! := 4;
+!0! := (!1! + 2)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_mr01.gold b/SBVTestSuite/GoldFiles/adt_mr01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_mr01.gold
@@ -0,0 +1,73 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (var val) (
+           (Con (getCon_1 val))
+           (Var (getVar_1 var))
+           (Add (getAdd_1 (Expr var val)) (getAdd_2 (Expr var val)))
+           (Mul (getMul_1 (Expr var val)) (getMul_2 (Expr var val)))
+       )))
+[GOOD] ; User defined ADT: Stmt
+[GOOD] (declare-datatype Stmt (par (var val) (
+           (Assign (getAssign_1 var) (getAssign_2 (Expr var val)))
+           (Seq (getSeq_1 (Stmt var val)) (getSeq_2 (Stmt var val)))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Stmt String (Maybe (Either Int Bool)))) ; tracks user variable "p"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Assign Bool) s0))
+[GOOD] (define-fun s2 () (Expr String (Maybe (Either Int Bool))) (getAssign_2 s0))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s2))
+[GOOD] (define-fun s4 () (Expr String (Maybe (Either Int Bool))) (getAdd_1 s2))
+[GOOD] (define-fun s5 () Bool ((as is-Con Bool) s4))
+[GOOD] (define-fun s6 () (Expr String (Maybe (Either Int Bool))) (getAdd_2 s2))
+[GOOD] (define-fun s7 () Bool ((as is-Con Bool) s6))
+[GOOD] (define-fun s8 () (Maybe (Either Int Bool)) (getCon_1 s4))
+[GOOD] (define-fun s9 () Bool ((as is-Nothing Bool) s8))
+[GOOD] (define-fun s10 () (Maybe (Either Int Bool)) (getCon_1 s6))
+[GOOD] (define-fun s11 () Bool ((as is-Just Bool) s10))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[GOOD] (assert s7)
+[GOOD] (assert s9)
+[GOOD] (assert s11)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Assign "!0!" (Add (Con Nothing) (Con (Just (Left 2)))))))
+
+Got:
+!0! := (Nothing + Just (Left 2))
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_mr02.gold b/SBVTestSuite/GoldFiles/adt_mr02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_mr02.gold
@@ -0,0 +1,50 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: A
+[GOOD] (declare-datatype A (par (a b) (
+           (Aa (getAa_1 a))
+           (Ab (getAb_1 b))
+           (Aab (getAab_1 a) (getAab_2 b))
+           (A2 (getA2_1 (A b String)))
+           (A3 (getA3_1 (A b a)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (A Int Bool)) ; tracks user variable "p"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-A2 Bool) s0))
+[GOOD] (define-fun s2 () (A Bool String) (getA2_1 s0))
+[GOOD] (define-fun s3 () Bool ((as is-A2 Bool) s2))
+[GOOD] (define-fun s4 () (A String String) (getA2_1 s2))
+[GOOD] (define-fun s5 () Bool ((as is-Aa Bool) s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (A2 ((as A2 (A Bool String)) (Aa "!0!")))))
+
+Got:
+A2 {a2 = A2 {a2 = Aa {aa = "!0!"}}}
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_mr03.gold b/SBVTestSuite/GoldFiles/adt_mr03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_mr03.gold
@@ -0,0 +1,47 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: A
+[GOOD] (declare-datatype A (par (a b) (
+           (Aa (getAa_1 a))
+           (Ab (getAb_1 b))
+           (Aab (getAab_1 a) (getAab_2 b))
+           (A2 (getA2_1 (A b String)))
+           (A3 (getA3_1 (A b a)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (A Int Bool)) ; tracks user variable "p"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-A3 Bool) s0))
+[GOOD] (define-fun s2 () (A Bool Int) (getA3_1 s0))
+[GOOD] (define-fun s3 () Bool ((as is-Ab Bool) s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (A3 (Ab 2))))
+
+Got:
+A3 {a3 = Ab {ab = 2}}
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_mr04.gold b/SBVTestSuite/GoldFiles/adt_mr04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_mr04.gold
@@ -0,0 +1,50 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: A
+[GOOD] (declare-datatype A (par (a b) (
+           (Aa (getAa_1 a))
+           (Ab (getAb_1 b))
+           (Aab (getAab_1 a) (getAab_2 b))
+           (A2 (getA2_1 (A b String)))
+           (A3 (getA3_1 (A b a)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (A Int (A (_ FloatingPoint  8 24) Bool))) ; tracks user variable "p"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-A2 Bool) s0))
+[GOOD] (define-fun s2 () (A (A (_ FloatingPoint  8 24) Bool) String) (getA2_1 s0))
+[GOOD] (define-fun s3 () Bool ((as is-A3 Bool) s2))
+[GOOD] (define-fun s4 () (A String (A (_ FloatingPoint  8 24) Bool)) (getA3_1 s2))
+[GOOD] (define-fun s5 () Bool ((as is-Aab Bool) s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 ((as A2 (A Int (A (_ FloatingPoint 8 24) Bool))) (A3 (Aab "!0!" (Ab false))))))
+
+Got:
+A2 {a2 = A3 {a3 = Aab {aba = "!0!", abb = Ab {ab = False}}}}
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pchk01.gold b/SBVTestSuite/GoldFiles/adt_pchk01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pchk01.gold
@@ -0,0 +1,40 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: A
+[GOOD] (declare-datatype A (
+           (A (getA_1 Int))
+           (B (getB_1 (_ BitVec 8)))
+           (C (getC_1 A) (getC_2 A))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () A ((as A A) 13))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () A) ; tracks user variable "res"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (A 13)))
+Result: A 13
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr00.gold b/SBVTestSuite/GoldFiles/adt_pexpr00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr00.gold
@@ -0,0 +1,96 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Val (Expr String Int)) 3))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 3)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s9 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s6 (proj_1_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s7 (= l2_s1 l2_s6)))
+                                                 (let ((l2_s8 (proj_2_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s10 (- l2_s2 l2_s9)))
+                                                 (let ((l2_s11 (seq.extract l2_s0 l2_s9 l2_s10)))
+                                                 (let ((l2_s12 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s11 l2_s1)))
+                                                 (let ((l2_s13 (ite l2_s7 l2_s8 l2_s12)))
+                                                 (let ((l2_s14 (ite l2_s4 l2_s3 l2_s13)))
+                                                 l2_s14))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| :: [(SString, SInteger)] -> Expr String Integer -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 (Expr String Int))) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr00c.gold b/SBVTestSuite/GoldFiles/adt_pexpr00c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr00c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr01.gold b/SBVTestSuite/GoldFiles/adt_pexpr01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr01.gold
@@ -0,0 +1,96 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 7)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s9 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s6 (proj_1_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s7 (= l2_s1 l2_s6)))
+                                                 (let ((l2_s8 (proj_2_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s10 (- l2_s2 l2_s9)))
+                                                 (let ((l2_s11 (seq.extract l2_s0 l2_s9 l2_s10)))
+                                                 (let ((l2_s12 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s11 l2_s1)))
+                                                 (let ((l2_s13 (ite l2_s7 l2_s8 l2_s12)))
+                                                 (let ((l2_s14 (ite l2_s4 l2_s3 l2_s13)))
+                                                 l2_s14))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| :: [(SString, SInteger)] -> Expr String Integer -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 (Expr String Int))) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr01c.gold b/SBVTestSuite/GoldFiles/adt_pexpr01c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr01c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr02.gold b/SBVTestSuite/GoldFiles/adt_pexpr02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr02.gold
@@ -0,0 +1,96 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 21)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s9 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s6 (proj_1_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s7 (= l2_s1 l2_s6)))
+                                                 (let ((l2_s8 (proj_2_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s10 (- l2_s2 l2_s9)))
+                                                 (let ((l2_s11 (seq.extract l2_s0 l2_s9 l2_s10)))
+                                                 (let ((l2_s12 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s11 l2_s1)))
+                                                 (let ((l2_s13 (ite l2_s7 l2_s8 l2_s12)))
+                                                 (let ((l2_s14 (ite l2_s4 l2_s3 l2_s13)))
+                                                 l2_s14))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| :: [(SString, SInteger)] -> Expr String Integer -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 (Expr String Int))) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr02c.gold b/SBVTestSuite/GoldFiles/adt_pexpr02c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr02c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr03.gold b/SBVTestSuite/GoldFiles/adt_pexpr03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr03.gold
@@ -0,0 +1,96 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Let (Expr String Int)) "a" ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 28)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s9 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s6 (proj_1_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s7 (= l2_s1 l2_s6)))
+                                                 (let ((l2_s8 (proj_2_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s10 (- l2_s2 l2_s9)))
+                                                 (let ((l2_s11 (seq.extract l2_s0 l2_s9 l2_s10)))
+                                                 (let ((l2_s12 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s11 l2_s1)))
+                                                 (let ((l2_s13 (ite l2_s7 l2_s8 l2_s12)))
+                                                 (let ((l2_s14 (ite l2_s4 l2_s3 l2_s13)))
+                                                 l2_s14))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| :: [(SString, SInteger)] -> Expr String Integer -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 (Expr String Int))) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr03c.gold b/SBVTestSuite/GoldFiles/adt_pexpr03c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr03c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr04.gold b/SBVTestSuite/GoldFiles/adt_pexpr04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr04.gold
@@ -0,0 +1,30 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 63)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "res"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 63))
+Result: 63
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr05.gold b/SBVTestSuite/GoldFiles/adt_pexpr05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr05.gold
@@ -0,0 +1,30 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 3969)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "res"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3969))
+Result: 3969
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr06.gold b/SBVTestSuite/GoldFiles/adt_pexpr06.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr06.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Var (Expr String Int)) "a"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s8 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr06c.gold b/SBVTestSuite/GoldFiles/adt_pexpr06c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr06c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr07.gold b/SBVTestSuite/GoldFiles/adt_pexpr07.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr07.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Var (Expr String Int)) "b"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s15 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr07c.gold b/SBVTestSuite/GoldFiles/adt_pexpr07c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr07c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr08.gold b/SBVTestSuite/GoldFiles/adt_pexpr08.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr08.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Var (Expr String Int)) "c"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s15 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr08c.gold b/SBVTestSuite/GoldFiles/adt_pexpr08c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr08c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr09.gold b/SBVTestSuite/GoldFiles/adt_pexpr09.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr09.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Var (Expr String Int)) "d"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s16 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr09c.gold b/SBVTestSuite/GoldFiles/adt_pexpr09c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr09c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr10.gold b/SBVTestSuite/GoldFiles/adt_pexpr10.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr10.gold
@@ -0,0 +1,454 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s15 () (Expr String Int) ((as Val (Expr String Int)) (- 5)))
+[GOOD] (define-fun s17 () (Expr String Int) ((as Val (Expr String Int)) (- 4)))
+[GOOD] (define-fun s19 () (Expr String Int) ((as Val (Expr String Int)) (- 3)))
+[GOOD] (define-fun s21 () (Expr String Int) ((as Val (Expr String Int)) (- 2)))
+[GOOD] (define-fun s23 () (Expr String Int) ((as Val (Expr String Int)) (- 1)))
+[GOOD] (define-fun s25 () (Expr String Int) ((as Val (Expr String Int)) 0))
+[GOOD] (define-fun s27 () (Expr String Int) ((as Val (Expr String Int)) 1))
+[GOOD] (define-fun s29 () (Expr String Int) ((as Val (Expr String Int)) 2))
+[GOOD] (define-fun s31 () (Expr String Int) ((as Val (Expr String Int)) 3))
+[GOOD] (define-fun s33 () (Expr String Int) ((as Val (Expr String Int)) 4))
+[GOOD] (define-fun s35 () (Expr String Int) ((as Val (Expr String Int)) 5))
+[GOOD] (define-fun s37 () (Expr String Int) ((as Val (Expr String Int)) 6))
+[GOOD] (define-fun s39 () (Expr String Int) ((as Val (Expr String Int)) 7))
+[GOOD] (define-fun s41 () (Expr String Int) ((as Val (Expr String Int)) 8))
+[GOOD] (define-fun s43 () (Expr String Int) ((as Val (Expr String Int)) 9))
+[GOOD] (define-fun s61 () String "a")
+[GOOD] (define-fun s64 () Int 0)
+[GOOD] (define-fun s65 () String "b")
+[GOOD] (define-fun s67 () String "c")
+[GOOD] (define-fun s71 () Int 1)
+[GOOD] (define-fun s72 () Int 2)
+[GOOD] (define-fun s75 () Int 10)
+[GOOD] (define-fun s78 () Int 3)
+[GOOD] (define-fun s81 () Int 4)
+[GOOD] (define-fun s84 () Int 5)
+[GOOD] (define-fun s85 () Int 6)
+[GOOD] (define-fun s414 () Int 45)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] (declare-fun s1 () (Expr String Int))
+[GOOD] (declare-fun s2 () (Expr String Int))
+[GOOD] (declare-fun s3 () (Expr String Int))
+[GOOD] (declare-fun s4 () (Expr String Int))
+[GOOD] (declare-fun s5 () (Expr String Int))
+[GOOD] (declare-fun s6 () (Expr String Int))
+[GOOD] (declare-fun s7 () (Expr String Int))
+[GOOD] (declare-fun s8 () (Expr String Int))
+[GOOD] (declare-fun s9 () (Expr String Int))
+[GOOD] (declare-fun s10 () (Expr String Int))
+[GOOD] (declare-fun s11 () (Expr String Int))
+[GOOD] (declare-fun s12 () (Expr String Int))
+[GOOD] (declare-fun s13 () (Expr String Int))
+[GOOD] (declare-fun s14 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s16 () Bool (= s0 s15))
+[GOOD] (define-fun s18 () Bool (= s1 s17))
+[GOOD] (define-fun s20 () Bool (= s2 s19))
+[GOOD] (define-fun s22 () Bool (= s3 s21))
+[GOOD] (define-fun s24 () Bool (= s4 s23))
+[GOOD] (define-fun s26 () Bool (= s5 s25))
+[GOOD] (define-fun s28 () Bool (= s6 s27))
+[GOOD] (define-fun s30 () Bool (= s7 s29))
+[GOOD] (define-fun s32 () Bool (= s8 s31))
+[GOOD] (define-fun s34 () Bool (= s9 s33))
+[GOOD] (define-fun s36 () Bool (= s10 s35))
+[GOOD] (define-fun s38 () Bool (= s11 s37))
+[GOOD] (define-fun s40 () Bool (= s12 s39))
+[GOOD] (define-fun s42 () Bool (= s13 s41))
+[GOOD] (define-fun s44 () Bool (= s14 s43))
+[GOOD] (define-fun s45 () Bool (and s42 s44))
+[GOOD] (define-fun s46 () Bool (and s40 s45))
+[GOOD] (define-fun s47 () Bool (and s38 s46))
+[GOOD] (define-fun s48 () Bool (and s36 s47))
+[GOOD] (define-fun s49 () Bool (and s34 s48))
+[GOOD] (define-fun s50 () Bool (and s32 s49))
+[GOOD] (define-fun s51 () Bool (and s30 s50))
+[GOOD] (define-fun s52 () Bool (and s28 s51))
+[GOOD] (define-fun s53 () Bool (and s26 s52))
+[GOOD] (define-fun s54 () Bool (and s24 s53))
+[GOOD] (define-fun s55 () Bool (and s22 s54))
+[GOOD] (define-fun s56 () Bool (and s20 s55))
+[GOOD] (define-fun s57 () Bool (and s18 s56))
+[GOOD] (define-fun s58 () Bool (and s16 s57))
+[GOOD] (define-fun s59 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s60 () String (getVar_1 s0))
+[GOOD] (define-fun s62 () Bool (= s60 s61))
+[GOOD] (define-fun s63 () Bool (and s59 s62))
+[GOOD] (define-fun s66 () Bool (= s60 s65))
+[GOOD] (define-fun s68 () Bool (= s60 s67))
+[GOOD] (define-fun s69 () Bool (or s66 s68))
+[GOOD] (define-fun s70 () Bool (and s59 s69))
+[GOOD] (define-fun s73 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s74 () Int (getVal_1 s0))
+[GOOD] (define-fun s76 () Bool (< s74 s75))
+[GOOD] (define-fun s77 () Bool (and s73 s76))
+[GOOD] (define-fun s79 () Bool (= s74 s75))
+[GOOD] (define-fun s80 () Bool (and s73 s79))
+[GOOD] (define-fun s82 () Bool (> s74 s75))
+[GOOD] (define-fun s83 () Bool (and s73 s82))
+[GOOD] (define-fun s86 () Int (ite s83 s84 s85))
+[GOOD] (define-fun s87 () Int (ite s80 s81 s86))
+[GOOD] (define-fun s88 () Int (ite s77 s78 s87))
+[GOOD] (define-fun s89 () Int (ite s59 s72 s88))
+[GOOD] (define-fun s90 () Int (ite s70 s71 s89))
+[GOOD] (define-fun s91 () Int (ite s63 s64 s90))
+[GOOD] (define-fun s92 () Bool ((as is-Var Bool) s1))
+[GOOD] (define-fun s93 () String (getVar_1 s1))
+[GOOD] (define-fun s94 () Bool (= s61 s93))
+[GOOD] (define-fun s95 () Bool (and s92 s94))
+[GOOD] (define-fun s96 () Bool (= s65 s93))
+[GOOD] (define-fun s97 () Bool (= s67 s93))
+[GOOD] (define-fun s98 () Bool (or s96 s97))
+[GOOD] (define-fun s99 () Bool (and s92 s98))
+[GOOD] (define-fun s100 () Bool ((as is-Val Bool) s1))
+[GOOD] (define-fun s101 () Int (getVal_1 s1))
+[GOOD] (define-fun s102 () Bool (< s101 s75))
+[GOOD] (define-fun s103 () Bool (and s100 s102))
+[GOOD] (define-fun s104 () Bool (= s75 s101))
+[GOOD] (define-fun s105 () Bool (and s100 s104))
+[GOOD] (define-fun s106 () Bool (> s101 s75))
+[GOOD] (define-fun s107 () Bool (and s100 s106))
+[GOOD] (define-fun s108 () Int (ite s107 s84 s85))
+[GOOD] (define-fun s109 () Int (ite s105 s81 s108))
+[GOOD] (define-fun s110 () Int (ite s103 s78 s109))
+[GOOD] (define-fun s111 () Int (ite s92 s72 s110))
+[GOOD] (define-fun s112 () Int (ite s99 s71 s111))
+[GOOD] (define-fun s113 () Int (ite s95 s64 s112))
+[GOOD] (define-fun s114 () Int (+ s91 s113))
+[GOOD] (define-fun s115 () Bool ((as is-Var Bool) s2))
+[GOOD] (define-fun s116 () String (getVar_1 s2))
+[GOOD] (define-fun s117 () Bool (= s61 s116))
+[GOOD] (define-fun s118 () Bool (and s115 s117))
+[GOOD] (define-fun s119 () Bool (= s65 s116))
+[GOOD] (define-fun s120 () Bool (= s67 s116))
+[GOOD] (define-fun s121 () Bool (or s119 s120))
+[GOOD] (define-fun s122 () Bool (and s115 s121))
+[GOOD] (define-fun s123 () Bool ((as is-Val Bool) s2))
+[GOOD] (define-fun s124 () Int (getVal_1 s2))
+[GOOD] (define-fun s125 () Bool (< s124 s75))
+[GOOD] (define-fun s126 () Bool (and s123 s125))
+[GOOD] (define-fun s127 () Bool (= s75 s124))
+[GOOD] (define-fun s128 () Bool (and s123 s127))
+[GOOD] (define-fun s129 () Bool (> s124 s75))
+[GOOD] (define-fun s130 () Bool (and s123 s129))
+[GOOD] (define-fun s131 () Int (ite s130 s84 s85))
+[GOOD] (define-fun s132 () Int (ite s128 s81 s131))
+[GOOD] (define-fun s133 () Int (ite s126 s78 s132))
+[GOOD] (define-fun s134 () Int (ite s115 s72 s133))
+[GOOD] (define-fun s135 () Int (ite s122 s71 s134))
+[GOOD] (define-fun s136 () Int (ite s118 s64 s135))
+[GOOD] (define-fun s137 () Int (+ s114 s136))
+[GOOD] (define-fun s138 () Bool ((as is-Var Bool) s3))
+[GOOD] (define-fun s139 () String (getVar_1 s3))
+[GOOD] (define-fun s140 () Bool (= s61 s139))
+[GOOD] (define-fun s141 () Bool (and s138 s140))
+[GOOD] (define-fun s142 () Bool (= s65 s139))
+[GOOD] (define-fun s143 () Bool (= s67 s139))
+[GOOD] (define-fun s144 () Bool (or s142 s143))
+[GOOD] (define-fun s145 () Bool (and s138 s144))
+[GOOD] (define-fun s146 () Bool ((as is-Val Bool) s3))
+[GOOD] (define-fun s147 () Int (getVal_1 s3))
+[GOOD] (define-fun s148 () Bool (< s147 s75))
+[GOOD] (define-fun s149 () Bool (and s146 s148))
+[GOOD] (define-fun s150 () Bool (= s75 s147))
+[GOOD] (define-fun s151 () Bool (and s146 s150))
+[GOOD] (define-fun s152 () Bool (> s147 s75))
+[GOOD] (define-fun s153 () Bool (and s146 s152))
+[GOOD] (define-fun s154 () Int (ite s153 s84 s85))
+[GOOD] (define-fun s155 () Int (ite s151 s81 s154))
+[GOOD] (define-fun s156 () Int (ite s149 s78 s155))
+[GOOD] (define-fun s157 () Int (ite s138 s72 s156))
+[GOOD] (define-fun s158 () Int (ite s145 s71 s157))
+[GOOD] (define-fun s159 () Int (ite s141 s64 s158))
+[GOOD] (define-fun s160 () Int (+ s137 s159))
+[GOOD] (define-fun s161 () Bool ((as is-Var Bool) s4))
+[GOOD] (define-fun s162 () String (getVar_1 s4))
+[GOOD] (define-fun s163 () Bool (= s61 s162))
+[GOOD] (define-fun s164 () Bool (and s161 s163))
+[GOOD] (define-fun s165 () Bool (= s65 s162))
+[GOOD] (define-fun s166 () Bool (= s67 s162))
+[GOOD] (define-fun s167 () Bool (or s165 s166))
+[GOOD] (define-fun s168 () Bool (and s161 s167))
+[GOOD] (define-fun s169 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s170 () Int (getVal_1 s4))
+[GOOD] (define-fun s171 () Bool (< s170 s75))
+[GOOD] (define-fun s172 () Bool (and s169 s171))
+[GOOD] (define-fun s173 () Bool (= s75 s170))
+[GOOD] (define-fun s174 () Bool (and s169 s173))
+[GOOD] (define-fun s175 () Bool (> s170 s75))
+[GOOD] (define-fun s176 () Bool (and s169 s175))
+[GOOD] (define-fun s177 () Int (ite s176 s84 s85))
+[GOOD] (define-fun s178 () Int (ite s174 s81 s177))
+[GOOD] (define-fun s179 () Int (ite s172 s78 s178))
+[GOOD] (define-fun s180 () Int (ite s161 s72 s179))
+[GOOD] (define-fun s181 () Int (ite s168 s71 s180))
+[GOOD] (define-fun s182 () Int (ite s164 s64 s181))
+[GOOD] (define-fun s183 () Int (+ s160 s182))
+[GOOD] (define-fun s184 () Bool ((as is-Var Bool) s5))
+[GOOD] (define-fun s185 () String (getVar_1 s5))
+[GOOD] (define-fun s186 () Bool (= s61 s185))
+[GOOD] (define-fun s187 () Bool (and s184 s186))
+[GOOD] (define-fun s188 () Bool (= s65 s185))
+[GOOD] (define-fun s189 () Bool (= s67 s185))
+[GOOD] (define-fun s190 () Bool (or s188 s189))
+[GOOD] (define-fun s191 () Bool (and s184 s190))
+[GOOD] (define-fun s192 () Bool ((as is-Val Bool) s5))
+[GOOD] (define-fun s193 () Int (getVal_1 s5))
+[GOOD] (define-fun s194 () Bool (< s193 s75))
+[GOOD] (define-fun s195 () Bool (and s192 s194))
+[GOOD] (define-fun s196 () Bool (= s75 s193))
+[GOOD] (define-fun s197 () Bool (and s192 s196))
+[GOOD] (define-fun s198 () Bool (> s193 s75))
+[GOOD] (define-fun s199 () Bool (and s192 s198))
+[GOOD] (define-fun s200 () Int (ite s199 s84 s85))
+[GOOD] (define-fun s201 () Int (ite s197 s81 s200))
+[GOOD] (define-fun s202 () Int (ite s195 s78 s201))
+[GOOD] (define-fun s203 () Int (ite s184 s72 s202))
+[GOOD] (define-fun s204 () Int (ite s191 s71 s203))
+[GOOD] (define-fun s205 () Int (ite s187 s64 s204))
+[GOOD] (define-fun s206 () Int (+ s183 s205))
+[GOOD] (define-fun s207 () Bool ((as is-Var Bool) s6))
+[GOOD] (define-fun s208 () String (getVar_1 s6))
+[GOOD] (define-fun s209 () Bool (= s61 s208))
+[GOOD] (define-fun s210 () Bool (and s207 s209))
+[GOOD] (define-fun s211 () Bool (= s65 s208))
+[GOOD] (define-fun s212 () Bool (= s67 s208))
+[GOOD] (define-fun s213 () Bool (or s211 s212))
+[GOOD] (define-fun s214 () Bool (and s207 s213))
+[GOOD] (define-fun s215 () Bool ((as is-Val Bool) s6))
+[GOOD] (define-fun s216 () Int (getVal_1 s6))
+[GOOD] (define-fun s217 () Bool (< s216 s75))
+[GOOD] (define-fun s218 () Bool (and s215 s217))
+[GOOD] (define-fun s219 () Bool (= s75 s216))
+[GOOD] (define-fun s220 () Bool (and s215 s219))
+[GOOD] (define-fun s221 () Bool (> s216 s75))
+[GOOD] (define-fun s222 () Bool (and s215 s221))
+[GOOD] (define-fun s223 () Int (ite s222 s84 s85))
+[GOOD] (define-fun s224 () Int (ite s220 s81 s223))
+[GOOD] (define-fun s225 () Int (ite s218 s78 s224))
+[GOOD] (define-fun s226 () Int (ite s207 s72 s225))
+[GOOD] (define-fun s227 () Int (ite s214 s71 s226))
+[GOOD] (define-fun s228 () Int (ite s210 s64 s227))
+[GOOD] (define-fun s229 () Int (+ s206 s228))
+[GOOD] (define-fun s230 () Bool ((as is-Var Bool) s7))
+[GOOD] (define-fun s231 () String (getVar_1 s7))
+[GOOD] (define-fun s232 () Bool (= s61 s231))
+[GOOD] (define-fun s233 () Bool (and s230 s232))
+[GOOD] (define-fun s234 () Bool (= s65 s231))
+[GOOD] (define-fun s235 () Bool (= s67 s231))
+[GOOD] (define-fun s236 () Bool (or s234 s235))
+[GOOD] (define-fun s237 () Bool (and s230 s236))
+[GOOD] (define-fun s238 () Bool ((as is-Val Bool) s7))
+[GOOD] (define-fun s239 () Int (getVal_1 s7))
+[GOOD] (define-fun s240 () Bool (< s239 s75))
+[GOOD] (define-fun s241 () Bool (and s238 s240))
+[GOOD] (define-fun s242 () Bool (= s75 s239))
+[GOOD] (define-fun s243 () Bool (and s238 s242))
+[GOOD] (define-fun s244 () Bool (> s239 s75))
+[GOOD] (define-fun s245 () Bool (and s238 s244))
+[GOOD] (define-fun s246 () Int (ite s245 s84 s85))
+[GOOD] (define-fun s247 () Int (ite s243 s81 s246))
+[GOOD] (define-fun s248 () Int (ite s241 s78 s247))
+[GOOD] (define-fun s249 () Int (ite s230 s72 s248))
+[GOOD] (define-fun s250 () Int (ite s237 s71 s249))
+[GOOD] (define-fun s251 () Int (ite s233 s64 s250))
+[GOOD] (define-fun s252 () Int (+ s229 s251))
+[GOOD] (define-fun s253 () Bool ((as is-Var Bool) s8))
+[GOOD] (define-fun s254 () String (getVar_1 s8))
+[GOOD] (define-fun s255 () Bool (= s61 s254))
+[GOOD] (define-fun s256 () Bool (and s253 s255))
+[GOOD] (define-fun s257 () Bool (= s65 s254))
+[GOOD] (define-fun s258 () Bool (= s67 s254))
+[GOOD] (define-fun s259 () Bool (or s257 s258))
+[GOOD] (define-fun s260 () Bool (and s253 s259))
+[GOOD] (define-fun s261 () Bool ((as is-Val Bool) s8))
+[GOOD] (define-fun s262 () Int (getVal_1 s8))
+[GOOD] (define-fun s263 () Bool (< s262 s75))
+[GOOD] (define-fun s264 () Bool (and s261 s263))
+[GOOD] (define-fun s265 () Bool (= s75 s262))
+[GOOD] (define-fun s266 () Bool (and s261 s265))
+[GOOD] (define-fun s267 () Bool (> s262 s75))
+[GOOD] (define-fun s268 () Bool (and s261 s267))
+[GOOD] (define-fun s269 () Int (ite s268 s84 s85))
+[GOOD] (define-fun s270 () Int (ite s266 s81 s269))
+[GOOD] (define-fun s271 () Int (ite s264 s78 s270))
+[GOOD] (define-fun s272 () Int (ite s253 s72 s271))
+[GOOD] (define-fun s273 () Int (ite s260 s71 s272))
+[GOOD] (define-fun s274 () Int (ite s256 s64 s273))
+[GOOD] (define-fun s275 () Int (+ s252 s274))
+[GOOD] (define-fun s276 () Bool ((as is-Var Bool) s9))
+[GOOD] (define-fun s277 () String (getVar_1 s9))
+[GOOD] (define-fun s278 () Bool (= s61 s277))
+[GOOD] (define-fun s279 () Bool (and s276 s278))
+[GOOD] (define-fun s280 () Bool (= s65 s277))
+[GOOD] (define-fun s281 () Bool (= s67 s277))
+[GOOD] (define-fun s282 () Bool (or s280 s281))
+[GOOD] (define-fun s283 () Bool (and s276 s282))
+[GOOD] (define-fun s284 () Bool ((as is-Val Bool) s9))
+[GOOD] (define-fun s285 () Int (getVal_1 s9))
+[GOOD] (define-fun s286 () Bool (< s285 s75))
+[GOOD] (define-fun s287 () Bool (and s284 s286))
+[GOOD] (define-fun s288 () Bool (= s75 s285))
+[GOOD] (define-fun s289 () Bool (and s284 s288))
+[GOOD] (define-fun s290 () Bool (> s285 s75))
+[GOOD] (define-fun s291 () Bool (and s284 s290))
+[GOOD] (define-fun s292 () Int (ite s291 s84 s85))
+[GOOD] (define-fun s293 () Int (ite s289 s81 s292))
+[GOOD] (define-fun s294 () Int (ite s287 s78 s293))
+[GOOD] (define-fun s295 () Int (ite s276 s72 s294))
+[GOOD] (define-fun s296 () Int (ite s283 s71 s295))
+[GOOD] (define-fun s297 () Int (ite s279 s64 s296))
+[GOOD] (define-fun s298 () Int (+ s275 s297))
+[GOOD] (define-fun s299 () Bool ((as is-Var Bool) s10))
+[GOOD] (define-fun s300 () String (getVar_1 s10))
+[GOOD] (define-fun s301 () Bool (= s61 s300))
+[GOOD] (define-fun s302 () Bool (and s299 s301))
+[GOOD] (define-fun s303 () Bool (= s65 s300))
+[GOOD] (define-fun s304 () Bool (= s67 s300))
+[GOOD] (define-fun s305 () Bool (or s303 s304))
+[GOOD] (define-fun s306 () Bool (and s299 s305))
+[GOOD] (define-fun s307 () Bool ((as is-Val Bool) s10))
+[GOOD] (define-fun s308 () Int (getVal_1 s10))
+[GOOD] (define-fun s309 () Bool (< s308 s75))
+[GOOD] (define-fun s310 () Bool (and s307 s309))
+[GOOD] (define-fun s311 () Bool (= s75 s308))
+[GOOD] (define-fun s312 () Bool (and s307 s311))
+[GOOD] (define-fun s313 () Bool (> s308 s75))
+[GOOD] (define-fun s314 () Bool (and s307 s313))
+[GOOD] (define-fun s315 () Int (ite s314 s84 s85))
+[GOOD] (define-fun s316 () Int (ite s312 s81 s315))
+[GOOD] (define-fun s317 () Int (ite s310 s78 s316))
+[GOOD] (define-fun s318 () Int (ite s299 s72 s317))
+[GOOD] (define-fun s319 () Int (ite s306 s71 s318))
+[GOOD] (define-fun s320 () Int (ite s302 s64 s319))
+[GOOD] (define-fun s321 () Int (+ s298 s320))
+[GOOD] (define-fun s322 () Bool ((as is-Var Bool) s11))
+[GOOD] (define-fun s323 () String (getVar_1 s11))
+[GOOD] (define-fun s324 () Bool (= s61 s323))
+[GOOD] (define-fun s325 () Bool (and s322 s324))
+[GOOD] (define-fun s326 () Bool (= s65 s323))
+[GOOD] (define-fun s327 () Bool (= s67 s323))
+[GOOD] (define-fun s328 () Bool (or s326 s327))
+[GOOD] (define-fun s329 () Bool (and s322 s328))
+[GOOD] (define-fun s330 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s331 () Int (getVal_1 s11))
+[GOOD] (define-fun s332 () Bool (< s331 s75))
+[GOOD] (define-fun s333 () Bool (and s330 s332))
+[GOOD] (define-fun s334 () Bool (= s75 s331))
+[GOOD] (define-fun s335 () Bool (and s330 s334))
+[GOOD] (define-fun s336 () Bool (> s331 s75))
+[GOOD] (define-fun s337 () Bool (and s330 s336))
+[GOOD] (define-fun s338 () Int (ite s337 s84 s85))
+[GOOD] (define-fun s339 () Int (ite s335 s81 s338))
+[GOOD] (define-fun s340 () Int (ite s333 s78 s339))
+[GOOD] (define-fun s341 () Int (ite s322 s72 s340))
+[GOOD] (define-fun s342 () Int (ite s329 s71 s341))
+[GOOD] (define-fun s343 () Int (ite s325 s64 s342))
+[GOOD] (define-fun s344 () Int (+ s321 s343))
+[GOOD] (define-fun s345 () Bool ((as is-Var Bool) s12))
+[GOOD] (define-fun s346 () String (getVar_1 s12))
+[GOOD] (define-fun s347 () Bool (= s61 s346))
+[GOOD] (define-fun s348 () Bool (and s345 s347))
+[GOOD] (define-fun s349 () Bool (= s65 s346))
+[GOOD] (define-fun s350 () Bool (= s67 s346))
+[GOOD] (define-fun s351 () Bool (or s349 s350))
+[GOOD] (define-fun s352 () Bool (and s345 s351))
+[GOOD] (define-fun s353 () Bool ((as is-Val Bool) s12))
+[GOOD] (define-fun s354 () Int (getVal_1 s12))
+[GOOD] (define-fun s355 () Bool (< s354 s75))
+[GOOD] (define-fun s356 () Bool (and s353 s355))
+[GOOD] (define-fun s357 () Bool (= s75 s354))
+[GOOD] (define-fun s358 () Bool (and s353 s357))
+[GOOD] (define-fun s359 () Bool (> s354 s75))
+[GOOD] (define-fun s360 () Bool (and s353 s359))
+[GOOD] (define-fun s361 () Int (ite s360 s84 s85))
+[GOOD] (define-fun s362 () Int (ite s358 s81 s361))
+[GOOD] (define-fun s363 () Int (ite s356 s78 s362))
+[GOOD] (define-fun s364 () Int (ite s345 s72 s363))
+[GOOD] (define-fun s365 () Int (ite s352 s71 s364))
+[GOOD] (define-fun s366 () Int (ite s348 s64 s365))
+[GOOD] (define-fun s367 () Int (+ s344 s366))
+[GOOD] (define-fun s368 () Bool ((as is-Var Bool) s13))
+[GOOD] (define-fun s369 () String (getVar_1 s13))
+[GOOD] (define-fun s370 () Bool (= s61 s369))
+[GOOD] (define-fun s371 () Bool (and s368 s370))
+[GOOD] (define-fun s372 () Bool (= s65 s369))
+[GOOD] (define-fun s373 () Bool (= s67 s369))
+[GOOD] (define-fun s374 () Bool (or s372 s373))
+[GOOD] (define-fun s375 () Bool (and s368 s374))
+[GOOD] (define-fun s376 () Bool ((as is-Val Bool) s13))
+[GOOD] (define-fun s377 () Int (getVal_1 s13))
+[GOOD] (define-fun s378 () Bool (< s377 s75))
+[GOOD] (define-fun s379 () Bool (and s376 s378))
+[GOOD] (define-fun s380 () Bool (= s75 s377))
+[GOOD] (define-fun s381 () Bool (and s376 s380))
+[GOOD] (define-fun s382 () Bool (> s377 s75))
+[GOOD] (define-fun s383 () Bool (and s376 s382))
+[GOOD] (define-fun s384 () Int (ite s383 s84 s85))
+[GOOD] (define-fun s385 () Int (ite s381 s81 s384))
+[GOOD] (define-fun s386 () Int (ite s379 s78 s385))
+[GOOD] (define-fun s387 () Int (ite s368 s72 s386))
+[GOOD] (define-fun s388 () Int (ite s375 s71 s387))
+[GOOD] (define-fun s389 () Int (ite s371 s64 s388))
+[GOOD] (define-fun s390 () Int (+ s367 s389))
+[GOOD] (define-fun s391 () Bool ((as is-Var Bool) s14))
+[GOOD] (define-fun s392 () String (getVar_1 s14))
+[GOOD] (define-fun s393 () Bool (= s61 s392))
+[GOOD] (define-fun s394 () Bool (and s391 s393))
+[GOOD] (define-fun s395 () Bool (= s65 s392))
+[GOOD] (define-fun s396 () Bool (= s67 s392))
+[GOOD] (define-fun s397 () Bool (or s395 s396))
+[GOOD] (define-fun s398 () Bool (and s391 s397))
+[GOOD] (define-fun s399 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s400 () Int (getVal_1 s14))
+[GOOD] (define-fun s401 () Bool (< s400 s75))
+[GOOD] (define-fun s402 () Bool (and s399 s401))
+[GOOD] (define-fun s403 () Bool (= s75 s400))
+[GOOD] (define-fun s404 () Bool (and s399 s403))
+[GOOD] (define-fun s405 () Bool (> s400 s75))
+[GOOD] (define-fun s406 () Bool (and s399 s405))
+[GOOD] (define-fun s407 () Int (ite s406 s84 s85))
+[GOOD] (define-fun s408 () Int (ite s404 s81 s407))
+[GOOD] (define-fun s409 () Int (ite s402 s78 s408))
+[GOOD] (define-fun s410 () Int (ite s391 s72 s409))
+[GOOD] (define-fun s411 () Int (ite s398 s71 s410))
+[GOOD] (define-fun s412 () Int (ite s394 s64 s411))
+[GOOD] (define-fun s413 () Int (+ s390 s412))
+[GOOD] (define-fun s415 () Bool (distinct s413 s414))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s58)
+[GOOD] (assert s415)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr10c.gold b/SBVTestSuite/GoldFiles/adt_pexpr10c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr10c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr11.gold b/SBVTestSuite/GoldFiles/adt_pexpr11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr11.gold
@@ -0,0 +1,102 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Expr String Int) ((as Val (Expr String Int)) 10))
+[GOOD] (define-fun s8 () String "a")
+[GOOD] (define-fun s11 () Int 0)
+[GOOD] (define-fun s12 () String "b")
+[GOOD] (define-fun s14 () String "c")
+[GOOD] (define-fun s18 () Int 1)
+[GOOD] (define-fun s19 () Int 2)
+[GOOD] (define-fun s22 () Int 10)
+[GOOD] (define-fun s25 () Int 3)
+[GOOD] (define-fun s28 () Int 4)
+[GOOD] (define-fun s31 () Int 5)
+[GOOD] (define-fun s32 () Int 6)
+[GOOD] (define-fun s62 () Int 8)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] (declare-fun s1 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] (define-fun s5 () Bool (and s3 s4))
+[GOOD] (define-fun s6 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s7 () String (getVar_1 s0))
+[GOOD] (define-fun s9 () Bool (= s7 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s13 () Bool (= s7 s12))
+[GOOD] (define-fun s15 () Bool (= s7 s14))
+[GOOD] (define-fun s16 () Bool (or s13 s15))
+[GOOD] (define-fun s17 () Bool (and s6 s16))
+[GOOD] (define-fun s20 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s21 () Int (getVal_1 s0))
+[GOOD] (define-fun s23 () Bool (< s21 s22))
+[GOOD] (define-fun s24 () Bool (and s20 s23))
+[GOOD] (define-fun s26 () Bool (= s21 s22))
+[GOOD] (define-fun s27 () Bool (and s20 s26))
+[GOOD] (define-fun s29 () Bool (> s21 s22))
+[GOOD] (define-fun s30 () Bool (and s20 s29))
+[GOOD] (define-fun s33 () Int (ite s30 s31 s32))
+[GOOD] (define-fun s34 () Int (ite s27 s28 s33))
+[GOOD] (define-fun s35 () Int (ite s24 s25 s34))
+[GOOD] (define-fun s36 () Int (ite s6 s19 s35))
+[GOOD] (define-fun s37 () Int (ite s17 s18 s36))
+[GOOD] (define-fun s38 () Int (ite s10 s11 s37))
+[GOOD] (define-fun s39 () Bool ((as is-Var Bool) s1))
+[GOOD] (define-fun s40 () String (getVar_1 s1))
+[GOOD] (define-fun s41 () Bool (= s8 s40))
+[GOOD] (define-fun s42 () Bool (and s39 s41))
+[GOOD] (define-fun s43 () Bool (= s12 s40))
+[GOOD] (define-fun s44 () Bool (= s14 s40))
+[GOOD] (define-fun s45 () Bool (or s43 s44))
+[GOOD] (define-fun s46 () Bool (and s39 s45))
+[GOOD] (define-fun s47 () Bool ((as is-Val Bool) s1))
+[GOOD] (define-fun s48 () Int (getVal_1 s1))
+[GOOD] (define-fun s49 () Bool (< s48 s22))
+[GOOD] (define-fun s50 () Bool (and s47 s49))
+[GOOD] (define-fun s51 () Bool (= s22 s48))
+[GOOD] (define-fun s52 () Bool (and s47 s51))
+[GOOD] (define-fun s53 () Bool (> s48 s22))
+[GOOD] (define-fun s54 () Bool (and s47 s53))
+[GOOD] (define-fun s55 () Int (ite s54 s31 s32))
+[GOOD] (define-fun s56 () Int (ite s52 s28 s55))
+[GOOD] (define-fun s57 () Int (ite s50 s25 s56))
+[GOOD] (define-fun s58 () Int (ite s39 s19 s57))
+[GOOD] (define-fun s59 () Int (ite s46 s18 s58))
+[GOOD] (define-fun s60 () Int (ite s42 s11 s59))
+[GOOD] (define-fun s61 () Int (+ s38 s60))
+[GOOD] (define-fun s63 () Bool (distinct s61 s62))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s5)
+[GOOD] (assert s63)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr11c.gold b/SBVTestSuite/GoldFiles/adt_pexpr11c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr11c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr12.gold b/SBVTestSuite/GoldFiles/adt_pexpr12.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr12.gold
@@ -0,0 +1,319 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s10 () (Expr String Int) ((as Val (Expr String Int)) 11))
+[GOOD] (define-fun s12 () (Expr String Int) ((as Val (Expr String Int)) 12))
+[GOOD] (define-fun s14 () (Expr String Int) ((as Val (Expr String Int)) 13))
+[GOOD] (define-fun s16 () (Expr String Int) ((as Val (Expr String Int)) 14))
+[GOOD] (define-fun s18 () (Expr String Int) ((as Val (Expr String Int)) 15))
+[GOOD] (define-fun s20 () (Expr String Int) ((as Val (Expr String Int)) 16))
+[GOOD] (define-fun s22 () (Expr String Int) ((as Val (Expr String Int)) 17))
+[GOOD] (define-fun s24 () (Expr String Int) ((as Val (Expr String Int)) 18))
+[GOOD] (define-fun s26 () (Expr String Int) ((as Val (Expr String Int)) 19))
+[GOOD] (define-fun s28 () (Expr String Int) ((as Val (Expr String Int)) 20))
+[GOOD] (define-fun s41 () String "a")
+[GOOD] (define-fun s44 () Int 0)
+[GOOD] (define-fun s45 () String "b")
+[GOOD] (define-fun s47 () String "c")
+[GOOD] (define-fun s51 () Int 1)
+[GOOD] (define-fun s52 () Int 2)
+[GOOD] (define-fun s55 () Int 10)
+[GOOD] (define-fun s58 () Int 3)
+[GOOD] (define-fun s61 () Int 4)
+[GOOD] (define-fun s64 () Int 5)
+[GOOD] (define-fun s65 () Int 6)
+[GOOD] (define-fun s279 () Int 50)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] (declare-fun s1 () (Expr String Int))
+[GOOD] (declare-fun s2 () (Expr String Int))
+[GOOD] (declare-fun s3 () (Expr String Int))
+[GOOD] (declare-fun s4 () (Expr String Int))
+[GOOD] (declare-fun s5 () (Expr String Int))
+[GOOD] (declare-fun s6 () (Expr String Int))
+[GOOD] (declare-fun s7 () (Expr String Int))
+[GOOD] (declare-fun s8 () (Expr String Int))
+[GOOD] (declare-fun s9 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s11 () Bool (= s0 s10))
+[GOOD] (define-fun s13 () Bool (= s1 s12))
+[GOOD] (define-fun s15 () Bool (= s2 s14))
+[GOOD] (define-fun s17 () Bool (= s3 s16))
+[GOOD] (define-fun s19 () Bool (= s4 s18))
+[GOOD] (define-fun s21 () Bool (= s5 s20))
+[GOOD] (define-fun s23 () Bool (= s6 s22))
+[GOOD] (define-fun s25 () Bool (= s7 s24))
+[GOOD] (define-fun s27 () Bool (= s8 s26))
+[GOOD] (define-fun s29 () Bool (= s9 s28))
+[GOOD] (define-fun s30 () Bool (and s27 s29))
+[GOOD] (define-fun s31 () Bool (and s25 s30))
+[GOOD] (define-fun s32 () Bool (and s23 s31))
+[GOOD] (define-fun s33 () Bool (and s21 s32))
+[GOOD] (define-fun s34 () Bool (and s19 s33))
+[GOOD] (define-fun s35 () Bool (and s17 s34))
+[GOOD] (define-fun s36 () Bool (and s15 s35))
+[GOOD] (define-fun s37 () Bool (and s13 s36))
+[GOOD] (define-fun s38 () Bool (and s11 s37))
+[GOOD] (define-fun s39 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s40 () String (getVar_1 s0))
+[GOOD] (define-fun s42 () Bool (= s40 s41))
+[GOOD] (define-fun s43 () Bool (and s39 s42))
+[GOOD] (define-fun s46 () Bool (= s40 s45))
+[GOOD] (define-fun s48 () Bool (= s40 s47))
+[GOOD] (define-fun s49 () Bool (or s46 s48))
+[GOOD] (define-fun s50 () Bool (and s39 s49))
+[GOOD] (define-fun s53 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s54 () Int (getVal_1 s0))
+[GOOD] (define-fun s56 () Bool (< s54 s55))
+[GOOD] (define-fun s57 () Bool (and s53 s56))
+[GOOD] (define-fun s59 () Bool (= s54 s55))
+[GOOD] (define-fun s60 () Bool (and s53 s59))
+[GOOD] (define-fun s62 () Bool (> s54 s55))
+[GOOD] (define-fun s63 () Bool (and s53 s62))
+[GOOD] (define-fun s66 () Int (ite s63 s64 s65))
+[GOOD] (define-fun s67 () Int (ite s60 s61 s66))
+[GOOD] (define-fun s68 () Int (ite s57 s58 s67))
+[GOOD] (define-fun s69 () Int (ite s39 s52 s68))
+[GOOD] (define-fun s70 () Int (ite s50 s51 s69))
+[GOOD] (define-fun s71 () Int (ite s43 s44 s70))
+[GOOD] (define-fun s72 () Bool ((as is-Var Bool) s1))
+[GOOD] (define-fun s73 () String (getVar_1 s1))
+[GOOD] (define-fun s74 () Bool (= s41 s73))
+[GOOD] (define-fun s75 () Bool (and s72 s74))
+[GOOD] (define-fun s76 () Bool (= s45 s73))
+[GOOD] (define-fun s77 () Bool (= s47 s73))
+[GOOD] (define-fun s78 () Bool (or s76 s77))
+[GOOD] (define-fun s79 () Bool (and s72 s78))
+[GOOD] (define-fun s80 () Bool ((as is-Val Bool) s1))
+[GOOD] (define-fun s81 () Int (getVal_1 s1))
+[GOOD] (define-fun s82 () Bool (< s81 s55))
+[GOOD] (define-fun s83 () Bool (and s80 s82))
+[GOOD] (define-fun s84 () Bool (= s55 s81))
+[GOOD] (define-fun s85 () Bool (and s80 s84))
+[GOOD] (define-fun s86 () Bool (> s81 s55))
+[GOOD] (define-fun s87 () Bool (and s80 s86))
+[GOOD] (define-fun s88 () Int (ite s87 s64 s65))
+[GOOD] (define-fun s89 () Int (ite s85 s61 s88))
+[GOOD] (define-fun s90 () Int (ite s83 s58 s89))
+[GOOD] (define-fun s91 () Int (ite s72 s52 s90))
+[GOOD] (define-fun s92 () Int (ite s79 s51 s91))
+[GOOD] (define-fun s93 () Int (ite s75 s44 s92))
+[GOOD] (define-fun s94 () Int (+ s71 s93))
+[GOOD] (define-fun s95 () Bool ((as is-Var Bool) s2))
+[GOOD] (define-fun s96 () String (getVar_1 s2))
+[GOOD] (define-fun s97 () Bool (= s41 s96))
+[GOOD] (define-fun s98 () Bool (and s95 s97))
+[GOOD] (define-fun s99 () Bool (= s45 s96))
+[GOOD] (define-fun s100 () Bool (= s47 s96))
+[GOOD] (define-fun s101 () Bool (or s99 s100))
+[GOOD] (define-fun s102 () Bool (and s95 s101))
+[GOOD] (define-fun s103 () Bool ((as is-Val Bool) s2))
+[GOOD] (define-fun s104 () Int (getVal_1 s2))
+[GOOD] (define-fun s105 () Bool (< s104 s55))
+[GOOD] (define-fun s106 () Bool (and s103 s105))
+[GOOD] (define-fun s107 () Bool (= s55 s104))
+[GOOD] (define-fun s108 () Bool (and s103 s107))
+[GOOD] (define-fun s109 () Bool (> s104 s55))
+[GOOD] (define-fun s110 () Bool (and s103 s109))
+[GOOD] (define-fun s111 () Int (ite s110 s64 s65))
+[GOOD] (define-fun s112 () Int (ite s108 s61 s111))
+[GOOD] (define-fun s113 () Int (ite s106 s58 s112))
+[GOOD] (define-fun s114 () Int (ite s95 s52 s113))
+[GOOD] (define-fun s115 () Int (ite s102 s51 s114))
+[GOOD] (define-fun s116 () Int (ite s98 s44 s115))
+[GOOD] (define-fun s117 () Int (+ s94 s116))
+[GOOD] (define-fun s118 () Bool ((as is-Var Bool) s3))
+[GOOD] (define-fun s119 () String (getVar_1 s3))
+[GOOD] (define-fun s120 () Bool (= s41 s119))
+[GOOD] (define-fun s121 () Bool (and s118 s120))
+[GOOD] (define-fun s122 () Bool (= s45 s119))
+[GOOD] (define-fun s123 () Bool (= s47 s119))
+[GOOD] (define-fun s124 () Bool (or s122 s123))
+[GOOD] (define-fun s125 () Bool (and s118 s124))
+[GOOD] (define-fun s126 () Bool ((as is-Val Bool) s3))
+[GOOD] (define-fun s127 () Int (getVal_1 s3))
+[GOOD] (define-fun s128 () Bool (< s127 s55))
+[GOOD] (define-fun s129 () Bool (and s126 s128))
+[GOOD] (define-fun s130 () Bool (= s55 s127))
+[GOOD] (define-fun s131 () Bool (and s126 s130))
+[GOOD] (define-fun s132 () Bool (> s127 s55))
+[GOOD] (define-fun s133 () Bool (and s126 s132))
+[GOOD] (define-fun s134 () Int (ite s133 s64 s65))
+[GOOD] (define-fun s135 () Int (ite s131 s61 s134))
+[GOOD] (define-fun s136 () Int (ite s129 s58 s135))
+[GOOD] (define-fun s137 () Int (ite s118 s52 s136))
+[GOOD] (define-fun s138 () Int (ite s125 s51 s137))
+[GOOD] (define-fun s139 () Int (ite s121 s44 s138))
+[GOOD] (define-fun s140 () Int (+ s117 s139))
+[GOOD] (define-fun s141 () Bool ((as is-Var Bool) s4))
+[GOOD] (define-fun s142 () String (getVar_1 s4))
+[GOOD] (define-fun s143 () Bool (= s41 s142))
+[GOOD] (define-fun s144 () Bool (and s141 s143))
+[GOOD] (define-fun s145 () Bool (= s45 s142))
+[GOOD] (define-fun s146 () Bool (= s47 s142))
+[GOOD] (define-fun s147 () Bool (or s145 s146))
+[GOOD] (define-fun s148 () Bool (and s141 s147))
+[GOOD] (define-fun s149 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s150 () Int (getVal_1 s4))
+[GOOD] (define-fun s151 () Bool (< s150 s55))
+[GOOD] (define-fun s152 () Bool (and s149 s151))
+[GOOD] (define-fun s153 () Bool (= s55 s150))
+[GOOD] (define-fun s154 () Bool (and s149 s153))
+[GOOD] (define-fun s155 () Bool (> s150 s55))
+[GOOD] (define-fun s156 () Bool (and s149 s155))
+[GOOD] (define-fun s157 () Int (ite s156 s64 s65))
+[GOOD] (define-fun s158 () Int (ite s154 s61 s157))
+[GOOD] (define-fun s159 () Int (ite s152 s58 s158))
+[GOOD] (define-fun s160 () Int (ite s141 s52 s159))
+[GOOD] (define-fun s161 () Int (ite s148 s51 s160))
+[GOOD] (define-fun s162 () Int (ite s144 s44 s161))
+[GOOD] (define-fun s163 () Int (+ s140 s162))
+[GOOD] (define-fun s164 () Bool ((as is-Var Bool) s5))
+[GOOD] (define-fun s165 () String (getVar_1 s5))
+[GOOD] (define-fun s166 () Bool (= s41 s165))
+[GOOD] (define-fun s167 () Bool (and s164 s166))
+[GOOD] (define-fun s168 () Bool (= s45 s165))
+[GOOD] (define-fun s169 () Bool (= s47 s165))
+[GOOD] (define-fun s170 () Bool (or s168 s169))
+[GOOD] (define-fun s171 () Bool (and s164 s170))
+[GOOD] (define-fun s172 () Bool ((as is-Val Bool) s5))
+[GOOD] (define-fun s173 () Int (getVal_1 s5))
+[GOOD] (define-fun s174 () Bool (< s173 s55))
+[GOOD] (define-fun s175 () Bool (and s172 s174))
+[GOOD] (define-fun s176 () Bool (= s55 s173))
+[GOOD] (define-fun s177 () Bool (and s172 s176))
+[GOOD] (define-fun s178 () Bool (> s173 s55))
+[GOOD] (define-fun s179 () Bool (and s172 s178))
+[GOOD] (define-fun s180 () Int (ite s179 s64 s65))
+[GOOD] (define-fun s181 () Int (ite s177 s61 s180))
+[GOOD] (define-fun s182 () Int (ite s175 s58 s181))
+[GOOD] (define-fun s183 () Int (ite s164 s52 s182))
+[GOOD] (define-fun s184 () Int (ite s171 s51 s183))
+[GOOD] (define-fun s185 () Int (ite s167 s44 s184))
+[GOOD] (define-fun s186 () Int (+ s163 s185))
+[GOOD] (define-fun s187 () Bool ((as is-Var Bool) s6))
+[GOOD] (define-fun s188 () String (getVar_1 s6))
+[GOOD] (define-fun s189 () Bool (= s41 s188))
+[GOOD] (define-fun s190 () Bool (and s187 s189))
+[GOOD] (define-fun s191 () Bool (= s45 s188))
+[GOOD] (define-fun s192 () Bool (= s47 s188))
+[GOOD] (define-fun s193 () Bool (or s191 s192))
+[GOOD] (define-fun s194 () Bool (and s187 s193))
+[GOOD] (define-fun s195 () Bool ((as is-Val Bool) s6))
+[GOOD] (define-fun s196 () Int (getVal_1 s6))
+[GOOD] (define-fun s197 () Bool (< s196 s55))
+[GOOD] (define-fun s198 () Bool (and s195 s197))
+[GOOD] (define-fun s199 () Bool (= s55 s196))
+[GOOD] (define-fun s200 () Bool (and s195 s199))
+[GOOD] (define-fun s201 () Bool (> s196 s55))
+[GOOD] (define-fun s202 () Bool (and s195 s201))
+[GOOD] (define-fun s203 () Int (ite s202 s64 s65))
+[GOOD] (define-fun s204 () Int (ite s200 s61 s203))
+[GOOD] (define-fun s205 () Int (ite s198 s58 s204))
+[GOOD] (define-fun s206 () Int (ite s187 s52 s205))
+[GOOD] (define-fun s207 () Int (ite s194 s51 s206))
+[GOOD] (define-fun s208 () Int (ite s190 s44 s207))
+[GOOD] (define-fun s209 () Int (+ s186 s208))
+[GOOD] (define-fun s210 () Bool ((as is-Var Bool) s7))
+[GOOD] (define-fun s211 () String (getVar_1 s7))
+[GOOD] (define-fun s212 () Bool (= s41 s211))
+[GOOD] (define-fun s213 () Bool (and s210 s212))
+[GOOD] (define-fun s214 () Bool (= s45 s211))
+[GOOD] (define-fun s215 () Bool (= s47 s211))
+[GOOD] (define-fun s216 () Bool (or s214 s215))
+[GOOD] (define-fun s217 () Bool (and s210 s216))
+[GOOD] (define-fun s218 () Bool ((as is-Val Bool) s7))
+[GOOD] (define-fun s219 () Int (getVal_1 s7))
+[GOOD] (define-fun s220 () Bool (< s219 s55))
+[GOOD] (define-fun s221 () Bool (and s218 s220))
+[GOOD] (define-fun s222 () Bool (= s55 s219))
+[GOOD] (define-fun s223 () Bool (and s218 s222))
+[GOOD] (define-fun s224 () Bool (> s219 s55))
+[GOOD] (define-fun s225 () Bool (and s218 s224))
+[GOOD] (define-fun s226 () Int (ite s225 s64 s65))
+[GOOD] (define-fun s227 () Int (ite s223 s61 s226))
+[GOOD] (define-fun s228 () Int (ite s221 s58 s227))
+[GOOD] (define-fun s229 () Int (ite s210 s52 s228))
+[GOOD] (define-fun s230 () Int (ite s217 s51 s229))
+[GOOD] (define-fun s231 () Int (ite s213 s44 s230))
+[GOOD] (define-fun s232 () Int (+ s209 s231))
+[GOOD] (define-fun s233 () Bool ((as is-Var Bool) s8))
+[GOOD] (define-fun s234 () String (getVar_1 s8))
+[GOOD] (define-fun s235 () Bool (= s41 s234))
+[GOOD] (define-fun s236 () Bool (and s233 s235))
+[GOOD] (define-fun s237 () Bool (= s45 s234))
+[GOOD] (define-fun s238 () Bool (= s47 s234))
+[GOOD] (define-fun s239 () Bool (or s237 s238))
+[GOOD] (define-fun s240 () Bool (and s233 s239))
+[GOOD] (define-fun s241 () Bool ((as is-Val Bool) s8))
+[GOOD] (define-fun s242 () Int (getVal_1 s8))
+[GOOD] (define-fun s243 () Bool (< s242 s55))
+[GOOD] (define-fun s244 () Bool (and s241 s243))
+[GOOD] (define-fun s245 () Bool (= s55 s242))
+[GOOD] (define-fun s246 () Bool (and s241 s245))
+[GOOD] (define-fun s247 () Bool (> s242 s55))
+[GOOD] (define-fun s248 () Bool (and s241 s247))
+[GOOD] (define-fun s249 () Int (ite s248 s64 s65))
+[GOOD] (define-fun s250 () Int (ite s246 s61 s249))
+[GOOD] (define-fun s251 () Int (ite s244 s58 s250))
+[GOOD] (define-fun s252 () Int (ite s233 s52 s251))
+[GOOD] (define-fun s253 () Int (ite s240 s51 s252))
+[GOOD] (define-fun s254 () Int (ite s236 s44 s253))
+[GOOD] (define-fun s255 () Int (+ s232 s254))
+[GOOD] (define-fun s256 () Bool ((as is-Var Bool) s9))
+[GOOD] (define-fun s257 () String (getVar_1 s9))
+[GOOD] (define-fun s258 () Bool (= s41 s257))
+[GOOD] (define-fun s259 () Bool (and s256 s258))
+[GOOD] (define-fun s260 () Bool (= s45 s257))
+[GOOD] (define-fun s261 () Bool (= s47 s257))
+[GOOD] (define-fun s262 () Bool (or s260 s261))
+[GOOD] (define-fun s263 () Bool (and s256 s262))
+[GOOD] (define-fun s264 () Bool ((as is-Val Bool) s9))
+[GOOD] (define-fun s265 () Int (getVal_1 s9))
+[GOOD] (define-fun s266 () Bool (< s265 s55))
+[GOOD] (define-fun s267 () Bool (and s264 s266))
+[GOOD] (define-fun s268 () Bool (= s55 s265))
+[GOOD] (define-fun s269 () Bool (and s264 s268))
+[GOOD] (define-fun s270 () Bool (> s265 s55))
+[GOOD] (define-fun s271 () Bool (and s264 s270))
+[GOOD] (define-fun s272 () Int (ite s271 s64 s65))
+[GOOD] (define-fun s273 () Int (ite s269 s61 s272))
+[GOOD] (define-fun s274 () Int (ite s267 s58 s273))
+[GOOD] (define-fun s275 () Int (ite s256 s52 s274))
+[GOOD] (define-fun s276 () Int (ite s263 s51 s275))
+[GOOD] (define-fun s277 () Int (ite s259 s44 s276))
+[GOOD] (define-fun s278 () Int (+ s255 s277))
+[GOOD] (define-fun s280 () Bool (distinct s278 s279))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s38)
+[GOOD] (assert s280)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr12c.gold b/SBVTestSuite/GoldFiles/adt_pexpr12c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr12c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr13.gold b/SBVTestSuite/GoldFiles/adt_pexpr13.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr13.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Val (Expr String Int)) 3))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s22 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr13c.gold b/SBVTestSuite/GoldFiles/adt_pexpr13c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr13c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr14.gold b/SBVTestSuite/GoldFiles/adt_pexpr14.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr14.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr14c.gold b/SBVTestSuite/GoldFiles/adt_pexpr14c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr14c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr15.gold b/SBVTestSuite/GoldFiles/adt_pexpr15.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr15.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr15c.gold b/SBVTestSuite/GoldFiles/adt_pexpr15c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr15c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr16.gold b/SBVTestSuite/GoldFiles/adt_pexpr16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr16.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Let (Expr String Int)) "a" ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr16c.gold b/SBVTestSuite/GoldFiles/adt_pexpr16c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr16c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr17.gold b/SBVTestSuite/GoldFiles/adt_pexpr17.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr17.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Add (Expr String Int)) ((as Let (Expr String Int)) "a" ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))) ((as Let (Expr String Int)) "a" ((as Let (Expr String Int)) "a" ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr17c.gold b/SBVTestSuite/GoldFiles/adt_pexpr17c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr17c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr18.gold b/SBVTestSuite/GoldFiles/adt_pexpr18.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr18.gold
@@ -0,0 +1,75 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Let (Expr String Int)) "a" ((as Add (Expr String Int)) ((as Let (Expr String Int)) "a" ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))) ((as Let (Expr String Int)) "a" ((as Let (Expr String Int)) "a" ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))))) ((as Mul (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Var (Expr String Int)) "a"))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr18c.gold b/SBVTestSuite/GoldFiles/adt_pexpr18c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr18c.gold
@@ -0,0 +1,25 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr19.gold b/SBVTestSuite/GoldFiles/adt_pexpr19.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr19.gold
@@ -0,0 +1,41 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr Int (_ BitVec 8))) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Let Bool) s0))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Let 2 (Var 3) (Var 4))))
+Result: (let 2 = 3 in 4)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr20.gold b/SBVTestSuite/GoldFiles/adt_pexpr20.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr20.gold
@@ -0,0 +1,51 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has rational values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr (_ BitVec 8) SBVRational)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Mul Bool) s0))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Mul (Var #x00) (Var #x00))))
+Result: (0 * 0)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr21.gold b/SBVTestSuite/GoldFiles/adt_pexpr21.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr21.gold
@@ -0,0 +1,52 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
+                                           ((left_SBVEither  (get_left_SBVEither  T1))
+                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
+                                           ((nothing_SBVMaybe)
+                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr (SBVMaybe (SBVTuple2 Int String)) (SBVEither (_ BitVec 8) (_ BitVec 16)))) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Let Bool) s0))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Let nothing_SBVMaybe
+            (Val (right_SBVEither #x0000))
+            (Val (right_SBVEither #x0000)))))
+Result: (let Nothing = Right 0 in Right 0)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen00.gold b/SBVTestSuite/GoldFiles/adt_pgen00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen00.gold
@@ -0,0 +1,149 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Seq String) (as seq.empty (Seq String)))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String (_ BitVec 16))) (as seq.empty (Seq (SBVTuple2 String (_ BitVec 16)))))
+[GOOD] (define-fun s5 () (_ BitVec 16) #x000c)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String (_ BitVec 16))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |valid @(SBV [[Char]] -> SBV (Expr [Char] Word16) -> SBV Bool)| :: [SString] -> Expr String Word16 -> SBool [Recursive]
+[GOOD] (define-fun-rec |valid @(SBV [[Char]] -> SBV (Expr [Char] Word16) -> SBV Bool)| ((l1_s0 (Seq String)) (l1_s1 (Expr String (_ BitVec 16)))) Bool
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s4 (getVar_1 l1_s1)))
+                                 (let ((l1_s5 (str.in_re l1_s4 (re.++ (re.range "a" "z") (re.* (re.union (re.range "a" "z") (re.range "A" "Z") (re.range "0" "9")))))))
+                                 (let ((l1_s6 (seq.unit l1_s4)))
+                                 (let ((l1_s7 (seq.contains l1_s0 l1_s6)))
+                                 (let ((l1_s8 (and l1_s5 l1_s7)))
+                                 (let ((l1_s9 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s10 (getAdd_1 l1_s1)))
+                                 (let ((l1_s11 (|valid @(SBV [[Char]] -> SBV (Expr [Char] Word16) -> SBV Bool)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (getAdd_2 l1_s1)))
+                                 (let ((l1_s13 (|valid @(SBV [[Char]] -> SBV (Expr [Char] Word16) -> SBV Bool)| l1_s0 l1_s12)))
+                                 (let ((l1_s14 (and l1_s11 l1_s13)))
+                                 (let ((l1_s15 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s16 (getMul_1 l1_s1)))
+                                 (let ((l1_s17 (|valid @(SBV [[Char]] -> SBV (Expr [Char] Word16) -> SBV Bool)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (getMul_2 l1_s1)))
+                                 (let ((l1_s19 (|valid @(SBV [[Char]] -> SBV (Expr [Char] Word16) -> SBV Bool)| l1_s0 l1_s18)))
+                                 (let ((l1_s20 (and l1_s17 l1_s19)))
+                                 (let ((l1_s21 (getLet_1 l1_s1)))
+                                 (let ((l1_s22 (str.in_re l1_s21 (re.++ (re.range "a" "z") (re.* (re.union (re.range "a" "z") (re.range "A" "Z") (re.range "0" "9")))))))
+                                 (let ((l1_s23 (getLet_2 l1_s1)))
+                                 (let ((l1_s24 (|valid @(SBV [[Char]] -> SBV (Expr [Char] Word16) -> SBV Bool)| l1_s0 l1_s23)))
+                                 (let ((l1_s25 (seq.unit l1_s21)))
+                                 (let ((l1_s26 (seq.++ l1_s25 l1_s0)))
+                                 (let ((l1_s27 (getLet_3 l1_s1)))
+                                 (let ((l1_s28 (|valid @(SBV [[Char]] -> SBV (Expr [Char] Word16) -> SBV Bool)| l1_s26 l1_s27)))
+                                 (let ((l1_s29 (and l1_s24 l1_s28)))
+                                 (let ((l1_s30 (and l1_s22 l1_s29)))
+                                 (let ((l1_s31 (ite l1_s15 l1_s20 l1_s30)))
+                                 (let ((l1_s32 (ite l1_s9 l1_s14 l1_s31)))
+                                 (let ((l1_s33 (ite l1_s3 l1_s8 l1_s32)))
+                                 (let ((l1_s34 (or l1_s2 l1_s33)))
+                                 l1_s34))))))))))))))))))))))))))))))))))
+[GOOD] ; |get @(SBV [([Char],Word16)] -> SBV [Char] -> SBV Word16)| :: [(SString, SWord16)] -> SString -> SWord16 [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Word16)] -> SBV [Char] -> SBV Word16)| ((l2_s0 (Seq (SBVTuple2 String (_ BitVec 16)))) (l2_s1 String)) (_ BitVec 16)
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s5 #x0000))
+                                                 (let ((l2_s10 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s11 (- l2_s2 l2_s10)))
+                                                 (let ((l2_s12 (seq.extract l2_s0 l2_s10 l2_s11)))
+                                                 (let ((l2_s13 (|get @(SBV [([Char],Word16)] -> SBV [Char] -> SBV Word16)| l2_s12 l2_s1)))
+                                                 (let ((l2_s14 (ite l2_s8 l2_s9 l2_s13)))
+                                                 (let ((l2_s15 (ite l2_s4 l2_s5 l2_s14)))
+                                                 l2_s15)))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Word16)] -> SBV (Expr [Char] Word16) -> SBV Word16)| :: [(SString, SWord16)] -> Expr String Word16 -> SWord16 [Recursive] [Refers to: |get @(SBV [([Char],Word16)] -> SBV [Char] -> SBV Word16)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Word16)] -> SBV (Expr [Char] Word16) -> SBV Word16)| ((l1_s0 (Seq (SBVTuple2 String (_ BitVec 16)))) (l1_s1 (Expr String (_ BitVec 16)))) (_ BitVec 16)
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Word16)] -> SBV [Char] -> SBV Word16)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Word16)] -> SBV (Expr [Char] Word16) -> SBV Word16)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Word16)] -> SBV (Expr [Char] Word16) -> SBV Word16)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (bvadd l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Word16)] -> SBV (Expr [Char] Word16) -> SBV Word16)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Word16)] -> SBV (Expr [Char] Word16) -> SBV Word16)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (bvmul l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Word16)] -> SBV (Expr [Char] Word16) -> SBV Word16)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String (_ BitVec 16))) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Word16)] -> SBV (Expr [Char] Word16) -> SBV Word16)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (|valid @(SBV [[Char]] -> SBV (Expr [Char] Word16) -> SBV Bool)| s1 s0))
+[GOOD] (define-fun s4 () (_ BitVec 16) (|eval @(SBV [([Char],Word16)] -> SBV (Expr [Char] Word16) -> SBV Word16)| s3 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s8 () (Expr String (_ BitVec 16)) (getLet_3 s0))
+[GOOD] (define-fun s9 () Bool ((as is-Let Bool) s8))
+[GOOD] (define-fun s10 () (Expr String (_ BitVec 16)) (getLet_3 s8))
+[GOOD] (define-fun s11 () Bool ((as is-Add Bool) s10))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[GOOD] (assert s7)
+[GOOD] (assert s9)
+[GOOD] (assert s11)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Let "j"
+            (Val #x0000)
+            (Let "a"
+                 (Add (Add (Add (Var "j") (Val #x0000)) (Var "j")) (Val #x0003))
+                 (Add (Mul (Var "a") (Var "a")) (Var "a"))))))
+
+Got: (let j = 0 in (let a = (((j + 0) + j) + 3) in ((a * a) + a)))
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen01.gold b/SBVTestSuite/GoldFiles/adt_pgen01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen01.gold
@@ -0,0 +1,83 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () (_ BitVec 16) #x000a)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] (define-fun s43 () Int (- 1))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String (_ BitVec 16))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () (_ BitVec 16) (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (bvult s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (bvugt s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s44 () Bool (= s42 s43))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s44)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen02.gold b/SBVTestSuite/GoldFiles/adt_pgen02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen02.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () (_ BitVec 16) #x000a)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String (_ BitVec 16))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () (_ BitVec 16) (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (bvult s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (bvugt s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s6 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Var "a")))
+
+Got: a
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen03.gold b/SBVTestSuite/GoldFiles/adt_pgen03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen03.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () (_ BitVec 16) #x000a)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String (_ BitVec 16))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () (_ BitVec 16) (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (bvult s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (bvugt s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s13 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Var "b")))
+
+Got: b
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen04.gold b/SBVTestSuite/GoldFiles/adt_pgen04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen04.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () (_ BitVec 16) #x000a)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String (_ BitVec 16))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () (_ BitVec 16) (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (bvult s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (bvugt s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s14 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Var "")))
+
+Got: 
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen05.gold b/SBVTestSuite/GoldFiles/adt_pgen05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen05.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () (_ BitVec 16) #x000a)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String (_ BitVec 16))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () (_ BitVec 16) (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (bvult s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (bvugt s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s20 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Val #x0000)))
+
+Got: 0
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen06.gold b/SBVTestSuite/GoldFiles/adt_pgen06.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen06.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () (_ BitVec 16) #x000a)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String (_ BitVec 16))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () (_ BitVec 16) (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (bvult s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (bvugt s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s23 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Val #x000a)))
+
+Got: 10
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen07.gold b/SBVTestSuite/GoldFiles/adt_pgen07.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen07.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () (_ BitVec 16) #x000a)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String (_ BitVec 16))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () (_ BitVec 16) (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (bvult s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (bvugt s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s26 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Val #x000b)))
+
+Got: 11
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen08.gold b/SBVTestSuite/GoldFiles/adt_pgen08.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen08.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () (_ BitVec 16) #x000a)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String (_ BitVec 16))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () (_ BitVec 16) (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (bvult s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (bvugt s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s28 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Add (Val #x0000) (Val #x0000))))
+
+Got: (0 + 0)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen09.gold b/SBVTestSuite/GoldFiles/adt_pgen09.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen09.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () (_ BitVec 16) #x000a)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String (_ BitVec 16))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () (_ BitVec 16) (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (bvult s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (bvugt s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s30 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Mul (Val #x0000) (Val #x0000))))
+
+Got: (0 * 0)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen10.gold b/SBVTestSuite/GoldFiles/adt_pgen10.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen10.gold
@@ -0,0 +1,85 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () (_ BitVec 16) #x000a)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String (_ BitVec 16))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () (_ BitVec 16) (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (bvult s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (bvugt s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s32 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Let "!0!" (Val #x0000) (Val #x0000))))
+
+Got: (let !0! = 0 in 0)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen11.gold b/SBVTestSuite/GoldFiles/adt_pgen11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen11.gold
@@ -0,0 +1,83 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () (_ BitVec 16) #x000a)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] (define-fun s43 () Int 9)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String (_ BitVec 16))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () (_ BitVec 16) (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (bvult s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (bvugt s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s44 () Bool (= s42 s43))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s44)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen12.gold b/SBVTestSuite/GoldFiles/adt_pgen12.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen12.gold
@@ -0,0 +1,82 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () (_ BitVec 16) #x000a)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String (_ BitVec 16))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () (_ BitVec 16) (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (bvult s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (bvugt s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s33 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/allSat7.gold b/SBVTestSuite/GoldFiles/allSat7.gold
--- a/SBVTestSuite/GoldFiles/allSat7.gold
+++ b/SBVTestSuite/GoldFiles/allSat7.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/allSat8.gold b/SBVTestSuite/GoldFiles/allSat8.gold
--- a/SBVTestSuite/GoldFiles/allSat8.gold
+++ b/SBVTestSuite/GoldFiles/allSat8.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/arrayGetValTest1.gold b/SBVTestSuite/GoldFiles/arrayGetValTest1.gold
--- a/SBVTestSuite/GoldFiles/arrayGetValTest1.gold
+++ b/SBVTestSuite/GoldFiles/arrayGetValTest1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_caching_01.gold b/SBVTestSuite/GoldFiles/array_caching_01.gold
--- a/SBVTestSuite/GoldFiles/array_caching_01.gold
+++ b/SBVTestSuite/GoldFiles/array_caching_01.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_caching_02.gold b/SBVTestSuite/GoldFiles/array_caching_02.gold
--- a/SBVTestSuite/GoldFiles/array_caching_02.gold
+++ b/SBVTestSuite/GoldFiles/array_caching_02.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_1.gold b/SBVTestSuite/GoldFiles/array_misc_1.gold
--- a/SBVTestSuite/GoldFiles/array_misc_1.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_11.gold b/SBVTestSuite/GoldFiles/array_misc_11.gold
--- a/SBVTestSuite/GoldFiles/array_misc_11.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_11.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/array_misc_12.gold b/SBVTestSuite/GoldFiles/array_misc_12.gold
--- a/SBVTestSuite/GoldFiles/array_misc_12.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_12.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/array_misc_13.gold b/SBVTestSuite/GoldFiles/array_misc_13.gold
--- a/SBVTestSuite/GoldFiles/array_misc_13.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_13.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/array_misc_14.gold b/SBVTestSuite/GoldFiles/array_misc_14.gold
--- a/SBVTestSuite/GoldFiles/array_misc_14.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_14.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_15.gold b/SBVTestSuite/GoldFiles/array_misc_15.gold
--- a/SBVTestSuite/GoldFiles/array_misc_15.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_15.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_16.gold b/SBVTestSuite/GoldFiles/array_misc_16.gold
--- a/SBVTestSuite/GoldFiles/array_misc_16.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_16.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_17.gold b/SBVTestSuite/GoldFiles/array_misc_17.gold
--- a/SBVTestSuite/GoldFiles/array_misc_17.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_17.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_18.gold b/SBVTestSuite/GoldFiles/array_misc_18.gold
--- a/SBVTestSuite/GoldFiles/array_misc_18.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_18.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_19.gold b/SBVTestSuite/GoldFiles/array_misc_19.gold
--- a/SBVTestSuite/GoldFiles/array_misc_19.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_19.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_2.gold b/SBVTestSuite/GoldFiles/array_misc_2.gold
--- a/SBVTestSuite/GoldFiles/array_misc_2.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_2.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_20.gold b/SBVTestSuite/GoldFiles/array_misc_20.gold
--- a/SBVTestSuite/GoldFiles/array_misc_20.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_20.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_21.gold b/SBVTestSuite/GoldFiles/array_misc_21.gold
--- a/SBVTestSuite/GoldFiles/array_misc_21.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_21.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_22.gold b/SBVTestSuite/GoldFiles/array_misc_22.gold
--- a/SBVTestSuite/GoldFiles/array_misc_22.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_22.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_23.gold b/SBVTestSuite/GoldFiles/array_misc_23.gold
--- a/SBVTestSuite/GoldFiles/array_misc_23.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_23.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_24.gold b/SBVTestSuite/GoldFiles/array_misc_24.gold
--- a/SBVTestSuite/GoldFiles/array_misc_24.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_24.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_25.gold b/SBVTestSuite/GoldFiles/array_misc_25.gold
--- a/SBVTestSuite/GoldFiles/array_misc_25.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_25.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_26.gold b/SBVTestSuite/GoldFiles/array_misc_26.gold
--- a/SBVTestSuite/GoldFiles/array_misc_26.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_26.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_27.gold b/SBVTestSuite/GoldFiles/array_misc_27.gold
--- a/SBVTestSuite/GoldFiles/array_misc_27.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_27.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_28.gold b/SBVTestSuite/GoldFiles/array_misc_28.gold
--- a/SBVTestSuite/GoldFiles/array_misc_28.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_28.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_29.gold b/SBVTestSuite/GoldFiles/array_misc_29.gold
--- a/SBVTestSuite/GoldFiles/array_misc_29.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_29.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_3.gold b/SBVTestSuite/GoldFiles/array_misc_3.gold
--- a/SBVTestSuite/GoldFiles/array_misc_3.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_3.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_BV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_30.gold b/SBVTestSuite/GoldFiles/array_misc_30.gold
--- a/SBVTestSuite/GoldFiles/array_misc_30.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_30.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_31.gold b/SBVTestSuite/GoldFiles/array_misc_31.gold
--- a/SBVTestSuite/GoldFiles/array_misc_31.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_31.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_BV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_5.gold b/SBVTestSuite/GoldFiles/array_misc_5.gold
--- a/SBVTestSuite/GoldFiles/array_misc_5.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_5.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; NB. User specified.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_7.gold b/SBVTestSuite/GoldFiles/array_misc_7.gold
--- a/SBVTestSuite/GoldFiles/array_misc_7.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_7.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_BV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/array_misc_9.gold b/SBVTestSuite/GoldFiles/array_misc_9.gold
--- a/SBVTestSuite/GoldFiles/array_misc_9.gold
+++ b/SBVTestSuite/GoldFiles/array_misc_9.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_BV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word16.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word16.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word16.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word32.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word32.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word32.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word64.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word64.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word64.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word8.gold
--- a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word8.gold
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word8.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/charConstr00.gold b/SBVTestSuite/GoldFiles/charConstr00.gold
--- a/SBVTestSuite/GoldFiles/charConstr00.gold
+++ b/SBVTestSuite/GoldFiles/charConstr00.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has chars, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/charConstr01.gold b/SBVTestSuite/GoldFiles/charConstr01.gold
--- a/SBVTestSuite/GoldFiles/charConstr01.gold
+++ b/SBVTestSuite/GoldFiles/charConstr01.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/charConstr02.gold b/SBVTestSuite/GoldFiles/charConstr02.gold
--- a/SBVTestSuite/GoldFiles/charConstr02.gold
+++ b/SBVTestSuite/GoldFiles/charConstr02.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
                                            ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
diff --git a/SBVTestSuite/GoldFiles/charConstr03.gold b/SBVTestSuite/GoldFiles/charConstr03.gold
--- a/SBVTestSuite/GoldFiles/charConstr03.gold
+++ b/SBVTestSuite/GoldFiles/charConstr03.gold
@@ -8,19 +8,21 @@
 [GOOD] (set-option :pp.max_depth      4294967295)
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
-[GOOD] (set-logic ALL) ; has either type, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s1 () (SBVEither String String) ((as left_SBVEither (SBVEither String String)) (_ char #x41)))
+[GOOD] (define-fun s1 () (Either String String) ((as Left (Either String String)) (_ char #x41)))
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVEither String String)) ; tracks user variable "x"
-[GOOD] (assert (and (=> ((_ is (left_SBVEither (String) (SBVEither String String))) s0) (= 1 (str.len (get_left_SBVEither s0))))
-                    (=> ((_ is (right_SBVEither (String) (SBVEither String String))) s0) (= 1 (str.len (get_right_SBVEither s0))))
+[GOOD] (declare-fun s0 () (Either String String)) ; tracks user variable "x"
+[GOOD] (assert (and (= 1 (str.len (getLeft_1 s0)))
+                    (= 1 (str.len (getRight_1 s0)))
                ))
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
@@ -34,7 +36,7 @@
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (left_SBVEither "B")))
+[RECV] ((s0 (Left "B")))
 
 MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Left 'B' :: Either Char Char)], modelUIFuns = []}
 DONE.*** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/charConstr04.gold b/SBVTestSuite/GoldFiles/charConstr04.gold
--- a/SBVTestSuite/GoldFiles/charConstr04.gold
+++ b/SBVTestSuite/GoldFiles/charConstr04.gold
@@ -9,17 +9,19 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s1 () (SBVEither Int String) ((as right_SBVEither (SBVEither Int String)) (_ char #x41)))
+[GOOD] (define-fun s1 () (Either Int String) ((as Right (Either Int String)) (_ char #x41)))
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVEither Int String)) ; tracks user variable "x"
-[GOOD] (assert (=> ((_ is (right_SBVEither (String) (SBVEither Int String))) s0) (= 1 (str.len (get_right_SBVEither s0)))))
+[GOOD] (declare-fun s0 () (Either Int String)) ; tracks user variable "x"
+[GOOD] (assert (= 1 (str.len (getRight_1 s0))))
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
@@ -32,7 +34,7 @@
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (left_SBVEither 2)))
+[RECV] ((s0 (Left 2)))
 
 MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Left 2 :: Either Integer Char)], modelUIFuns = []}
 DONE.*** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/charConstr05.gold b/SBVTestSuite/GoldFiles/charConstr05.gold
--- a/SBVTestSuite/GoldFiles/charConstr05.gold
+++ b/SBVTestSuite/GoldFiles/charConstr05.gold
@@ -9,17 +9,19 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s1 () (SBVEither String Int) ((as left_SBVEither (SBVEither String Int)) (_ char #x41)))
+[GOOD] (define-fun s1 () (Either String Int) ((as Left (Either String Int)) (_ char #x41)))
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVEither String Int)) ; tracks user variable "x"
-[GOOD] (assert (=> ((_ is (left_SBVEither (String) (SBVEither String Int))) s0) (= 1 (str.len (get_left_SBVEither s0)))))
+[GOOD] (declare-fun s0 () (Either String Int)) ; tracks user variable "x"
+[GOOD] (assert (= 1 (str.len (getLeft_1 s0))))
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
@@ -32,8 +34,8 @@
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (right_SBVEither 2)))
+[RECV] ((s0 (Left "B")))
 
-MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Right 2 :: Either Char Integer)], modelUIFuns = []}
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Left 'B' :: Either Char Integer)], modelUIFuns = []}
 DONE.*** Solver   : Z3
 *** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/charConstr06.gold b/SBVTestSuite/GoldFiles/charConstr06.gold
--- a/SBVTestSuite/GoldFiles/charConstr06.gold
+++ b/SBVTestSuite/GoldFiles/charConstr06.gold
@@ -9,18 +9,20 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s1 () (SBVEither String (SBVEither String Int)) ((as left_SBVEither (SBVEither String (SBVEither String Int))) (_ char #x41)))
+[GOOD] (define-fun s1 () (Either String (Either String Int)) ((as Left (Either String (Either String Int))) (_ char #x41)))
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVEither String (SBVEither String Int))) ; tracks user variable "x"
-[GOOD] (assert (and (=> ((_ is (left_SBVEither (String) (SBVEither String (SBVEither String Int)))) s0) (= 1 (str.len (get_left_SBVEither s0))))
-                    (=> ((_ is (right_SBVEither ((SBVEither String Int)) (SBVEither String (SBVEither String Int)))) s0) (=> ((_ is (left_SBVEither (String) (SBVEither String Int))) (get_right_SBVEither s0)) (= 1 (str.len (get_left_SBVEither (get_right_SBVEither s0))))))
+[GOOD] (declare-fun s0 () (Either String (Either String Int))) ; tracks user variable "x"
+[GOOD] (assert (and (= 1 (str.len (getLeft_1 s0)))
+                    (= 1 (str.len (getLeft_1 (getRight_1 s0))))
                ))
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
@@ -34,7 +36,7 @@
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 ((as left_SBVEither (SBVEither String (SBVEither String Int))) "B")))
+[RECV] ((s0 ((as Left (Either String (Either String Int))) "B")))
 
 MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Left 'B' :: Either Char (Either Char Integer))], modelUIFuns = []}
 DONE.*** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/charConstr07.gold b/SBVTestSuite/GoldFiles/charConstr07.gold
--- a/SBVTestSuite/GoldFiles/charConstr07.gold
+++ b/SBVTestSuite/GoldFiles/charConstr07.gold
@@ -8,34 +8,35 @@
 [GOOD] (set-option :pp.max_depth      4294967295)
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
-[GOOD] (set-logic ALL) ; has maybe type, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
-                                           ((nothing_SBVMaybe)
-                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s3 () (SBVMaybe String) ((as just_SBVMaybe (SBVMaybe String)) (_ char #x41)))
+[GOOD] (define-fun s2 () (Maybe String) ((as Just (Maybe String)) (_ char #x41)))
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVMaybe String)) ; tracks user variable "x"
-[GOOD] (assert (=> ((_ is (just_SBVMaybe (String) (SBVMaybe String))) s0) (= 1 (str.len (get_just_SBVMaybe s0)))))
+[GOOD] (declare-fun s0 () (Maybe String)) ; tracks user variable "x"
+[GOOD] (assert (= 1 (str.len (getJust_1 s0))))
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s1 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe String))) s0))
-[GOOD] (define-fun s2 () Bool (ite s1 false true))
-[GOOD] (define-fun s4 () Bool (distinct s0 s3))
-[GOOD] (define-fun s5 () Bool (and s2 s4))
+[GOOD] (define-fun s1 () Bool ((as is-Just Bool) s0))
+[GOOD] (define-fun s3 () Bool (distinct s0 s2))
+[GOOD] (define-fun s4 () Bool (and s1 s3))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
-[GOOD] (assert s5)
+[GOOD] (assert s4)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (just_SBVMaybe "B")))
+[RECV] ((s0 (Just "B")))
 
 MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Just 'B' :: Maybe Char)], modelUIFuns = []}
 DONE.*** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/charConstr08.gold b/SBVTestSuite/GoldFiles/charConstr08.gold
--- a/SBVTestSuite/GoldFiles/charConstr08.gold
+++ b/SBVTestSuite/GoldFiles/charConstr08.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has sets, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/charConstr09.gold b/SBVTestSuite/GoldFiles/charConstr09.gold
--- a/SBVTestSuite/GoldFiles/charConstr09.gold
+++ b/SBVTestSuite/GoldFiles/charConstr09.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/charConstr10.gold b/SBVTestSuite/GoldFiles/charConstr10.gold
--- a/SBVTestSuite/GoldFiles/charConstr10.gold
+++ b/SBVTestSuite/GoldFiles/charConstr10.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/charConstr11.gold b/SBVTestSuite/GoldFiles/charConstr11.gold
--- a/SBVTestSuite/GoldFiles/charConstr11.gold
+++ b/SBVTestSuite/GoldFiles/charConstr11.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/check1.gold b/SBVTestSuite/GoldFiles/check1.gold
--- a/SBVTestSuite/GoldFiles/check1.gold
+++ b/SBVTestSuite/GoldFiles/check1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_BV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/check2.gold b/SBVTestSuite/GoldFiles/check2.gold
--- a/SBVTestSuite/GoldFiles/check2.gold
+++ b/SBVTestSuite/GoldFiles/check2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_BV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/constArr2_SArray.gold b/SBVTestSuite/GoldFiles/constArr2_SArray.gold
--- a/SBVTestSuite/GoldFiles/constArr2_SArray.gold
+++ b/SBVTestSuite/GoldFiles/constArr2_SArray.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/constArr_SArray.gold b/SBVTestSuite/GoldFiles/constArr_SArray.gold
--- a/SBVTestSuite/GoldFiles/constArr_SArray.gold
+++ b/SBVTestSuite/GoldFiles/constArr_SArray.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/doctest_sanity.gold b/SBVTestSuite/GoldFiles/doctest_sanity.gold
--- a/SBVTestSuite/GoldFiles/doctest_sanity.gold
+++ b/SBVTestSuite/GoldFiles/doctest_sanity.gold
@@ -1,3 +1,3 @@
-Total:      1020; Tried: 1020; Skipped:    0; Success: 1020; Errors:    0; Failures    0
-Examples:    910; Tried:  910; Skipped:    0; Success:  910; Errors:    0; Failures    0
-Setup:       110; Tried:  110; Skipped:    0; Success:  110; Errors:    0; Failures    0
+Total:      1069; Tried: 1069; Skipped:    0; Success: 1069; Errors:    0; Failures    0
+Examples:    954; Tried:  954; Skipped:    0; Success:  954; Errors:    0; Failures    0
+Setup:       115; Tried:  115; Skipped:    0; Success:  115; Errors:    0; Failures    0
diff --git a/SBVTestSuite/GoldFiles/dsat01.gold b/SBVTestSuite/GoldFiles/dsat01.gold
--- a/SBVTestSuite/GoldFiles/dsat01.gold
+++ b/SBVTestSuite/GoldFiles/dsat01.gold
@@ -6,7 +6,6 @@
 [ISSUE] (set-option :smtlib2_compliant true)
 [ISSUE] (set-option :produce-models true)
 [ISSUE] (set-logic ALL) ; has unbounded values, using catch-all.
-[ISSUE] ; --- uninterpreted sorts ---
 [ISSUE] ; --- tuples ---
 [ISSUE] ; --- sums ---
 [ISSUE] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/exceptionLocal1.gold b/SBVTestSuite/GoldFiles/exceptionLocal1.gold
--- a/SBVTestSuite/GoldFiles/exceptionLocal1.gold
+++ b/SBVTestSuite/GoldFiles/exceptionLocal1.gold
@@ -4,7 +4,6 @@
 [GOOD] (set-option :global-declarations true)
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/exceptionLocal2.gold b/SBVTestSuite/GoldFiles/exceptionLocal2.gold
--- a/SBVTestSuite/GoldFiles/exceptionLocal2.gold
+++ b/SBVTestSuite/GoldFiles/exceptionLocal2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_LIA) ; NB. User specified.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/freshVars.gold b/SBVTestSuite/GoldFiles/freshVars.gold
--- a/SBVTestSuite/GoldFiles/freshVars.gold
+++ b/SBVTestSuite/GoldFiles/freshVars.gold
@@ -8,7 +8,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
@@ -37,10 +36,15 @@
 [GOOD] (declare-fun s13 () (_ FloatingPoint 11 53))
 [GOOD] (declare-fun s14 () Real)
 [GOOD] (declare-fun s15 () Int)
-[GOOD] (declare-datatypes ((BinOp 0)) (((Plus) (Minus) (Times))))
-[GOOD] (define-fun BinOp_constrIndex ((x BinOp)) Int
-          (ite (= x Plus) 0 (ite (= x Minus) 1 2))
-       )
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] ; User defined ADT: BinOp
+[GOOD] (declare-datatype BinOp (
+           (Plus)
+           (Minus)
+           (Times)
+       ))
 [GOOD] (declare-fun s16 () BinOp)
 [GOOD] (declare-fun s17 () (_ FloatingPoint 15 113))
 [GOOD] (declare-fun s18 () (_ FloatingPoint 15 113))
@@ -81,7 +85,7 @@
 [GOOD] (define-fun s41 () Int 12)
 [GOOD] (define-fun s42 () Bool (= s15 s41))
 [GOOD] (assert s42)
-[GOOD] (define-fun s43 () BinOp Plus)
+[GOOD] (define-fun s43 () BinOp (as Plus BinOp))
 [GOOD] (define-fun s44 () Bool (= s16 s43))
 [GOOD] (assert s44)
 [GOOD] (define-fun s45 () Bool (fp.eq s17 s18))
diff --git a/SBVTestSuite/GoldFiles/genBenchMark1.gold b/SBVTestSuite/GoldFiles/genBenchMark1.gold
--- a/SBVTestSuite/GoldFiles/genBenchMark1.gold
+++ b/SBVTestSuite/GoldFiles/genBenchMark1.gold
@@ -2,7 +2,6 @@
 (set-option :diagnostic-output-channel "stdout")
 (set-option :produce-models true)
 (set-logic QF_BV)
-; --- uninterpreted sorts ---
 ; --- tuples ---
 ; --- sums ---
 ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/genBenchMark2.gold b/SBVTestSuite/GoldFiles/genBenchMark2.gold
--- a/SBVTestSuite/GoldFiles/genBenchMark2.gold
+++ b/SBVTestSuite/GoldFiles/genBenchMark2.gold
@@ -2,7 +2,6 @@
 (set-option :diagnostic-output-channel "stdout")
 (set-option :produce-models true)
 (set-logic QF_BV)
-; --- uninterpreted sorts ---
 ; --- tuples ---
 ; --- sums ---
 ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda04.gold b/SBVTestSuite/GoldFiles/lambda04.gold
--- a/SBVTestSuite/GoldFiles/lambda04.gold
+++ b/SBVTestSuite/GoldFiles/lambda04.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda05.gold b/SBVTestSuite/GoldFiles/lambda05.gold
--- a/SBVTestSuite/GoldFiles/lambda05.gold
+++ b/SBVTestSuite/GoldFiles/lambda05.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda06.gold b/SBVTestSuite/GoldFiles/lambda06.gold
--- a/SBVTestSuite/GoldFiles/lambda06.gold
+++ b/SBVTestSuite/GoldFiles/lambda06.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda07.gold b/SBVTestSuite/GoldFiles/lambda07.gold
--- a/SBVTestSuite/GoldFiles/lambda07.gold
+++ b/SBVTestSuite/GoldFiles/lambda07.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda08.gold b/SBVTestSuite/GoldFiles/lambda08.gold
--- a/SBVTestSuite/GoldFiles/lambda08.gold
+++ b/SBVTestSuite/GoldFiles/lambda08.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda09.gold b/SBVTestSuite/GoldFiles/lambda09.gold
--- a/SBVTestSuite/GoldFiles/lambda09.gold
+++ b/SBVTestSuite/GoldFiles/lambda09.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda10.gold b/SBVTestSuite/GoldFiles/lambda10.gold
--- a/SBVTestSuite/GoldFiles/lambda10.gold
+++ b/SBVTestSuite/GoldFiles/lambda10.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda11.gold b/SBVTestSuite/GoldFiles/lambda11.gold
--- a/SBVTestSuite/GoldFiles/lambda11.gold
+++ b/SBVTestSuite/GoldFiles/lambda11.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda12.gold b/SBVTestSuite/GoldFiles/lambda12.gold
--- a/SBVTestSuite/GoldFiles/lambda12.gold
+++ b/SBVTestSuite/GoldFiles/lambda12.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda13.gold b/SBVTestSuite/GoldFiles/lambda13.gold
--- a/SBVTestSuite/GoldFiles/lambda13.gold
+++ b/SBVTestSuite/GoldFiles/lambda13.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda14.gold b/SBVTestSuite/GoldFiles/lambda14.gold
--- a/SBVTestSuite/GoldFiles/lambda14.gold
+++ b/SBVTestSuite/GoldFiles/lambda14.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda15.gold b/SBVTestSuite/GoldFiles/lambda15.gold
--- a/SBVTestSuite/GoldFiles/lambda15.gold
+++ b/SBVTestSuite/GoldFiles/lambda15.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda16.gold b/SBVTestSuite/GoldFiles/lambda16.gold
--- a/SBVTestSuite/GoldFiles/lambda16.gold
+++ b/SBVTestSuite/GoldFiles/lambda16.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda17.gold b/SBVTestSuite/GoldFiles/lambda17.gold
--- a/SBVTestSuite/GoldFiles/lambda17.gold
+++ b/SBVTestSuite/GoldFiles/lambda17.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda18.gold b/SBVTestSuite/GoldFiles/lambda18.gold
--- a/SBVTestSuite/GoldFiles/lambda18.gold
+++ b/SBVTestSuite/GoldFiles/lambda18.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda19.gold b/SBVTestSuite/GoldFiles/lambda19.gold
--- a/SBVTestSuite/GoldFiles/lambda19.gold
+++ b/SBVTestSuite/GoldFiles/lambda19.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda20.gold b/SBVTestSuite/GoldFiles/lambda20.gold
--- a/SBVTestSuite/GoldFiles/lambda20.gold
+++ b/SBVTestSuite/GoldFiles/lambda20.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda21.gold b/SBVTestSuite/GoldFiles/lambda21.gold
--- a/SBVTestSuite/GoldFiles/lambda21.gold
+++ b/SBVTestSuite/GoldFiles/lambda21.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda22.gold b/SBVTestSuite/GoldFiles/lambda22.gold
--- a/SBVTestSuite/GoldFiles/lambda22.gold
+++ b/SBVTestSuite/GoldFiles/lambda22.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda23.gold b/SBVTestSuite/GoldFiles/lambda23.gold
--- a/SBVTestSuite/GoldFiles/lambda23.gold
+++ b/SBVTestSuite/GoldFiles/lambda23.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda24.gold b/SBVTestSuite/GoldFiles/lambda24.gold
--- a/SBVTestSuite/GoldFiles/lambda24.gold
+++ b/SBVTestSuite/GoldFiles/lambda24.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda25.gold b/SBVTestSuite/GoldFiles/lambda25.gold
--- a/SBVTestSuite/GoldFiles/lambda25.gold
+++ b/SBVTestSuite/GoldFiles/lambda25.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda26.gold b/SBVTestSuite/GoldFiles/lambda26.gold
--- a/SBVTestSuite/GoldFiles/lambda26.gold
+++ b/SBVTestSuite/GoldFiles/lambda26.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda27.gold b/SBVTestSuite/GoldFiles/lambda27.gold
--- a/SBVTestSuite/GoldFiles/lambda27.gold
+++ b/SBVTestSuite/GoldFiles/lambda27.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda28.gold b/SBVTestSuite/GoldFiles/lambda28.gold
--- a/SBVTestSuite/GoldFiles/lambda28.gold
+++ b/SBVTestSuite/GoldFiles/lambda28.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda29.gold b/SBVTestSuite/GoldFiles/lambda29.gold
--- a/SBVTestSuite/GoldFiles/lambda29.gold
+++ b/SBVTestSuite/GoldFiles/lambda29.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda30.gold b/SBVTestSuite/GoldFiles/lambda30.gold
--- a/SBVTestSuite/GoldFiles/lambda30.gold
+++ b/SBVTestSuite/GoldFiles/lambda30.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda31.gold b/SBVTestSuite/GoldFiles/lambda31.gold
--- a/SBVTestSuite/GoldFiles/lambda31.gold
+++ b/SBVTestSuite/GoldFiles/lambda31.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda32.gold b/SBVTestSuite/GoldFiles/lambda32.gold
--- a/SBVTestSuite/GoldFiles/lambda32.gold
+++ b/SBVTestSuite/GoldFiles/lambda32.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda46.gold b/SBVTestSuite/GoldFiles/lambda46.gold
--- a/SBVTestSuite/GoldFiles/lambda46.gold
+++ b/SBVTestSuite/GoldFiles/lambda46.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda47.gold b/SBVTestSuite/GoldFiles/lambda47.gold
--- a/SBVTestSuite/GoldFiles/lambda47.gold
+++ b/SBVTestSuite/GoldFiles/lambda47.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda47_c.gold b/SBVTestSuite/GoldFiles/lambda47_c.gold
--- a/SBVTestSuite/GoldFiles/lambda47_c.gold
+++ b/SBVTestSuite/GoldFiles/lambda47_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda48.gold b/SBVTestSuite/GoldFiles/lambda48.gold
--- a/SBVTestSuite/GoldFiles/lambda48.gold
+++ b/SBVTestSuite/GoldFiles/lambda48.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda48_c.gold b/SBVTestSuite/GoldFiles/lambda48_c.gold
--- a/SBVTestSuite/GoldFiles/lambda48_c.gold
+++ b/SBVTestSuite/GoldFiles/lambda48_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda49.gold b/SBVTestSuite/GoldFiles/lambda49.gold
--- a/SBVTestSuite/GoldFiles/lambda49.gold
+++ b/SBVTestSuite/GoldFiles/lambda49.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda49_c.gold b/SBVTestSuite/GoldFiles/lambda49_c.gold
--- a/SBVTestSuite/GoldFiles/lambda49_c.gold
+++ b/SBVTestSuite/GoldFiles/lambda49_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda50.gold b/SBVTestSuite/GoldFiles/lambda50.gold
--- a/SBVTestSuite/GoldFiles/lambda50.gold
+++ b/SBVTestSuite/GoldFiles/lambda50.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda50_c.gold b/SBVTestSuite/GoldFiles/lambda50_c.gold
--- a/SBVTestSuite/GoldFiles/lambda50_c.gold
+++ b/SBVTestSuite/GoldFiles/lambda50_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda51.gold b/SBVTestSuite/GoldFiles/lambda51.gold
--- a/SBVTestSuite/GoldFiles/lambda51.gold
+++ b/SBVTestSuite/GoldFiles/lambda51.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda51_c.gold b/SBVTestSuite/GoldFiles/lambda51_c.gold
--- a/SBVTestSuite/GoldFiles/lambda51_c.gold
+++ b/SBVTestSuite/GoldFiles/lambda51_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda52.gold b/SBVTestSuite/GoldFiles/lambda52.gold
--- a/SBVTestSuite/GoldFiles/lambda52.gold
+++ b/SBVTestSuite/GoldFiles/lambda52.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda52_c.gold b/SBVTestSuite/GoldFiles/lambda52_c.gold
--- a/SBVTestSuite/GoldFiles/lambda52_c.gold
+++ b/SBVTestSuite/GoldFiles/lambda52_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda53.gold b/SBVTestSuite/GoldFiles/lambda53.gold
--- a/SBVTestSuite/GoldFiles/lambda53.gold
+++ b/SBVTestSuite/GoldFiles/lambda53.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda54.gold b/SBVTestSuite/GoldFiles/lambda54.gold
--- a/SBVTestSuite/GoldFiles/lambda54.gold
+++ b/SBVTestSuite/GoldFiles/lambda54.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda55.gold b/SBVTestSuite/GoldFiles/lambda55.gold
--- a/SBVTestSuite/GoldFiles/lambda55.gold
+++ b/SBVTestSuite/GoldFiles/lambda55.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda56.gold b/SBVTestSuite/GoldFiles/lambda56.gold
--- a/SBVTestSuite/GoldFiles/lambda56.gold
+++ b/SBVTestSuite/GoldFiles/lambda56.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda57.gold b/SBVTestSuite/GoldFiles/lambda57.gold
--- a/SBVTestSuite/GoldFiles/lambda57.gold
+++ b/SBVTestSuite/GoldFiles/lambda57.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda60.gold b/SBVTestSuite/GoldFiles/lambda60.gold
--- a/SBVTestSuite/GoldFiles/lambda60.gold
+++ b/SBVTestSuite/GoldFiles/lambda60.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda61.gold b/SBVTestSuite/GoldFiles/lambda61.gold
--- a/SBVTestSuite/GoldFiles/lambda61.gold
+++ b/SBVTestSuite/GoldFiles/lambda61.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda62.gold b/SBVTestSuite/GoldFiles/lambda62.gold
--- a/SBVTestSuite/GoldFiles/lambda62.gold
+++ b/SBVTestSuite/GoldFiles/lambda62.gold
@@ -5,12 +5,11 @@
 [GOOD] (set-option :smtlib2_compliant true)
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
-[GOOD] (set-logic ALL) ; has user-defined sorts, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
-[GOOD] (declare-sort P 0)  ; N.B. Uninterpreted sort.
-[GOOD] (declare-fun P_witness () P)
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] (declare-sort P 0) ; N.B. Uninterpreted sort.
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/lambda63.gold b/SBVTestSuite/GoldFiles/lambda63.gold
--- a/SBVTestSuite/GoldFiles/lambda63.gold
+++ b/SBVTestSuite/GoldFiles/lambda63.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda64.gold b/SBVTestSuite/GoldFiles/lambda64.gold
--- a/SBVTestSuite/GoldFiles/lambda64.gold
+++ b/SBVTestSuite/GoldFiles/lambda64.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] ; has special relations, no logic set.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda65.gold b/SBVTestSuite/GoldFiles/lambda65.gold
--- a/SBVTestSuite/GoldFiles/lambda65.gold
+++ b/SBVTestSuite/GoldFiles/lambda65.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] ; has special relations, no logic set.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda66.gold b/SBVTestSuite/GoldFiles/lambda66.gold
--- a/SBVTestSuite/GoldFiles/lambda66.gold
+++ b/SBVTestSuite/GoldFiles/lambda66.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] ; has special relations, no logic set.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda67.gold b/SBVTestSuite/GoldFiles/lambda67.gold
--- a/SBVTestSuite/GoldFiles/lambda67.gold
+++ b/SBVTestSuite/GoldFiles/lambda67.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] ; has special relations, no logic set.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda68.gold b/SBVTestSuite/GoldFiles/lambda68.gold
--- a/SBVTestSuite/GoldFiles/lambda68.gold
+++ b/SBVTestSuite/GoldFiles/lambda68.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda69.gold b/SBVTestSuite/GoldFiles/lambda69.gold
--- a/SBVTestSuite/GoldFiles/lambda69.gold
+++ b/SBVTestSuite/GoldFiles/lambda69.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda70.gold b/SBVTestSuite/GoldFiles/lambda70.gold
--- a/SBVTestSuite/GoldFiles/lambda70.gold
+++ b/SBVTestSuite/GoldFiles/lambda70.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda81.gold b/SBVTestSuite/GoldFiles/lambda81.gold
--- a/SBVTestSuite/GoldFiles/lambda81.gold
+++ b/SBVTestSuite/GoldFiles/lambda81.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda82.gold b/SBVTestSuite/GoldFiles/lambda82.gold
--- a/SBVTestSuite/GoldFiles/lambda82.gold
+++ b/SBVTestSuite/GoldFiles/lambda82.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/lambda85.gold b/SBVTestSuite/GoldFiles/lambda85.gold
--- a/SBVTestSuite/GoldFiles/lambda85.gold
+++ b/SBVTestSuite/GoldFiles/lambda85.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda86.gold b/SBVTestSuite/GoldFiles/lambda86.gold
--- a/SBVTestSuite/GoldFiles/lambda86.gold
+++ b/SBVTestSuite/GoldFiles/lambda86.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda87.gold b/SBVTestSuite/GoldFiles/lambda87.gold
--- a/SBVTestSuite/GoldFiles/lambda87.gold
+++ b/SBVTestSuite/GoldFiles/lambda87.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/lambda88.gold b/SBVTestSuite/GoldFiles/lambda88.gold
--- a/SBVTestSuite/GoldFiles/lambda88.gold
+++ b/SBVTestSuite/GoldFiles/lambda88.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/listFloat2.gold b/SBVTestSuite/GoldFiles/listFloat2.gold
--- a/SBVTestSuite/GoldFiles/listFloat2.gold
+++ b/SBVTestSuite/GoldFiles/listFloat2.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/listFloat3.gold b/SBVTestSuite/GoldFiles/listFloat3.gold
--- a/SBVTestSuite/GoldFiles/listFloat3.gold
+++ b/SBVTestSuite/GoldFiles/listFloat3.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has lists, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/nested1.gold b/SBVTestSuite/GoldFiles/nested1.gold
--- a/SBVTestSuite/GoldFiles/nested1.gold
+++ b/SBVTestSuite/GoldFiles/nested1.gold
@@ -2,9 +2,6 @@
 
 Data.SBV: Mismatched contexts detected.
 ***
-***   Current context: SBVContext (-531973508589804280)
-***   Mixed with     : SBVContext (-7749304166575005736)
-***
 *** This happens if you call a proof-function (prove/sat/runSMT/isSatisfiable) etc.
 *** while another one is in execution, or use results from one such call in another.
 *** Please avoid such nested calls, all interactions should be from the same context.
diff --git a/SBVTestSuite/GoldFiles/nested2.gold b/SBVTestSuite/GoldFiles/nested2.gold
--- a/SBVTestSuite/GoldFiles/nested2.gold
+++ b/SBVTestSuite/GoldFiles/nested2.gold
@@ -2,9 +2,6 @@
 
 Data.SBV: Mismatched contexts detected.
 ***
-***   Current context: SBVContext (-531973508589804280)
-***   Mixed with     : SBVContext (-7749304166575005736)
-***
 *** This happens if you call a proof-function (prove/sat/runSMT/isSatisfiable) etc.
 *** while another one is in execution, or use results from one such call in another.
 *** Please avoid such nested calls, all interactions should be from the same context.
diff --git a/SBVTestSuite/GoldFiles/nested3.gold b/SBVTestSuite/GoldFiles/nested3.gold
--- a/SBVTestSuite/GoldFiles/nested3.gold
+++ b/SBVTestSuite/GoldFiles/nested3.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
@@ -24,9 +23,6 @@
 CAUGHT EXCEPTION
 
 Data.SBV: Mismatched contexts detected.
-***
-***   Current context: SBVContext (-7749304166575005736)
-***   Mixed with     : SBVContext (-531973508589804280)
 ***
 *** This happens if you call a proof-function (prove/sat/runSMT/isSatisfiable) etc.
 *** while another one is in execution, or use results from one such call in another.
diff --git a/SBVTestSuite/GoldFiles/nested4.gold b/SBVTestSuite/GoldFiles/nested4.gold
--- a/SBVTestSuite/GoldFiles/nested4.gold
+++ b/SBVTestSuite/GoldFiles/nested4.gold
@@ -2,9 +2,6 @@
 
 Data.SBV: Mismatched contexts detected.
 ***
-***   Current context: SBVContext (-531973508589804280)
-***   Mixed with     : SBVContext (-7749304166575005736)
-***
 *** This happens if you call a proof-function (prove/sat/runSMT/isSatisfiable) etc.
 *** while another one is in execution, or use results from one such call in another.
 *** Please avoid such nested calls, all interactions should be from the same context.
diff --git a/SBVTestSuite/GoldFiles/noOpt1.gold b/SBVTestSuite/GoldFiles/noOpt1.gold
--- a/SBVTestSuite/GoldFiles/noOpt1.gold
+++ b/SBVTestSuite/GoldFiles/noOpt1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_BV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/noOpt2.gold b/SBVTestSuite/GoldFiles/noOpt2.gold
--- a/SBVTestSuite/GoldFiles/noOpt2.gold
+++ b/SBVTestSuite/GoldFiles/noOpt2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_BV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/nonlinear_cvc4.gold b/SBVTestSuite/GoldFiles/nonlinear_cvc4.gold
--- a/SBVTestSuite/GoldFiles/nonlinear_cvc4.gold
+++ b/SBVTestSuite/GoldFiles/nonlinear_cvc4.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has algebraic reals, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/nonlinear_cvc5.gold b/SBVTestSuite/GoldFiles/nonlinear_cvc5.gold
--- a/SBVTestSuite/GoldFiles/nonlinear_cvc5.gold
+++ b/SBVTestSuite/GoldFiles/nonlinear_cvc5.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic HO_ALL) ; has algebraic reals, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/nonlinear_z3.gold b/SBVTestSuite/GoldFiles/nonlinear_z3.gold
--- a/SBVTestSuite/GoldFiles/nonlinear_z3.gold
+++ b/SBVTestSuite/GoldFiles/nonlinear_z3.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has algebraic reals, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/pbAtLeast.gold b/SBVTestSuite/GoldFiles/pbAtLeast.gold
--- a/SBVTestSuite/GoldFiles/pbAtLeast.gold
+++ b/SBVTestSuite/GoldFiles/pbAtLeast.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/pbAtMost.gold b/SBVTestSuite/GoldFiles/pbAtMost.gold
--- a/SBVTestSuite/GoldFiles/pbAtMost.gold
+++ b/SBVTestSuite/GoldFiles/pbAtMost.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/pbEq.gold b/SBVTestSuite/GoldFiles/pbEq.gold
--- a/SBVTestSuite/GoldFiles/pbEq.gold
+++ b/SBVTestSuite/GoldFiles/pbEq.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/pbEq2.gold b/SBVTestSuite/GoldFiles/pbEq2.gold
--- a/SBVTestSuite/GoldFiles/pbEq2.gold
+++ b/SBVTestSuite/GoldFiles/pbEq2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/pbExactly.gold b/SBVTestSuite/GoldFiles/pbExactly.gold
--- a/SBVTestSuite/GoldFiles/pbExactly.gold
+++ b/SBVTestSuite/GoldFiles/pbExactly.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/pbGe.gold b/SBVTestSuite/GoldFiles/pbGe.gold
--- a/SBVTestSuite/GoldFiles/pbGe.gold
+++ b/SBVTestSuite/GoldFiles/pbGe.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/pbLe.gold b/SBVTestSuite/GoldFiles/pbLe.gold
--- a/SBVTestSuite/GoldFiles/pbLe.gold
+++ b/SBVTestSuite/GoldFiles/pbLe.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/pbMutexed.gold b/SBVTestSuite/GoldFiles/pbMutexed.gold
--- a/SBVTestSuite/GoldFiles/pbMutexed.gold
+++ b/SBVTestSuite/GoldFiles/pbMutexed.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/pbStronglyMutexed.gold b/SBVTestSuite/GoldFiles/pbStronglyMutexed.gold
--- a/SBVTestSuite/GoldFiles/pbStronglyMutexed.gold
+++ b/SBVTestSuite/GoldFiles/pbStronglyMutexed.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/qEnum1.gold b/SBVTestSuite/GoldFiles/qEnum1.gold
--- a/SBVTestSuite/GoldFiles/qEnum1.gold
+++ b/SBVTestSuite/GoldFiles/qEnum1.gold
@@ -5,15 +5,25 @@
 [GOOD] (set-option :smtlib2_compliant true)
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
-[GOOD] (set-logic ALL) ; has user-defined sorts, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
-[GOOD] (declare-datatypes ((BinOp 0)) (((Plus) (Minus) (Times))))
-[GOOD] (define-fun BinOp_constrIndex ((x BinOp)) Int
-          (ite (= x Plus) 0 (ite (= x Minus) 1 2))
-       )
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: BinOp
+[GOOD] (declare-datatype BinOp (
+           (Plus)
+           (Minus)
+           (Times)
+       ))
 [GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () BinOp (as Plus BinOp))
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] (define-fun s6 () BinOp (as Minus BinOp))
+[GOOD] (define-fun s8 () Int 1)
+[GOOD] (define-fun s9 () Int 2)
 [GOOD] ; --- top level inputs ---
 [GOOD] (declare-fun s0 () BinOp) ; tracks user variable "p"
 [GOOD] (declare-fun s1 () BinOp) ; tracks user variable "m"
@@ -23,14 +33,26 @@
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s3 () Bool (<= (BinOp_constrIndex s0) (BinOp_constrIndex s1)))
-[GOOD] (define-fun s4 () Bool (<= (BinOp_constrIndex s1) (BinOp_constrIndex s2)))
-[GOOD] (define-fun s5 () Bool (distinct s0 s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s7 () Bool (= s0 s6))
+[GOOD] (define-fun s10 () Int (ite s7 s8 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s5 s10))
+[GOOD] (define-fun s12 () Bool (= s1 s3))
+[GOOD] (define-fun s13 () Bool (= s1 s6))
+[GOOD] (define-fun s14 () Int (ite s13 s8 s9))
+[GOOD] (define-fun s15 () Int (ite s12 s5 s14))
+[GOOD] (define-fun s16 () Bool (<= s11 s15))
+[GOOD] (define-fun s17 () Bool (= s2 s3))
+[GOOD] (define-fun s18 () Bool (= s2 s6))
+[GOOD] (define-fun s19 () Int (ite s18 s8 s9))
+[GOOD] (define-fun s20 () Int (ite s17 s5 s19))
+[GOOD] (define-fun s21 () Bool (<= s15 s20))
+[GOOD] (define-fun s22 () Bool (distinct s0 s1 s2))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
-[GOOD] (assert s3)
-[GOOD] (assert s4)
-[GOOD] (assert s5)
+[GOOD] (assert s16)
+[GOOD] (assert s21)
+[GOOD] (assert s22)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
diff --git a/SBVTestSuite/GoldFiles/qUninterp1.gold b/SBVTestSuite/GoldFiles/qUninterp1.gold
--- a/SBVTestSuite/GoldFiles/qUninterp1.gold
+++ b/SBVTestSuite/GoldFiles/qUninterp1.gold
@@ -5,14 +5,18 @@
 [GOOD] (set-option :smtlib2_compliant true)
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
-[GOOD] (set-logic ALL) ; has user-defined sorts, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
-[GOOD] (declare-datatypes ((L 0)) (((A) (B))))
-[GOOD] (define-fun L_constrIndex ((x L)) Int
-          (ite (= x A) 0 1)
-       )
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: L
+[GOOD] (declare-datatype L (
+           (A)
+           (B)
+       ))
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
 [GOOD] (declare-fun s0 () L)
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_0.gold b/SBVTestSuite/GoldFiles/quantifiedB_0.gold
--- a/SBVTestSuite/GoldFiles/quantifiedB_0.gold
+++ b/SBVTestSuite/GoldFiles/quantifiedB_0.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_1.gold b/SBVTestSuite/GoldFiles/quantifiedB_1.gold
--- a/SBVTestSuite/GoldFiles/quantifiedB_1.gold
+++ b/SBVTestSuite/GoldFiles/quantifiedB_1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_2.gold b/SBVTestSuite/GoldFiles/quantifiedB_2.gold
--- a/SBVTestSuite/GoldFiles/quantifiedB_2.gold
+++ b/SBVTestSuite/GoldFiles/quantifiedB_2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_3.gold b/SBVTestSuite/GoldFiles/quantifiedB_3.gold
--- a/SBVTestSuite/GoldFiles/quantifiedB_3.gold
+++ b/SBVTestSuite/GoldFiles/quantifiedB_3.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_4.gold b/SBVTestSuite/GoldFiles/quantifiedB_4.gold
--- a/SBVTestSuite/GoldFiles/quantifiedB_4.gold
+++ b/SBVTestSuite/GoldFiles/quantifiedB_4.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_5.gold b/SBVTestSuite/GoldFiles/quantifiedB_5.gold
--- a/SBVTestSuite/GoldFiles/quantifiedB_5.gold
+++ b/SBVTestSuite/GoldFiles/quantifiedB_5.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_6.gold b/SBVTestSuite/GoldFiles/quantifiedB_6.gold
--- a/SBVTestSuite/GoldFiles/quantifiedB_6.gold
+++ b/SBVTestSuite/GoldFiles/quantifiedB_6.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_7.gold b/SBVTestSuite/GoldFiles/quantifiedB_7.gold
--- a/SBVTestSuite/GoldFiles/quantifiedB_7.gold
+++ b/SBVTestSuite/GoldFiles/quantifiedB_7.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_8.gold b/SBVTestSuite/GoldFiles/quantifiedB_8.gold
--- a/SBVTestSuite/GoldFiles/quantifiedB_8.gold
+++ b/SBVTestSuite/GoldFiles/quantifiedB_8.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_9.gold b/SBVTestSuite/GoldFiles/quantifiedB_9.gold
--- a/SBVTestSuite/GoldFiles/quantifiedB_9.gold
+++ b/SBVTestSuite/GoldFiles/quantifiedB_9.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_A.gold b/SBVTestSuite/GoldFiles/quantifiedB_A.gold
--- a/SBVTestSuite/GoldFiles/quantifiedB_A.gold
+++ b/SBVTestSuite/GoldFiles/quantifiedB_A.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_B.gold b/SBVTestSuite/GoldFiles/quantifiedB_B.gold
--- a/SBVTestSuite/GoldFiles/quantifiedB_B.gold
+++ b/SBVTestSuite/GoldFiles/quantifiedB_B.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_c.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_p.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query1.gold b/SBVTestSuite/GoldFiles/query1.gold
--- a/SBVTestSuite/GoldFiles/query1.gold
+++ b/SBVTestSuite/GoldFiles/query1.gold
@@ -15,7 +15,6 @@
 [GOOD] (set-info :bad what)
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
@@ -73,7 +72,7 @@
 [SEND] (get-info :reason-unknown)
 [RECV] (:reason-unknown "state of the most recent check-sat command is not known")
 [SEND] (get-info :version)
-[RECV] (:version "4.15.3")
+[RECV] (:version "4.15.5")
 [SEND] (get-info :status)
 [RECV] (:status sat)
 [GOOD] (define-fun s16 () Int 4)
@@ -104,7 +103,7 @@
 [SEND] (get-info :reason-unknown)
 [RECV] (:reason-unknown "unknown")
 [SEND] (get-info :version)
-[RECV] (:version "4.15.3")
+[RECV] (:version "4.15.5")
 [SEND] (get-info :memory)
 [RECV] unsupported
 [SEND] (get-info :time)
diff --git a/SBVTestSuite/GoldFiles/queryArrays1.gold b/SBVTestSuite/GoldFiles/queryArrays1.gold
--- a/SBVTestSuite/GoldFiles/queryArrays1.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/queryArrays10.gold b/SBVTestSuite/GoldFiles/queryArrays10.gold
--- a/SBVTestSuite/GoldFiles/queryArrays10.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays10.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/queryArrays11.gold b/SBVTestSuite/GoldFiles/queryArrays11.gold
--- a/SBVTestSuite/GoldFiles/queryArrays11.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays11.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has non-bitvector arrays, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/queryArrays12.gold b/SBVTestSuite/GoldFiles/queryArrays12.gold
--- a/SBVTestSuite/GoldFiles/queryArrays12.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays12.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
diff --git a/SBVTestSuite/GoldFiles/queryArrays13.gold b/SBVTestSuite/GoldFiles/queryArrays13.gold
--- a/SBVTestSuite/GoldFiles/queryArrays13.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays13.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
diff --git a/SBVTestSuite/GoldFiles/queryArrays14.gold b/SBVTestSuite/GoldFiles/queryArrays14.gold
--- a/SBVTestSuite/GoldFiles/queryArrays14.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays14.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has rational values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
diff --git a/SBVTestSuite/GoldFiles/queryArrays15.gold b/SBVTestSuite/GoldFiles/queryArrays15.gold
--- a/SBVTestSuite/GoldFiles/queryArrays15.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays15.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has rational values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
diff --git a/SBVTestSuite/GoldFiles/queryArrays16.gold b/SBVTestSuite/GoldFiles/queryArrays16.gold
--- a/SBVTestSuite/GoldFiles/queryArrays16.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays16.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has rational values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
diff --git a/SBVTestSuite/GoldFiles/queryArrays17.gold b/SBVTestSuite/GoldFiles/queryArrays17.gold
--- a/SBVTestSuite/GoldFiles/queryArrays17.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays17.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has rational values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/queryArrays2.gold b/SBVTestSuite/GoldFiles/queryArrays2.gold
--- a/SBVTestSuite/GoldFiles/queryArrays2.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV) ; NB. User specified.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/queryArrays3.gold b/SBVTestSuite/GoldFiles/queryArrays3.gold
--- a/SBVTestSuite/GoldFiles/queryArrays3.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays3.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV) ; NB. User specified.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/queryArrays4.gold b/SBVTestSuite/GoldFiles/queryArrays4.gold
--- a/SBVTestSuite/GoldFiles/queryArrays4.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays4.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV) ; NB. User specified.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/queryArrays5.gold b/SBVTestSuite/GoldFiles/queryArrays5.gold
--- a/SBVTestSuite/GoldFiles/queryArrays5.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays5.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/queryArrays6.gold b/SBVTestSuite/GoldFiles/queryArrays6.gold
--- a/SBVTestSuite/GoldFiles/queryArrays6.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays6.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/queryArrays7.gold b/SBVTestSuite/GoldFiles/queryArrays7.gold
--- a/SBVTestSuite/GoldFiles/queryArrays7.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays7.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/queryArrays8.gold b/SBVTestSuite/GoldFiles/queryArrays8.gold
--- a/SBVTestSuite/GoldFiles/queryArrays8.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays8.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/queryArrays9.gold b/SBVTestSuite/GoldFiles/queryArrays9.gold
--- a/SBVTestSuite/GoldFiles/queryArrays9.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays9.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/queryTables.gold b/SBVTestSuite/GoldFiles/queryTables.gold
--- a/SBVTestSuite/GoldFiles/queryTables.gold
+++ b/SBVTestSuite/GoldFiles/queryTables.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
@@ -34,17 +33,19 @@
 [GOOD] (set-option :pp.max_depth      4294967295)
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
                                                          (proj_2_SBVTuple2 T2))))))
-[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
-                                           ((nothing_SBVMaybe)
-                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
 [GOOD] (define-fun s13 () (_ BitVec 16) #x000a)
 [GOOD] (define-fun s15 () (_ BitVec 16) (bvneg #x0001))
 [GOOD] (define-fun s17 () (_ BitVec 16) #x0007)
-[GOOD] (define-fun s19 () (SBVMaybe (_ BitVec 16)) ((as just_SBVMaybe (SBVMaybe (_ BitVec 16))) #x0000))
-[GOOD] (define-fun s20 () (SBVMaybe (_ BitVec 16)) (as nothing_SBVMaybe (SBVMaybe (_ BitVec 16))))
+[GOOD] (define-fun s19 () (Maybe (_ BitVec 16)) ((as Just (Maybe (_ BitVec 16))) #x0000))
+[GOOD] (define-fun s20 () (Maybe (_ BitVec 16)) (as Nothing (Maybe (_ BitVec 16))))
 [GOOD] (define-fun s28 () (_ BitVec 16) #x00ff)
 [GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 16))
 [GOOD] (define-fun s10 () (SBVTuple2 (_ BitVec 16) (_ BitVec 16)) ((as mkSBVTuple2 (SBVTuple2 (_ BitVec 16) (_ BitVec 16))) s0 s6))
@@ -53,10 +54,10 @@
 [GOOD] (define-fun s14 () Bool (= s11 s13))
 [GOOD] (define-fun s16 () (_ BitVec 16) (proj_2_SBVTuple2 s10))
 [GOOD] (define-fun s18 () Bool (= s16 s17))
-[GOOD] (define-fun s21 () (SBVMaybe (_ BitVec 16)) (ite s18 s19 s20))
-[GOOD] (define-fun s22 () (_ BitVec 16) (get_just_SBVMaybe s21))
-[GOOD] (define-fun s23 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe (_ BitVec 16)))) s21))
-[GOOD] (define-fun s24 () (_ BitVec 16) (ite s23 s15 s22))
+[GOOD] (define-fun s21 () (Maybe (_ BitVec 16)) (ite s18 s19 s20))
+[GOOD] (define-fun s22 () Bool ((as is-Nothing Bool) s21))
+[GOOD] (define-fun s23 () (_ BitVec 16) (getJust_1 s21))
+[GOOD] (define-fun s24 () (_ BitVec 16) (ite s22 s15 s23))
 [GOOD] (define-fun s25 () (_ BitVec 16) (ite (or (bvslt s24 #x0000) (bvsle #x0001 s24)) s15 (table0 s24)))
 [GOOD] (define-fun s26 () Bool (= s1 s25))
 [GOOD] (define-fun s27 () Bool (= s1 s24))
@@ -107,10 +108,10 @@
 [GOOD] (define-fun s60 () Bool (= s1 s59))
 [GOOD] (define-fun s61 () Bool (= s13 s44))
 [GOOD] (define-fun s62 () Bool (= s17 s46))
-[GOOD] (define-fun s63 () (SBVMaybe (_ BitVec 16)) (ite s62 s19 s20))
-[GOOD] (define-fun s64 () (_ BitVec 16) (get_just_SBVMaybe s63))
-[GOOD] (define-fun s65 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe (_ BitVec 16)))) s63))
-[GOOD] (define-fun s66 () (_ BitVec 16) (ite s65 s15 s64))
+[GOOD] (define-fun s63 () (Maybe (_ BitVec 16)) (ite s62 s19 s20))
+[GOOD] (define-fun s64 () Bool ((as is-Nothing Bool) s63))
+[GOOD] (define-fun s65 () (_ BitVec 16) (getJust_1 s63))
+[GOOD] (define-fun s66 () (_ BitVec 16) (ite s64 s15 s65))
 [GOOD] (define-fun s67 () (_ BitVec 16) (ite (or (bvslt s66 #x0000) (bvsle #x0001 s66)) s15 (table2 s66)))
 [GOOD] (define-fun s68 () Bool (= s1 s67))
 [GOOD] (define-fun s69 () Bool (= s1 s66))
diff --git a/SBVTestSuite/GoldFiles/query_Chars1.gold b/SBVTestSuite/GoldFiles/query_Chars1.gold
--- a/SBVTestSuite/GoldFiles/query_Chars1.gold
+++ b/SBVTestSuite/GoldFiles/query_Chars1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_Interpolant1.gold b/SBVTestSuite/GoldFiles/query_Interpolant1.gold
--- a/SBVTestSuite/GoldFiles/query_Interpolant1.gold
+++ b/SBVTestSuite/GoldFiles/query_Interpolant1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :produce-interpolants true)
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_Interpolant2.gold b/SBVTestSuite/GoldFiles/query_Interpolant2.gold
--- a/SBVTestSuite/GoldFiles/query_Interpolant2.gold
+++ b/SBVTestSuite/GoldFiles/query_Interpolant2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :produce-interpolants true)
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_Interpolant3.gold b/SBVTestSuite/GoldFiles/query_Interpolant3.gold
--- a/SBVTestSuite/GoldFiles/query_Interpolant3.gold
+++ b/SBVTestSuite/GoldFiles/query_Interpolant3.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_Interpolant4.gold b/SBVTestSuite/GoldFiles/query_Interpolant4.gold
--- a/SBVTestSuite/GoldFiles/query_Interpolant4.gold
+++ b/SBVTestSuite/GoldFiles/query_Interpolant4.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_ListOfMaybe.gold b/SBVTestSuite/GoldFiles/query_ListOfMaybe.gold
--- a/SBVTestSuite/GoldFiles/query_ListOfMaybe.gold
+++ b/SBVTestSuite/GoldFiles/query_ListOfMaybe.gold
@@ -9,45 +9,42 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
-                                           ((nothing_SBVMaybe)
-                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s2 () Int 2)
-[GOOD] (define-fun s4 () Int 0)
-[GOOD] (define-fun s8 () Int 1)
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s4 () Int 1)
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (Seq (SBVMaybe String))) ; tracks user variable "lst"
-[GOOD] (assert (forall ((seq0 Int)) (=> (and (>= seq0 0) (< seq0 (seq.len s0))) (=> ((_ is (just_SBVMaybe (String) (SBVMaybe String))) (seq.nth s0 seq0)) (= 1 (str.len (get_just_SBVMaybe (seq.nth s0 seq0))))))))
+[GOOD] (declare-fun s0 () (Seq (Maybe String))) ; tracks user variable "lst"
+[GOOD] (assert (forall ((seq0 Int)) (=> (and (>= seq0 0) (< seq0 (seq.len s0))) (= 1 (str.len (getJust_1 (seq.nth s0 seq0)))))))
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s1 () Int (seq.len s0))
-[GOOD] (define-fun s3 () Bool (= s1 s2))
-[GOOD] (define-fun s5 () (SBVMaybe String) (seq.nth s0 s4))
-[GOOD] (define-fun s6 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe String))) s5))
-[GOOD] (define-fun s7 () Bool (ite s6 false true))
-[GOOD] (define-fun s9 () Int (- s1 s8))
-[GOOD] (define-fun s10 () (Seq (SBVMaybe String)) (seq.extract s0 s8 s9))
-[GOOD] (define-fun s11 () (SBVMaybe String) (seq.nth s10 s4))
-[GOOD] (define-fun s12 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe String))) s11))
-[GOOD] (define-fun s13 () Bool (ite s12 true false))
+[GOOD] (define-fun s2 () (Maybe String) (seq.nth s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Just Bool) s2))
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Int (- s5 s4))
+[GOOD] (define-fun s7 () (Seq (Maybe String)) (seq.extract s0 s4 s6))
+[GOOD] (define-fun s8 () (Maybe String) (seq.nth s7 s1))
+[GOOD] (define-fun s9 () Bool ((as is-Nothing Bool) s8))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
 [GOOD] (assert s3)
-[GOOD] (assert s7)
-[GOOD] (assert s13)
+[GOOD] (assert s9)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (seq.++ (seq.unit (just_SBVMaybe "A")) (seq.unit nothing_SBVMaybe))))
+[RECV] ((s0 (seq.unit (Just "A"))))
 *** Solver   : Z3
 *** Exit code: ExitSuccess
 
 FINAL OUTPUT:
-[Just 'A',Nothing]
+[Just 'A']
diff --git a/SBVTestSuite/GoldFiles/query_ListOfSum.gold b/SBVTestSuite/GoldFiles/query_ListOfSum.gold
--- a/SBVTestSuite/GoldFiles/query_ListOfSum.gold
+++ b/SBVTestSuite/GoldFiles/query_ListOfSum.gold
@@ -9,45 +9,41 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s2 () Int 2)
-[GOOD] (define-fun s4 () Int 0)
-[GOOD] (define-fun s8 () Int 1)
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s4 () Int 1)
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (Seq (SBVEither Int String))) ; tracks user variable "lst"
-[GOOD] (assert (forall ((seq0 Int)) (=> (and (>= seq0 0) (< seq0 (seq.len s0))) (=> ((_ is (right_SBVEither (String) (SBVEither Int String))) (seq.nth s0 seq0)) (= 1 (str.len (get_right_SBVEither (seq.nth s0 seq0))))))))
+[GOOD] (declare-fun s0 () (Seq (Either Int Int))) ; tracks user variable "lst"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s1 () Int (seq.len s0))
-[GOOD] (define-fun s3 () Bool (= s1 s2))
-[GOOD] (define-fun s5 () (SBVEither Int String) (seq.nth s0 s4))
-[GOOD] (define-fun s6 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int String))) s5))
-[GOOD] (define-fun s7 () Bool (ite s6 true false))
-[GOOD] (define-fun s9 () Int (- s1 s8))
-[GOOD] (define-fun s10 () (Seq (SBVEither Int String)) (seq.extract s0 s8 s9))
-[GOOD] (define-fun s11 () (SBVEither Int String) (seq.nth s10 s4))
-[GOOD] (define-fun s12 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int String))) s11))
-[GOOD] (define-fun s13 () Bool (ite s12 false true))
+[GOOD] (define-fun s2 () (Either Int Int) (seq.nth s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Left Bool) s2))
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Int (- s5 s4))
+[GOOD] (define-fun s7 () (Seq (Either Int Int)) (seq.extract s0 s4 s6))
+[GOOD] (define-fun s8 () (Either Int Int) (seq.nth s7 s1))
+[GOOD] (define-fun s9 () Bool ((as is-Right Bool) s8))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
 [GOOD] (assert s3)
-[GOOD] (assert s7)
-[GOOD] (assert s13)
+[GOOD] (assert s9)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (seq.++ (seq.unit (left_SBVEither 3)) (seq.unit (right_SBVEither "A")))))
+[RECV] ((s0 (seq.unit (Left 3))))
 *** Solver   : Z3
 *** Exit code: ExitSuccess
 
 FINAL OUTPUT:
-[Left 3,Right 'A']
+[Left 3]
diff --git a/SBVTestSuite/GoldFiles/query_Lists1.gold b/SBVTestSuite/GoldFiles/query_Lists1.gold
--- a/SBVTestSuite/GoldFiles/query_Lists1.gold
+++ b/SBVTestSuite/GoldFiles/query_Lists1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_Maybe.gold b/SBVTestSuite/GoldFiles/query_Maybe.gold
--- a/SBVTestSuite/GoldFiles/query_Maybe.gold
+++ b/SBVTestSuite/GoldFiles/query_Maybe.gold
@@ -9,32 +9,35 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
-                                           ((nothing_SBVMaybe)
-                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 1)
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVMaybe Int)) ; tracks user variable "a"
+[GOOD] (declare-fun s0 () (Maybe Int)) ; tracks user variable "a"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s1 () Int (get_just_SBVMaybe s0))
-[GOOD] (define-fun s3 () Bool (= s1 s2))
-[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s0))
-[GOOD] (define-fun s5 () Bool (ite s4 false s3))
+[GOOD] (define-fun s1 () Bool ((as is-Nothing Bool) s0))
+[GOOD] (define-fun s2 () Int (getJust_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (not s1))
+[GOOD] (define-fun s6 () Bool (and s4 s5))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
-[GOOD] (assert s5)
+[GOOD] (assert s6)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (just_SBVMaybe 1)))
+[RECV] ((s0 (Just 1)))
 *** Solver   : Z3
 *** Exit code: ExitSuccess
 
diff --git a/SBVTestSuite/GoldFiles/query_Strings1.gold b/SBVTestSuite/GoldFiles/query_Strings1.gold
--- a/SBVTestSuite/GoldFiles/query_Strings1.gold
+++ b/SBVTestSuite/GoldFiles/query_Strings1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has strings, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
@@ -17,7 +16,7 @@
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s1 () Bool (str.in.re s0 ((_ re.loop 5 5) (str.to.re "xyz"))))
+[GOOD] (define-fun s1 () Bool (str.in_re s0 ((_ re.loop 5 5) (str.to.re "xyz"))))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
 [GOOD] (assert s1)
diff --git a/SBVTestSuite/GoldFiles/query_SumMaybeBoth.gold b/SBVTestSuite/GoldFiles/query_SumMaybeBoth.gold
--- a/SBVTestSuite/GoldFiles/query_SumMaybeBoth.gold
+++ b/SBVTestSuite/GoldFiles/query_SumMaybeBoth.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
@@ -21,29 +20,31 @@
 [GOOD] (set-option :pp.max_depth      4294967295)
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
-[GOOD] (declare-fun s0 () (SBVEither Int Int))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] (declare-fun s0 () (Either Int Int))
 [GOOD] (set-option :pp.max_depth      4294967295)
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
-[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
-                                           ((nothing_SBVMaybe)
-                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
-[GOOD] (declare-fun s1 () (SBVMaybe Int))
-[GOOD] (define-fun s2 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Int))) s0))
-[GOOD] (define-fun s3 () Bool (ite s2 true false))
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] (declare-fun s1 () (Maybe Int))
+[GOOD] (define-fun s2 () Bool ((as is-Left Bool) s0))
+[GOOD] (assert s2)
+[GOOD] (define-fun s3 () Bool ((as is-Just Bool) s1))
 [GOOD] (assert s3)
-[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s1))
-[GOOD] (define-fun s5 () Bool (ite s4 false true))
-[GOOD] (assert s5)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (left_SBVEither 2)))
+[RECV] ((s0 (Left 2)))
 [SEND] (get-value (s1))
-[RECV] ((s1 (just_SBVMaybe 3)))
+[RECV] ((s1 (Just 3)))
 *** Solver   : Z3
 *** Exit code: ExitSuccess
 
diff --git a/SBVTestSuite/GoldFiles/query_Sums.gold b/SBVTestSuite/GoldFiles/query_Sums.gold
--- a/SBVTestSuite/GoldFiles/query_Sums.gold
+++ b/SBVTestSuite/GoldFiles/query_Sums.gold
@@ -9,33 +9,35 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 1)
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVEither Int String)) ; tracks user variable "a"
-[GOOD] (assert (=> ((_ is (right_SBVEither (String) (SBVEither Int String))) s0) (= 1 (str.len (get_right_SBVEither s0)))))
+[GOOD] (declare-fun s0 () (Either Int String)) ; tracks user variable "a"
+[GOOD] (assert (= 1 (str.len (getRight_1 s0))))
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s1 () Int (get_left_SBVEither s0))
-[GOOD] (define-fun s3 () Bool (= s1 s2))
-[GOOD] (define-fun s4 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int String))) s0))
-[GOOD] (define-fun s5 () Bool (ite s4 s3 false))
+[GOOD] (define-fun s1 () Bool ((as is-Left Bool) s0))
+[GOOD] (define-fun s2 () Int (getLeft_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
 [GOOD] (assert s5)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (left_SBVEither 1)))
+[RECV] ((s0 (Left 1)))
 *** Solver   : Z3
 *** Exit code: ExitSuccess
 
diff --git a/SBVTestSuite/GoldFiles/query_Tuples1.gold b/SBVTestSuite/GoldFiles/query_Tuples1.gold
--- a/SBVTestSuite/GoldFiles/query_Tuples1.gold
+++ b/SBVTestSuite/GoldFiles/query_Tuples1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/query_Tuples2.gold b/SBVTestSuite/GoldFiles/query_Tuples2.gold
--- a/SBVTestSuite/GoldFiles/query_Tuples2.gold
+++ b/SBVTestSuite/GoldFiles/query_Tuples2.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple0 0)) (((mkSBVTuple0))))
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
diff --git a/SBVTestSuite/GoldFiles/query_abc.gold b/SBVTestSuite/GoldFiles/query_abc.gold
--- a/SBVTestSuite/GoldFiles/query_abc.gold
+++ b/SBVTestSuite/GoldFiles/query_abc.gold
@@ -6,7 +6,6 @@
 [ISSUE] (set-option :diagnostic-output-channel "stdout")
 [ISSUE] (set-option :produce-models true)
 [ISSUE] (set-logic ALL) ; external query, using all logics.
-[ISSUE] ; --- uninterpreted sorts ---
 [ISSUE] ; --- tuples ---
 [ISSUE] ; --- sums ---
 [ISSUE] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_bitwuzla.gold b/SBVTestSuite/GoldFiles/query_bitwuzla.gold
--- a/SBVTestSuite/GoldFiles/query_bitwuzla.gold
+++ b/SBVTestSuite/GoldFiles/query_bitwuzla.gold
@@ -4,7 +4,6 @@
 [GOOD] (set-option :global-declarations true)
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_boolector.gold b/SBVTestSuite/GoldFiles/query_boolector.gold
--- a/SBVTestSuite/GoldFiles/query_boolector.gold
+++ b/SBVTestSuite/GoldFiles/query_boolector.gold
@@ -4,7 +4,6 @@
 [GOOD] (set-option :global-declarations true)
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_cvc4.gold b/SBVTestSuite/GoldFiles/query_cvc4.gold
--- a/SBVTestSuite/GoldFiles/query_cvc4.gold
+++ b/SBVTestSuite/GoldFiles/query_cvc4.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_cvc5.gold b/SBVTestSuite/GoldFiles/query_cvc5.gold
--- a/SBVTestSuite/GoldFiles/query_cvc5.gold
+++ b/SBVTestSuite/GoldFiles/query_cvc5.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_mathsat.gold b/SBVTestSuite/GoldFiles/query_mathsat.gold
--- a/SBVTestSuite/GoldFiles/query_mathsat.gold
+++ b/SBVTestSuite/GoldFiles/query_mathsat.gold
@@ -5,7 +5,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_sumMergeEither1.gold b/SBVTestSuite/GoldFiles/query_sumMergeEither1.gold
--- a/SBVTestSuite/GoldFiles/query_sumMergeEither1.gold
+++ b/SBVTestSuite/GoldFiles/query_sumMergeEither1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
@@ -21,22 +20,23 @@
 [GOOD] (set-option :pp.max_depth      4294967295)
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
-[GOOD] (declare-fun s0 () (SBVEither Int Bool))
-[GOOD] (declare-fun s1 () (SBVEither Int Bool))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] (declare-fun s0 () (Either Int Bool))
+[GOOD] (declare-fun s1 () (Either Int Bool))
 [GOOD] (declare-fun s2 () Bool)
-[GOOD] (define-fun s3 () (SBVEither Int Bool) (ite s2 s0 s1))
-[GOOD] (define-fun s4 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Bool))) s3))
-[GOOD] (define-fun s5 () Bool (ite s4 true false))
-[GOOD] (assert s5)
+[GOOD] (define-fun s3 () (Either Int Bool) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Left Bool) s3))
+[GOOD] (assert s4)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (left_SBVEither 2)))
+[RECV] ((s0 (Left 2)))
 [SEND] (get-value (s1))
-[RECV] ((s1 (left_SBVEither 2)))
+[RECV] ((s1 (Left 2)))
 [SEND] (get-value (s2))
 [RECV] ((s2 false))
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/query_sumMergeEither2.gold b/SBVTestSuite/GoldFiles/query_sumMergeEither2.gold
--- a/SBVTestSuite/GoldFiles/query_sumMergeEither2.gold
+++ b/SBVTestSuite/GoldFiles/query_sumMergeEither2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
@@ -21,22 +20,23 @@
 [GOOD] (set-option :pp.max_depth      4294967295)
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
-[GOOD] (declare-fun s0 () (SBVEither Int Bool))
-[GOOD] (declare-fun s1 () (SBVEither Int Bool))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] (declare-fun s0 () (Either Int Bool))
+[GOOD] (declare-fun s1 () (Either Int Bool))
 [GOOD] (declare-fun s2 () Bool)
-[GOOD] (define-fun s3 () (SBVEither Int Bool) (ite s2 s0 s1))
-[GOOD] (define-fun s4 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Bool))) s3))
-[GOOD] (define-fun s5 () Bool (ite s4 false true))
-[GOOD] (assert s5)
+[GOOD] (define-fun s3 () (Either Int Bool) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Right Bool) s3))
+[GOOD] (assert s4)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (right_SBVEither false)))
+[RECV] ((s0 (Right false)))
 [SEND] (get-value (s1))
-[RECV] ((s1 (right_SBVEither false)))
+[RECV] ((s1 (Right false)))
 [SEND] (get-value (s2))
 [RECV] ((s2 false))
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/query_sumMergeMaybe1.gold b/SBVTestSuite/GoldFiles/query_sumMergeMaybe1.gold
--- a/SBVTestSuite/GoldFiles/query_sumMergeMaybe1.gold
+++ b/SBVTestSuite/GoldFiles/query_sumMergeMaybe1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
@@ -21,22 +20,23 @@
 [GOOD] (set-option :pp.max_depth      4294967295)
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
-[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
-                                           ((nothing_SBVMaybe)
-                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
-[GOOD] (declare-fun s0 () (SBVMaybe Int))
-[GOOD] (declare-fun s1 () (SBVMaybe Int))
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] (declare-fun s0 () (Maybe Int))
+[GOOD] (declare-fun s1 () (Maybe Int))
 [GOOD] (declare-fun s2 () Bool)
-[GOOD] (define-fun s3 () (SBVMaybe Int) (ite s2 s0 s1))
-[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s3))
-[GOOD] (define-fun s5 () Bool (ite s4 true false))
-[GOOD] (assert s5)
+[GOOD] (define-fun s3 () (Maybe Int) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Nothing Bool) s3))
+[GOOD] (assert s4)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 nothing_SBVMaybe))
+[RECV] ((s0 Nothing))
 [SEND] (get-value (s1))
-[RECV] ((s1 nothing_SBVMaybe))
+[RECV] ((s1 Nothing))
 [SEND] (get-value (s2))
 [RECV] ((s2 false))
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/query_sumMergeMaybe2.gold b/SBVTestSuite/GoldFiles/query_sumMergeMaybe2.gold
--- a/SBVTestSuite/GoldFiles/query_sumMergeMaybe2.gold
+++ b/SBVTestSuite/GoldFiles/query_sumMergeMaybe2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
@@ -21,22 +20,23 @@
 [GOOD] (set-option :pp.max_depth      4294967295)
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
-[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
-                                           ((nothing_SBVMaybe)
-                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
-[GOOD] (declare-fun s0 () (SBVMaybe Int))
-[GOOD] (declare-fun s1 () (SBVMaybe Int))
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] (declare-fun s0 () (Maybe Int))
+[GOOD] (declare-fun s1 () (Maybe Int))
 [GOOD] (declare-fun s2 () Bool)
-[GOOD] (define-fun s3 () (SBVMaybe Int) (ite s2 s0 s1))
-[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s3))
-[GOOD] (define-fun s5 () Bool (ite s4 false true))
-[GOOD] (assert s5)
+[GOOD] (define-fun s3 () (Maybe Int) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Just Bool) s3))
+[GOOD] (assert s4)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (just_SBVMaybe 2)))
+[RECV] ((s0 (Just 2)))
 [SEND] (get-value (s1))
-[RECV] ((s1 (just_SBVMaybe 2)))
+[RECV] ((s1 (Just 2)))
 [SEND] (get-value (s2))
 [RECV] ((s2 false))
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/query_uiSat_test1.gold b/SBVTestSuite/GoldFiles/query_uiSat_test1.gold
--- a/SBVTestSuite/GoldFiles/query_uiSat_test1.gold
+++ b/SBVTestSuite/GoldFiles/query_uiSat_test1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; NB. User specified.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_uiSat_test2.gold b/SBVTestSuite/GoldFiles/query_uiSat_test2.gold
--- a/SBVTestSuite/GoldFiles/query_uiSat_test2.gold
+++ b/SBVTestSuite/GoldFiles/query_uiSat_test2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; NB. User specified.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_uisatex1.gold b/SBVTestSuite/GoldFiles/query_uisatex1.gold
--- a/SBVTestSuite/GoldFiles/query_uisatex1.gold
+++ b/SBVTestSuite/GoldFiles/query_uisatex1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_uisatex2.gold b/SBVTestSuite/GoldFiles/query_uisatex2.gold
--- a/SBVTestSuite/GoldFiles/query_uisatex2.gold
+++ b/SBVTestSuite/GoldFiles/query_uisatex2.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_uisatex3.gold b/SBVTestSuite/GoldFiles/query_uisatex3.gold
--- a/SBVTestSuite/GoldFiles/query_uisatex3.gold
+++ b/SBVTestSuite/GoldFiles/query_uisatex3.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
@@ -34,5 +33,5 @@
 *** Exit code: ExitSuccess
 
  FINAL:
-("y x = 3 * x",(True,Just ["x"],EApp [ECon "lambda",EApp [EApp [ECon "x!1",ECon "Int"]],EApp [ECon "*",ENum (3,Nothing),ECon "x!1"]]))
+("y x = 3 * x",(True,Just ["x"],EApp [ECon "lambda",EApp [EApp [ECon "x!1",ECon "Int"]],EApp [ECon "*",ENum (3,Nothing,False),ECon "x!1"]]))
 DONE!
diff --git a/SBVTestSuite/GoldFiles/query_yices.gold b/SBVTestSuite/GoldFiles/query_yices.gold
--- a/SBVTestSuite/GoldFiles/query_yices.gold
+++ b/SBVTestSuite/GoldFiles/query_yices.gold
@@ -4,7 +4,6 @@
 [GOOD] (set-option :global-declarations true)
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/query_z3.gold b/SBVTestSuite/GoldFiles/query_z3.gold
--- a/SBVTestSuite/GoldFiles/query_z3.gold
+++ b/SBVTestSuite/GoldFiles/query_z3.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/safe1.gold b/SBVTestSuite/GoldFiles/safe1.gold
--- a/SBVTestSuite/GoldFiles/safe1.gold
+++ b/SBVTestSuite/GoldFiles/safe1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/safe2.gold b/SBVTestSuite/GoldFiles/safe2.gold
--- a/SBVTestSuite/GoldFiles/safe2.gold
+++ b/SBVTestSuite/GoldFiles/safe2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/seqConcat.gold b/SBVTestSuite/GoldFiles/seqConcat.gold
--- a/SBVTestSuite/GoldFiles/seqConcat.gold
+++ b/SBVTestSuite/GoldFiles/seqConcat.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/seqConcatBad.gold b/SBVTestSuite/GoldFiles/seqConcatBad.gold
--- a/SBVTestSuite/GoldFiles/seqConcatBad.gold
+++ b/SBVTestSuite/GoldFiles/seqConcatBad.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/seqExamples1.gold b/SBVTestSuite/GoldFiles/seqExamples1.gold
--- a/SBVTestSuite/GoldFiles/seqExamples1.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/seqExamples2.gold b/SBVTestSuite/GoldFiles/seqExamples2.gold
--- a/SBVTestSuite/GoldFiles/seqExamples2.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples2.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/seqExamples3.gold b/SBVTestSuite/GoldFiles/seqExamples3.gold
--- a/SBVTestSuite/GoldFiles/seqExamples3.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples3.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/seqExamples4.gold b/SBVTestSuite/GoldFiles/seqExamples4.gold
--- a/SBVTestSuite/GoldFiles/seqExamples4.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples4.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/seqExamples5.gold b/SBVTestSuite/GoldFiles/seqExamples5.gold
--- a/SBVTestSuite/GoldFiles/seqExamples5.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples5.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/seqExamples6.gold b/SBVTestSuite/GoldFiles/seqExamples6.gold
--- a/SBVTestSuite/GoldFiles/seqExamples6.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples6.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/seqExamples7.gold b/SBVTestSuite/GoldFiles/seqExamples7.gold
--- a/SBVTestSuite/GoldFiles/seqExamples7.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples7.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/seqExamples8.gold b/SBVTestSuite/GoldFiles/seqExamples8.gold
--- a/SBVTestSuite/GoldFiles/seqExamples8.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples8.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/seqIndexOf.gold b/SBVTestSuite/GoldFiles/seqIndexOf.gold
--- a/SBVTestSuite/GoldFiles/seqIndexOf.gold
+++ b/SBVTestSuite/GoldFiles/seqIndexOf.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/seqIndexOfBad.gold b/SBVTestSuite/GoldFiles/seqIndexOfBad.gold
--- a/SBVTestSuite/GoldFiles/seqIndexOfBad.gold
+++ b/SBVTestSuite/GoldFiles/seqIndexOfBad.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/set_compl1.gold b/SBVTestSuite/GoldFiles/set_compl1.gold
--- a/SBVTestSuite/GoldFiles/set_compl1.gold
+++ b/SBVTestSuite/GoldFiles/set_compl1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/set_delete1.gold b/SBVTestSuite/GoldFiles/set_delete1.gold
--- a/SBVTestSuite/GoldFiles/set_delete1.gold
+++ b/SBVTestSuite/GoldFiles/set_delete1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/set_diff1.gold b/SBVTestSuite/GoldFiles/set_diff1.gold
--- a/SBVTestSuite/GoldFiles/set_diff1.gold
+++ b/SBVTestSuite/GoldFiles/set_diff1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/set_disj1.gold b/SBVTestSuite/GoldFiles/set_disj1.gold
--- a/SBVTestSuite/GoldFiles/set_disj1.gold
+++ b/SBVTestSuite/GoldFiles/set_disj1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/set_empty1.gold b/SBVTestSuite/GoldFiles/set_empty1.gold
--- a/SBVTestSuite/GoldFiles/set_empty1.gold
+++ b/SBVTestSuite/GoldFiles/set_empty1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/set_full1.gold b/SBVTestSuite/GoldFiles/set_full1.gold
--- a/SBVTestSuite/GoldFiles/set_full1.gold
+++ b/SBVTestSuite/GoldFiles/set_full1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/set_insert1.gold b/SBVTestSuite/GoldFiles/set_insert1.gold
--- a/SBVTestSuite/GoldFiles/set_insert1.gold
+++ b/SBVTestSuite/GoldFiles/set_insert1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/set_intersect1.gold b/SBVTestSuite/GoldFiles/set_intersect1.gold
--- a/SBVTestSuite/GoldFiles/set_intersect1.gold
+++ b/SBVTestSuite/GoldFiles/set_intersect1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/set_member1.gold b/SBVTestSuite/GoldFiles/set_member1.gold
--- a/SBVTestSuite/GoldFiles/set_member1.gold
+++ b/SBVTestSuite/GoldFiles/set_member1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/set_notMember1.gold b/SBVTestSuite/GoldFiles/set_notMember1.gold
--- a/SBVTestSuite/GoldFiles/set_notMember1.gold
+++ b/SBVTestSuite/GoldFiles/set_notMember1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/set_psubset1.gold b/SBVTestSuite/GoldFiles/set_psubset1.gold
--- a/SBVTestSuite/GoldFiles/set_psubset1.gold
+++ b/SBVTestSuite/GoldFiles/set_psubset1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/set_subset1.gold b/SBVTestSuite/GoldFiles/set_subset1.gold
--- a/SBVTestSuite/GoldFiles/set_subset1.gold
+++ b/SBVTestSuite/GoldFiles/set_subset1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/set_tupleSet.gold b/SBVTestSuite/GoldFiles/set_tupleSet.gold
--- a/SBVTestSuite/GoldFiles/set_tupleSet.gold
+++ b/SBVTestSuite/GoldFiles/set_tupleSet.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has tuples, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/set_uninterp1.gold b/SBVTestSuite/GoldFiles/set_uninterp1.gold
--- a/SBVTestSuite/GoldFiles/set_uninterp1.gold
+++ b/SBVTestSuite/GoldFiles/set_uninterp1.gold
@@ -8,14 +8,16 @@
 [GOOD] (set-option :pp.max_depth      4294967295)
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
-[GOOD] (set-logic ALL) ; has user-defined sorts, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
-[GOOD] (declare-datatypes ((E 0)) (((A) (B) (C))))
-[GOOD] (define-fun E_constrIndex ((x E)) Int
-          (ite (= x A) 0 (ite (= x B) 1 2))
-       )
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: E
+[GOOD] (declare-datatype E (
+           (A)
+           (B)
+           (C)
+       ))
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
 [GOOD] (declare-fun s0 () (Array E Bool))
@@ -40,63 +42,63 @@
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (store ((as const (Array E Bool)) false) B true)))
+[RECV] ((s0 ((as const (Array E Bool)) true)))
 [GOOD] (push 1)
-[GOOD] (define-fun s3 () (Array E Bool) (store ((as const (Array E Bool)) false) B true))
+[GOOD] (define-fun s3 () (Array E Bool) ((as const (Array E Bool)) true))
 [GOOD] (define-fun s4 () Bool (distinct s0 s3))
 [GOOD] (assert s4)
 Fast allSat, Looking for solution 3
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (store ((as const (Array E Bool)) false) A true)))
+[RECV] ((s0 (store ((as const (Array E Bool)) true) A false)))
 [GOOD] (push 1)
-[GOOD] (define-fun s5 () (Array E Bool) (store ((as const (Array E Bool)) false) A true))
+[GOOD] (define-fun s5 () (Array E Bool) (store ((as const (Array E Bool)) true) (as A E) false))
 [GOOD] (define-fun s6 () Bool (distinct s0 s5))
 [GOOD] (assert s6)
 Fast allSat, Looking for solution 4
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (store (store ((as const (Array E Bool)) false) C true) A true)))
+[RECV] ((s0 (store ((as const (Array E Bool)) false) A true)))
 [GOOD] (push 1)
-[GOOD] (define-fun s7 () (Array E Bool) (store (store ((as const (Array E Bool)) false) C true) A true))
+[GOOD] (define-fun s7 () (Array E Bool) (store ((as const (Array E Bool)) false) (as A E) true))
 [GOOD] (define-fun s8 () Bool (distinct s0 s7))
 [GOOD] (assert s8)
 Fast allSat, Looking for solution 5
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 ((as const (Array E Bool)) true)))
+[RECV] ((s0 (store (store ((as const (Array E Bool)) false) C true) A true)))
 [GOOD] (push 1)
-[GOOD] (define-fun s9 () (Array E Bool) ((as const (Array E Bool)) true))
+[GOOD] (define-fun s9 () (Array E Bool) (store (store ((as const (Array E Bool)) false) (as C E) true) (as A E) true))
 [GOOD] (define-fun s10 () Bool (distinct s0 s9))
 [GOOD] (assert s10)
 Fast allSat, Looking for solution 6
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (store (store ((as const (Array E Bool)) false) B true) A true)))
+[RECV] ((s0 (store ((as const (Array E Bool)) false) C true)))
 [GOOD] (push 1)
-[GOOD] (define-fun s11 () (Array E Bool) (store (store ((as const (Array E Bool)) false) B true) A true))
+[GOOD] (define-fun s11 () (Array E Bool) (store ((as const (Array E Bool)) false) (as C E) true))
 [GOOD] (define-fun s12 () Bool (distinct s0 s11))
 [GOOD] (assert s12)
 Fast allSat, Looking for solution 7
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (store (store ((as const (Array E Bool)) false) C true) B true)))
+[RECV] ((s0 (store (store ((as const (Array E Bool)) true) C false) A false)))
 [GOOD] (push 1)
-[GOOD] (define-fun s13 () (Array E Bool) (store (store ((as const (Array E Bool)) false) C true) B true))
+[GOOD] (define-fun s13 () (Array E Bool) (store (store ((as const (Array E Bool)) true) (as C E) false) (as A E) false))
 [GOOD] (define-fun s14 () Bool (distinct s0 s13))
 [GOOD] (assert s14)
 Fast allSat, Looking for solution 8
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (store ((as const (Array E Bool)) false) C true)))
+[RECV] ((s0 (store ((as const (Array E Bool)) true) C false)))
 [GOOD] (push 1)
-[GOOD] (define-fun s15 () (Array E Bool) (store ((as const (Array E Bool)) false) C true))
+[GOOD] (define-fun s15 () (Array E Bool) (store ((as const (Array E Bool)) true) (as C E) false))
 [GOOD] (define-fun s16 () Bool (distinct s0 s15))
 [GOOD] (assert s16)
 Fast allSat, Looking for solution 9
@@ -115,19 +117,19 @@
 
 FINAL:
 Solution #1:
-  s0 = {C} :: {E}
+  s0 = U - {C} :: {E}
 Solution #2:
-  s0 = {B,C} :: {E}
+  s0 = U - {A,C} :: {E}
 Solution #3:
-  s0 = {A,B} :: {E}
+  s0 = {C} :: {E}
 Solution #4:
-  s0 = U :: {E}
-Solution #5:
   s0 = {A,C} :: {E}
-Solution #6:
+Solution #5:
   s0 = {A} :: {E}
+Solution #6:
+  s0 = U - {A} :: {E}
 Solution #7:
-  s0 = {B} :: {E}
+  s0 = U :: {E}
 Solution #8:
   s0 = {} :: {E}
 Found 8 different solutions.
diff --git a/SBVTestSuite/GoldFiles/set_uninterp2.gold b/SBVTestSuite/GoldFiles/set_uninterp2.gold
--- a/SBVTestSuite/GoldFiles/set_uninterp2.gold
+++ b/SBVTestSuite/GoldFiles/set_uninterp2.gold
@@ -8,14 +8,16 @@
 [GOOD] (set-option :pp.max_depth      4294967295)
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
-[GOOD] (set-logic ALL) ; has user-defined sorts, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
-[GOOD] (declare-datatypes ((E 0)) (((A) (B) (C))))
-[GOOD] (define-fun E_constrIndex ((x E)) Int
-          (ite (= x A) 0 (ite (= x B) 1 2))
-       )
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: E
+[GOOD] (declare-datatype E (
+           (A)
+           (B)
+           (C)
+       ))
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
 [GOOD] (declare-fun s0 () (Array E Bool)) ; tracks user variable "a"
diff --git a/SBVTestSuite/GoldFiles/set_union1.gold b/SBVTestSuite/GoldFiles/set_union1.gold
--- a/SBVTestSuite/GoldFiles/set_union1.gold
+++ b/SBVTestSuite/GoldFiles/set_union1.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strConcat.gold b/SBVTestSuite/GoldFiles/strConcat.gold
--- a/SBVTestSuite/GoldFiles/strConcat.gold
+++ b/SBVTestSuite/GoldFiles/strConcat.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strConcatBad.gold b/SBVTestSuite/GoldFiles/strConcatBad.gold
--- a/SBVTestSuite/GoldFiles/strConcatBad.gold
+++ b/SBVTestSuite/GoldFiles/strConcatBad.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strExamples1.gold b/SBVTestSuite/GoldFiles/strExamples1.gold
--- a/SBVTestSuite/GoldFiles/strExamples1.gold
+++ b/SBVTestSuite/GoldFiles/strExamples1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strExamples10.gold b/SBVTestSuite/GoldFiles/strExamples10.gold
--- a/SBVTestSuite/GoldFiles/strExamples10.gold
+++ b/SBVTestSuite/GoldFiles/strExamples10.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
@@ -18,7 +17,7 @@
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s1 () Bool (str.in.re s0 ((_ re.loop 1 3) (str.to.re "ab"))))
+[GOOD] (define-fun s1 () Bool (str.in_re s0 ((_ re.loop 1 3) (str.to.re "ab"))))
 [GOOD] (define-fun s2 () Int (str.len s0))
 [GOOD] (define-fun s4 () Bool (> s2 s3))
 [GOOD] ; --- delayedEqualities ---
diff --git a/SBVTestSuite/GoldFiles/strExamples11.gold b/SBVTestSuite/GoldFiles/strExamples11.gold
--- a/SBVTestSuite/GoldFiles/strExamples11.gold
+++ b/SBVTestSuite/GoldFiles/strExamples11.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strExamples12.gold b/SBVTestSuite/GoldFiles/strExamples12.gold
--- a/SBVTestSuite/GoldFiles/strExamples12.gold
+++ b/SBVTestSuite/GoldFiles/strExamples12.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strExamples13.gold b/SBVTestSuite/GoldFiles/strExamples13.gold
--- a/SBVTestSuite/GoldFiles/strExamples13.gold
+++ b/SBVTestSuite/GoldFiles/strExamples13.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strExamples2.gold b/SBVTestSuite/GoldFiles/strExamples2.gold
--- a/SBVTestSuite/GoldFiles/strExamples2.gold
+++ b/SBVTestSuite/GoldFiles/strExamples2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has strings, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strExamples3.gold b/SBVTestSuite/GoldFiles/strExamples3.gold
--- a/SBVTestSuite/GoldFiles/strExamples3.gold
+++ b/SBVTestSuite/GoldFiles/strExamples3.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has strings, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strExamples4.gold b/SBVTestSuite/GoldFiles/strExamples4.gold
--- a/SBVTestSuite/GoldFiles/strExamples4.gold
+++ b/SBVTestSuite/GoldFiles/strExamples4.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strExamples5.gold b/SBVTestSuite/GoldFiles/strExamples5.gold
--- a/SBVTestSuite/GoldFiles/strExamples5.gold
+++ b/SBVTestSuite/GoldFiles/strExamples5.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has strings, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strExamples6.gold b/SBVTestSuite/GoldFiles/strExamples6.gold
--- a/SBVTestSuite/GoldFiles/strExamples6.gold
+++ b/SBVTestSuite/GoldFiles/strExamples6.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has strings, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strExamples7.gold b/SBVTestSuite/GoldFiles/strExamples7.gold
--- a/SBVTestSuite/GoldFiles/strExamples7.gold
+++ b/SBVTestSuite/GoldFiles/strExamples7.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has strings, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strExamples8.gold b/SBVTestSuite/GoldFiles/strExamples8.gold
--- a/SBVTestSuite/GoldFiles/strExamples8.gold
+++ b/SBVTestSuite/GoldFiles/strExamples8.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strExamples9.gold b/SBVTestSuite/GoldFiles/strExamples9.gold
--- a/SBVTestSuite/GoldFiles/strExamples9.gold
+++ b/SBVTestSuite/GoldFiles/strExamples9.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
@@ -18,7 +17,7 @@
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s1 () Bool (str.in.re s0 ((_ re.loop 1 3) (str.to.re "ab"))))
+[GOOD] (define-fun s1 () Bool (str.in_re s0 ((_ re.loop 1 3) (str.to.re "ab"))))
 [GOOD] (define-fun s2 () Int (str.len s0))
 [GOOD] (define-fun s4 () Bool (= s2 s3))
 [GOOD] ; --- delayedEqualities ---
diff --git a/SBVTestSuite/GoldFiles/strIndexOf.gold b/SBVTestSuite/GoldFiles/strIndexOf.gold
--- a/SBVTestSuite/GoldFiles/strIndexOf.gold
+++ b/SBVTestSuite/GoldFiles/strIndexOf.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/strIndexOfBad.gold b/SBVTestSuite/GoldFiles/strIndexOfBad.gold
--- a/SBVTestSuite/GoldFiles/strIndexOfBad.gold
+++ b/SBVTestSuite/GoldFiles/strIndexOfBad.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/sumBimapPlus.gold b/SBVTestSuite/GoldFiles/sumBimapPlus.gold
--- a/SBVTestSuite/GoldFiles/sumBimapPlus.gold
+++ b/SBVTestSuite/GoldFiles/sumBimapPlus.gold
@@ -9,35 +9,37 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 1)
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVEither Int Int)) ; tracks user variable "x"
+[GOOD] (declare-fun s0 () (Either Int Int)) ; tracks user variable "x"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s1 () Int (get_left_SBVEither s0))
-[GOOD] (define-fun s3 () Int (+ s1 s2))
-[GOOD] (define-fun s4 () (SBVEither Int Int) ((as left_SBVEither (SBVEither Int Int)) s3))
-[GOOD] (define-fun s5 () Int (get_right_SBVEither s0))
-[GOOD] (define-fun s6 () Int (+ s2 s5))
-[GOOD] (define-fun s7 () (SBVEither Int Int) ((as right_SBVEither (SBVEither Int Int)) s6))
-[GOOD] (define-fun s8 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Int))) s0))
-[GOOD] (define-fun s9 () (SBVEither Int Int) (ite s8 s4 s7))
-[GOOD] (define-fun s10 () Int (get_left_SBVEither s9))
-[GOOD] (define-fun s11 () Int (get_right_SBVEither s9))
-[GOOD] (define-fun s12 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Int))) s9))
-[GOOD] (define-fun s13 () Int (ite s12 s10 s11))
-[GOOD] (define-fun s14 () Int (ite s8 s1 s5))
-[GOOD] (define-fun s15 () Int (+ s2 s14))
+[GOOD] (define-fun s1 () Bool ((as is-Left Bool) s0))
+[GOOD] (define-fun s2 () Int (getLeft_1 s0))
+[GOOD] (define-fun s4 () Int (+ s2 s3))
+[GOOD] (define-fun s5 () (Either Int Int) ((as Left (Either Int Int)) s4))
+[GOOD] (define-fun s6 () Int (getRight_1 s0))
+[GOOD] (define-fun s7 () Int (+ s3 s6))
+[GOOD] (define-fun s8 () (Either Int Int) ((as Right (Either Int Int)) s7))
+[GOOD] (define-fun s9 () (Either Int Int) (ite s1 s5 s8))
+[GOOD] (define-fun s10 () Bool ((as is-Left Bool) s9))
+[GOOD] (define-fun s11 () Int (getLeft_1 s9))
+[GOOD] (define-fun s12 () Int (getRight_1 s9))
+[GOOD] (define-fun s13 () Int (ite s10 s11 s12))
+[GOOD] (define-fun s14 () Int (ite s1 s2 s6))
+[GOOD] (define-fun s15 () Int (+ s3 s14))
 [GOOD] (define-fun s16 () Bool (= s13 s15))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
@@ -45,8 +47,8 @@
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (left_SBVEither 0)))
+[RECV] ((s0 (Left (- 1))))
 
-MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Left 0 :: Either Integer Integer)], modelUIFuns = []}
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Left (-1) :: Either Integer Integer)], modelUIFuns = []}
 DONE.*** Solver   : Z3
 *** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/sumEitherSat.gold b/SBVTestSuite/GoldFiles/sumEitherSat.gold
--- a/SBVTestSuite/GoldFiles/sumEitherSat.gold
+++ b/SBVTestSuite/GoldFiles/sumEitherSat.gold
@@ -9,34 +9,36 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 0)
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVEither Int Bool)) ; tracks user variable "x"
+[GOOD] (declare-fun s0 () (Either Int Bool)) ; tracks user variable "x"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s1 () Int (get_left_SBVEither s0))
-[GOOD] (define-fun s3 () Bool (> s1 s2))
-[GOOD] (define-fun s4 () Bool (get_right_SBVEither s0))
-[GOOD] (define-fun s5 () Bool (not s4))
-[GOOD] (define-fun s6 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Bool))) s0))
-[GOOD] (define-fun s7 () Bool (ite s6 s3 s5))
+[GOOD] (define-fun s1 () Bool ((as is-Left Bool) s0))
+[GOOD] (define-fun s2 () Int (getLeft_1 s0))
+[GOOD] (define-fun s4 () Bool (> s2 s3))
+[GOOD] (define-fun s5 () Bool (getRight_1 s0))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () Bool (ite s1 s4 s6))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
 [GOOD] (assert s7)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (right_SBVEither false)))
+[RECV] ((s0 (Right false)))
 
 MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Right False :: Either Integer Bool)], modelUIFuns = []}
 DONE.*** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/sumLiftEither.gold b/SBVTestSuite/GoldFiles/sumLiftEither.gold
--- a/SBVTestSuite/GoldFiles/sumLiftEither.gold
+++ b/SBVTestSuite/GoldFiles/sumLiftEither.gold
@@ -9,12 +9,14 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
 [GOOD] (declare-fun s0 () Int) ; tracks user variable "i"
@@ -25,16 +27,14 @@
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s2 () (SBVEither Int String) ((as left_SBVEither (SBVEither Int String)) s0))
-[GOOD] (define-fun s3 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int String))) s2))
-[GOOD] (define-fun s4 () Bool (ite s3 true false))
-[GOOD] (define-fun s5 () (SBVEither Int String) ((as right_SBVEither (SBVEither Int String)) s1))
-[GOOD] (define-fun s6 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int String))) s5))
-[GOOD] (define-fun s7 () Bool (ite s6 false true))
+[GOOD] (define-fun s2 () (Either Int String) ((as Left (Either Int String)) s0))
+[GOOD] (define-fun s3 () Bool ((as is-Left Bool) s2))
+[GOOD] (define-fun s4 () (Either Int String) ((as Right (Either Int String)) s1))
+[GOOD] (define-fun s5 () Bool ((as is-Right Bool) s4))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
-[GOOD] (assert s4)
-[GOOD] (assert s7)
+[GOOD] (assert s3)
+[GOOD] (assert s5)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
diff --git a/SBVTestSuite/GoldFiles/sumLiftMaybe.gold b/SBVTestSuite/GoldFiles/sumLiftMaybe.gold
--- a/SBVTestSuite/GoldFiles/sumLiftMaybe.gold
+++ b/SBVTestSuite/GoldFiles/sumLiftMaybe.gold
@@ -9,14 +9,16 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
-                                           ((nothing_SBVMaybe)
-                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s2 () (SBVMaybe Int) (as nothing_SBVMaybe (SBVMaybe Int)))
+[GOOD] (define-fun s2 () (Maybe Int) (as Nothing (Maybe Int)))
 [GOOD] ; --- top level inputs ---
 [GOOD] (declare-fun s0 () Int) ; tracks user variable "i"
 [GOOD] ; --- constant tables ---
@@ -24,7 +26,7 @@
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s1 () (SBVMaybe Int) ((as just_SBVMaybe (SBVMaybe Int)) s0))
+[GOOD] (define-fun s1 () (Maybe Int) ((as Just (Maybe Int)) s0))
 [GOOD] (define-fun s3 () Bool (distinct s1 s2))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
diff --git a/SBVTestSuite/GoldFiles/sumMaybe.gold b/SBVTestSuite/GoldFiles/sumMaybe.gold
--- a/SBVTestSuite/GoldFiles/sumMaybe.gold
+++ b/SBVTestSuite/GoldFiles/sumMaybe.gold
@@ -9,49 +9,49 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
-                                           ((nothing_SBVMaybe)
-                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s3 () (SBVMaybe Int) (as nothing_SBVMaybe (SBVMaybe Int)))
-[GOOD] (define-fun s5 () Int 1)
-[GOOD] (define-fun s15 () Int 0)
+[GOOD] (define-fun s2 () (Maybe Int) (as Nothing (Maybe Int)))
+[GOOD] (define-fun s4 () Int 1)
+[GOOD] (define-fun s13 () Int 0)
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVMaybe Int)) ; tracks user variable "x"
+[GOOD] (declare-fun s0 () (Maybe Int)) ; tracks user variable "x"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s1 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s0))
-[GOOD] (define-fun s2 () Bool (ite s1 true false))
-[GOOD] (define-fun s4 () Int (get_just_SBVMaybe s0))
-[GOOD] (define-fun s6 () Int (+ s4 s5))
-[GOOD] (define-fun s7 () (SBVMaybe Int) ((as just_SBVMaybe (SBVMaybe Int)) s6))
-[GOOD] (define-fun s8 () (SBVMaybe Int) (ite s1 s3 s7))
-[GOOD] (define-fun s9 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s8))
-[GOOD] (define-fun s10 () Bool (ite s9 true false))
-[GOOD] (define-fun s11 () Bool (= s2 s10))
-[GOOD] (define-fun s12 () Bool (ite s1 false true))
-[GOOD] (define-fun s13 () Bool (ite s9 false true))
-[GOOD] (define-fun s14 () Bool (= s12 s13))
-[GOOD] (define-fun s16 () Int (ite s1 s15 s4))
-[GOOD] (define-fun s17 () Int (get_just_SBVMaybe s8))
-[GOOD] (define-fun s18 () Int (ite s9 s15 s17))
-[GOOD] (define-fun s19 () Int (- s18 s5))
-[GOOD] (define-fun s20 () Bool (= s16 s19))
+[GOOD] (define-fun s1 () Bool ((as is-Nothing Bool) s0))
+[GOOD] (define-fun s3 () Int (getJust_1 s0))
+[GOOD] (define-fun s5 () Int (+ s3 s4))
+[GOOD] (define-fun s6 () (Maybe Int) ((as Just (Maybe Int)) s5))
+[GOOD] (define-fun s7 () (Maybe Int) (ite s1 s2 s6))
+[GOOD] (define-fun s8 () Bool ((as is-Nothing Bool) s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool ((as is-Just Bool) s0))
+[GOOD] (define-fun s11 () Bool ((as is-Just Bool) s7))
+[GOOD] (define-fun s12 () Bool (= s10 s11))
+[GOOD] (define-fun s14 () Int (ite s1 s13 s3))
+[GOOD] (define-fun s15 () Int (getJust_1 s7))
+[GOOD] (define-fun s16 () Int (ite s8 s13 s15))
+[GOOD] (define-fun s17 () Int (- s16 s4))
+[GOOD] (define-fun s18 () Bool (= s14 s17))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
-[GOOD] (assert s11)
-[GOOD] (assert s14)
-[GOOD] (assert s20)
+[GOOD] (assert s9)
+[GOOD] (assert s12)
+[GOOD] (assert s18)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (just_SBVMaybe 0)))
+[RECV] ((s0 (Just 0)))
 
 MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Just 0 :: Maybe Integer)], modelUIFuns = []}
 DONE.*** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/sumMaybeBoth.gold b/SBVTestSuite/GoldFiles/sumMaybeBoth.gold
--- a/SBVTestSuite/GoldFiles/sumMaybeBoth.gold
+++ b/SBVTestSuite/GoldFiles/sumMaybeBoth.gold
@@ -9,38 +9,40 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
-[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
-                                           ((nothing_SBVMaybe)
-                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVEither Int Int))
-[GOOD] (declare-fun s1 () (SBVMaybe Int))
+[GOOD] (declare-fun s0 () (Either Int Int))
+[GOOD] (declare-fun s1 () (Maybe Int))
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s2 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Int))) s0))
-[GOOD] (define-fun s3 () Bool (ite s2 true false))
-[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s1))
-[GOOD] (define-fun s5 () Bool (ite s4 false true))
+[GOOD] (define-fun s2 () Bool ((as is-Left Bool) s0))
+[GOOD] (define-fun s3 () Bool ((as is-Just Bool) s1))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
+[GOOD] (assert s2)
 [GOOD] (assert s3)
-[GOOD] (assert s5)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (left_SBVEither 2)))
+[RECV] ((s0 (Left 2)))
 [SEND] (get-value (s1))
-[RECV] ((s1 (just_SBVMaybe 3)))
+[RECV] ((s1 (Just 3)))
 
 MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("s0",Left 2 :: Either Integer Integer),("s1",Just 3 :: Maybe Integer)], modelUIFuns = []}
 DONE.*** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/sumMergeEither1.gold b/SBVTestSuite/GoldFiles/sumMergeEither1.gold
--- a/SBVTestSuite/GoldFiles/sumMergeEither1.gold
+++ b/SBVTestSuite/GoldFiles/sumMergeEither1.gold
@@ -9,34 +9,35 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVEither Int Bool))
-[GOOD] (declare-fun s1 () (SBVEither Int Bool))
+[GOOD] (declare-fun s0 () (Either Int Bool))
+[GOOD] (declare-fun s1 () (Either Int Bool))
 [GOOD] (declare-fun s2 () Bool)
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s3 () (SBVEither Int Bool) (ite s2 s0 s1))
-[GOOD] (define-fun s4 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Bool))) s3))
-[GOOD] (define-fun s5 () Bool (ite s4 true false))
+[GOOD] (define-fun s3 () (Either Int Bool) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Left Bool) s3))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
-[GOOD] (assert s5)
+[GOOD] (assert s4)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (left_SBVEither 2)))
+[RECV] ((s0 (Left 2)))
 [SEND] (get-value (s1))
-[RECV] ((s1 (left_SBVEither 2)))
+[RECV] ((s1 (Left 2)))
 [SEND] (get-value (s2))
 [RECV] ((s2 false))
 
diff --git a/SBVTestSuite/GoldFiles/sumMergeEither2.gold b/SBVTestSuite/GoldFiles/sumMergeEither2.gold
--- a/SBVTestSuite/GoldFiles/sumMergeEither2.gold
+++ b/SBVTestSuite/GoldFiles/sumMergeEither2.gold
@@ -9,34 +9,35 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
-                                           ((left_SBVEither  (get_left_SBVEither  T1))
-                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVEither Int Bool))
-[GOOD] (declare-fun s1 () (SBVEither Int Bool))
+[GOOD] (declare-fun s0 () (Either Int Bool))
+[GOOD] (declare-fun s1 () (Either Int Bool))
 [GOOD] (declare-fun s2 () Bool)
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s3 () (SBVEither Int Bool) (ite s2 s0 s1))
-[GOOD] (define-fun s4 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Bool))) s3))
-[GOOD] (define-fun s5 () Bool (ite s4 false true))
+[GOOD] (define-fun s3 () (Either Int Bool) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Right Bool) s3))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
-[GOOD] (assert s5)
+[GOOD] (assert s4)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (right_SBVEither false)))
+[RECV] ((s0 (Right false)))
 [SEND] (get-value (s1))
-[RECV] ((s1 (right_SBVEither false)))
+[RECV] ((s1 (Right false)))
 [SEND] (get-value (s2))
 [RECV] ((s2 false))
 
diff --git a/SBVTestSuite/GoldFiles/sumMergeMaybe1.gold b/SBVTestSuite/GoldFiles/sumMergeMaybe1.gold
--- a/SBVTestSuite/GoldFiles/sumMergeMaybe1.gold
+++ b/SBVTestSuite/GoldFiles/sumMergeMaybe1.gold
@@ -9,34 +9,35 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
-                                           ((nothing_SBVMaybe)
-                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVMaybe Int))
-[GOOD] (declare-fun s1 () (SBVMaybe Int))
+[GOOD] (declare-fun s0 () (Maybe Int))
+[GOOD] (declare-fun s1 () (Maybe Int))
 [GOOD] (declare-fun s2 () Bool)
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s3 () (SBVMaybe Int) (ite s2 s0 s1))
-[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s3))
-[GOOD] (define-fun s5 () Bool (ite s4 true false))
+[GOOD] (define-fun s3 () (Maybe Int) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Nothing Bool) s3))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
-[GOOD] (assert s5)
+[GOOD] (assert s4)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 nothing_SBVMaybe))
+[RECV] ((s0 Nothing))
 [SEND] (get-value (s1))
-[RECV] ((s1 nothing_SBVMaybe))
+[RECV] ((s1 Nothing))
 [SEND] (get-value (s2))
 [RECV] ((s2 false))
 
diff --git a/SBVTestSuite/GoldFiles/sumMergeMaybe2.gold b/SBVTestSuite/GoldFiles/sumMergeMaybe2.gold
--- a/SBVTestSuite/GoldFiles/sumMergeMaybe2.gold
+++ b/SBVTestSuite/GoldFiles/sumMergeMaybe2.gold
@@ -9,34 +9,35 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
-[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
-                                           ((nothing_SBVMaybe)
-                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
-[GOOD] (declare-fun s0 () (SBVMaybe Int))
-[GOOD] (declare-fun s1 () (SBVMaybe Int))
+[GOOD] (declare-fun s0 () (Maybe Int))
+[GOOD] (declare-fun s1 () (Maybe Int))
 [GOOD] (declare-fun s2 () Bool)
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- non-constant tables ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user defined functions ---
 [GOOD] ; --- assignments ---
-[GOOD] (define-fun s3 () (SBVMaybe Int) (ite s2 s0 s1))
-[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s3))
-[GOOD] (define-fun s5 () Bool (ite s4 false true))
+[GOOD] (define-fun s3 () (Maybe Int) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Just Bool) s3))
 [GOOD] ; --- delayedEqualities ---
 [GOOD] ; --- formula ---
-[GOOD] (assert s5)
+[GOOD] (assert s4)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (just_SBVMaybe 2)))
+[RECV] ((s0 (Just 2)))
 [SEND] (get-value (s1))
-[RECV] ((s1 (just_SBVMaybe 2)))
+[RECV] ((s1 (Just 2)))
 [SEND] (get-value (s2))
 [RECV] ((s2 false))
 
diff --git a/SBVTestSuite/GoldFiles/tuple_enum.gold b/SBVTestSuite/GoldFiles/tuple_enum.gold
--- a/SBVTestSuite/GoldFiles/tuple_enum.gold
+++ b/SBVTestSuite/GoldFiles/tuple_enum.gold
@@ -9,22 +9,24 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
-[GOOD] (declare-datatypes ((E 0)) (((A) (B) (C))))
-[GOOD] (define-fun E_constrIndex ((x E)) Int
-          (ite (= x A) 0 (ite (= x B) 1 2))
-       )
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
                                                          (proj_2_SBVTuple2 T2))))))
 [GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: E
+[GOOD] (declare-datatype E (
+           (A)
+           (B)
+           (C)
+       ))
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s3 () Int 1)
 [GOOD] (define-fun s6 () (Seq Bool) (seq.unit true))
 [GOOD] (define-fun s11 () Int 3)
 [GOOD] (define-fun s13 () Int 2)
-[GOOD] (define-fun s16 () E C)
+[GOOD] (define-fun s16 () E (as C E))
 [GOOD] (define-fun s20 () Int 6)
 [GOOD] (define-fun s22 () Int 4)
 [GOOD] ; --- top level inputs ---
@@ -67,10 +69,10 @@
                                                          (proj_3_SBVTuple3 T3))))))
 [GOOD] (declare-fun s24 () (SBVTuple2 (_ BitVec 8) (SBVTuple3 E String Int)))
 [GOOD] (assert (= 1 (str.len (proj_2_SBVTuple3 (proj_2_SBVTuple2 s24)))))
-[GOOD] (define-fun s25 () (SBVTuple2 (_ BitVec 8) (SBVTuple3 E String Int)) (mkSBVTuple2 #x05 (mkSBVTuple3 C (_ char #x41) 812)))
+[GOOD] (define-fun s25 () (SBVTuple2 (_ BitVec 8) (SBVTuple3 E String Int)) (mkSBVTuple2 #x05 (mkSBVTuple3 (as C E) (_ char #x41) 812)))
 [GOOD] (define-fun s26 () Bool (= s24 s25))
 [GOOD] (assert s26)
-[GOOD] (define-fun s27 () (Seq (SBVTuple2 E (Seq Bool))) (seq.++ (seq.unit (mkSBVTuple2 B (as seq.empty (Seq Bool)))) (seq.unit (mkSBVTuple2 A (seq.++ (seq.unit true) (seq.unit false)))) (seq.unit (mkSBVTuple2 C (seq.++ (seq.unit false) (seq.unit false) (seq.unit false) (seq.unit false) (seq.unit true) (seq.unit false))))))
+[GOOD] (define-fun s27 () (Seq (SBVTuple2 E (Seq Bool))) (seq.++ (seq.unit (mkSBVTuple2 (as B E) (as seq.empty (Seq Bool)))) (seq.unit (mkSBVTuple2 (as A E) (seq.++ (seq.unit true) (seq.unit false)))) (seq.unit (mkSBVTuple2 (as C E) (seq.++ (seq.unit false) (seq.unit false) (seq.unit false) (seq.unit false) (seq.unit true) (seq.unit false))))))
 [GOOD] (define-fun s28 () Bool (= s0 s27))
 [GOOD] (assert s28)
 [SEND] (check-sat)
diff --git a/SBVTestSuite/GoldFiles/tuple_list.gold b/SBVTestSuite/GoldFiles/tuple_list.gold
--- a/SBVTestSuite/GoldFiles/tuple_list.gold
+++ b/SBVTestSuite/GoldFiles/tuple_list.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/tuple_nested.gold b/SBVTestSuite/GoldFiles/tuple_nested.gold
--- a/SBVTestSuite/GoldFiles/tuple_nested.gold
+++ b/SBVTestSuite/GoldFiles/tuple_nested.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/tuple_swap.gold b/SBVTestSuite/GoldFiles/tuple_swap.gold
--- a/SBVTestSuite/GoldFiles/tuple_swap.gold
+++ b/SBVTestSuite/GoldFiles/tuple_swap.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
                                            ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
diff --git a/SBVTestSuite/GoldFiles/tuple_twoTwo.gold b/SBVTestSuite/GoldFiles/tuple_twoTwo.gold
--- a/SBVTestSuite/GoldFiles/tuple_twoTwo.gold
+++ b/SBVTestSuite/GoldFiles/tuple_twoTwo.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/tuple_unequal.gold b/SBVTestSuite/GoldFiles/tuple_unequal.gold
--- a/SBVTestSuite/GoldFiles/tuple_unequal.gold
+++ b/SBVTestSuite/GoldFiles/tuple_unequal.gold
@@ -9,7 +9,6 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-option :model.inline_def  true      )
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
diff --git a/SBVTestSuite/GoldFiles/uiSat_test1.gold b/SBVTestSuite/GoldFiles/uiSat_test1.gold
--- a/SBVTestSuite/GoldFiles/uiSat_test1.gold
+++ b/SBVTestSuite/GoldFiles/uiSat_test1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; NB. User specified.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/uiSat_test2.gold b/SBVTestSuite/GoldFiles/uiSat_test2.gold
--- a/SBVTestSuite/GoldFiles/uiSat_test2.gold
+++ b/SBVTestSuite/GoldFiles/uiSat_test2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; NB. User specified.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/uiSat_test3.gold b/SBVTestSuite/GoldFiles/uiSat_test3.gold
--- a/SBVTestSuite/GoldFiles/uiSat_test3.gold
+++ b/SBVTestSuite/GoldFiles/uiSat_test3.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; NB. User specified.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/unint-axioms-empty.gold b/SBVTestSuite/GoldFiles/unint-axioms-empty.gold
--- a/SBVTestSuite/GoldFiles/unint-axioms-empty.gold
+++ b/SBVTestSuite/GoldFiles/unint-axioms-empty.gold
@@ -5,12 +5,11 @@
 [GOOD] (set-option :smtlib2_compliant true)
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
-[GOOD] (set-logic ALL) ; has user-defined sorts, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
-[GOOD] (declare-sort Thing 0)  ; N.B. Uninterpreted sort.
-[GOOD] (declare-fun Thing_witness () Thing)
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] (declare-sort Thing 0) ; N.B. Uninterpreted sort.
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
 [GOOD] (declare-fun s2 () Thing) ; tracks user variable "__internal_sbv_s2"
diff --git a/SBVTestSuite/GoldFiles/unint-axioms-query.gold b/SBVTestSuite/GoldFiles/unint-axioms-query.gold
--- a/SBVTestSuite/GoldFiles/unint-axioms-query.gold
+++ b/SBVTestSuite/GoldFiles/unint-axioms-query.gold
@@ -5,12 +5,11 @@
 [GOOD] (set-option :smtlib2_compliant true)
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
-[GOOD] (set-logic ALL) ; has user-defined sorts, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
-[GOOD] (declare-sort B 0)  ; N.B. Uninterpreted sort.
-[GOOD] (declare-fun B_witness () B)
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] (declare-sort B 0) ; N.B. Uninterpreted sort.
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
 [GOOD] (declare-fun s0 () B) ; tracks user variable "p"
diff --git a/SBVTestSuite/GoldFiles/unint-axioms.gold b/SBVTestSuite/GoldFiles/unint-axioms.gold
--- a/SBVTestSuite/GoldFiles/unint-axioms.gold
+++ b/SBVTestSuite/GoldFiles/unint-axioms.gold
@@ -5,12 +5,11 @@
 [GOOD] (set-option :smtlib2_compliant true)
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
-[GOOD] (set-logic ALL) ; has user-defined sorts, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
-[GOOD] (declare-sort Bitstring 0)  ; N.B. Uninterpreted sort.
-[GOOD] (declare-fun Bitstring_witness () Bitstring)
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] (declare-sort Bitstring 0) ; N.B. Uninterpreted sort.
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
 [GOOD] (declare-fun s1 () Bitstring) ; tracks user variable "p"
diff --git a/SBVTestSuite/GoldFiles/unint-sort01.gold b/SBVTestSuite/GoldFiles/unint-sort01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/unint-sort01.gold
@@ -0,0 +1,37 @@
+Solution #1:
+  l  = L_1 :: L
+  l0 = L_0 :: L
+  l1 = L_1 :: L
+  x  =   1 :: Integer
+
+  len :: L -> Integer
+  len L_1 = 1
+  len _   = 0
+Solution #2:
+  l  = L_0 :: L
+  l0 = L_0 :: L
+  l1 = L_1 :: L
+  x  =   0 :: Integer
+
+  len :: L -> Integer
+  len L_1 = 1
+  len _   = 0
+Solution #3:
+  l  = L_1 :: L
+  l0 = L_0 :: L
+  l1 = L_1 :: L
+  x  =   0 :: Integer
+
+  len :: L -> Integer
+  len L_1 = 1
+  len _   = 0
+Solution #4:
+  l  = L_0 :: L
+  l0 = L_0 :: L
+  l1 = L_1 :: L
+  x  =   1 :: Integer
+
+  len :: L -> Integer
+  len L_1 = 1
+  len _   = 0
+Found 4 different solutions.
diff --git a/SBVTestSuite/GoldFiles/uninterpreted-3.gold b/SBVTestSuite/GoldFiles/uninterpreted-3.gold
--- a/SBVTestSuite/GoldFiles/uninterpreted-3.gold
+++ b/SBVTestSuite/GoldFiles/uninterpreted-3.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/uninterpreted-3a.gold b/SBVTestSuite/GoldFiles/uninterpreted-3a.gold
--- a/SBVTestSuite/GoldFiles/uninterpreted-3a.gold
+++ b/SBVTestSuite/GoldFiles/uninterpreted-3a.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_UFBV)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/uninterpreted-4.gold b/SBVTestSuite/GoldFiles/uninterpreted-4.gold
--- a/SBVTestSuite/GoldFiles/uninterpreted-4.gold
+++ b/SBVTestSuite/GoldFiles/uninterpreted-4.gold
@@ -5,12 +5,11 @@
 [GOOD] (set-option :smtlib2_compliant true)
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
-[GOOD] (set-logic ALL) ; has user-defined sorts, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
-[GOOD] (declare-sort Q 0)  ; N.B. Uninterpreted sort.
-[GOOD] (declare-fun Q_witness () Q)
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] (declare-sort Q 0) ; N.B. Uninterpreted sort.
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/uninterpreted-4a.gold b/SBVTestSuite/GoldFiles/uninterpreted-4a.gold
--- a/SBVTestSuite/GoldFiles/uninterpreted-4a.gold
+++ b/SBVTestSuite/GoldFiles/uninterpreted-4a.gold
@@ -5,12 +5,11 @@
 [GOOD] (set-option :smtlib2_compliant true)
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
-[GOOD] (set-logic ALL) ; has user-defined sorts, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
-[GOOD] (declare-sort Q 0)  ; N.B. Uninterpreted sort.
-[GOOD] (declare-fun Q_witness () Q)
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] (declare-sort Q 0) ; N.B. Uninterpreted sort.
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- top level inputs ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/validate_0.gold b/SBVTestSuite/GoldFiles/validate_0.gold
--- a/SBVTestSuite/GoldFiles/validate_0.gold
+++ b/SBVTestSuite/GoldFiles/validate_0.gold
@@ -6,7 +6,6 @@
 [ISSUE] (set-option :diagnostic-output-channel "stdout")
 [ISSUE] (set-option :produce-models true)
 [ISSUE] (set-logic QF_BV)
-[ISSUE] ; --- uninterpreted sorts ---
 [ISSUE] ; --- tuples ---
 [ISSUE] ; --- sums ---
 [ISSUE] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/validate_1.gold b/SBVTestSuite/GoldFiles/validate_1.gold
--- a/SBVTestSuite/GoldFiles/validate_1.gold
+++ b/SBVTestSuite/GoldFiles/validate_1.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_FP)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/validate_2.gold b/SBVTestSuite/GoldFiles/validate_2.gold
--- a/SBVTestSuite/GoldFiles/validate_2.gold
+++ b/SBVTestSuite/GoldFiles/validate_2.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic QF_FP)
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/validate_3.gold b/SBVTestSuite/GoldFiles/validate_3.gold
--- a/SBVTestSuite/GoldFiles/validate_3.gold
+++ b/SBVTestSuite/GoldFiles/validate_3.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/validate_4.gold b/SBVTestSuite/GoldFiles/validate_4.gold
--- a/SBVTestSuite/GoldFiles/validate_4.gold
+++ b/SBVTestSuite/GoldFiles/validate_4.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/validate_5.gold b/SBVTestSuite/GoldFiles/validate_5.gold
--- a/SBVTestSuite/GoldFiles/validate_5.gold
+++ b/SBVTestSuite/GoldFiles/validate_5.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/validate_6.gold b/SBVTestSuite/GoldFiles/validate_6.gold
--- a/SBVTestSuite/GoldFiles/validate_6.gold
+++ b/SBVTestSuite/GoldFiles/validate_6.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/GoldFiles/validate_7.gold b/SBVTestSuite/GoldFiles/validate_7.gold
--- a/SBVTestSuite/GoldFiles/validate_7.gold
+++ b/SBVTestSuite/GoldFiles/validate_7.gold
@@ -6,7 +6,6 @@
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has quantified booleans, using catch-all.
-[GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
diff --git a/SBVTestSuite/SBVTest.hs b/SBVTestSuite/SBVTest.hs
--- a/SBVTestSuite/SBVTest.hs
+++ b/SBVTestSuite/SBVTest.hs
@@ -9,14 +9,16 @@
 -- Main entry point to the test suite
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
-
 {-# OPTIONS_GHC -Wall -Werror #-}
 
 module Main(main) where
 
 import Test.Tasty
 
+import qualified TestSuite.ADT.ADT
+import qualified TestSuite.ADT.Expr
+import qualified TestSuite.ADT.MutRec
+import qualified TestSuite.ADT.PExpr
 import qualified TestSuite.Arrays.InitVals
 import qualified TestSuite.Arrays.Memory
 import qualified TestSuite.Arrays.Query
@@ -120,6 +122,7 @@
 import qualified TestSuite.Queries.UISatEx
 import qualified TestSuite.Queries.Uninterpreted
 import qualified TestSuite.QuickCheck.QC
+import qualified TestSuite.CompileTests.SCase
 import qualified TestSuite.Transformers.SymbolicEval
 import qualified TestSuite.Uninterpreted.AUF
 import qualified TestSuite.Uninterpreted.Axioms
@@ -128,8 +131,13 @@
 import qualified TestSuite.Uninterpreted.Uninterpreted
 
 main :: IO ()
-main = defaultMain $ testGroup "SBV" [
-                        TestSuite.Arrays.InitVals.tests
+main = do sCaseTests <- TestSuite.CompileTests.SCase.tests
+          defaultMain $ testGroup "SBV" [
+                        TestSuite.ADT.ADT.tests
+                      , TestSuite.ADT.Expr.tests
+                      , TestSuite.ADT.MutRec.tests
+                      , TestSuite.ADT.PExpr.tests
+                      , TestSuite.Arrays.InitVals.tests
                       , TestSuite.Arrays.Memory.tests
                       , TestSuite.Arrays.Query.tests
                       , TestSuite.Arrays.Caching.tests
@@ -240,4 +248,5 @@
                       , TestSuite.Uninterpreted.Function.tests
                       , TestSuite.Uninterpreted.Sort.tests
                       , TestSuite.Uninterpreted.Uninterpreted.tests
+                      , sCaseTests
                       ]
diff --git a/SBVTestSuite/TestSuite/ADT/ADT.hs b/SBVTestSuite/TestSuite/ADT/ADT.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/ADT/ADT.hs
@@ -0,0 +1,131 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.ADT.ADT
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing ADTs
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-unused-top-binds #-}
+
+module TestSuite.ADT.ADT(tests) where
+
+import Utils.SBVTestFramework
+import Data.SBV.Control
+import Data.SBV.Maybe
+
+data ADT  = AEmpty
+          | ABool     Bool
+          | AInteger  Integer
+          | AWord8    Word8
+          | AWord16   Word16
+          | AWord32   Word32
+          | AWord64   Word64
+          | AInt8     Int8
+          | AInt16    Int16
+          | AInt32    Int32
+          | AInt64    Int64
+          | AWord1    (WordN  1)
+          | AWord5    (WordN  5)
+          | AWord30   (WordN 30)
+          | AInt1     (IntN   1)
+          | AInt5     (IntN   5)
+          | AInt30    (IntN  30)
+          | AReal     AlgReal
+          | AFloat    Float
+          | ADouble   Double
+          | AFP       (FloatingPoint 5 12)
+          | AString   String
+          | AList     [Integer]
+          | ATuple    (Double, [(WordN 5, [Float])])
+          | AMaybe    (Maybe (AlgReal, Float, (Either Integer Float, [Bool])))
+          | AEither   (Either (Maybe Integer, Bool) [Integer])
+          | APair     ADT ADT
+          | KChar     Char
+          | KRational Rational
+          {-
+          | KADT      String (Maybe [(String, [Kind])])
+          | KSet  Kind
+          | KArray  Kind Kind
+          -}
+          deriving Show
+
+mkSymbolic [''ADT]
+
+tests :: TestTree
+tests =
+  testGroup "ADT" [
+      goldenCapturedIO "adt00" $ checkWith t00
+    , goldenCapturedIO "adt01" $ checkWith t01
+    , goldenCapturedIO "adt02" $ checkWith t02
+    , goldenCapturedIO "adt03" $ checkWith t03
+    , goldenCapturedIO "adt04" t04
+    , goldenCapturedIO "adt05" t05
+    , goldenCapturedIO "adt06" t06
+    ]
+
+checkWith :: Symbolic () -> FilePath -> IO ()
+checkWith props rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+        _ <- props
+        query $ do cs <- checkSat
+                   case cs of
+                     Unsat  -> io $ appendFile rf "\nUNSAT"
+                     DSat{} -> io $ appendFile rf "\nDSAT"
+                     Sat{}  -> getModel         >>= \m -> io $ appendFile rf $ "\nMODEL: "   ++ show m ++ "\nDONE."
+                     Unk    -> getUnknownReason >>= \r -> io $ appendFile rf $ "\nUNKNOWN: " ++ show r ++ "\nDONE."
+
+t00 :: Symbolic ()
+t00 = do a :: SADT <- free "e"
+         constrain $ a ./== a
+
+t01 :: Symbolic ()
+t01 = do a :: SADT <- free "e"
+         constrain $ a .=== literal (APair (AInt64 4) (AMaybe (Just (0, 12, (Left 3, [False, True])))))
+
+t02 :: Symbolic ()
+t02 = do a :: SADT <- free "e"
+         constrain $ isAList a
+
+t03 :: Symbolic ()
+t03 = do a :: SADT <- free "e"
+         constrain $ isAList a .&& isAFP a
+
+t04 :: FilePath -> IO ()
+t04 rf = do AllSatResult _ _ _ ms <- allSatWith z3{verbose=True, redirectVerbose = Just rf} t
+            let sh m = appendFile rf $ "\nMODEL:" ++ show (SatResult m)
+            mapM_ sh ms
+  where t = do a :: SADT <- free "a"
+               constrain $ isAInteger a
+               constrain $ getAInteger_1 a .>= 0
+               constrain $ getAInteger_1 a .<= 5
+
+-- z3 is buggy on this. So we use cvc5. See: https://github.com/Z3Prover/z3/issues/7842
+t05 :: FilePath -> IO ()
+t05 rf = do AllSatResult _ _ _ ms <- allSatWith cvc5{verbose=True, redirectVerbose = Just rf, allSatMaxModelCount=Just 10} t
+            let sh m = appendFile rf $ "\nMODEL:" ++ show (SatResult m)
+            mapM_ sh ms
+  where t = do a :: SADT <- free "a"
+               b :: SADT <- free "b"
+               constrain $ isAFloat a .&& getAFloat_1 a .== 4
+               constrain $ isAFloat b .&& fpIsNaN (getAFloat_1 b)
+
+t06 :: FilePath -> IO ()
+t06 rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+             a :: SADT <- free "a"
+             constrain $ isAMaybe a
+             constrain $ isJust (getAMaybe_1 a)
+             query $ do cs <- checkSat
+                        case cs of
+                         Sat{} -> do v <- getValue a
+                                     io $ do appendFile rf $ "\ngetValue: " ++ show v
+                                             appendFile rf   "\nDONE\n"
+                         _     -> error ("BAD RESULT: " ++ show cs)
diff --git a/SBVTestSuite/TestSuite/ADT/Expr.hs b/SBVTestSuite/TestSuite/ADT/Expr.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/ADT/Expr.hs
@@ -0,0 +1,228 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.ADT.Expr
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing ADTs, expressions
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.ADT.Expr(tests) where
+
+import Data.SBV
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+import Documentation.SBV.Examples.ADT.Expr
+
+-- Testing constructor/type name conflct
+data A = A Integer
+       | B Word8
+       | C A A
+       deriving Show
+
+mkSymbolic [''A]
+
+tests :: TestTree
+tests =
+  testGroup "ADT" [
+      goldenCapturedIO "adt_expr00c" $ evalCheck  (eval e00,  3)
+    , goldenCapturedIO "adt_expr00"  $ evalCheckS eval (e00,  3)
+
+    , goldenCapturedIO "adt_expr01c" $ evalCheck  (eval e01,  7)
+    , goldenCapturedIO "adt_expr01"  $ evalCheckS eval (e01,  7)
+
+    , goldenCapturedIO "adt_expr02c" $ evalCheck  (eval e02, 21)
+    , goldenCapturedIO "adt_expr02"  $ evalCheckS eval (e02, 21)
+
+    , goldenCapturedIO "adt_expr03c" $ evalCheck  (eval e03, 28)
+    , goldenCapturedIO "adt_expr03"  $ evalCheckS eval (e03, 28)
+
+    , goldenCapturedIO "adt_expr04" $ evalTest  (eval e04)
+    , goldenCapturedIO "adt_expr05" $ evalTest  (eval e05)
+
+    , goldenCapturedIO "adt_expr06c" $ evalCheck  (f (sVar (literal "a")), 0)
+    , goldenCapturedIO "adt_expr06"  $ evalCheckS f  (sVar (literal "a") , 0)
+
+    , goldenCapturedIO "adt_expr07c" $ evalCheck  (f (sVar (literal "b")), 1)
+    , goldenCapturedIO "adt_expr07"  $ evalCheckS f  (sVar (literal "b") , 1)
+
+    , goldenCapturedIO "adt_expr08c" $ evalCheck  (f (sVar (literal "c")), 1)
+    , goldenCapturedIO "adt_expr08"  $ evalCheckS f  (sVar (literal "c") , 1)
+
+    , goldenCapturedIO "adt_expr09c" $ evalCheck  (f (sVar (literal "d")), 2)
+    , goldenCapturedIO "adt_expr09"  $ evalCheckS f  (sVar (literal "d") , 2)
+
+    , goldenCapturedIO "adt_expr10c" $ evalCheck   (sum (map (f . sVal . literal)      [-5 .. 9]),  45)
+    , goldenCapturedIO "adt_expr10"  $ evalCheckSL (sum . map f) (map (sVal . literal) [-5 .. 9],   45)
+
+    , goldenCapturedIO "adt_expr11c" $ evalCheck   (sum (map (f . sVal . literal)      [10, 10]),    8)
+    , goldenCapturedIO "adt_expr11"  $ evalCheckSL (sum . map f) (map (sVal . literal) [10, 10],     8)
+
+    , goldenCapturedIO "adt_expr12c" $ evalCheck   (sum (map (f . sVal . literal)      [11 .. 20]), 50)
+    , goldenCapturedIO "adt_expr12"  $ evalCheckSL (sum . map f) (map (sVal . literal) [11 .. 20],  50)
+
+    , goldenCapturedIO "adt_expr13c" $ evalCheck  (f e00, 3)
+    , goldenCapturedIO "adt_expr13"  $ evalCheckS f (e00, 3)
+
+    , goldenCapturedIO "adt_expr14c" $ evalCheck  (f e01, 6)
+    , goldenCapturedIO "adt_expr14"  $ evalCheckS f (e01, 6)
+
+    , goldenCapturedIO "adt_expr15c" $ evalCheck  (f e02, 6)
+    , goldenCapturedIO "adt_expr15"  $ evalCheckS f (e02, 6)
+
+    , goldenCapturedIO "adt_expr16c" $ evalCheck  (f e03, 6)
+    , goldenCapturedIO "adt_expr16"  $ evalCheckS f (e03, 6)
+
+    , goldenCapturedIO "adt_expr17c" $ evalCheck  (f e04, 6)
+    , goldenCapturedIO "adt_expr17"  $ evalCheckS f (e04, 6)
+
+    , goldenCapturedIO "adt_expr18c" $ evalCheck  (f e05, 6)
+    , goldenCapturedIO "adt_expr18"  $ evalCheckS f (e05, 6)
+
+    , goldenCapturedIO "adt_gen00"  t00
+    , goldenCapturedIO "adt_gen01"  $ tSat (-1)
+    , goldenCapturedIO "adt_gen02"  $ tSat 0
+    , goldenCapturedIO "adt_gen03"  $ tSat 1
+    , goldenCapturedIO "adt_gen04"  $ tSat 2
+    , goldenCapturedIO "adt_gen05"  $ tSat 3
+    , goldenCapturedIO "adt_gen06"  $ tSat 4
+    , goldenCapturedIO "adt_gen07"  $ tSat 5
+    , goldenCapturedIO "adt_gen08"  $ tSat 6
+    , goldenCapturedIO "adt_gen09"  $ tSat 7
+    , goldenCapturedIO "adt_gen10"  $ tSat 8
+    , goldenCapturedIO "adt_gen11"  $ tSat 9
+    , goldenCapturedIO "adt_gen12"  $ tSat 100
+    , goldenCapturedIO "adt_chk01"  $ evalTest (t (sA 12))
+    ]
+    where a = literal "a"
+          b = literal "a"
+
+          e00 = 3                                -- 3
+          e01 = 3 + 4                            -- 7
+          e02 = e00 * e01                        -- 21
+          e03 = sLet a e02 (sVar a + e01)        -- 28
+          e04 = e03 + sLet a e03 (sVar a + e01)  -- 28 + 28 + 7 = 63
+          e05 = sLet b e04 (sVar b * sVar b)     -- 63 * 63 = 3969
+
+evalCheck :: SymVal a => (SBV a, a) -> FilePath -> IO ()
+evalCheck (sv, v) rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                        constrain $ sv ./= literal v
+                        query $ do cs <- checkSat
+                                   case cs of
+                                     Unsat{} -> io $ appendFile rf "All good.\n"
+                                     _       -> error $ "Unexpected: " ++ show cs
+
+evalCheckS :: (SExpr -> SInteger) -> (SExpr, Integer) -> FilePath -> IO ()
+evalCheckS fun (e, v) rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                        se :: SExpr <- free_
+                        constrain $ se .== e
+                        constrain $ fun se ./= literal v
+                        query $ do cs <- checkSat
+                                   case cs of
+                                     Unsat{} -> io $ appendFile rf "All good.\n"
+                                     _       -> error $ "Unexpected: " ++ show cs
+
+evalCheckSL :: ([SExpr] -> SInteger) -> ([SExpr], Integer) -> FilePath -> IO ()
+evalCheckSL fun (e, v) rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                        ses :: [SExpr] <- mapM (const free_) e
+                        constrain $ ses .== e
+                        constrain $ fun ses ./= literal v
+                        query $ do cs <- checkSat
+                                   case cs of
+                                     Unsat{} -> io $ appendFile rf "All good.\n"
+                                     _       -> error $ "Unexpected: " ++ show cs
+
+evalTest :: (Show a, SymVal a) => SBV a -> FilePath -> IO ()
+evalTest sv rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                    res <- free "res"
+                    constrain $ sv .== res
+                    query $ do cs <- checkSat
+                               case cs of
+                                 Sat -> do r <- getValue res
+                                           io $ appendFile rf ("Result: " ++ show r ++ "\n")
+                                 _       -> error $ "Unexpected: " ++ show cs
+
+f :: SExpr -> SInteger
+f e = [sCase|Expr e of
+         Var s     | s .== literal "a"                       -> 0
+                   | s .== literal "b" .|| s .== literal "c" -> 1
+                   | sTrue                                   -> 2
+
+         Val i     | i .<  10                                -> 3
+                   | i .== 10                                -> 4
+                   | i .>  10                                -> 5
+
+         _                                                   -> 6
+      |]
+
+-- Create something like:
+--       let a = _
+--    in let b = _
+--    in _ + _
+-- such that it evaluates to 12
+t00 :: FilePath -> IO ()
+t00 rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+            a :: SExpr <- free "a"
+            constrain $ isValid a
+            constrain $ eval a .== 12
+
+            constrain $ isLet a
+            constrain $ isLet (getLet_3 a)
+            constrain $ isAdd (getLet_3 (getLet_3 a))
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat{} -> do v <- getValue a
+                                     io $ do appendFile rf $ "\nGot: " ++ show v
+                                             appendFile rf   "\nDONE\n"
+                         _     -> error $ "Unexpected: " ++ show cs
+
+g :: SExpr -> SInteger
+g e = [sCase|Expr e of
+         Var s     | s .== literal "a"                       -> 0
+                   | s .== literal "b" .|| s .== literal "c" -> 1
+                   | sTrue                                   -> 2
+
+         Val i     | i .<  10                                -> 3
+                   | i .== 10                                -> 4
+                   | i .>  10                                -> 5
+
+         Add _ _ -> 6
+         Mul _ _ -> 7
+         Let{}   -> 8
+
+         _ -> 100
+      |]
+
+-- Show that g can never produce anything but 0..8
+tSat :: Integer -> FilePath -> IO ()
+tSat i rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+              a :: SExpr <- free "a"
+              constrain $ g a .== literal i
+
+              query $ do cs <- checkSat
+                         case cs of
+                           Sat{} -> do v <- getValue a
+                                       io $ do appendFile rf $ "\nGot: " ++ show v
+                                               appendFile rf   "\nDONE\n"
+                           Unsat -> io $ do appendFile rf "\nUNSAT\n"
+                           _     -> error $ "Unexpected: " ++ show cs
+
+t :: SA -> SA
+t = smtFunction "t" $ \a ->
+       [sCase|A a of
+         A u     -> sA (u+1)
+         B w     -> sB (w+2)
+         C a1 a2 -> sC (t a1) (t a2)
+      |]
diff --git a/SBVTestSuite/TestSuite/ADT/MutRec.hs b/SBVTestSuite/TestSuite/ADT/MutRec.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/ADT/MutRec.hs
@@ -0,0 +1,192 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.ADT.MutRec
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing ADTs, mutual-recursion and other parameterization checks
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.ADT.MutRec(tests) where
+
+import Data.SBV
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+import Data.SBV.RegExp
+import Data.SBV.Tuple
+import Data.SBV.Maybe
+import qualified Data.SBV.List  as SL
+import qualified Data.SBV.Tuple as ST
+
+-- | Expression layer
+data Expr var val = Con { con :: val }
+                  | Var { var :: var }
+                  | Add { add1 :: Expr var val, add2 :: Expr var val }
+                  | Mul { mul1 :: Expr var val, mul2 :: Expr var val }
+
+-- | Statement layer
+data Stmt var val = Assign {lhs  :: var,          rhs  :: Expr var val }
+                  | Seq    {seqH :: Stmt var val, seqT :: Stmt var val }
+
+mkSymbolic [''Expr, ''Stmt]
+
+data A a b = Aa   { aa :: a }
+           | Ab   { ab :: b }
+           | Aab  { aba :: a, abb :: b }
+           | A2   { a2 :: A b String }
+           | A3   { a3 :: A b a }
+           deriving Show
+
+mkSymbolic [''A]
+
+-- | Show instance for 'Expr'.
+instance (Show var, Show val) => Show (Expr var val) where
+  show (Con i)   = show i
+  show (Var a)   = show a
+  show (Add l r) = "(" ++ show l ++ " + " ++ show r ++ ")"
+  show (Mul l r) = "(" ++ show l ++ " * " ++ show r ++ ")"
+
+-- | Show instance for 'Stmt'.
+instance (Show var, Show val) => Show (Stmt var val) where
+  show (Assign v e) = show v ++ " := " ++ show e
+  show (Seq a b)    = show a ++ ";\n" ++ show b
+
+-- | Show instance for 'Expr' specialized when var is string.
+instance {-# OVERLAPPING #-} Show val => Show (Expr String val) where
+  show (Con i)   = show i
+  show (Var a)   = a
+  show (Add l r) = "(" ++ show l ++ " + " ++ show r ++ ")"
+  show (Mul l r) = "(" ++ show l ++ " * " ++ show r ++ ")"
+
+-- | Show instance for 'Stmt' specialized when var is string.
+instance {-# OVERLAPPING #-} Show val => Show (Stmt String val) where
+  show (Assign v e) =      v ++ " := " ++ show e
+  show (Seq a b)    = show a ++ ";\n" ++ show b
+
+-- | Validity: We require each variable appearing to be an identifier (lowercase letter followed by
+-- any number of upper-lower case letters and digits), and all expressions are closed; i.e., any
+-- variable referenced is assigned by a prior assignment expression.
+isValid :: forall val. SymVal val => SStmt String val -> SBool
+isValid = ST.fst . goS SL.nil
+  where isId s = s `match` (asciiLower * KStar (asciiLetter + digit))
+
+        goE :: SList String -> SExpr String val -> SBool
+        goE = smtFunction "validE" $ \env expr -> [sCase|Expr expr of
+                                                     Con _   -> sTrue
+                                                     Var s   -> isId s .&& s `SL.elem` env
+                                                     Add l r -> goE env l .&& goE env r
+                                                     Mul l r -> goE env l .&& goE env r
+                                                  |]
+
+        goS :: SList String -> SStmt String val -> STuple Bool [String]
+        goS = smtFunction "validS" $ \env stmt -> [sCase|Stmt stmt of
+                                                     Assign v e -> tuple (isId v .&& goE env e, v SL..: env)
+                                                     Seq    a b -> let (lv, env')  = untuple $ goS env  a
+                                                                       (rv, env'') = untuple $ goS env' b
+                                                                   in tuple (lv .&& rv, env'')
+                                                  |]
+
+tests :: TestTree
+tests =
+  testGroup "ADT_MR" [
+      goldenCapturedIO "adt_mr00" $ r t00
+    , goldenCapturedIO "adt_mr01" $ r t01
+    , goldenCapturedIO "adt_mr02" $ r t02
+    , goldenCapturedIO "adt_mr03" $ r t03
+    , goldenCapturedIO "adt_mr04" $ r t04
+    ]
+  where r p rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} (p rf)
+
+t00 :: FilePath -> Symbolic ()
+t00 rf = do p :: SStmt String Integer <- free "p"
+
+            -- Make sure there's some structure to the program:
+            constrain $ isSeq    p
+            constrain $ isSeq    (getSeq_2 p)
+            constrain $ isSeq    (getSeq_2 (getSeq_2 p))
+            constrain $ isAssign (getSeq_2 (getSeq_2 (getSeq_2 p)))
+            constrain $ isAdd    (getAssign_2 (getSeq_2 (getSeq_2 (getSeq_2 p))))
+            constrain $ isVar    (getAdd_1    (getAssign_2 (getSeq_2 (getSeq_2 (getSeq_2 p)))))
+
+            -- Would love to have the following. But it creates too big of a problem.
+            -- constrain $ isValid p
+            constrain $ isValid (sAssign (literal "a") (sCon (literal 1)) :: SStmt String Float)
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat -> do r <- getValue p
+                                   io $ do appendFile rf $ "\nGot:\n" ++ show r
+                                           appendFile rf   "\nDONE\n"
+                         _   -> error $ "Unexpected result: " ++ show cs
+
+t01 :: FilePath -> Symbolic ()
+t01 rf = do p :: SStmt String (Maybe (Either Integer Bool)) <- free "p"
+
+            constrain $ isAssign  p
+            constrain $ isAdd     (srhs p)
+            constrain $ isCon     (sadd1 (srhs p))
+            constrain $ isCon     (sadd2 (srhs p))
+            constrain $ isNothing (scon (sadd1 (srhs p)))
+            constrain $ isJust    (scon (sadd2 (srhs p)))
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat -> do r <- getValue p
+                                   io $ do appendFile rf $ "\nGot:\n" ++ show r
+                                           appendFile rf   "\nDONE\n"
+                         _   -> error $ "Unexpected result: " ++ show cs
+
+t02 :: FilePath -> Symbolic ()
+t02 rf = do p :: SA Integer Bool <- free "p"
+
+            constrain $ isA2 p
+            constrain $ isA2 (sa2 p)
+            constrain $ isAa (sa2 (sa2 p))
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat -> do r <- getValue p
+                                   io $ do appendFile rf $ "\nGot:\n" ++ show r
+                                           appendFile rf   "\nDONE\n"
+                         _   -> error $ "Unexpected result: " ++ show cs
+
+t03 :: FilePath -> Symbolic ()
+t03 rf = do p :: SA Integer Bool <- free "p"
+
+            constrain $ isA3 p
+            constrain $ isAb (sa3 p)
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat -> do r <- getValue p
+                                   io $ do appendFile rf $ "\nGot:\n" ++ show r
+                                           appendFile rf   "\nDONE\n"
+                         _   -> error $ "Unexpected result: " ++ show cs
+
+t04 :: FilePath -> Symbolic ()
+t04 rf = do p :: SA Integer (A Float Bool) <- free "p"
+
+            constrain $ isA2 p
+            constrain $ isA3 (sa2 p)
+            constrain $ isAab (sa3 (sa2 p))
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat -> do r <- getValue p
+                                   io $ do appendFile rf $ "\nGot:\n" ++ show r
+                                           appendFile rf   "\nDONE\n"
+                         _   -> error $ "Unexpected result: " ++ show cs
+
+_unused :: a
+_unused = undefined con var add1 add2 mul1 mul2 lhs rhs seqH seqT
diff --git a/SBVTestSuite/TestSuite/ADT/PExpr.hs b/SBVTestSuite/TestSuite/ADT/PExpr.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/ADT/PExpr.hs
@@ -0,0 +1,230 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.ADT.PExpr
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing ADTs, parameterized expressions
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.ADT.PExpr(tests) where
+
+import Data.SBV
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+import Documentation.SBV.Examples.ADT.Param
+
+-- Testing constructor/type name conflct
+data A = A Integer
+       | B Word8
+       | C A A
+       deriving Show
+
+mkSymbolic [''A]
+
+tests :: TestTree
+tests =
+  testGroup "ADT" [
+      goldenCapturedIO "adt_pexpr00c" $ evalCheck  (eval e00,  3)
+    , goldenCapturedIO "adt_pexpr00"  $ evalCheckS eval (e00,  3)
+
+    , goldenCapturedIO "adt_pexpr01c" $ evalCheck  (eval e01,  7)
+    , goldenCapturedIO "adt_pexpr01"  $ evalCheckS eval (e01,  7)
+
+    , goldenCapturedIO "adt_pexpr02c" $ evalCheck  (eval e02, 21)
+    , goldenCapturedIO "adt_pexpr02"  $ evalCheckS eval (e02, 21)
+
+    , goldenCapturedIO "adt_pexpr03c" $ evalCheck  (eval e03, 28)
+    , goldenCapturedIO "adt_pexpr03"  $ evalCheckS eval (e03, 28)
+
+    , goldenCapturedIO "adt_pexpr04" $ evalTest  (eval e04)
+    , goldenCapturedIO "adt_pexpr05" $ evalTest  (eval e05)
+
+    , goldenCapturedIO "adt_pexpr06c" $ evalCheck  (f (sVar (literal "a")), 0)
+    , goldenCapturedIO "adt_pexpr06"  $ evalCheckS f  (sVar (literal "a") , 0)
+
+    , goldenCapturedIO "adt_pexpr07c" $ evalCheck  (f (sVar (literal "b")), 1)
+    , goldenCapturedIO "adt_pexpr07"  $ evalCheckS f  (sVar (literal "b") , 1)
+
+    , goldenCapturedIO "adt_pexpr08c" $ evalCheck  (f (sVar (literal "c")), 1)
+    , goldenCapturedIO "adt_pexpr08"  $ evalCheckS f  (sVar (literal "c") , 1)
+
+    , goldenCapturedIO "adt_pexpr09c" $ evalCheck  (f (sVar (literal "d")), 2)
+    , goldenCapturedIO "adt_pexpr09"  $ evalCheckS f  (sVar (literal "d") , 2)
+
+    , goldenCapturedIO "adt_pexpr10c" $ evalCheck   (sum (map (f . sVal . literal)      [-5 .. 9]), 45)
+    , goldenCapturedIO "adt_pexpr10"  $ evalCheckSL (sum . map f) (map (sVal . literal) [-5 .. 9],  45)
+
+    , goldenCapturedIO "adt_pexpr11c" $ evalCheck   (sum (map (f . sVal . literal)      [10, 10]),   8)
+    , goldenCapturedIO "adt_pexpr11"  $ evalCheckSL (sum . map f) (map (sVal . literal) [10, 10],    8)
+
+    , goldenCapturedIO "adt_pexpr12c" $ evalCheck   (sum (map (f . sVal . literal)      [11 .. 20]), 50)
+    , goldenCapturedIO "adt_pexpr12"  $ evalCheckSL (sum . map f) (map (sVal . literal) [11 .. 20],  50)
+
+    , goldenCapturedIO "adt_pexpr13c" $ evalCheck  (f e00, 3)
+    , goldenCapturedIO "adt_pexpr13"  $ evalCheckS f (e00, 3)
+
+    , goldenCapturedIO "adt_pexpr14c" $ evalCheck  (f e01, 6)
+    , goldenCapturedIO "adt_pexpr14"  $ evalCheckS f (e01, 6)
+
+    , goldenCapturedIO "adt_pexpr15c" $ evalCheck  (f e02, 6)
+    , goldenCapturedIO "adt_pexpr15"  $ evalCheckS f (e02, 6)
+
+    , goldenCapturedIO "adt_pexpr16c" $ evalCheck  (f e03, 6)
+    , goldenCapturedIO "adt_pexpr16"  $ evalCheckS f (e03, 6)
+
+    , goldenCapturedIO "adt_pexpr17c" $ evalCheck  (f e04, 6)
+    , goldenCapturedIO "adt_pexpr17"  $ evalCheckS f (e04, 6)
+
+    , goldenCapturedIO "adt_pexpr18c" $ evalCheck  (f e05, 6)
+    , goldenCapturedIO "adt_pexpr18"  $ evalCheckS f (e05, 6)
+
+    , goldenCapturedIO "adt_pgen00"  t00
+    , goldenCapturedIO "adt_pgen01"  $ tSat (-1)
+    , goldenCapturedIO "adt_pgen02"  $ tSat 0
+    , goldenCapturedIO "adt_pgen03"  $ tSat 1
+    , goldenCapturedIO "adt_pgen04"  $ tSat 2
+    , goldenCapturedIO "adt_pgen05"  $ tSat 3
+    , goldenCapturedIO "adt_pgen06"  $ tSat 4
+    , goldenCapturedIO "adt_pgen07"  $ tSat 5
+    , goldenCapturedIO "adt_pgen08"  $ tSat 6
+    , goldenCapturedIO "adt_pgen09"  $ tSat 7
+    , goldenCapturedIO "adt_pgen10"  $ tSat 8
+    , goldenCapturedIO "adt_pgen11"  $ tSat 9
+    , goldenCapturedIO "adt_pgen12"  $ tSat 100
+    , goldenCapturedIO "adt_pchk01"  $ evalTest (t (sA 12))
+    ]
+    where a = literal "a"
+          b = literal "a"
+
+          e00, e01, e02, e03, e04, e05 :: SExpr String Integer
+          e00 = 3                                -- 3
+          e01 = 3 + 4                            -- 7
+          e02 = e00 * e01                        -- 21
+          e03 = sLet a e02 (sVar a + e01)        -- 28
+          e04 = e03 + sLet a e03 (sVar a + e01)  -- 28 + 28 + 7 = 63
+          e05 = sLet b e04 (sVar b * sVar b)     -- 63 * 63 = 3969
+
+evalCheck :: SymVal a => (SBV a, a) -> FilePath -> IO ()
+evalCheck (sv, v) rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                        constrain $ sv ./= literal v
+                        query $ do cs <- checkSat
+                                   case cs of
+                                     Unsat{} -> io $ appendFile rf "All good.\n"
+                                     _       -> error $ "Unexpected: " ++ show cs
+
+evalCheckS :: (SExpr String Integer -> SInteger) -> (SExpr String Integer , Integer) -> FilePath -> IO ()
+evalCheckS fun (e, v) rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                        se :: SExpr String Integer <- free_
+                        constrain $ se .== e
+                        constrain $ fun se ./= literal v
+                        query $ do cs <- checkSat
+                                   case cs of
+                                     Unsat{} -> io $ appendFile rf "All good.\n"
+                                     _       -> error $ "Unexpected: " ++ show cs
+
+evalCheckSL :: ([SExpr String Integer] -> SInteger) -> ([SExpr String Integer], Integer) -> FilePath -> IO ()
+evalCheckSL fun (e, v) rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                        ses :: [SExpr String Integer] <- mapM (const free_) e
+                        constrain $ ses .== e
+                        constrain $ fun ses ./= literal v
+                        query $ do cs <- checkSat
+                                   case cs of
+                                     Unsat{} -> io $ appendFile rf "All good.\n"
+                                     _       -> error $ "Unexpected: " ++ show cs
+
+evalTest :: (Show a, SymVal a) => SBV a -> FilePath -> IO ()
+evalTest sv rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                    res <- free "res"
+                    constrain $ sv .== res
+                    query $ do cs <- checkSat
+                               case cs of
+                                 Sat -> do r <- getValue res
+                                           io $ appendFile rf ("Result: " ++ show r ++ "\n")
+                                 _       -> error $ "Unexpected: " ++ show cs
+
+f :: SExpr String Integer -> SInteger
+f e = [sCase|Expr e of
+         Var s     | s .== literal "a"                       -> 0
+                   | s .== literal "b" .|| s .== literal "c" -> 1
+                   | sTrue                                   -> 2
+
+         Val i     | i .<  10                                -> 3
+                   | i .== 10                                -> 4
+                   | i .>  10                                -> 5
+
+         _                                                   -> 6
+      |]
+
+-- Create something like:
+--       let a = _
+--    in let b = _
+--    in _ + _
+-- such that it evaluates to 12
+t00 :: FilePath -> IO ()
+t00 rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+            a :: SExpr String Word16 <- free "a"
+            constrain $ isValid isId a
+            constrain $ eval a .== 12
+
+            constrain $ isLet a
+            constrain $ isLet (getLet_3 a)
+            constrain $ isAdd (getLet_3 (getLet_3 a))
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat{} -> do v <- getValue a
+                                     io $ do appendFile rf $ "\nGot: " ++ show v
+                                             appendFile rf   "\nDONE\n"
+                         _     -> error $ "Unexpected: " ++ show cs
+
+g :: (SymVal val, OrdSymbolic (SBV val), Num (SBV val)) => SExpr String val -> SInteger
+g e = [sCase|Expr e of
+         Var s     | s .== literal "a"                       -> 0
+                   | s .== literal "b" .|| s .== literal "c" -> 1
+                   | sTrue                                   -> 2
+
+         Val i     | i .<  10                                -> 3
+                   | i .== 10                                -> 4
+                   | i .>  10                                -> 5
+
+         Add _ _ -> 6
+         Mul _ _ -> 7
+         Let{}   -> 8
+
+         _ -> 100
+      |]
+
+-- Show that g can never produce anything but 0..8
+tSat :: Integer -> FilePath -> IO ()
+tSat i rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+              a :: SExpr String Word16 <- free "a"
+              constrain $ g a .== literal i
+
+              query $ do cs <- checkSat
+                         case cs of
+                           Sat{} -> do v <- getValue a
+                                       io $ do appendFile rf $ "\nGot: " ++ show v
+                                               appendFile rf   "\nDONE\n"
+                           Unsat -> io $ do appendFile rf "\nUNSAT\n"
+                           _     -> error $ "Unexpected: " ++ show cs
+
+t :: SA -> SA
+t = smtFunction "t" $ \a ->
+       [sCase|A a of
+         A u     -> sA (u+1)
+         B w     -> sB (w+2)
+         C a1 a2 -> sC (t a1) (t a2)
+      |]
diff --git a/SBVTestSuite/TestSuite/Basics/AllSat.hs b/SBVTestSuite/TestSuite/Basics/AllSat.hs
--- a/SBVTestSuite/TestSuite/Basics/AllSat.hs
+++ b/SBVTestSuite/TestSuite/Basics/AllSat.hs
@@ -9,10 +9,7 @@
 -- Test suite for basic allsat calls
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
@@ -27,7 +24,7 @@
 import qualified Control.Exception as C
 
 data Q
-mkUninterpretedSort ''Q
+mkSymbolic [''Q]
 
 tests :: TestTree
 tests =
diff --git a/SBVTestSuite/TestSuite/Basics/ArithNoSolver.hs b/SBVTestSuite/TestSuite/Basics/ArithNoSolver.hs
--- a/SBVTestSuite/TestSuite/Basics/ArithNoSolver.hs
+++ b/SBVTestSuite/TestSuite/Basics/ArithNoSolver.hs
@@ -10,11 +10,9 @@
 -- the constant folding based arithmetic implementation in SBV
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE CPP              #-}
-{-# LANGUAGE DataKinds        #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE Rank2Types       #-}
-{-# LANGUAGE TupleSections    #-}
+{-# LANGUAGE CPP           #-}
+{-# LANGUAGE Rank2Types    #-}
+{-# LANGUAGE TupleSections #-}
 
 #if MIN_VERSION_base(4,19,0)
 {-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-uni-patterns -Wno-x-partial #-}
@@ -29,9 +27,7 @@
 
 import Data.Maybe (fromJust, fromMaybe)
 
-import qualified Data.Char     as C
-
-import qualified Data.SBV.Char () -- instances only
+import qualified Data.Char as C
 
 -- Test suite
 tests :: TestTree
@@ -162,8 +158,6 @@
         -- Haskell's divMod and quotRem differs from SBV's in two ways:
         --     - when y is 0, Haskell throws an exception, SBV sets the result to 0; like in division
         --     - Haskell overflows if x == minBound and y == -1 for bounded signed types; but SBV returns minBound, 0; which is more meaningful
-        -- NB. There was a ticket filed against the second anomaly above, See: http://ghc.haskell.org/trac/ghc/ticket/8695
-        -- But the Haskell folks decided not to fix it. Sigh..
         overflow x y = x == minBound && y == -1
         divMod0  x y = if y == 0       then (0, x) else x `divMod`   y
         divMod1  x y = if overflow x y then (x, 0) else x `divMod0`  y
diff --git a/SBVTestSuite/TestSuite/Basics/ArithNoSolver2.hs b/SBVTestSuite/TestSuite/Basics/ArithNoSolver2.hs
--- a/SBVTestSuite/TestSuite/Basics/ArithNoSolver2.hs
+++ b/SBVTestSuite/TestSuite/Basics/ArithNoSolver2.hs
@@ -10,18 +10,14 @@
 -- the constant folding based arithmetic implementation in SBV
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE CPP                #-}
-{-# LANGUAGE DataKinds          #-}
-{-# LANGUAGE DeriveAnyClass     #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE FlexibleContexts   #-}
-{-# LANGUAGE FlexibleInstances  #-}
-{-# LANGUAGE Rank2Types         #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE TemplateHaskell    #-}
-{-# LANGUAGE TupleSections      #-}
-{-# LANGUAGE TypeApplications   #-}
-{-# LANGUAGE QuasiQuotes        #-}
+{-# LANGUAGE CPP               #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE Rank2Types        #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+{-# LANGUAGE QuasiQuotes       #-}
 
 #if MIN_VERSION_base(4,19,0)
 {-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-uni-patterns -Wno-x-partial #-}
@@ -42,8 +38,8 @@
 import qualified Data.SBV.Char   as SC
 import qualified Data.SBV.List   as SL
 
-data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving (Bounded, Enum, Eq)
-mkSymbolicEnumeration  ''Day
+data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving (Show, Eq, Enum, Bounded)
+mkSymbolic  [''Day]
 
 -- Test suite
 tests :: TestTree
@@ -449,7 +445,6 @@
 
         -- NB. Precision here is important. If you pick too small of a significand
         -- size then you can turn this enumeration into an infinite list, busting the tests.
-        -- For details see: https://gitlab.haskell.org/ghc/ghc/-/issues/15081
         fps :: [FloatingPoint 5 8]
         fps = [-3.4, -3.2 .. 3.5]
 
@@ -539,6 +534,8 @@
 
 -- Quiet GHC about unused enum elts
 _unused :: SDay
-_unused = undefined sMon sTue sWed sThu sFri sSat sSun
+_unused = undefined  sMon  sTue  sWed  sThu  sFri  sSat  sSun
+                    isMon isTue isWed isThu isFri isSat isSun
+                    (sCaseDay @SInteger)
 
 {- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Basics/ArithSolver.hs b/SBVTestSuite/TestSuite/Basics/ArithSolver.hs
--- a/SBVTestSuite/TestSuite/Basics/ArithSolver.hs
+++ b/SBVTestSuite/TestSuite/Basics/ArithSolver.hs
@@ -13,14 +13,11 @@
 
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE DataKinds           #-}
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE FlexibleInstances   #-}
-{-# LANGUAGE Rank2Types          #-}
 {-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE Rank2Types          #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
 {-# LANGUAGE TypeApplications    #-}
 
@@ -41,8 +38,8 @@
 import qualified Data.SBV.Char   as SC
 import qualified Data.SBV.List   as SL
 
-data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving (Bounded, Enum, Eq)
-mkSymbolicEnumeration  ''Day
+data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving (Show, Bounded, Enum, Eq)
+mkSymbolic  [''Day]
 
 -- Test suite
 tests :: TestTree
@@ -1029,8 +1026,6 @@
 
         -- NB. Precision here is important. If you pick too small of a significand
         -- size then you can turn this enumeration into an infinite list, busting the tests.
-        -- For details see: https://gitlab.haskell.org/ghc/ghc/-/issues/15081
-        -- And likewise, constant folding doesn't happen, too difficult for z3
         fps :: [FloatingPoint 5 8]
         -- fps = [-3.4, -3.2 .. 3.5]
         fps = []
@@ -1046,6 +1041,8 @@
 
 -- Quiet GHC about unused enum elts
 _unused :: SDay
-_unused = undefined sMon sTue sWed sThu sFri sSat sSun
+_unused = undefined  sMon  sTue  sWed  sThu  sFri  sSat  sSun
+                    isMon isTue isWed isThu isFri isSat isSun
+                    (sCaseDay @SInteger)
 
 {- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Basics/BarrelRotate.hs b/SBVTestSuite/TestSuite/Basics/BarrelRotate.hs
--- a/SBVTestSuite/TestSuite/Basics/BarrelRotate.hs
+++ b/SBVTestSuite/TestSuite/Basics/BarrelRotate.hs
@@ -10,7 +10,6 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE FlexibleContexts    #-}
-{-# LANGUAGE RankNTypes          #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications    #-}
 
diff --git a/SBVTestSuite/TestSuite/Basics/Lambda.hs b/SBVTestSuite/TestSuite/Basics/Lambda.hs
--- a/SBVTestSuite/TestSuite/Basics/Lambda.hs
+++ b/SBVTestSuite/TestSuite/Basics/Lambda.hs
@@ -10,14 +10,10 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE DataKinds           #-}
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE OverloadedLists     #-}
 {-# LANGUAGE QuasiQuotes         #-}
-{-# LANGUAGE RankNTypes          #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
 {-# LANGUAGE TypeApplications    #-}
 
@@ -46,7 +42,7 @@
 import Utils.SBVTestFramework
 
 data P
-mkUninterpretedSort ''P
+mkSymbolic [''P]
 
 drinker :: Predicate
 drinker = pure $ quantifiedBool $ \(Exists x) (Forall y) -> d x .=> d y
diff --git a/SBVTestSuite/TestSuite/Basics/List.hs b/SBVTestSuite/TestSuite/Basics/List.hs
--- a/SBVTestSuite/TestSuite/Basics/List.hs
+++ b/SBVTestSuite/TestSuite/Basics/List.hs
@@ -133,7 +133,7 @@
   constrain $ sNot $ c `L.isInfixOf` b
   constrain $ sNot $ b `L.isInfixOf` c
 
--- Any string is equal to the prefix and suffix that add up to a its length.
+-- Any string is equal to the prefix and suffix that add up to its length.
 seqExamples8 :: Symbolic ()
 seqExamples8 = do
   [a, b, c :: SList Integer] <- sLists ["a", "b", "c"]
diff --git a/SBVTestSuite/TestSuite/Basics/Quantifiers.hs b/SBVTestSuite/TestSuite/Basics/Quantifiers.hs
--- a/SBVTestSuite/TestSuite/Basics/Quantifiers.hs
+++ b/SBVTestSuite/TestSuite/Basics/Quantifiers.hs
@@ -13,7 +13,6 @@
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications    #-}
 
 #if MIN_VERSION_base(4,19,0)
 {-# LANGUAGE TypeAbstractions    #-}
diff --git a/SBVTestSuite/TestSuite/Basics/Set.hs b/SBVTestSuite/TestSuite/Basics/Set.hs
--- a/SBVTestSuite/TestSuite/Basics/Set.hs
+++ b/SBVTestSuite/TestSuite/Basics/Set.hs
@@ -9,12 +9,10 @@
 -- Test sets.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -29,11 +27,8 @@
 
 import Utils.SBVTestFramework hiding (complement)
 
-data E = A | B | C deriving (Bounded, Enum, Ord, Eq)
-mkSymbolicEnumeration ''E
-
-__unused :: SE
-__unused = error "stop GHC from complaining unused names" sA sB sC
+data E = A | B | C deriving (Show, Eq, Ord)
+mkSymbolic [''E]
 
 type SC = SSet  Integer
 type RC = RCSet Integer
diff --git a/SBVTestSuite/TestSuite/Basics/String.hs b/SBVTestSuite/TestSuite/Basics/String.hs
--- a/SBVTestSuite/TestSuite/Basics/String.hs
+++ b/SBVTestSuite/TestSuite/Basics/String.hs
@@ -135,7 +135,7 @@
   constrain $ sNot $ c `S.isInfixOf` b
   constrain $ sNot $ b `S.isInfixOf` c
 
--- Any string is equal to the prefix and suffix that add up to a its length.
+-- Any string is equal to the prefix and suffix that add up to its length.
 strExamples8 :: Symbolic ()
 strExamples8 = do
   [a, b, c] <- sStrings ["a", "b", "c"]
diff --git a/SBVTestSuite/TestSuite/Basics/Sum.hs b/SBVTestSuite/TestSuite/Basics/Sum.hs
--- a/SBVTestSuite/TestSuite/Basics/Sum.hs
+++ b/SBVTestSuite/TestSuite/Basics/Sum.hs
@@ -86,7 +86,7 @@
 -- Test 'sMaybe', 'map', 'isNothing', 'isJust', and 'maybe'
 sumMaybe :: Symbolic ()
 sumMaybe = do
-  x <- sMaybe @Integer "x"
+  x :: SMaybe Integer <- free "x"
   let x' = M.map (+1) x
   constrain $ isNothing x .== isNothing x'
   constrain $ isJust x    .== isJust x'
@@ -105,23 +105,23 @@
 sumMaybeBoth :: Symbolic ()
 sumMaybeBoth = do
    (x :: SEither Integer Integer) <- sEither_
-   (y :: SMaybe Integer)          <- sMaybe_
+   (y :: SMaybe Integer)          <- free_
 
    constrain $ isLeft x
    constrain $ isJust y
 
 sumMergeMaybe1 :: Symbolic ()
 sumMergeMaybe1 = do
-   (x :: SMaybe Integer) <- sMaybe_
-   (y :: SMaybe Integer) <- sMaybe_
+   (x :: SMaybe Integer) <- free_
+   (y :: SMaybe Integer) <- free_
    b  <- sBool_
 
    constrain $ isNothing $ ite b x y
 
 sumMergeMaybe2 :: Symbolic ()
 sumMergeMaybe2 = do
-   (x :: SMaybe Integer) <- sMaybe_
-   (y :: SMaybe Integer) <- sMaybe_
+   (x :: SMaybe Integer) <- free_
+   (y :: SMaybe Integer) <- free_
    b  <- sBool_
 
    constrain $ isJust $ ite b x y
diff --git a/SBVTestSuite/TestSuite/Basics/Tuple.hs b/SBVTestSuite/TestSuite/Basics/Tuple.hs
--- a/SBVTestSuite/TestSuite/Basics/Tuple.hs
+++ b/SBVTestSuite/TestSuite/Basics/Tuple.hs
@@ -9,12 +9,8 @@
 -- Test tuples.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DataKinds           #-}
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
 {-# LANGUAGE TypeApplications    #-}
 
@@ -32,11 +28,8 @@
 
 import Utils.SBVTestFramework
 
-data E = A | B | C deriving (Bounded, Enum)
-mkSymbolicEnumeration ''E
-
-__unused :: SE
-__unused = error "stop GHC from complaining unused names" sA sB sC
+data E = A | B | C deriving Show
+mkSymbolic [''E]
 
 -- Test suite
 tests :: TestTree
diff --git a/SBVTestSuite/TestSuite/Basics/UISat.hs b/SBVTestSuite/TestSuite/Basics/UISat.hs
--- a/SBVTestSuite/TestSuite/Basics/UISat.hs
+++ b/SBVTestSuite/TestSuite/Basics/UISat.hs
@@ -8,7 +8,6 @@
 --
 -- Testing UI function sat examples
 -----------------------------------------------------------------------------
-{-# LANGUAGE OverloadedStrings #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
diff --git a/SBVTestSuite/TestSuite/Char/Char.hs b/SBVTestSuite/TestSuite/Char/Char.hs
--- a/SBVTestSuite/TestSuite/Char/Char.hs
+++ b/SBVTestSuite/TestSuite/Char/Char.hs
@@ -18,10 +18,10 @@
 import Utils.SBVTestFramework
 import Data.SBV.Control
 
+import qualified Data.SBV.Either as E
 import qualified Data.SBV.List   as L
-import qualified Data.SBV.Set    as S
 import qualified Data.SBV.Maybe  as M
-import qualified Data.SBV.Either as E
+import qualified Data.SBV.Set    as S
 import Data.SBV.Tuple
 
 tests :: TestTree
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase.hs b/SBVTestSuite/TestSuite/CompileTests/SCase.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase.hs
@@ -0,0 +1,19 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CompileTests.SCase
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing TH messages
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CompileTests.SCase(tests) where
+
+import Utils.SBVTestFramework
+
+tests :: IO TestTree
+tests = testGroup "THTests.SCase" <$> mkCompileTestGlob "SBVTestSuite/TestSuite/CompileTests/SCase/SCase*.hs"
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/Expr.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/Expr.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/Expr.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Expr where
+
+import Data.SBV
+
+data Expr = Zero
+          | Num Integer
+          | Var String
+          | Add Expr Expr
+          | Let String Expr Expr
+          deriving Show
+
+mkSymbolic [''Expr]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase01.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase01.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase01.hs
@@ -0,0 +1,11 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of|]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase01.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase01.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase01.stderr
@@ -0,0 +1,8 @@
+SCase01.hs:11:14: error: [GHC-39584]
+    " SCase01.hs:11:13: Parse error: EOF
+
+    " In the quasi-quotation: [sCase|Expr e of|]
+   |
+11 | t e = [sCase|Expr e of|]
+   |              ^^^^^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase02.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase02.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase02.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+        Zero  -> 0
+        Num i -> i
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase02.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase02.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase02.stderr
@@ -0,0 +1,17 @@
+SCase02.hs:11:14: error: [GHC-39584]
+    " sCase: Pattern match(es) are non-exhaustive.
+        Not matched     : Var
+        Patterns of type: Expr
+        Must match each : Zero, Num, Var, Add, Let
+
+      You can use a '_' to match multiple cases.
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+        Zero  -> 0
+        Num i -> i
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase03.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase03.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase03.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+        Zero  -> 0
+        Num _ _ -> i
+        Var _ -> 0
+        Add _ _ -> 2
+        Let _ _ _ -> 3
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase03.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase03.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase03.stderr
@@ -0,0 +1,19 @@
+SCase03.hs:11:14: error: [GHC-39584]
+    " SCase03.hs:13:9-15: sCase: Arity mismatch.
+        Type       : Expr
+        Constructor: Num
+        Expected   : 1
+        Given      : 2
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+        Zero  -> 0
+        Num _ _ -> i
+        Var _ -> 0
+        Add _ _ -> 2
+        Let _ _ _ -> 3
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase04.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase04.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase04.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Rejected at the top level
+[sCase|Expr e of
+        Zero  -> 0
+        Num i -> i
+      |]
+
+{- HLint ignore module "Unused LANGUAGE pragma" -}
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase04.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase04.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase04.stderr
@@ -0,0 +1,6 @@
+SCase04.hs:11:8: error: [GHC-39584]
+    sCase: not usable in declaration context
+   |
+11 | [sCase|Expr e of
+   |        ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase05.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase05.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase05.hs
@@ -0,0 +1,12 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- bad syntax
+t :: SExpr -> SInteger
+t e = [sCase|Expr e + 1|]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase05.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase05.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase05.stderr
@@ -0,0 +1,13 @@
+SCase05.hs:12:14: error: [GHC-39584]
+    " sCase: Failed to parse a symbolic case-expression.
+
+           Instead of:   case      expr of alts
+           Write     : [sCase|Type expr of alts|]
+
+        where Type is the underlying concrete type of the expression.
+
+    " In the quasi-quotation: [sCase|Expr e + 1|]
+   |
+12 | t e = [sCase|Expr e + 1|]
+   |              ^^^^^^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase06.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase06.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase06.hs
@@ -0,0 +1,12 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- bad type
+t :: SExpr -> SInteger
+t e = [sCase|FExpr e of Num _ -> 1|]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase06.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase06.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase06.stderr
@@ -0,0 +1,12 @@
+SCase06.hs:12:14: error: [GHC-39584]
+    " sCase: Unknown symbolic ADT: FExpr
+
+        To use a symbolic case expression, declare your ADT, and then:
+             mkSymbolic [''FExpr]
+        In a template-haskell context.
+
+    " In the quasi-quotation: [sCase|FExpr e of Num _ -> 1|]
+   |
+12 | t e = [sCase|FExpr e of Num _ -> 1|]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase07.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase07.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase07.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero          -> 0
+               Num i | Just 1 <- Just i         -> i
+               Var s        -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase07.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase07.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase07.stderr
@@ -0,0 +1,16 @@
+SCase07.hs:11:14: error: [GHC-39584]
+    " sCase: Pattern guards are not supported: 
+        Just 1 <- Just i
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero          -> 0
+               Num i | Just 1 <- Just i         -> i
+               Var s        -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase08.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase08.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase08.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero          -> 0
+               Num i | Just 1 <- Just i         -> i
+               Var s        -> ite (s .== "a") 1 else 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase08.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase08.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase08.stderr
@@ -0,0 +1,15 @@
+SCase08.hs:11:14: error: [GHC-39584]
+    " SCase08.hs:14:50: Parse error: else
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero          -> 0
+               Num i | Just 1 <- Just i         -> i
+               Var s        -> ite (s .== "a") 1 else 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase09.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase09.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase09.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero          -> 0
+               Num i         -> i
+               Viar s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase09.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase09.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase09.stderr
@@ -0,0 +1,14 @@
+SCase09.hs:11:14: error: [GHC-39584]
+    " SCase09.hs:14:16-21: sCase: Not in scope: data constructor: Viar
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero          -> 0
+               Num i         -> i
+               Viar s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase10.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase10.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase10.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero          -> 0
+               Num (Num i)   -> i
+               Viar s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase10.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase10.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase10.stderr
@@ -0,0 +1,18 @@
+SCase10.hs:11:14: error: [GHC-39584]
+    " SCase10.hs:13:16-26: sCase: Unsupported complex pattern match.
+        Saw: (Num i)
+
+      Only variables and wild-card are supported.
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero          -> 0
+               Num (Num i)   -> i
+               Viar s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase11.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase11.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase11.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero          -> 0
+               Num i         -> i
+               _ -> 3
+               Var s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase11.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase11.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase11.stderr
@@ -0,0 +1,19 @@
+SCase11.hs:11:14: error: [GHC-39584]
+    " SCase11.hs:14:16: sCase: Wildcard makes the remaining matches redundant:
+        SCase11.hs:15:16-20: Var s
+        SCase11.hs:16:16-22: Add a b
+        SCase11.hs:17:16-28: Let _ _a b
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero          -> 0
+               Num i         -> i
+               _ -> 3
+               Var s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase12.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase12.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase12.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero          -> 0
+               Num i         -> i
+               _ -> 3
+               _ -> 5
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase12.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase12.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase12.stderr
@@ -0,0 +1,15 @@
+SCase12.hs:11:14: error: [GHC-39584]
+    " SCase12.hs:14:16: sCase: Wildcard makes the remaining matches redundant:
+        SCase12.hs:15:16: _
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero          -> 0
+               Num i         -> i
+               _ -> 3
+               _ -> 5
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase13.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase13.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase13.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero          -> 0
+               Num i         -> i
+               Var {} _      -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase13.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase13.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase13.stderr
@@ -0,0 +1,15 @@
+SCase13.hs:11:14: error: [GHC-39584]
+    " SCase13.hs:14:30: Parse error in pattern: Var{}
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero          -> 0
+               Num i         -> i
+               Var {} _      -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase14.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase14.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase14.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero          -> 0
+               Num i         -> i
+               Var s _       -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase14.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase14.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase14.stderr
@@ -0,0 +1,19 @@
+SCase14.hs:11:14: error: [GHC-39584]
+    " SCase14.hs:14:16-22: sCase: Arity mismatch.
+        Type       : Expr
+        Constructor: Var
+        Expected   : 1
+        Given      : 2
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero          -> 0
+               Num i         -> i
+               Var s _       -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase15.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase15.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase15.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero          -> 0
+               Num i         -> i
+               Var s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               _ _ -> 3
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase15.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase15.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase15.stderr
@@ -0,0 +1,15 @@
+SCase15.hs:11:14: error: [GHC-39584]
+    " SCase15.hs:16:20: Parse error in pattern: _
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero          -> 0
+               Num i         -> i
+               Var s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               _ _ -> 3
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase16.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase16.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase16.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero           -> 0
+               Num i | i .< 3 -> i
+               Var s          -> ite (s .== "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase16.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase16.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase16.stderr
@@ -0,0 +1,18 @@
+SCase16.hs:11:14: error: [GHC-39584]
+    " SCase16.hs:13:16-20: sCase: Non-exhaustive match:
+        Type       : Expr
+        Constructor: Num i | i .< 3
+      NB. Guarded match might fail.
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero           -> 0
+               Num i | i .< 3 -> i
+               Var s          -> ite (s .== "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase17.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase17.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase17.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero           -> 0
+               Num i | i .< 3 -> i
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t a + t b
+               Num i          -> i+1
+               Let _   _a  b  -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase17.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase17.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase17.stderr
@@ -0,0 +1,1 @@
+There was no failure during compilation.
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase18.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase18.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase18.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero           -> 0
+               Num i -> 4
+               Num i | i .< 3 -> i
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase18.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase18.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase18.stderr
@@ -0,0 +1,20 @@
+SCase18.hs:11:14: error: [GHC-39584]
+    " SCase18.hs:14:16-20: sCase: Overlapping case constructors:
+        Type       : Expr
+        Constructor: Num i | i .< 3
+      Overlaps with:
+        SCase18.hs:13:16-20: Num i
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero           -> 0
+               Num i -> 4
+               Num i | i .< 3 -> i
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase19.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase19.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase19.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero           -> 0
+               Num i -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+               _ | 2 .>= 3 -> 4
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase19.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase19.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase19.stderr
@@ -0,0 +1,19 @@
+SCase19.hs:11:14: error: [GHC-39584]
+    " SCase19.hs:17:16: sCase: Non-exhaustive match:
+        Type       : Expr
+        Constructor: _ | 2 .>= 3
+      NB. Guarded match might fail.
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero           -> 0
+               Num i -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+               _ | 2 .>= 3 -> 4
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase20.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase20.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase20.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero           -> 0
+               Num i          -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+               _ -> 4
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase20.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase20.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase20.stderr
@@ -0,0 +1,15 @@
+SCase20.hs:11:14: error: [GHC-39584]
+    " SCase20.hs:17:16: sCase: Wildcard match is redundant
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero           -> 0
+               Num i          -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+               _ -> 4
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase21.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase21.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase21.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero           -> 0
+               Num i | i .> 4 -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase21.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase21.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase21.stderr
@@ -0,0 +1,18 @@
+SCase21.hs:11:14: error: [GHC-39584]
+    " SCase21.hs:13:16-20: sCase: Non-exhaustive match:
+        Type       : Expr
+        Constructor: Num i | i .> 4
+      NB. Guarded match might fail.
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero           -> 0
+               Num i | i .> 4 -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase22.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase22.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase22.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero           -> 0
+               Num i | i .> 4 -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+               _ | 2 .>= 3    -> 5
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase22.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase22.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase22.stderr
@@ -0,0 +1,19 @@
+SCase22.hs:11:14: error: [GHC-39584]
+    " SCase22.hs:13:16-20: sCase: Non-exhaustive match:
+        Type       : Expr
+        Constructor: Num i | i .> 4
+      NB. Guarded match might fail.
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Zero           -> 0
+               Num i | i .> 4 -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+               _ | 2 .>= 3    -> 5
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase23.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase23.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase23.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero           -> 0
+               Num i          -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t a + t b
+               Let _   _a  b  -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase23.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase23.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase23.stderr
@@ -0,0 +1,6 @@
+SCase23.hs:11:14: error: [GHC-40910] [-Wunused-matches, Werror=unused-matches]
+    Defined but not used: i
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase24.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase24.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase24.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Zero           -> 0
+               Num _          -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b | t a .== 4 -> t b
+               Let _   _a  b  -> t b
+               _ -> 2
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase24.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase24.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase24.stderr
@@ -0,0 +1,1 @@
+There was no failure during compilation.
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase25.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase25.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase25.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+f :: SExpr -> SInteger
+f e = [sCase|Expr e of
+         Var s     | s .== literal "a"                       -> 0
+                   | s .== literal "b" .|| s .== literal "c" -> 1
+                   | sTrue                                   -> 2
+
+         Num i     | sTrue                                   -> 3
+
+         _                                                   -> 6
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase25.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase25.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase25.stderr
@@ -0,0 +1,6 @@
+SCase25.hs:11:14: error: [GHC-40910] [-Wunused-matches, Werror=unused-matches]
+    Defined but not used: i
+   |
+11 | f e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase26.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase26.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase26.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Data.SBV
+
+data A = A1 { u :: Integer }
+       | B1 { s :: String, k :: Float }
+       | C1
+
+mkSymbolic [''A]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase26.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase26.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase26.stderr
@@ -0,0 +1,1 @@
+There was no failure during compilation.
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase27.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase27.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase27.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Data.SBV
+
+-- don't allow multiple accessors
+data A = A1 { u :: Integer }
+       | B1 { u :: Integer, s :: String}
+       | C1
+
+mkSymbolic [''A]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase27.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase27.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase27.stderr
@@ -0,0 +1,11 @@
+SCase27.hs:14:1: error: [GHC-39584]
+    mkSymbolic: Unsupported field accessor definition.
+      Multiply used: u
+      
+      SBV does not support cases where accessor fields are replicated.
+      Please use each accessor only once.
+
+   |
+14 | mkSymbolic [''A]
+   | ^^^^^^^^^^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase28.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase28.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase28.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Num i | i .> 3 -> 5
+                     | sTrue  -> 12
+
+               Zero{} -> 0
+               Var{}  -> 0
+               Add{}  -> 0
+               Let{}  -> 0
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase28.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase28.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase28.stderr
@@ -0,0 +1,1 @@
+There was no failure during compilation.
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase29.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase29.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase29.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase|Expr e of
+               Num i | i > 3  -> 5
+                     | sTrue  -> 12
+               Num i | i > 12 -> 7
+
+               Zero{} -> 0
+               Var{}  -> 0
+               Add{}  -> 0
+               Let{}  -> 0
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase29.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase29.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase29.stderr
@@ -0,0 +1,22 @@
+SCase29.hs:11:14: error: [GHC-39584]
+    " SCase29.hs:14:16-20: sCase: Overlapping case constructors:
+        Type       : Expr
+        Constructor: Num i | i > 12
+      Overlaps with:
+        SCase29.hs:12:16-20: Num i
+
+    " In the quasi-quotation:
+        [sCase|Expr e of
+               Num i | i > 3  -> 5
+                     | sTrue  -> 12
+               Num i | i > 12 -> 7
+
+               Zero{} -> 0
+               Var{}  -> 0
+               Add{}  -> 0
+               Let{}  -> 0
+      |]
+   |
+11 | t e = [sCase|Expr e of
+   |              ^^^^^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase30.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase30.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase30.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Data.SBV
+
+-- Testing constructor/type name conflct
+data A = A Integer
+       | B Float
+       | C A A
+
+mkSymbolic [''A]
+
+t :: SA -> SA
+t a = [sCase|A a of
+         A u     -> sA (u+1)
+         B f     -> sB (f+2)
+         C a1 a2 -> sC (t a1) (t a2)
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase30.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase30.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase30.stderr
@@ -0,0 +1,1 @@
+There was no failure during compilation.
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase31.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase31.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase31.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE TemplateHaskell   #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Data.SBV
+
+-- Testing bad fields
+data A = F (Integer -> Bool)
+       | I Integer
+
+mkSymbolic [''A]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase31.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase31.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase31.stderr
@@ -0,0 +1,12 @@
+SCase31.hs:13:1: error: [GHC-39584]
+    mkSymbolic: Unsupported constructor kind
+      Datatype   : A
+      Constructor: F
+      Kind       : GHC.Num.Integer.Integer -> GHC.Types.Bool
+      
+      Higher order fields (i.e., function values) are not supported.
+
+   |
+13 | mkSymbolic [''A]
+   | ^^^^^^^^^^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase32.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase32.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase32.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE TemplateHaskell   #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module T where
+
+import Data.SBV
+
+-- Testing bad fields
+data A = F (A -> Bool)
+       | I Integer
+
+mkSymbolic [''A]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase32.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase32.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase32.stderr
@@ -0,0 +1,12 @@
+SCase32.hs:13:1: error: [GHC-39584]
+    mkSymbolic: Unsupported constructor kind
+      Datatype   : A
+      Constructor: F
+      Kind       : T.A -> GHC.Types.Bool
+      
+      Higher order fields (i.e., function values) are not supported.
+
+   |
+13 | mkSymbolic [''A]
+   | ^^^^^^^^^^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/Optimization/NoOpt.hs b/SBVTestSuite/TestSuite/Optimization/NoOpt.hs
--- a/SBVTestSuite/TestSuite/Optimization/NoOpt.hs
+++ b/SBVTestSuite/TestSuite/Optimization/NoOpt.hs
@@ -9,9 +9,9 @@
 -- Check that if optimization is done, there must be goals and vice versa
 -----------------------------------------------------------------------------
 
-{-# OPTIONS_GHC -Wall -Werror #-}
-
 {-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
 
 module TestSuite.Optimization.NoOpt(tests) where
 
diff --git a/SBVTestSuite/TestSuite/Queries/Enums.hs b/SBVTestSuite/TestSuite/Queries/Enums.hs
--- a/SBVTestSuite/TestSuite/Queries/Enums.hs
+++ b/SBVTestSuite/TestSuite/Queries/Enums.hs
@@ -9,12 +9,10 @@
 -- Test suite for Documentation.SBV.Examples.Uninterpreted.AUF
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -24,8 +22,8 @@
 
 import Utils.SBVTestFramework
 
-data BinOp  = Plus | Minus | Times deriving (Enum, Bounded, Ord, Eq)
-mkSymbolicEnumeration ''BinOp
+data BinOp  = Plus | Minus | Times
+mkSymbolic [''BinOp]
 
 -- Test suite
 tests :: TestTree
diff --git a/SBVTestSuite/TestSuite/Queries/FreshVars.hs b/SBVTestSuite/TestSuite/Queries/FreshVars.hs
--- a/SBVTestSuite/TestSuite/Queries/FreshVars.hs
+++ b/SBVTestSuite/TestSuite/Queries/FreshVars.hs
@@ -9,14 +9,12 @@
 -- Testing fresh-vars in query mode
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE OverloadedLists     #-}
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -26,11 +24,8 @@
 
 import Utils.SBVTestFramework
 
-data BinOp  = Plus | Minus | Times deriving (Enum, Bounded)
-mkSymbolicEnumeration ''BinOp
-
-_unused :: a
-_unused = error "stop GHC from complaining unused names" sPlus sMinus sTimes
+data BinOp  = Plus | Minus | Times
+mkSymbolic [''BinOp]
 
 -- Test suite
 tests :: TestTree
diff --git a/SBVTestSuite/TestSuite/Queries/Sums.hs b/SBVTestSuite/TestSuite/Queries/Sums.hs
--- a/SBVTestSuite/TestSuite/Queries/Sums.hs
+++ b/SBVTestSuite/TestSuite/Queries/Sums.hs
@@ -60,24 +60,23 @@
        then return av
        else error $ "Didn't expect this: " ++ show av
 
-queryListOfSum :: Symbolic [Either Integer Char]
+-- This one has decidability problems if I force
+-- the list to have two elements. The current model
+-- returned has only one element; which is fine.
+-- (Adding a constraint to set the length to be anything causes unknown)
+queryListOfSum :: Symbolic [Either Integer Integer]
 queryListOfSum = do
-  lst <- sList @(Either Integer Char) "lst"
-  constrain $ L.length lst .== 2
+  lst <- sList @(Either Integer Integer) "lst"
   constrain $ isLeft $ L.head lst
   constrain $ isRight $ L.head $ L.tail lst
 
   query $ do
-    _  <- checkSat
-    av <- getValue lst
-
-    case av of
-      [Left _, Right _] -> return av
-      _                 -> error $ "Didn't expect this: " ++ show av
+    ensureSat
+    getValue lst
 
 queryMaybe :: Symbolic (Maybe Integer)
 queryMaybe = do
-  a <- sMaybe @Integer "a"
+  a :: M.SMaybe Integer <- free "a"
 
   constrain $ M.maybe sFalse (.== 1) a
 
@@ -90,20 +89,19 @@
        then return av
        else error $ "Didn't expect this: " ++ show av
 
+-- This one has decidability problems if I force
+-- the list to have two elements. The current model
+-- returned has only one element; which is fine.
+-- (Adding a constraint to set the length to be anything causes unknown)
 queryListOfMaybe :: Symbolic [Maybe Char]
 queryListOfMaybe = do
   lst <- sList @(Maybe Char) "lst"
-  constrain $ L.length lst .== 2
-  constrain $ isJust $ L.head lst
-  constrain $ isNothing $ L.head $ L.tail lst
+  constrain $ isJust (L.head lst)
+  constrain $ isNothing (L.head (L.tail lst))
 
   query $ do
-    _  <- checkSat
-    av <- getValue lst
-
-    case av of
-      [Just _, Nothing] -> return av
-      _                 -> error $ "Didn't expect this: " ++ show av
+    ensureSat
+    getValue lst
 
 querySumMaybeBoth :: Symbolic (Either Integer Integer, Maybe Integer)
 querySumMaybeBoth = query $ do
diff --git a/SBVTestSuite/TestSuite/Queries/Tables.hs b/SBVTestSuite/TestSuite/Queries/Tables.hs
--- a/SBVTestSuite/TestSuite/Queries/Tables.hs
+++ b/SBVTestSuite/TestSuite/Queries/Tables.hs
@@ -9,11 +9,11 @@
 -- Test case for https://github.com/LeventErkok/sbv/issues/539
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass                #-}
-{-# LANGUAGE DeriveGeneric                 #-}
-{-# LANGUAGE FlexibleContexts              #-}
-{-# LANGUAGE Rank2Types                    #-}
-{-# LANGUAGE QuantifiedConstraints         #-}
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE Rank2Types            #-}
+{-# LANGUAGE QuantifiedConstraints #-}
 
 {-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
 
@@ -124,7 +124,7 @@
     return $ map (.== 1) locs `pbExactly` 1
 
 perform :: SInput -> Engine ()
-perform (verb, noun) = sCase verb (return ())
+perform (verb, noun) = goCase verb (return ())
     [ (1, builtin_go)
     , (10, builtin_get)
     ]
@@ -153,8 +153,8 @@
 replaceAt :: (Mergeable a) => SInt16 -> a -> [a] -> [a]
 replaceAt i x' = zipWith (\j x -> ite (i .== literal j) x' x) [0..]
 
-sCase :: (Mergeable a) => SInt16 -> a -> [(Int16, a)] -> a
-sCase x def = go
+goCase :: (Mergeable a) => SInt16 -> a -> [(Int16, a)] -> a
+goCase x def = go
   where
     go [] = def
     go ((k,v):kvs) = ite (x .== literal k) v (go kvs)
@@ -165,7 +165,7 @@
 sWhen :: (Monad m, Mergeable (m ())) => SBool -> m () -> m ()
 sWhen b act = ite b act (return ())
 
-sFindIndex :: (a -> SBool) -> [a] -> SMaybe Int16
+sFindIndex :: (a -> SBool) -> [a] -> SBV.SMaybe Int16
 sFindIndex p = go 0
   where
     go _ [] = SBV.sNothing
diff --git a/SBVTestSuite/TestSuite/Queries/Uninterpreted.hs b/SBVTestSuite/TestSuite/Queries/Uninterpreted.hs
--- a/SBVTestSuite/TestSuite/Queries/Uninterpreted.hs
+++ b/SBVTestSuite/TestSuite/Queries/Uninterpreted.hs
@@ -9,12 +9,10 @@
 -- Testing uninterpreted value extraction
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -23,8 +21,8 @@
 import Data.SBV.Control
 import Utils.SBVTestFramework
 
-data L = A | B deriving (Enum, Bounded)
-mkSymbolicEnumeration ''L
+data L = A | B deriving Show
+mkSymbolic [''L]
 
 -- Test suite
 tests :: TestTree
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/Axioms.hs b/SBVTestSuite/TestSuite/Uninterpreted/Axioms.hs
--- a/SBVTestSuite/TestSuite/Uninterpreted/Axioms.hs
+++ b/SBVTestSuite/TestSuite/Uninterpreted/Axioms.hs
@@ -9,10 +9,7 @@
 -- Test suite for basic axioms and uninterpreted functions
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass     #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE TemplateHaskell    #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -26,9 +23,9 @@
 data B
 data Thing
 
-mkUninterpretedSort ''Bitstring
-mkUninterpretedSort ''B
-mkUninterpretedSort ''Thing
+mkSymbolic [''Bitstring]
+mkSymbolic [''B]
+mkSymbolic [''Thing]
 
 tests :: TestTree
 tests =
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/Function.hs b/SBVTestSuite/TestSuite/Uninterpreted/Function.hs
--- a/SBVTestSuite/TestSuite/Uninterpreted/Function.hs
+++ b/SBVTestSuite/TestSuite/Uninterpreted/Function.hs
@@ -9,11 +9,7 @@
 -- Testsuite for Documentation.SBV.Examples.Uninterpreted.Function
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
-{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
 
@@ -24,40 +20,40 @@
 import Utils.SBVTestFramework
 
 data A1
-mkUninterpretedSort ''A1
+mkSymbolic [''A1]
 
 data A2
-mkUninterpretedSort ''A2
+mkSymbolic [''A2]
 
 data A3
-mkUninterpretedSort ''A3
+mkSymbolic [''A3]
 
 data A4
-mkUninterpretedSort ''A4
+mkSymbolic [''A4]
 
 data A5
-mkUninterpretedSort ''A5
+mkSymbolic [''A5]
 
 data A6
-mkUninterpretedSort ''A6
+mkSymbolic [''A6]
 
 data A7
-mkUninterpretedSort ''A7
+mkSymbolic [''A7]
 
 data A8
-mkUninterpretedSort ''A8
+mkSymbolic [''A8]
 
 data A9
-mkUninterpretedSort ''A9
+mkSymbolic [''A9]
 
 data A10
-mkUninterpretedSort ''A10
+mkSymbolic [''A10]
 
 data A11
-mkUninterpretedSort ''A11
+mkSymbolic [''A11]
 
 data A12
-mkUninterpretedSort ''A12
+mkSymbolic [''A12]
 
 
 f1 :: SA1 -> SBool
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/Sort.hs b/SBVTestSuite/TestSuite/Uninterpreted/Sort.hs
--- a/SBVTestSuite/TestSuite/Uninterpreted/Sort.hs
+++ b/SBVTestSuite/TestSuite/Uninterpreted/Sort.hs
@@ -9,10 +9,7 @@
 -- Test suite for uninterpreted sorts
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving  #-}
 {-# LANGUAGE TemplateHaskell     #-}
 
 {-# OPTIONS_GHC -Wall -Werror #-}
@@ -22,13 +19,12 @@
 import Utils.SBVTestFramework
 
 data L
-mkUninterpretedSort ''L
+mkSymbolic [''L]
 
 tests :: TestTree
 tests =
   testGroup "Uninterpreted.Sort"
-    [ testCase "unint-sort"
-        (assert . (==4) . length . (extractModels :: AllSatResult -> [L]) =<< allSat p0)
+    [ goldenVsStringShow "unint-sort01" $ allSat p0
     ]
 
 len :: SL -> SInteger
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/Uninterpreted.hs b/SBVTestSuite/TestSuite/Uninterpreted/Uninterpreted.hs
--- a/SBVTestSuite/TestSuite/Uninterpreted/Uninterpreted.hs
+++ b/SBVTestSuite/TestSuite/Uninterpreted/Uninterpreted.hs
@@ -8,18 +8,16 @@
 --
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DeriveAnyClass     #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE TemplateHaskell    #-}
-{-# OPTIONS_GHC -Wall -Werror   #-}
+{-# LANGUAGE TemplateHaskell #-}
 
+{-# OPTIONS_GHC -Wall -Werror #-}
+
 module TestSuite.Uninterpreted.Uninterpreted(tests) where
 
 import Utils.SBVTestFramework
 
 data Q
-mkUninterpretedSort ''Q
+mkSymbolic [''Q]
 
 -- Test suite
 tests :: TestTree
diff --git a/SBVTestSuite/Utils/SBVTestFramework.hs b/SBVTestSuite/Utils/SBVTestFramework.hs
--- a/SBVTestSuite/Utils/SBVTestFramework.hs
+++ b/SBVTestSuite/Utils/SBVTestFramework.hs
@@ -26,6 +26,8 @@
         , goldenCapturedIO
         , qc1, qc2
         , shouldNotTypeCheck
+        , mkCompileTest
+        , mkCompileTestGlob
         -- module exports to simplify life
         , module Test.Tasty
         , module Test.Tasty.HUnit
@@ -44,7 +46,7 @@
 import Test.Tasty            (testGroup, TestTree, TestName)
 import Test.Tasty.HUnit      ((@?), Assertion, testCase, AssertionPredicable, assertFailure)
 
-import Test.Tasty.Golden     (goldenVsString, goldenVsFileDiff)
+import Test.Tasty.Golden     (goldenVsString, goldenVsFileDiff, goldenVsStringDiff)
 
 import qualified Test.Tasty.QuickCheck   as QC
 import qualified Test.QuickCheck.Monadic as QC
@@ -54,10 +56,17 @@
 import Data.SBV
 import Data.SBV.Control
 
-import System.FilePath ((</>), (<.>))
+import System.FilePath      ((</>), (<.>), takeDirectory, takeBaseName)
+import System.FilePath.Glob (glob)
+
 import Data.List       (isInfixOf, isSuffixOf)
 
+import System.Exit
+import System.Process
+import System.IO hiding (stderr)
 
+import System.IO.Temp (withSystemTempDirectory)
+
 import Data.SBV.Internals (runSymbolic, Result, SBVRunMode(..), IStage(..), SBV(..), SVal(..), showModel, SMTModel(..), QueryContext(..), Outputtable)
 
 -- | Generic assertion. This is less safe than usual, but will do.
@@ -231,5 +240,74 @@
               -> pure ()
       | True
       -> throwIO e
+
+-- | Like readProcessWithExitCode, but in a given directory
+readProcessInDir :: FilePath -> String -> [String] -> String -> IO (ExitCode, String, String)
+readProcessInDir dir cmd args input = do
+    let cp = (proc cmd args)
+                { cwd     = Just dir
+                , std_in  = CreatePipe
+                , std_out = CreatePipe
+                , std_err = CreatePipe
+                }
+    withCreateProcess cp $ \mIn mOut mErr ph -> do
+        -- feed input if needed
+        case mIn of
+            Just hin -> hPutStr hin input >> hClose hin
+            Nothing  -> return ()
+
+        out <- case mOut of
+            Just hout -> do
+                s <- hGetContents hout
+                _ <- evaluate (length s)  -- force full read
+                return s
+            Nothing -> return ""
+
+        err <- case mErr of
+            Just herr -> do
+                s <- hGetContents herr
+                _ <- evaluate (length s)  -- force full read
+                return s
+            Nothing -> return ""
+
+        exitCode <- waitForProcess ph
+        return (exitCode, out, err)
+
+-- | Make a compilation test from all the files matching glob
+mkCompileTestGlob :: String -> IO [TestTree]
+mkCompileTestGlob g = do fs <- glob g
+                         pure $ map mkCompileTest fs
+
+-- | Make a compilation test
+mkCompileTest :: FilePath -> TestTree
+mkCompileTest file = goldenVsStringDiff nm diffCmd (testDir </> nm <.> "stderr") (compile (nm <.> "hs"))
+  where testDir = takeDirectory file
+        nm      = takeBaseName  file
+
+        diffCmd ref new = ["diff", "-u", ref, new]
+
+        packages = [ "QuickCheck"
+                   , "array"
+                   , "containers"
+                   , "deepseq"
+                   , "libBF"
+                   , "mtl"
+                   , "random"
+                   , "syb"
+                   , "template-haskell"
+                   , "text"
+                   , "time"
+                   , "transformers"
+                   , "uniplate"
+                   ]
+
+        args td  =  "-XHaskell2010 -fforce-recomp -tmpdir " ++ td ++ " -outputdir " ++ td
+                 ++ concat [" -package " ++ pkg | pkg <- packages]
+
+        compile path = withSystemTempDirectory "SBVTempDir" $ \tmpDir -> do
+           (exitCode, _stdout, stderr) <- readProcessInDir testDir "ghc" (words (args tmpDir) ++ [path]) ""
+           case exitCode of
+             ExitSuccess   -> return $ LBC.pack "There was no failure during compilation."
+             ExitFailure _ -> return $ LBC.pack stderr
 
 {- HLint ignore module "Reduce duplication" -}
diff --git a/sbv.cabal b/sbv.cabal
--- a/sbv.cabal
+++ b/sbv.cabal
@@ -1,7 +1,7 @@
 Cabal-Version: 2.2
 
 Name        : sbv
-Version     : 12.2
+Version     : 13.0
 Category    : Formal Methods, Theorem Provers, Bit vectors, Symbolic Computation, Math, SMT
 Synopsis    : SMT Based Verification: Symbolic Haskell theorem prover using SMT solving.
 Description : Express properties about Haskell programs and automatically prove them using SMT
@@ -17,6 +17,8 @@
 Maintainer         : Levent Erkok (erkokl@gmail.com)
 Build-Type         : Simple
 Data-Files         : SBVTestSuite/GoldFiles/*.gold
+                     SBVTestSuite/TestSuite/CompileTests/SCase/*.hs
+                     SBVTestSuite/TestSuite/CompileTests/SCase/*.stderr
 Extra-Doc-Files    : INSTALL, README.md, COPYRIGHT, CHANGES.md
 
 Tested-With        : GHC==9.10.1
@@ -64,7 +66,6 @@
                      OverloadedStrings
                      PackageImports
                      ParallelListComp
-                     PatternGuards
                      QuantifiedConstraints
                      QuasiQuotes
                      Rank2Types
@@ -114,6 +115,7 @@
                   , random
                   , syb
                   , template-haskell
+                  , th-expand-syns
                   , text
                   , time
                   , transformers
@@ -146,6 +148,9 @@
                   , Data.SBV.Tools.WeakestPreconditions
                   , Data.SBV.Trans
                   , Data.SBV.Trans.Control
+                  , Documentation.SBV.Examples.ADT.Expr
+                  , Documentation.SBV.Examples.ADT.Param
+                  , Documentation.SBV.Examples.ADT.Types
                   , Documentation.SBV.Examples.BitPrecise.BitTricks
                   , Documentation.SBV.Examples.BitPrecise.BrokenSearch
                   , Documentation.SBV.Examples.BitPrecise.Legato
@@ -246,6 +251,7 @@
                   , Documentation.SBV.Examples.TP.Majority
                   , Documentation.SBV.Examples.TP.MergeSort
                   , Documentation.SBV.Examples.TP.Numeric
+                  , Documentation.SBV.Examples.TP.Peano
                   , Documentation.SBV.Examples.TP.PowerMod
                   , Documentation.SBV.Examples.TP.QuickSort
                   , Documentation.SBV.Examples.TP.RevAcc
@@ -256,6 +262,7 @@
                   , Documentation.SBV.Examples.TP.StrongInduction
                   , Documentation.SBV.Examples.TP.SumReverse
                   , Documentation.SBV.Examples.TP.Tao
+                  , Documentation.SBV.Examples.TP.VM
                   , Documentation.SBV.Examples.Transformers.SymbolicEval
                   , Documentation.SBV.Examples.Uninterpreted.AUF
                   , Documentation.SBV.Examples.Uninterpreted.Deduce
@@ -283,6 +290,7 @@
                   , Data.SBV.Compilers.C
                   , Data.SBV.Compilers.CodeGen
                   , Data.SBV.Lambda
+                  , Data.SBV.SCase
                   , Data.SBV.SEnum
                   , Data.SBV.SMT.SMT
                   , Data.SBV.SMT.SMTLib
@@ -316,22 +324,29 @@
   default-language : Haskell2010
   type             : exitcode-stdio-1.0
   ghc-options      : -with-rtsopts=-K64m
-  build-depends   : QuickCheck
+  build-depends   : Glob
+                  , QuickCheck
                   , bytestring
                   , containers
                   , deepseq
                   , directory
                   , filepath
                   , mtl
+                  , process
                   , random
                   , sbv
                   , tasty
                   , tasty-golden
                   , tasty-hunit
                   , tasty-quickcheck
+                  , temporary
   hs-source-dirs  : SBVTestSuite
   main-is         : SBVTest.hs
   other-modules   : Utils.SBVTestFramework
+                  , TestSuite.ADT.ADT
+                  , TestSuite.ADT.Expr
+                  , TestSuite.ADT.MutRec
+                  , TestSuite.ADT.PExpr
                   , TestSuite.Arrays.InitVals
                   , TestSuite.Arrays.Memory
                   , TestSuite.Arrays.Query
@@ -368,6 +383,11 @@
                   , TestSuite.Basics.TOut
                   , TestSuite.Basics.Tuple
                   , TestSuite.Basics.UISat
+                  , TestSuite.CRC.CCITT
+                  , TestSuite.CRC.CCITT_Unidir
+                  , TestSuite.CRC.GenPoly
+                  , TestSuite.CRC.Parity
+                  , TestSuite.CRC.USB5
                   , TestSuite.Char.Char
                   , TestSuite.BitPrecise.BitTricks
                   , TestSuite.BitPrecise.Legato
@@ -381,11 +401,7 @@
                   , TestSuite.CodeGeneration.GCD
                   , TestSuite.CodeGeneration.PopulationCount
                   , TestSuite.CodeGeneration.Uninterpreted
-                  , TestSuite.CRC.CCITT
-                  , TestSuite.CRC.CCITT_Unidir
-                  , TestSuite.CRC.GenPoly
-                  , TestSuite.CRC.Parity
-                  , TestSuite.CRC.USB5
+                  , TestSuite.CompileTests.SCase
                   , TestSuite.Crypto.AES
                   , TestSuite.Crypto.RC4
                   , TestSuite.Crypto.SHA
