packages feed

liquid-fixpoint 0.9.6.3.2 → 0.9.6.3.3

raw patch · 22 files changed

+277/−113 lines, 22 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Types.Constraints.Equation
+ Language.Fixpoint.Horn.Types: [qDefs] :: Query a -> ![Equation]
+ Language.Fixpoint.Smt.Interface: [ctxDefines] :: Context -> ![Equation]
+ Language.Fixpoint.Smt.Theories: instance Language.Fixpoint.Types.Theories.TheorySymbols Language.Fixpoint.Types.Config.SMTSolver
+ Language.Fixpoint.Smt.Theories: instance Language.Fixpoint.Types.Theories.TheorySymbols [Language.Fixpoint.Types.Constraints.Equation]
+ Language.Fixpoint.Smt.Theories: instance Language.Fixpoint.Types.Theories.TheorySymbols [Language.Fixpoint.Types.Sorts.DataDecl]
+ Language.Fixpoint.Smt.Types: [ctxDefines] :: Context -> ![Equation]
+ Language.Fixpoint.Types.Constraints: [defns] :: GInfo c a -> ![Equation]
+ Language.Fixpoint.Types.Sorts: coerceDataDecl :: ElabFlags -> DataDecl -> DataDecl
+ Language.Fixpoint.Types.Theories: Defined :: Sem
+ Language.Fixpoint.Types.Theories: class TheorySymbols a
+ Language.Fixpoint.Types.Theories: theorySymbols :: TheorySymbols a => a -> SEnv TheorySymbol
- Language.Fixpoint.Horn.Types: Query :: ![Qualifier] -> ![Var a] -> !Cstr a -> HashMap Symbol Sort -> HashMap Symbol Sort -> ![Equation] -> ![Rewrite] -> ![DataDecl] -> ![String] -> ![Symbol] -> Query a
+ Language.Fixpoint.Horn.Types: Query :: ![Qualifier] -> ![Var a] -> !Cstr a -> HashMap Symbol Sort -> HashMap Symbol Sort -> ![Equation] -> ![Equation] -> ![Rewrite] -> ![DataDecl] -> ![String] -> ![Symbol] -> Query a
- Language.Fixpoint.Smt.Interface: Ctx :: Solver -> ElabFlags -> IO () -> !Maybe Handle -> !Bool -> !SymEnv -> Context
+ Language.Fixpoint.Smt.Interface: Ctx :: Solver -> ElabFlags -> IO () -> !Maybe Handle -> !Bool -> !SymEnv -> ![Equation] -> Context
- Language.Fixpoint.Smt.Interface: makeContextWithSEnv :: Config -> FilePath -> SymEnv -> IO Context
+ Language.Fixpoint.Smt.Interface: makeContextWithSEnv :: Config -> FilePath -> SymEnv -> [Equation] -> IO Context
- Language.Fixpoint.Smt.Theories: theorySymbols :: SMTSolver -> [DataDecl] -> SEnv TheorySymbol
+ Language.Fixpoint.Smt.Theories: theorySymbols :: TheorySymbols a => a -> SEnv TheorySymbol
- Language.Fixpoint.Smt.Types: Ctx :: Solver -> ElabFlags -> IO () -> !Maybe Handle -> !Bool -> !SymEnv -> Context
+ Language.Fixpoint.Smt.Types: Ctx :: Solver -> ElabFlags -> IO () -> !Maybe Handle -> !Bool -> !SymEnv -> ![Equation] -> Context
- Language.Fixpoint.Solver.Sanitize: sanitize :: Config -> SInfo a -> SanitizeM (SInfo a)
+ Language.Fixpoint.Solver.Sanitize: sanitize :: Show a => Config -> SInfo a -> SanitizeM (SInfo a)
- Language.Fixpoint.SortCheck: elabExpr :: ElabParam -> Expr -> Expr
+ Language.Fixpoint.SortCheck: elabExpr :: ElabParam -> Maybe Sort -> Expr -> Expr
- Language.Fixpoint.Types.Constraints: FI :: !HashMap SubcId (c a) -> !HashMap KVar (WfC a) -> !BindEnv a -> ![BindId] -> !SEnv Sort -> !SEnv Sort -> !Kuts -> ![Qualifier] -> !HashMap BindId a -> ![DataDecl] -> !HOInfo -> ![Triggered Expr] -> AxiomEnv -> LocalRewritesEnv -> GInfo c a
+ Language.Fixpoint.Types.Constraints: FI :: !HashMap SubcId (c a) -> !HashMap KVar (WfC a) -> !BindEnv a -> ![BindId] -> !SEnv Sort -> !SEnv Sort -> !Kuts -> ![Qualifier] -> !HashMap BindId a -> ![DataDecl] -> !HOInfo -> ![Triggered Expr] -> AxiomEnv -> LocalRewritesEnv -> ![Equation] -> GInfo c a

Files

CHANGES.md view
@@ -2,6 +2,14 @@  ## NEXT +## 0.9.6.3.3 (2025-03-22)++- Add support for GHC HEAD (9.13) [#745](https://github.com/ucsd-progsys/liquid-fixpoint/pull/745).+- Expose SMTLIB define-fun to users of liquid-fixpoint [#744](https://github.com/ucsd-progsys/liquid-fixpoint/pull/744).+- Check that expressions in refinements are Bool-sorted [#743](https://github.com/ucsd-progsys/liquid-fixpoint/pull/743).+- Fix crashes when a datatype is declared with a `Map_t` field [#738](https://github.com/ucsd-progsys/liquid-fixpoint/issues/738).+- Simplify expressions in fqout files [#741](https://github.com/ucsd-progsys/liquid-fixpoint/pull/741).+ ## 0.9.6.3.2 (2025-03-06)  - Expose relatedSymbols from EnvironmentReduction. Needed for improving error
liquid-fixpoint.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4 name:               liquid-fixpoint-version:            0.9.6.3.2+version:            0.9.6.3.3 synopsis:           Predicate Abstraction-based Horn-Clause/Implication Constraint Solver description:   This package implements an SMTLIB based Horn-Clause\/Logical Implication constraint@@ -25,7 +25,7 @@ license:            BSD-3-Clause license-file:       LICENSE build-type:         Simple-tested-with:        GHC == 9.10.1, GHC == 9.8.2, GHC == 9.6.5+tested-with:        GHC == 9.12.2, GHC == 9.10.1, GHC == 9.8.2 extra-source-files: tests/neg/*.fq                     tests/pos/*.fq                     unix/Language/Fixpoint/Utils/*.hs
src/Language/Fixpoint/Horn/Info.hs view
@@ -30,6 +30,7 @@   , F.ae        = axEnv cfg q cs   , F.ddecls    = H.qData q   , F.hoInfo    = F.cfgHoInfo cfg+  , F.defns     = H.qDefs q   }   where     be0         = F.emptyBindEnv
src/Language/Fixpoint/Horn/Parse.hs view
@@ -36,6 +36,7 @@   , H.qData  =            [ dd    | HDat dd <- things ]   , H.qOpts  =            [ o     | HOpt o  <- things ]   , H.qNums  =            [ n     | HNum n  <- things ]+  , H.qDefs  =            []   }  -- | A @HThing@ describes the kinds of things we may see, in no particular order
src/Language/Fixpoint/Horn/SMTParse.hs view
@@ -126,16 +126,17 @@  mkQuery :: [HThing a] -> H.Query a mkQuery things = H.Query-  { H.qQuals =            [ q     | HQual q  <- things ]-  , H.qVars  =            [ k     | HVar  k  <- things ]-  , H.qCstr  = H.CAnd     [ c     | HCstr c  <- things ]-  , H.qCon   = M.fromList [ (x,t) | HCon x t <- things ]-  , H.qDis   = M.fromList [ (x,t) | HDis x t <- things ]-  , H.qEqns  =            [ e     | HDef e   <- things ]-  , H.qMats  =            [ m     | HMat m   <- things ]-  , H.qData  =            [ dd    | HDat dd  <- things ]-  , H.qOpts  =            [ o     | HOpt o   <- things ]-  , H.qNums  =            [ s     | HNum s   <- things ]+  { H.qQuals =              [ q     | HQual q  <- things ]+  , H.qVars  =              [ k     | HVar  k  <- things ]+  , H.qCstr  = H.CAnd       [ c     | HCstr c  <- things ]+  , H.qCon   = M.fromList   [ (x,t) | HCon x t <- things ]+  , H.qDis   = M.fromList   [ (x,t) | HDis x t <- things ]+  , H.qEqns  =              [ e     | HDef e   <- things ]+  , H.qDefs  =              [ e     | HDfn e   <- things ]+  , H.qMats  =              [ m     | HMat m   <- things ]+  , H.qData  =              [ dd    | HDat dd  <- things ]+  , H.qOpts  =              [ o     | HOpt o   <- things ]+  , H.qNums  =              [ s     | HNum s   <- things ]   }  -- | A @HThing@ describes the kinds of things we may see, in no particular order@@ -150,6 +151,7 @@   | HCon  F.Symbol F.Sort   | HDis  F.Symbol F.Sort   | HDef  F.Equation+  | HDfn  F.Equation   | HMat  F.Rewrite   | HDat !F.DataDecl   | HOpt !String@@ -166,6 +168,7 @@         <|> HCon  <$> (reserved "constant"   *> symbolP) <*> sortP         <|> HDis  <$> (reserved "distinct"   *> symbolP) <*> sortP         <|> HDef  <$> (reserved "define"     *> defineP)+        <|> HDfn  <$> (reserved "define_fun" *> defineP)         <|> HMat  <$> (reserved "match"      *> matchP)         <|> HDat  <$> (reserved "datatype"   *> dataDeclP)         <|> HNum  <$> (reserved "numeric"    *> numericDeclP)
src/Language/Fixpoint/Horn/Solve.hs view
@@ -34,9 +34,9 @@   q <- parseQuery baseCfg    -- If you want to set --eliminate=none, you better make it a pragma-  cfgElim <- if F.eliminate baseCfg == F.None-           then pure (baseCfg { F.eliminate =  F.Some })-           else pure baseCfg+  let cfgElim = if F.eliminate baseCfg == F.None+                  then baseCfg { F.eliminate =  F.Some }+                  else baseCfg    cfgPragmas <- F.withPragmas cfgElim (H.qOpts q) 
src/Language/Fixpoint/Horn/Transformations.hs view
@@ -647,7 +647,8 @@       Nothing -> []       Just vertex -> nub $ filter (/= F.EVar x) $ mconcat [es | ((_, es), _, _) <- vf <$> DG.reachable eGraph vertex] -    argsAndPrims = args `S.union` S.fromList (map fst $ F.toListSEnv $ F.theorySymbols (F.solver cfg) []) `S.union`measures+    argsAndPrims = args `S.union` S.fromList (fst <$> F.toListSEnv thySyms) `S.union`measures+    thySyms = F.theorySymbols (F.solver cfg)      isWellFormed :: F.Expr -> Bool     isWellFormed e = S.fromList (F.syms e) `S.isSubsetOf` argsAndPrims
src/Language/Fixpoint/Horn/Types.hs view
@@ -196,9 +196,10 @@   { qQuals :: ![F.Qualifier]             -- ^ qualifiers over which to solve cstrs   , qVars  :: ![Var a]                   -- ^ kvars, with parameter-sorts   , qCstr  :: !(Cstr a)                  -- ^ list of constraints-  , qCon   :: M.HashMap F.Symbol F.Sort  -- ^ list of constants (uninterpreted functions)+  , qCon   :: M.HashMap F.Symbol F.Sort  -- ^ list of constants (un/interpreted functions)   , qDis   :: M.HashMap F.Symbol F.Sort  -- ^ list of *distinct* constants (uninterpreted functions)   , qEqns  :: ![F.Equation]              -- ^ list of equations+  , qDefs  :: ![F.Equation]              -- ^ list of equations to be sent to SMT as define-fun   , qMats  :: ![F.Rewrite]               -- ^ list of match-es   , qData  :: ![F.DataDecl]              -- ^ list of data-declarations   , qOpts  :: ![String]                  -- ^ list of fixpoint options@@ -340,7 +341,8 @@     , P.vcat   (toHornSMT <$> qQuals q)     , P.vcat   (toHornSMT <$> qVars q)     , P.vcat   [toHornCon x t | (x, t) <- M.toList (qCon q)]-    , P.vcat   (toHornSMT <$> qEqns q)+    , P.vcat   (eqnToHornSMT "define"     <$> qEqns q)+    , P.vcat   (eqnToHornSMT "define_fun" <$> qDefs q)     , P.vcat   (toHornSMT <$> qData q)     , P.vcat   (toHornSMT <$> qMats q)     , P.parens (P.vcat ["constraint", P.nest 1 (toHornSMT (qCstr q))])@@ -371,8 +373,9 @@ toHornAnd :: (a -> P.Doc) -> [a] -> P.Doc toHornAnd f xs = P.parens (P.vcat ("and" : (P.nest 1 . f <$> xs))) -instance ToHornSMT F.Equation where-  toHornSMT (F.Equ f xs e s _) = P.parens ("define" P.<+> F.pprint f P.<+> toHornSMT xs P.<+> toHornSMT s P.<+> toHornSMT e)+eqnToHornSMT :: P.Doc -> F.Equation -> P.Doc+eqnToHornSMT keyword (F.Equ f xs e s _) = P.parens (keyword P.<+> F.pprint f P.<+> toHornSMT xs P.<+> toHornSMT s P.<+> toHornSMT e)+  instance ToHornSMT F.DataDecl where   toHornSMT (F.DDecl tc n ctors) =
src/Language/Fixpoint/Parse.hs view
@@ -1449,7 +1449,7 @@     <|> (reserved "False" >> return False)  defsFInfo :: [Def a] -> FInfo a-defsFInfo defs = {- SCC "defsFI" -} Types.FI cm ws bs ebs lts dts kts qs binfo adts mempty mempty ae lrws+defsFInfo defs = {- SCC "defsFI" -} Types.FI cm ws bs ebs lts dts kts qs binfo adts mempty mempty ae lrws mempty   where     cm         = Misc.safeFromList                    "defs-cm"        [(cid c, c)         | Cst c       <- defs]
src/Language/Fixpoint/Smt/Interface.hs view
@@ -7,6 +7,8 @@ {-# LANGUAGE ScopedTypeVariables       #-} {-# LANGUAGE PatternGuards             #-} {-# LANGUAGE DoAndIfThenElse           #-}+{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}+{-# HLINT ignore "Use isNothing" #-}  -- | This module contains an SMTLIB2 interface for --   1. checking the validity, and,@@ -252,20 +254,19 @@     where        smtFile = extFileName Smt2 f -makeContextWithSEnv :: Config -> FilePath -> SymEnv -> IO Context-makeContextWithSEnv cfg f env = do+makeContextWithSEnv :: Config -> FilePath -> SymEnv -> [Equation] -> IO Context+makeContextWithSEnv cfg f env defns = do   ctx     <- makeContext cfg f-  let ctx' = ctx {ctxSymEnv = env}+  let ctx' = ctx {ctxSymEnv = env, ctxDefines = defns}   declare ctx'   return ctx'-  -- where msg = "makeContextWithSEnv" ++ show env  makeContextNoLog :: Config -> IO Context-makeContextNoLog cfg-  = do me  <- makeContext' cfg Nothing-       pre <- smtPreamble cfg (solver cfg) me-       mapM_ (SMTLIB.Backends.command_ (ctxSolver me)) pre-       return me+makeContextNoLog cfg = do+  me  <- makeContext' cfg Nothing+  pre <- smtPreamble cfg (solver cfg) me+  mapM_ (SMTLIB.Backends.command_ (ctxSolver me)) pre+  return me  makeProcess   :: Maybe Handle@@ -302,11 +303,11 @@          Cvc4    -> makeProcess ctxLog $                       Process.defaultConfig                              { Process.exe = "cvc4"-                             , Process.args = ["--incremental", "-L", "smtlib2"] }+                             , Process.args = ["-L", "smtlib2"] }          Cvc5    -> makeProcess ctxLog $                       Process.defaultConfig                              { Process.exe = "cvc5"-                             , Process.args = ["--incremental", "-L", "smtlib2"] }+                             , Process.args = ["-L", "smtlib2"] }        solver <- SMTLIB.Backends.initSolver SMTLIB.Backends.Queuing backend        loud <- isLoud        return Ctx { ctxSolver    = solver@@ -315,6 +316,7 @@                   , ctxLog       = ctxLog                   , ctxVerbose   = loud                   , ctxSymEnv    = mempty+                  , ctxDefines   = mempty                   }  -- | Close file handles and release the solver backend's resources.@@ -331,7 +333,7 @@   | s == Z3 || s == Z3mem     = do v <- getZ3Version me          checkValidStringFlag Z3 v cfg-         return $ z3_options ++ makeMbqi cfg ++ makeTimeout cfg ++ Thy.preamble cfg Z3+         return $ makeMbqi cfg ++ makeTimeout cfg ++ Thy.preamble cfg Z3   | otherwise     = checkValidStringFlag s [] cfg >> return (Thy.preamble cfg s) @@ -404,10 +406,13 @@ smtAssert :: Context -> Expr -> IO () smtAssert me p = interact' me (Assert Nothing p) +smtDefineEqn :: Context -> Equation -> IO ()+smtDefineEqn me Equ {..} = smtDefineFunc me eqName eqArgs eqSort eqBody+ smtDefineFunc :: Context -> Symbol -> [(Symbol, F.Sort)] -> F.Sort -> Expr -> IO () smtDefineFunc me name symList rsort e =   let env = seData (ctxSymEnv me)-   in interact' me $+  in interact' me $         DefineFunc           name           (map (sortSmtSort False env <$>) symList)@@ -456,13 +461,7 @@   | gradual cfg = [""]   | otherwise   = ["\n(set-option :smt.mbqi false)"] -z3_options :: [Builder]-z3_options-  = [ "(set-option :auto-config false)"-    , "(set-option :model true)" ] -- -------------------------------------------------------------------------------- declare :: Context -> IO () --------------------------------------------------------------------------------@@ -471,6 +470,7 @@   forM_ thyXTs $ uncurry $ smtDecl     me   forM_ qryXTs $ uncurry $ smtDecl     me   forM_ ats    $ uncurry $ smtFuncDecl me+  forM_ defs   $           smtDefineEqn me   forM_ ess    $           smtDistinct me   forM_ axs    $           smtAssert   me   where@@ -479,12 +479,13 @@     lts        = F.toListSEnv . F.seLits $ env     ess        = distinctLiterals  lts     axs        = Thy.axiomLiterals lts-    thyXTs     =                    filter (isKind 1) xts-    qryXTs     = fmap tx <$> filter (isKind 2) xts-    isKind n   = (n ==)  . symKind env . fst-    xts        = {- tracepp "symbolSorts" $ -} symbolSorts (F.seSort env)+    thyXTs     =             [ (x, t) | (x, t) <- xts, symKind env x == Just F.Uninterp ]+    qryXTs     = fmap tx <$> [ (x, t) | (x, t) <- xts, symKind env x == Nothing ]+    -- isKind n   = (n ==)  . symKind env . fst+    xts        = symbolSorts (F.seSort env)     tx         = elaborate (ElabParam (ctxElabF me) "declare" env)     ats        = funcSortVars env+    defs       = ctxDefines me  symbolSorts :: F.SEnv F.Sort -> [(F.Symbol, F.Sort)] symbolSorts env = [(x, tx t) | (x, t) <- F.toListSEnv env ]@@ -507,24 +508,8 @@     lamSort (s,t) = ([s, t], F.SInt)     argSort (s,_) = ([]    , s) --- | 'symKind' returns {0, 1, 2} where:---   0 = Theory-Definition,---   1 = Theory-Declaration,---   2 = Query-Binder--symKind :: F.SymEnv -> F.Symbol -> Int-symKind env x = case F.tsInterp <$> F.symEnvTheory x env of-                  Just F.Theory   -> 0-                  Just F.Ctor     -> 0-                  Just F.Test     -> 0-                  Just F.Field    -> 0-                  Just F.Uninterp -> 1-                  Nothing         -> 2-              -- Just t  -> if tsInterp t then 0 else 1----- assumes :: [F.Expr] -> SolveM ()--- assumes es = withContext $ \me -> forM_  es $ smtAssert me+symKind :: F.SymEnv -> F.Symbol -> Maybe Sem+symKind env x = F.tsInterp <$> F.symEnvTheory x env  -- | `distinctLiterals` is used solely to determine the set of literals --   (of each sort) that are *disequal* to each other, e.g. EQ, LT, GT,
src/Language/Fixpoint/Smt/Theories.hs view
@@ -8,6 +8,7 @@  {-# OPTIONS_GHC -Wno-orphans           #-} {-# LANGUAGE TupleSections #-}+{-# LANGUAGE InstanceSigs #-}  module Language.Fixpoint.Smt.Theories      (@@ -237,7 +238,7 @@   = bFun f [("x", "Int"), ("y", "Int")] "Int" (key2 (fromText op) "x" "y")  onlyLinearArith :: Config -> Bool-onlyLinearArith cfg = linear cfg || solver cfg `notElem` [Z3, Cvc5]+onlyLinearArith cfg = linear cfg || solver cfg `notElem` [Z3, Z3mem, Cvc5]  preamble :: Config -> SMTSolver -> [Builder] preamble cfg s = snd <$> filter (matchesCondition s . fst) (solverPreamble cfg)@@ -249,8 +250,12 @@  solverPreamble :: Config -> [Preamble] solverPreamble cfg-  =  [(SOnly [Cvc4], "(set-logic ALL_SUPPORTED)")]-  ++ [(SOnly [Cvc5], "(set-logic ALL)")]+  =  [ (SOnly [Z3, Z3mem],  "(set-option :auto-config false)")+     , (SOnly [Z3, Z3mem],  "(set-option :model true)")+     , (SOnly [Cvc4],       "(set-logic ALL_SUPPORTED)")+     , (SOnly [Cvc5],       "(set-logic ALL)")+     , (SOnly [Cvc4, Cvc5], "(set-option :incremental true)")+     ]   ++ boolPreamble cfg   ++ arithPreamble cfg   ++ stringPreamble cfg@@ -375,13 +380,22 @@ --   symbols, and `interpSEnv` is for interpreted symbols. -------------------------------------------------------------------------------- --- | `theorySymbols` contains the list of ALL SMT symbols with interpretations,---   i.e. which are given via `define-fun` (as opposed to `declare-fun`)-theorySymbols :: SMTSolver -> [DataDecl] -> SEnv TheorySymbol -- M.HashMap Symbol TheorySymbol-theorySymbols cfg ds = fromListSEnv $  -- SHIFTLAM uninterpSymbols-                                  interpSymbols cfg-                               ++ concatMap dataDeclSymbols ds+instance TheorySymbols SMTSolver where+  theorySymbols :: SMTSolver -> SEnv TheorySymbol+  theorySymbols = fromListSEnv . interpSymbols +instance TheorySymbols [DataDecl] where+  theorySymbols :: [DataDecl] -> SEnv TheorySymbol+  theorySymbols = fromListSEnv . concatMap dataDeclSymbols++instance TheorySymbols [Equation] where+  theorySymbols = fromListSEnv . fmap equationSymbol++equationSymbol :: Equation -> (Symbol, TheorySymbol)+equationSymbol eq = (sym, Thy sym (symbolRaw sym) sort Defined)+  where+    sym  = eqName eq+    sort = mkFFunc 0 ((snd <$> eqArgs eq) <> [eqSort eq])  -------------------------------------------------------------------------------- interpSymbols :: SMTSolver -> [(Symbol, TheorySymbol)]
src/Language/Fixpoint/Smt/Types.hs view
@@ -102,6 +102,7 @@   , ctxLog     :: !(Maybe Handle)   , ctxVerbose :: !Bool   , ctxSymEnv  :: !SymEnv+  , ctxDefines :: ![Equation]   }  --------------------------------------------------------------------------------
src/Language/Fixpoint/Solver.hs view
@@ -34,7 +34,7 @@ import           System.Exit                        (ExitCode (..)) import           System.Console.CmdArgs.Verbosity   (whenNormal, whenLoud) import           Text.PrettyPrint.HughesPJ          (render)-import           Control.Monad                      (when)+import           Control.Monad                      (mplus, when) import           Control.Exception                  (catch) import           Language.Fixpoint.Solver.EnvironmentReduction   (reduceEnvironments, simplifyBindings)@@ -59,7 +59,7 @@ import           Language.Fixpoint.Solver.Instantiate (instantiate) import           Control.DeepSeq import qualified Data.ByteString as B-import Data.Maybe (catMaybes)+import Data.Maybe (catMaybes, mapMaybe)  --------------------------------------------------------------------------- -- | Solve an .fq file ----------------------------------------------------@@ -271,7 +271,8 @@  solveNative' !cfg !fi0 = do   si6 <- simplifyFInfo cfg fi0-  res <- {- SCC "Sol.solve" -} Sol.solve cfg $!! si6+  res0 <- {- SCC "Sol.solve" -} Sol.solve cfg $!! si6+  let res = simplifyResult res0   -- rnf soln `seq` donePhase Loud "Solve2"   --let stat = resStatus res   -- saveSolution cfg res@@ -305,8 +306,10 @@     , "Solution:"     , showpp (resSolution  res)     ] ++-    ( if gradual cfg then ["", "", showpp (gresSolution res)]-      else []+    ( if gradual cfg then+        ["", "", showpp $ gresSolution res]+      else+        []     ) ++     [ ""     , ""@@ -314,3 +317,106 @@     , ""     , showpp (HashMap.map unElab $ resNonCutsSolution res)     ]++simplifyResult :: Result a -> Result a+simplifyResult res =+    res+      { resSolution = HashMap.map simplifyKVar (resSolution res)+      , resNonCutsSolution = HashMap.map simplifyKVar (resNonCutsSolution res)+      }++-- | Simplifies existential expressions with unused or inconsequential bindings.+--+-- For instance, in the following example, "x" is not used at all.+--+-- > simplifyKVar "exists x y. y == z && y == C" == "exists y. y == z && y == C"+--+-- And in the following example, @x@ is used but in a way that doesn't+-- contribute any useful knowledge.+--+-- > simplifyKVar "exists x y. x == C && y == z && y == C"+-- >   ==+-- > "exists y. y == z && y == C"+--+-- We require that relevant variables occur more than once, or that+-- they occur in some other place than as an argument to @==@.+--+simplifyKVar :: Expr -> Expr+simplifyKVar (POr es) = POr $ map simplifyKVar es+simplifyKVar (PExist bs e@(PAnd es)) =+    let fvs = L.group $ L.sort $ collectFreeVarOccurrences e+        esv = map (isUniqueEq fvs) es+        removed = mapMaybe fst esv+        needed = map head fvs L.\\ removed+        bs' = filter ((`elem` needed) . fst) bs+     in+        PExist bs' $ PAnd $ [ei | (Nothing, ei) <- esv]+  where+    -- | Determine if the expression is an equality that sets the value of+    -- a variable that doesn't occur elsewhere.+    --+    -- In @isUniqueEq fvs e@, @fvs@ contains the occurrences of the free+    -- variables, so we can infer if there is more than one occurrence+    -- of a given free variable, and @e@ is the equality to analyze.+    --+    -- Yields @(Just v, e)@ if @v@ doesn't occur elsewhere, and @e@ has+    -- the form @v == e'@.+    isUniqueEq :: [[Symbol]] -> Expr -> (Maybe Symbol, Expr)+    isUniqueEq fvs er = case unElab er of+      PAtom brel e0 e1+        | isEqRel brel ->+          let m = isVarToDrop fvs e0 `mplus` isVarToDrop fvs e1+           in (m, er)+      _ ->+        (Nothing, er)++    -- | Tells if the binary relation is an equality.+    isEqRel Eq = True+    isEqRel Ueq = True+    isEqRel _ = False++    -- | @isVarToDrop fvs s@ yields @Just s@ if the variable @s@ doesn't occur+    -- elsewhere according to @fvs@.+    --+    -- > isVarToDrop fvs (cast_as_int s) == isVarToDrop fvs s+    --+    isVarToDrop fvs (EApp (EVar "cast_as_int") ei) = isVarToDrop fvs ei+    isVarToDrop fvs (EVar s)+      | elem [s] fvs = Just s+    isVarToDrop _fvs _ = Nothing++simplifyKVar e = e++-- | Produces the free variables of an expressions as many times as they occur.+--+-- There are no guarantees on the order in which the variables are produced. For+-- instance,+--+-- > collectFreeVarOccurrences "z (y x) (y x)" == ["z", "y", "x", "y", "x"]+--+collectFreeVarOccurrences :: Expr -> [Symbol]+collectFreeVarOccurrences = go []+  where+    go acc e0 = case e0 of+      ESym _ -> acc+      ECon _ -> acc+      EVar v -> v : acc+      PKVar _ (Su m) -> foldr (flip go) acc $ HashMap.elems m+      PGrad _ (Su m) _ e -> foldr (flip go) acc $ e : HashMap.elems m+      ENeg e -> go acc e+      PNot p -> go acc p+      ECst e _t -> go acc e+      PAll _xts p -> go acc p+      ELam (b, _) e -> go acc e L.\\ [b]+      ECoerc _a _t e -> go acc e+      PExist _xts p -> go acc p+      ETApp e _s -> go acc e+      ETAbs e _s -> go acc e+      EApp g e -> go (go acc e) g+      EBin _o e1 e2 -> go (go acc e2) e1+      PImp p1 p2 -> go (go acc p2) p1+      PIff p1 p2 -> go (go acc p2) p1+      PAtom _r e1 e2 -> go (go acc e2) e1+      EIte p e1 e2 -> go (go (go acc e2) e1) p+      PAnd ps -> foldr (flip go) acc ps+      POr ps -> foldr (flip go) acc ps
src/Language/Fixpoint/Solver/Extensionality.hs view
@@ -214,6 +214,11 @@             DField (dummyLoc (symbol "lqdc$select$GHC.Tuple.Prim.(,)$1")) (FVar 0)           , DField (dummyLoc (symbol "lqdc$select$GHC.Tuple.Prim.(,)$2")) (FVar 1)           ]+#elif MIN_TOOL_VERSION_ghc(9,13,0)+    ct = DCtor (dummyLoc (symbol "GHC.Internal.Tuple.(,)")) [+            DField (dummyLoc (symbol "lqdc$select$GHC.Internal.Tuple.(,)$1")) (FVar 0)+          , DField (dummyLoc (symbol "lqdc$select$GHC.Internal.Tuple.(,)$2")) (FVar 1)+          ] #else     ct = DCtor (dummyLoc (symbol "GHC.Tuple.(,)")) [             DField (dummyLoc (symbol "lqdc$select$GHC.Tuple.(,)$1")) (FVar 0)
src/Language/Fixpoint/Solver/Instantiate.hs view
@@ -82,7 +82,7 @@                       ,  maybe True (i `L.elem`) subcIds ]     let t  = mkCTrie cs                                               -- 1. BUILD the Trie     res   <- withProgress (1 + length cs) $-               withCtx cfg file sEnv (pleTrie t . instEnv cfg info cs)  -- 2. TRAVERSE Trie to compute InstRes+               withCtx cfg file sEnv (defns info) (pleTrie t . instEnv cfg info cs)  -- 2. TRAVERSE Trie to compute InstRes     return $ resSInfo cfg sEnv info res                                 -- 3. STRENGTHEN SInfo using InstRes   where     file   = srcFile cfg ++ ".evals"@@ -296,7 +296,7 @@ -- | "Old" GLOBAL PLE -------------------------------------------------------------------------------- instantiate' :: (Loc a) => Config -> SInfo a -> Maybe [SubcId] -> IO (SInfo a)-instantiate' cfg info subcIds = sInfo cfg env info <$> withCtx cfg file env act+instantiate' cfg info subcIds = sInfo cfg env info <$> withCtx cfg file env (defns info) act   where     act ctx         = forM cstrs $ \(i, c) ->                         ((i,srcSpan c),) . mytracepp  ("INSTANTIATE i = " ++ show i) <$> instSimpC cfg ctx (bs info) aenv i c@@ -800,9 +800,9 @@ -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -withCtx :: Config -> FilePath -> SymEnv -> (SMT.Context -> IO a) -> IO a-withCtx cfg file env k = do-  ctx <- SMT.makeContextWithSEnv cfg file env+withCtx :: Config -> FilePath -> SymEnv -> [Equation] -> (SMT.Context -> IO a) -> IO a+withCtx cfg file env defns k = do+  ctx <- SMT.makeContextWithSEnv cfg file env defns   _   <- SMT.smtPush ctx   res <- k ctx   SMT.cleanupContext ctx
src/Language/Fixpoint/Solver/Monad.hs view
@@ -84,7 +84,7 @@     s0 ctx   = SS ctx be (stats0 fi)     act'     = assumesAxioms (F.asserts fi) >> act     release  = cleanupContext-    acquire  = makeContextWithSEnv cfg file initEnv+    acquire  = makeContextWithSEnv cfg file initEnv (F.defns fi)     initEnv  = symbolEnv cfg fi     be       = F.bs fi     file     = C.srcFile cfg
src/Language/Fixpoint/Solver/PLE.hs view
@@ -80,7 +80,7 @@                (cm info)     let t  = mkCTrie (M.toList cs)                                          -- 1. BUILD the Trie     res   <- withRESTSolver $ \solver -> withProgress (1 + M.size cs) $-               withCtx cfg file sEnv $ \ctx -> do+               withCtx cfg file sEnv (defns fi') $ \ctx -> do                   env <- instEnv cfg info cs solver ctx                   pleTrie t env                                             -- 2. TRAVERSE Trie to compute InstRes     savePLEEqualities cfg info sEnv res@@ -107,6 +107,7 @@   where     equalitiesPerConstraint (cid, c) =       (cid, L.sort [ e | i <- elemsIBindEnv (senv c), Just e <- [M.lookup i res] ])+    elabParam = ElabParam (solverFlags $ solver cfg) "savePLEEqualities" sEnv     renderConstraintRewrite (cid, eqs) =       "constraint id" <+> text (show cid ++ ":")       $+$ nest 2@@ -114,7 +115,7 @@             map (toFix . unElab) $ Set.toList $ Set.fromList $             -- call elabExpr to try to bring equations that are missing             -- some casts into a fully annotated form for comparison-            map (elabExpr (ElabParam (solverFlags $ solver cfg) "savePLEEqualities" sEnv)) $+            map (elabExpr elabParam (Just boolSort)) $             concatMap conjuncts eqs            )       $+$ ""@@ -1334,9 +1335,9 @@ -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -withCtx :: Config -> FilePath -> SymEnv -> (SMT.Context -> IO a) -> IO a-withCtx cfg file env k = do-  ctx <- SMT.makeContextWithSEnv cfg file env+withCtx :: Config -> FilePath -> SymEnv -> [Equation] -> (SMT.Context -> IO a) -> IO a+withCtx cfg file env defns k = do+  ctx <- SMT.makeContextWithSEnv cfg file env defns   _   <- SMT.smtPush ctx   res <- k ctx   SMT.cleanupContext ctx
src/Language/Fixpoint/Solver/Sanitize.hs view
@@ -34,12 +34,12 @@ import qualified Data.Text                                         as T import           Data.Maybe          (isNothing, mapMaybe, fromMaybe) import           Control.Monad       ((>=>))-import           Text.PrettyPrint.HughesPJ+import           Text.PrettyPrint.HughesPJ hiding ((<>))  type SanitizeM a = Either E.Error a  ---------------------------------------------------------------------------------sanitize :: Config -> F.SInfo a -> SanitizeM (F.SInfo a)+sanitize :: (Show a) => Config -> F.SInfo a -> SanitizeM (F.SInfo a) -------------------------------------------------------------------------------- sanitize cfg =       banIrregularData          >=> Misc.fM dropFuncSortedShadowedBinders@@ -152,14 +152,20 @@       splitApp (fvar, arg:args)     fapp' e = pure (e, []) -    theorySymbols = F.notracepp "theorySymbols" $ Thy.theorySymbols (Cfg.solver cfg) $ F.ddecls si+    thySyms = theoryEnv cfg si      splitApp (e, es)-      | isNothing $ F.notracepp ("isSmt2App? " ++ showpp e) $ Thy.isSmt2App theorySymbols $ stripCasts e+      | isNothing $ F.notracepp ("isSmt2App? " ++ showpp e) $ Thy.isSmt2App thySyms (stripCasts e)       = pure (e,es)       | otherwise       = Nothing +theoryEnv :: Config -> F.GInfo c a -> F.SEnv F.TheorySymbol+theoryEnv cfg si+  =  Thy.theorySymbols (Cfg.solver cfg)+  <> Thy.theorySymbols (F.defns si)+  <> Thy.theorySymbols (F.ddecls si)+ -------------------------------------------------------------------------------- -- | See issue liquid-fixpoint issue #230. This checks that whenever we have, --      G1        |- K.su1@@ -317,8 +323,9 @@ known cfg fi  = \x -> F.memberSEnv x lits || F.memberSEnv x prims   where     lits  = F.gLits fi-    prims = Thy.theorySymbols (Cfg.solver cfg) . F.ddecls $ fi+    prims = theoryEnv cfg fi + cNoFreeVars :: F.SInfo a -> (F.Symbol -> Bool) -> F.SimpC a -> Maybe [F.Symbol] cNoFreeVars fi knownSym c = if S.null fv then Nothing else Just (S.toList fv)   where@@ -387,15 +394,15 @@ --   it makes it hard to actually find the fundefs within (breaking PLE.) -------------------------------------------------------------------------------- symbolEnv :: Config -> F.SInfo a -> F.SymEnv-symbolEnv cfg si = F.symEnv sEnv tEnv ds lits (ts ++ ts')+symbolEnv cfg si = F.symEnv sEnv thyEnv ds lits (ts ++ ts')   where     ts'          = applySorts ae'     ae'          = elaborate (ElabParam ef (F.atLoc E.dummySpan "symbolEnv") env0) (F.ae si)-    env0         = F.symEnv sEnv tEnv ds lits ts-    tEnv         = Thy.theorySymbols slv ds+    env0         = F.symEnv sEnv thyEnv ds lits ts+    thyEnv       = theoryEnv cfg si     ds           = F.ddecls si     ts           = Misc.setNub (applySorts si ++ [t | (_, t) <- F.toListSEnv sEnv])-    sEnv         = F.coerceSortEnv ef $ (F.tsSort <$> tEnv) `mappend` F.fromListSEnv xts+    sEnv         = F.coerceSortEnv ef $ (F.tsSort <$> thyEnv) `mappend` F.fromListSEnv xts     slv          = Cfg.solver cfg     ef           = solverFlags slv     xts          = symbolSorts cfg si ++ alits@@ -488,7 +495,6 @@     ws'        = deleteWfCBinds drops <$> F.ws si     (_,drops)  = filterBindEnv keepF   $  F.bs si     keepF      = conjKF [nonConstantF si, nonFunctionF si, _nonDerivedLH]-    -- drops   = F.tracepp "sanitizeWfC: dropping" $ L.sort drops'  conjKF :: [KeepBindF] -> KeepBindF conjKF fs x t = and [f x t | f <- fs]
src/Language/Fixpoint/SortCheck.hs view
@@ -141,6 +141,7 @@     { F.cm      = elaborate ep <$> F.cm      si     , F.bs      = elaborate ep  $  F.bs      si     , F.asserts = elaborate ep <$> F.asserts si+    , F.ddecls  = coerceDataDecl (epFlags ep) <$> F.ddecls si     }  @@ -178,13 +179,16 @@       ep' = ep { epEnv = insertsSymEnv (epEnv ep) (eqArgs eq) }  instance Elaborate Expr where-  elaborate (ElabParam ef msg env) =-    elabNumeric . elabApply env' . elabExpr (ElabParam ef msg env') . elabFMap . (if Cfg.elabSetBag ef then elabFSetBagZ3 else id)+  elaborate p e = elaborateExpr p e Nothing++elaborateExpr :: ElabParam -> Expr -> Maybe Sort -> Expr+elaborateExpr (ElabParam ef msg env) e t =+    elabNumeric . elabApply env' . elabExpr (ElabParam ef msg env') t . elabFMap . (if Cfg.elabSetBag ef then elabFSetBagZ3 else id) $ e       where         env' = coerceEnv ef env  skipElabExpr :: ElabParam -> Expr -> Expr-skipElabExpr ep e = case elabExprE ep e of+skipElabExpr ep e = case elabExprE ep Nothing e of   Left _   -> e   Right e' -> elabNumeric . elabApply (epEnv ep) $ e' @@ -211,7 +215,7 @@ instance Elaborate SortedReft where   elaborate ep (RR s (Reft (v, e))) = RR s (Reft (v, e'))     where-      e'   = elaborate ep' e+      e'   = elaborateExpr ep' e (Just boolSort) -- check that a SortedReft is in fact a bool       ep' = ep { epEnv = insertSymEnv v s (epEnv ep) }  instance (Loc a) => Elaborate (BindEnv a) where@@ -307,21 +311,28 @@ -------------------------------------------------------------------------------- -- | 'elabExpr' adds "casts" to decorate polymorphic instantiation sites. ---------------------------------------------------------------------------------elabExpr :: ElabParam -> Expr -> Expr-elabExpr ep e = case elabExprE ep e of+elabExpr :: ElabParam -> Maybe Sort -> Expr ->  Expr+elabExpr ep t e = case elabExprE ep t e of   Left ex  -> die ex   Right e' -> F.notracepp ("elabExp " ++ showpp e) e' -elabExprE :: ElabParam -> Expr -> Either Error Expr-elabExprE (ElabParam ef msg env) e =+validateSort :: Sort -> Maybe Sort -> CheckM ()+validateSort t (Just t')+  | t == t'            = return ()+  | otherwise          = throwErrorAt $ printf "unexpected sort: got `%s` but expected `%s`" (showpp t) (showpp t')+validateSort _ Nothing = return ()++elabExprE :: ElabParam -> Maybe Sort -> Expr -> Either Error Expr+elabExprE (ElabParam ef msg env) t e =   case runCM0 (srcSpan msg) (Just ef) $ do-    (!e', _) <- elab (env, envLookup) e+    (!e', eSort) <- elab (env, envLookup) e+    validateSort eSort t     finalThetaRef <- asks chTVSubst     finalTheta <- liftIO $ readIORef finalThetaRef     return (applyExpr finalTheta e') of     Left (ChError f') ->       let e' = f' ()-       in Left $ err (srcSpan e') (d (val e'))+      in Left $ err (srcSpan e') (d (val e'))     Right s  -> Right s   where     sEnv = seSort env@@ -334,6 +345,7 @@                 , nest 4 (pprint $ subEnv sEnv e)                 ] + -------------------------------------------------------------------------------- -- | 'elabApply' replaces all direct function calls indirect calls via `apply` --------------------------------------------------------------------------------@@ -431,9 +443,6 @@ -------------------------------------------------------------------------------- mkSearchEnv env x = lookupSEnvWithDistance x env --- withError :: CheckM a -> ChError -> CheckM a--- act `withError` e' = act `catchError` (\e -> throwError (atLoc e (val e ++ "\n  because\n" ++ val e')))- withError :: HasCallStack => CheckM a -> String -> CheckM a act `withError` msg = do   r <- ask@@ -730,7 +739,6 @@ isUndef s = case bkAbs s of   (is, FVar j) -> j `elem` is   _            -> False-  elabAddEnv :: Eq a => (t, a -> SESearch b) -> [(a, b)] -> (t, a -> SESearch b) elabAddEnv (g, f) bs = (g, addEnv f bs)
src/Language/Fixpoint/Types/Constraints.hs view
@@ -697,7 +697,8 @@        , ae       = axe        , ddecls   = adts        , ebinds   = ebs-       , lrws = mempty+       , lrws     = mempty+       , defns    = mempty        }   where     --TODO handle duplicates gracefully instead (merge envs by intersect?)@@ -744,6 +745,7 @@   , asserts  :: ![Triggered Expr]          -- ^ TODO: what is this?   , ae       :: AxiomEnv                   -- ^ Information about reflected function defs   , lrws     :: LocalRewritesEnv           -- ^ Local rewrites+  , defns    :: ![Equation]                -- ^ `define_fun` definitions to be passed to SMT   }   deriving (Eq, Show, Functor, Generic) @@ -773,6 +775,7 @@                 , asserts  = asserts i1  <> asserts i2                 , ae       = ae i1       <> ae i2                 , lrws     = lrws i1     <> lrws i2+                , defns    = defns i1    <> defns i2                 }  @@ -791,6 +794,7 @@                      , asserts  = mempty                      , ae       = mempty                      , lrws     = mempty+                     , defns    = mempty                      }  instance PTable (SInfo a) where@@ -1073,7 +1077,7 @@ instance Fixpoint LocalRewritesEnv where   toFix (LocalRewritesMap rws) = vcat $ uncurry toFixLocal <$> M.toList rws     where-      toFixLocal bid (LocalRewrites rws) = text "defineLocal" <+> toFix bid +      toFixLocal bid (LocalRewrites rws) = text "defineLocal" <+> toFix bid         <+> brackets (vcat $ punctuate ";" $ uncurry toFixRewrite <$> M.toList rws)       toFixRewrite sym eq = toFix sym <+> text ":=" <+> toFix eq 
src/Language/Fixpoint/Types/Sorts.hs view
@@ -87,6 +87,7 @@   -- * Sort coercion for SMT theory encoding   , coerceMapToArray   , coerceSetBagToArray+  , coerceDataDecl   ) where  import qualified Data.Store as S@@ -104,6 +105,7 @@ #endif import           Control.DeepSeq import           Data.Maybe                (fromMaybe)+import           Language.Fixpoint.Types.Config (ElabFlags, elabSetBag) import           Language.Fixpoint.Types.Names import           Language.Fixpoint.Types.PrettyPrint import           Language.Fixpoint.Types.Spans@@ -706,3 +708,12 @@   | isBag sf = arraySort (coerceSetBagToArray sa) intSort   | otherwise = FApp (coerceSetBagToArray sf) (coerceSetBagToArray sa) coerceSetBagToArray s = s++coerceDataField :: ElabFlags -> DataField -> DataField+coerceDataField ef (DField x t)  = DField x (((if elabSetBag ef then coerceSetBagToArray else id) . coerceMapToArray) t)++coerceDataCtor :: ElabFlags -> DataCtor -> DataCtor+coerceDataCtor ef (DCtor x flds) = DCtor x (coerceDataField ef <$> flds)++coerceDataDecl :: ElabFlags -> DataDecl -> DataDecl+coerceDataDecl ef (DDecl tc n ctors) = DDecl tc n (coerceDataCtor ef <$> ctors)
src/Language/Fixpoint/Types/Theories.hs view
@@ -37,6 +37,7 @@     -- * Coercing sorts in environments     , coerceEnv     , coerceSortEnv+    , TheorySymbols(..)     ) where  @@ -250,6 +251,10 @@   }   deriving (Eq, Ord, Show, Data, Typeable, Generic) ++class TheorySymbols a where+  theorySymbols :: a ->  SEnv TheorySymbol+ instance NFData Sem instance NFData TheorySymbol instance S.Store TheorySymbol@@ -273,6 +278,7 @@   | Test          -- ^ for ADT tests : `is$cons`   | Field         -- ^ for ADT field: `hd`, `tl`   | Theory        -- ^ for theory ops: mem, cup, select+  | Defined       -- ^ for user-defined `define-fun`   deriving (Eq, Ord, Show, Data, Typeable, Generic)  instance S.Store Sem