liquid-fixpoint 0.9.6.3.3 → 0.9.6.3.4
raw patch · 129 files changed
+4184/−5364 lines, 129 filesdep +gitrevdep −parallelPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: gitrev
Dependencies removed: parallel
API changes (from Hackage documentation)
- Language.Fixpoint.Graph.Types: EBind :: !Symbol -> CVertex
- Language.Fixpoint.Horn.Types: Any :: !Bind a -> !Cstr a -> Cstr a
- Language.Fixpoint.Horn.Types: class ToHornSMT a
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT (Language.Fixpoint.Horn.Types.Bind a)
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT (Language.Fixpoint.Horn.Types.Cstr a)
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT (Language.Fixpoint.Horn.Types.Query a)
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT (Language.Fixpoint.Horn.Types.Var a)
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Horn.Types.Pred
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Horn.Types.Tag
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Types.Constraints.QualParam
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Types.Constraints.Qualifier
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Types.Constraints.Rewrite
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Types.Names.Symbol
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Types.Refinements.Expr
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Types.Refinements.KVar
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Types.Refinements.Subst
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Types.Sorts.DataCtor
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Types.Sorts.DataDecl
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Types.Sorts.DataField
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Types.Sorts.FTycon
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT Language.Fixpoint.Types.Sorts.Sort
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT a => Language.Fixpoint.Horn.Types.ToHornSMT (Language.Fixpoint.Types.Names.Symbol, a)
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT a => Language.Fixpoint.Horn.Types.ToHornSMT (Language.Fixpoint.Types.Spans.Located a)
- Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Horn.Types.ToHornSMT a => Language.Fixpoint.Horn.Types.ToHornSMT [a]
- Language.Fixpoint.Horn.Types: toHornSMT :: ToHornSMT a => a -> Doc
- Language.Fixpoint.Misc: type (|->) a b = HashMap a b
- Language.Fixpoint.Parse: instance Language.Fixpoint.Parse.Inputable (Language.Fixpoint.Types.Errors.FixResult GHC.Num.Integer.Integer, Language.Fixpoint.Types.Constraints.FixSolution)
- Language.Fixpoint.Smt.Interface: smtCheckSat :: Context -> Expr -> IO Bool
- Language.Fixpoint.Solver: type Solver a = Config -> FInfo a -> IO (Result (Integer, a))
- Language.Fixpoint.Solver.GradualSolution: init :: Fixpoint a => Config -> SInfo a -> [(KVar, (GWInfo, [Expr]))]
- Language.Fixpoint.Solver.GradualSolve: solveGradual :: (NFData a, Fixpoint a) => Config -> SInfo a -> IO (Result (Integer, a))
- Language.Fixpoint.Solver.Instantiate: instance GHC.Classes.Eq Language.Fixpoint.Solver.Instantiate.Recur
- Language.Fixpoint.Solver.Instantiate: instance GHC.Show.Show Language.Fixpoint.Solver.Instantiate.Recur
- Language.Fixpoint.Solver.Instantiate: instance Language.Fixpoint.Types.PrettyPrint.PPrint Language.Fixpoint.Solver.Instantiate.Recur
- Language.Fixpoint.Solver.Instantiate: instantiate :: Loc a => Config -> SInfo a -> Maybe [SubcId] -> IO (SInfo a)
- Language.Fixpoint.Solver.Monad: [ssBinds] :: SolverState ann -> !BindEnv ann
- Language.Fixpoint.Solver.Monad: checkSat :: Expr -> SolveM ann Bool
- Language.Fixpoint.Solver.Monad: filterValidGradual :: [Expr] -> Cand a -> SolveM ann [a]
- Language.Fixpoint.Solver.Monad: getBinds :: SolveM ann (BindEnv ann)
- Language.Fixpoint.Solver.PLE: [knContext] :: Knowledge -> Context
- Language.Fixpoint.Solver.PLE: instance GHC.Show.Show Language.Fixpoint.Solver.PLE.FinalExpand
- Language.Fixpoint.Solver.Solution: instance Language.Fixpoint.Types.Spans.Loc (Language.Fixpoint.Solver.Solution.CombinedEnv a)
- Language.Fixpoint.Solver.Solve: solverInfo :: Config -> SInfo a -> SolverInfo a b
- Language.Fixpoint.Types.Config: [ginteractive] :: Config -> Bool
- Language.Fixpoint.Types.Config: [gradual] :: Config -> Bool
- Language.Fixpoint.Types.Config: [inlineANFBindings] :: Config -> Bool
- Language.Fixpoint.Types.Config: [noEnvironmentReduction] :: Config -> Bool
- Language.Fixpoint.Types.Config: [noIncrPle] :: Config -> Bool
- Language.Fixpoint.Types.Config: [noLazyPLE] :: Config -> Bool
- Language.Fixpoint.Types.Config: [oldPLE] :: Config -> Bool
- Language.Fixpoint.Types.Config: [pleWithUndecidedGuards] :: Config -> Bool
- Language.Fixpoint.Types.Config: [rwTerminationCheck] :: Config -> Bool
- Language.Fixpoint.Types.Config: [stringTheory] :: Config -> Bool
- Language.Fixpoint.Types.Config: newtype ElabFlags
- Language.Fixpoint.Types.Constraints: GWInfo :: Symbol -> Sort -> Expr -> GradInfo -> GWInfo
- Language.Fixpoint.Types.Constraints: GWfC :: !IBindEnv -> !(Symbol, Sort, KVar) -> !a -> !Expr -> !GradInfo -> WfC a
- Language.Fixpoint.Types.Constraints: [ebinds] :: GInfo c a -> ![BindId]
- Language.Fixpoint.Types.Constraints: [gexpr] :: GWInfo -> Expr
- Language.Fixpoint.Types.Constraints: [ginfo] :: GWInfo -> GradInfo
- Language.Fixpoint.Types.Constraints: [gresSolution] :: Result a -> !GFixSolution
- Language.Fixpoint.Types.Constraints: [gsort] :: GWInfo -> Sort
- Language.Fixpoint.Types.Constraints: [gsym] :: GWInfo -> Symbol
- Language.Fixpoint.Types.Constraints: [wexpr] :: WfC a -> !Expr
- Language.Fixpoint.Types.Constraints: [wloc] :: WfC a -> !GradInfo
- Language.Fixpoint.Types.Constraints: data GWInfo
- Language.Fixpoint.Types.Constraints: gwInfo :: WfC a -> GWInfo
- Language.Fixpoint.Types.Constraints: instance Control.DeepSeq.NFData Language.Fixpoint.Types.Constraints.GFixSolution
- Language.Fixpoint.Types.Constraints: instance Control.DeepSeq.NFData Language.Fixpoint.Types.Constraints.GWInfo
- Language.Fixpoint.Types.Constraints: instance Data.Store.Impl.Store Language.Fixpoint.Types.Constraints.GFixSolution
- Language.Fixpoint.Types.Constraints: instance Data.Store.Impl.Store Language.Fixpoint.Types.Constraints.GWInfo
- Language.Fixpoint.Types.Constraints: instance GHC.Base.Functor Language.Fixpoint.Types.Constraints.GFixSol
- Language.Fixpoint.Types.Constraints: instance GHC.Base.Monoid (Language.Fixpoint.Types.Constraints.GFixSol e)
- Language.Fixpoint.Types.Constraints: instance GHC.Base.Semigroup (Language.Fixpoint.Types.Constraints.GFixSol e)
- Language.Fixpoint.Types.Constraints: instance GHC.Classes.Eq Language.Fixpoint.Types.Constraints.GWInfo
- Language.Fixpoint.Types.Constraints: instance GHC.Generics.Generic (Language.Fixpoint.Types.Constraints.GFixSol e)
- Language.Fixpoint.Types.Constraints: instance GHC.Generics.Generic Language.Fixpoint.Types.Constraints.GWInfo
- Language.Fixpoint.Types.Constraints: instance GHC.Show.Show Language.Fixpoint.Types.Constraints.GFixSolution
- Language.Fixpoint.Types.Constraints: instance Language.Fixpoint.Types.PrettyPrint.PPrint (Language.Fixpoint.Types.Constraints.QualifierV v)
- Language.Fixpoint.Types.Constraints: instance Language.Fixpoint.Types.PrettyPrint.PPrint Language.Fixpoint.Types.Constraints.GFixSolution
- Language.Fixpoint.Types.Constraints: instance Language.Fixpoint.Types.Refinements.HasGradual (Language.Fixpoint.Types.Constraints.GInfo c a)
- Language.Fixpoint.Types.Constraints: instance Language.Fixpoint.Types.Refinements.HasGradual (Language.Fixpoint.Types.Constraints.WfC a)
- Language.Fixpoint.Types.Constraints: isGWfc :: WfC a -> Bool
- Language.Fixpoint.Types.Constraints: toGFixSol :: HashMap KVar (e, [e]) -> GFixSol e
- Language.Fixpoint.Types.Constraints: type GFixSolution = GFixSol Expr
- Language.Fixpoint.Types.Constraints: type Solver a = Config -> FInfo a -> IO (Result (Integer, a))
- Language.Fixpoint.Types.Constraints: updateWfCExpr :: (Expr -> Expr) -> WfC a -> WfC a
- Language.Fixpoint.Types.Graduals: class Gradual a
- Language.Fixpoint.Types.Graduals: data GSol
- Language.Fixpoint.Types.Graduals: gsubst :: Gradual a => ElabFlags -> GSol -> a -> a
- Language.Fixpoint.Types.Graduals: instance GHC.Base.Monoid Language.Fixpoint.Types.Graduals.GSol
- Language.Fixpoint.Types.Graduals: instance GHC.Base.Semigroup Language.Fixpoint.Types.Graduals.GSol
- Language.Fixpoint.Types.Graduals: instance GHC.Show.Show Language.Fixpoint.Types.Graduals.GSol
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Graduals.Gradual (Language.Fixpoint.Types.Constraints.SInfo a)
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Graduals.Gradual (Language.Fixpoint.Types.Constraints.SimpC a)
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Graduals.Gradual (Language.Fixpoint.Types.Environments.BindEnv a)
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Graduals.Gradual Language.Fixpoint.Types.Refinements.Expr
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Graduals.Gradual Language.Fixpoint.Types.Refinements.Reft
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Graduals.Gradual Language.Fixpoint.Types.Refinements.SortedReft
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Graduals.Gradual v => Language.Fixpoint.Types.Graduals.Gradual (Data.HashMap.Internal.HashMap k v)
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Graduals.Unique ann Language.Fixpoint.Types.Environments.BindId
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Graduals.Unique ann Language.Fixpoint.Types.Environments.IBindEnv
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Graduals.Unique ann Language.Fixpoint.Types.Refinements.Expr
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Graduals.Unique ann Language.Fixpoint.Types.Refinements.Reft
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Graduals.Unique ann Language.Fixpoint.Types.Refinements.SortedReft
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Graduals.Unique ann a => Language.Fixpoint.Types.Graduals.Unique ann (Data.HashMap.Internal.HashMap Language.Fixpoint.Types.Constraints.SubcId a)
- Language.Fixpoint.Types.Graduals: instance Language.Fixpoint.Types.Spans.Loc a => Language.Fixpoint.Types.Graduals.Unique a (Language.Fixpoint.Types.Constraints.SimpC a)
- Language.Fixpoint.Types.Graduals: makeSolutions :: (NFData a, Fixpoint a, Show a) => Config -> SInfo a -> [(KVar, (GWInfo, [[Expr]]))] -> Maybe [GSol]
- Language.Fixpoint.Types.Graduals: uniquify :: (NFData a, Fixpoint a, Loc a) => SInfo a -> SInfo a
- Language.Fixpoint.Types.Names: gradIntSymbol :: Integer -> Symbol
- Language.Fixpoint.Types.Refinements: GradInfo :: SrcSpan -> Maybe SrcSpan -> GradInfo
- Language.Fixpoint.Types.Refinements: PGrad :: !KVar -> !SubstV v -> !GradInfo -> !ExprV v -> ExprV v
- Language.Fixpoint.Types.Refinements: [gsrc] :: GradInfo -> SrcSpan
- Language.Fixpoint.Types.Refinements: [gused] :: GradInfo -> Maybe SrcSpan
- Language.Fixpoint.Types.Refinements: class HasGradual a
- Language.Fixpoint.Types.Refinements: data GradInfo
- Language.Fixpoint.Types.Refinements: gVars :: HasGradual a => a -> [KVar]
- Language.Fixpoint.Types.Refinements: instance Control.DeepSeq.NFData Language.Fixpoint.Types.Refinements.GradInfo
- Language.Fixpoint.Types.Refinements: instance Data.Aeson.Types.FromJSON.FromJSON Language.Fixpoint.Types.Refinements.GradInfo
- Language.Fixpoint.Types.Refinements: instance Data.Aeson.Types.ToJSON.ToJSON Language.Fixpoint.Types.Refinements.GradInfo
- Language.Fixpoint.Types.Refinements: instance Data.Binary.Class.Binary Language.Fixpoint.Types.Refinements.GradInfo
- Language.Fixpoint.Types.Refinements: instance Data.Data.Data Language.Fixpoint.Types.Refinements.GradInfo
- Language.Fixpoint.Types.Refinements: instance Data.Hashable.Class.Hashable Language.Fixpoint.Types.Refinements.GradInfo
- Language.Fixpoint.Types.Refinements: instance Data.Store.Impl.Store Language.Fixpoint.Types.Refinements.GradInfo
- Language.Fixpoint.Types.Refinements: instance GHC.Classes.Eq Language.Fixpoint.Types.Refinements.GradInfo
- Language.Fixpoint.Types.Refinements: instance GHC.Classes.Ord Language.Fixpoint.Types.Refinements.GradInfo
- Language.Fixpoint.Types.Refinements: instance GHC.Generics.Generic Language.Fixpoint.Types.Refinements.GradInfo
- Language.Fixpoint.Types.Refinements: instance GHC.Show.Show Language.Fixpoint.Types.Refinements.GradInfo
- Language.Fixpoint.Types.Refinements: instance Language.Fixpoint.Types.Refinements.HasGradual Language.Fixpoint.Types.Refinements.Expr
- Language.Fixpoint.Types.Refinements: instance Language.Fixpoint.Types.Refinements.HasGradual Language.Fixpoint.Types.Refinements.Reft
- Language.Fixpoint.Types.Refinements: instance Language.Fixpoint.Types.Refinements.HasGradual Language.Fixpoint.Types.Refinements.SortedReft
- Language.Fixpoint.Types.Refinements: isGradual :: HasGradual a => a -> Bool
- Language.Fixpoint.Types.Refinements: pGAnd :: (Fixpoint v, Ord v) => ExprV v -> ExprV v -> ExprV v
- Language.Fixpoint.Types.Refinements: pGAnds :: (Fixpoint v, Ord v) => [ExprV v] -> ExprV v
- Language.Fixpoint.Types.Refinements: srcGradInfo :: SourcePos -> GradInfo
- Language.Fixpoint.Types.Refinements: ungrad :: HasGradual a => a -> a
- Language.Fixpoint.Types.Solutions: EbDef :: [SimpC ()] -> Symbol -> EbindSol
- Language.Fixpoint.Types.Solutions: EbIncr :: EbindSol
- Language.Fixpoint.Types.Solutions: EbSol :: Expr -> EbindSol
- Language.Fixpoint.Types.Solutions: data EbindSol
- Language.Fixpoint.Types.Solutions: data GBind
- Language.Fixpoint.Types.Solutions: data QBind
- Language.Fixpoint.Types.Solutions: emptyGMap :: GSolution -> GSolution
- Language.Fixpoint.Types.Solutions: equalsGb :: [[EQual]] -> GBind
- Language.Fixpoint.Types.Solutions: fromList :: SymEnv -> [(KVar, a)] -> [(KVar, b)] -> [(KVar, Hyp)] -> HashMap KVar IBindEnv -> [(BindId, EbindSol)] -> SEnv (BindId, Sort) -> Sol a b
- Language.Fixpoint.Types.Solutions: gbEquals :: GBind -> [[EQual]]
- Language.Fixpoint.Types.Solutions: gbFilterM :: Monad m => ([EQual] -> m Bool) -> GBind -> m GBind
- Language.Fixpoint.Types.Solutions: gbToQbs :: GBind -> [QBind]
- Language.Fixpoint.Types.Solutions: glookup :: GSolution -> KVar -> Either Hyp (Either QBind (((Symbol, Sort), Expr), GBind))
- Language.Fixpoint.Types.Solutions: instance (Control.DeepSeq.NFData b, Control.DeepSeq.NFData a) => Control.DeepSeq.NFData (Language.Fixpoint.Types.Solutions.Sol b a)
- Language.Fixpoint.Types.Solutions: instance (Language.Fixpoint.Types.PrettyPrint.PPrint a, Language.Fixpoint.Types.PrettyPrint.PPrint b) => Language.Fixpoint.Types.PrettyPrint.PPrint (Language.Fixpoint.Types.Solutions.Sol a b)
- Language.Fixpoint.Types.Solutions: instance Control.DeepSeq.NFData Language.Fixpoint.Types.Solutions.EbindSol
- Language.Fixpoint.Types.Solutions: instance Control.DeepSeq.NFData Language.Fixpoint.Types.Solutions.GBind
- Language.Fixpoint.Types.Solutions: instance Data.Data.Data Language.Fixpoint.Types.Solutions.GBind
- Language.Fixpoint.Types.Solutions: instance GHC.Base.Functor (Language.Fixpoint.Types.Solutions.Sol a)
- Language.Fixpoint.Types.Solutions: instance GHC.Base.Monoid (Language.Fixpoint.Types.Solutions.Sol a b)
- Language.Fixpoint.Types.Solutions: instance GHC.Base.Semigroup (Language.Fixpoint.Types.Solutions.Sol a b)
- Language.Fixpoint.Types.Solutions: instance GHC.Generics.Generic (Language.Fixpoint.Types.Solutions.Sol b a)
- Language.Fixpoint.Types.Solutions: instance GHC.Generics.Generic Language.Fixpoint.Types.Solutions.EbindSol
- Language.Fixpoint.Types.Solutions: instance GHC.Generics.Generic Language.Fixpoint.Types.Solutions.GBind
- Language.Fixpoint.Types.Solutions: instance GHC.Show.Show Language.Fixpoint.Types.Solutions.EbindSol
- Language.Fixpoint.Types.Solutions: instance GHC.Show.Show Language.Fixpoint.Types.Solutions.GBind
- Language.Fixpoint.Types.Solutions: instance Language.Fixpoint.Types.PrettyPrint.PPrint Language.Fixpoint.Types.Solutions.EbindSol
- Language.Fixpoint.Types.Solutions: qbToGb :: QBind -> GBind
- Language.Fixpoint.Types.Solutions: resultGradual :: GSolution -> HashMap KVar (Expr, [Expr])
- Language.Fixpoint.Types.Solutions: sHyp :: Sol b a -> HashMap KVar Hyp
- Language.Fixpoint.Types.Solutions: sScp :: Sol b a -> HashMap KVar IBindEnv
- Language.Fixpoint.Types.Solutions: type GSolution = Sol (((Symbol, Sort), Expr), GBind) QBind
- Language.Fixpoint.Types.Solutions: updateEbind :: Sol a b -> BindId -> Pred -> Sol a b
- Language.Fixpoint.Types.Solutions: updateGMap :: Sol b a -> HashMap KVar b -> Sol b a
- Language.Fixpoint.Types.Solutions: updateGMapWithKey :: [(KVar, QBind)] -> GSolution -> GSolution
- Language.Fixpoint.Types.Theories: symbolAtSmtName :: PPrint a => Symbol -> SymEnv -> a -> FuncSort -> Text
- Language.Fixpoint.Types.Visitor: mapGVars' :: Visitable t => ((KVar, Subst) -> Maybe Expr) -> t -> t
+ Control.Exception.Compat: ExceptionWithContext :: ExceptionContext -> a -> ExceptionWithContext a
+ Control.Exception.Compat: data ExceptionWithContext a
+ Control.Exception.Compat: displayExceptionContext :: ExceptionContext -> String
+ Control.Exception.Compat: wrapExceptionWithContext :: a -> ExceptionWithContext a
+ Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT (Language.Fixpoint.Horn.Types.Bind a)
+ Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT (Language.Fixpoint.Horn.Types.Cstr a)
+ Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT (Language.Fixpoint.Horn.Types.Query a)
+ Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT (Language.Fixpoint.Horn.Types.Var a)
+ Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Horn.Types.Pred
+ Language.Fixpoint.Horn.Types: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Horn.Types.Tag
+ Language.Fixpoint.Misc: type a |-> b = HashMap a b
+ Language.Fixpoint.Parse: [allowExists] :: PStateV v -> !Bool
+ Language.Fixpoint.Parse: doParse'' :: Bool -> Parser a -> SourceName -> String -> a
+ Language.Fixpoint.Smt.Interface: Comment :: Text -> Command
+ Language.Fixpoint.Smt.Interface: [config] :: Context -> !Config
+ Language.Fixpoint.Smt.Interface: [ctxIxs] :: Context -> ![Int]
+ Language.Fixpoint.Smt.Interface: [ctxLams] :: Context -> !Bool
+ Language.Fixpoint.Smt.Interface: funcSortVars :: Bool -> SymEnv -> [(Text, ([SmtSort], SmtSort))]
+ Language.Fixpoint.Smt.Interface: smtAssertDecl :: HasCallStack => Expr -> SmtM ()
+ Language.Fixpoint.Smt.Interface: smtComment :: Text -> SmtM ()
+ Language.Fixpoint.Smt.Serialize: instance Language.Fixpoint.Smt.Types.SMTLIB2 (Language.Fixpoint.Types.Names.Symbol, Language.Fixpoint.Types.Refinements.Expr)
+ Language.Fixpoint.Smt.Theories: ffAdd :: IsString a => a
+ Language.Fixpoint.Smt.Theories: ffMul :: IsString a => a
+ Language.Fixpoint.Smt.Theories: ffVal :: IsString a => a
+ Language.Fixpoint.Smt.Theories: instance Language.Fixpoint.Types.Theories.TheorySymbols Language.Fixpoint.Types.Constraints.DefinedFuns
+ Language.Fixpoint.Smt.Theories: setCard :: IsString a => a
+ Language.Fixpoint.Smt.Types: Comment :: Text -> Command
+ Language.Fixpoint.Smt.Types: [config] :: Context -> !Config
+ Language.Fixpoint.Smt.Types: [ctxIxs] :: Context -> ![Int]
+ Language.Fixpoint.Smt.Types: [ctxLams] :: Context -> !Bool
+ Language.Fixpoint.Smt.Types: bracketSMT :: SmtM a -> (a -> IO b) -> (a -> SmtM c) -> SmtM c
+ Language.Fixpoint.Smt.Types: catchSMT :: Exception e => SmtM a -> (e -> IO a) -> SmtM a
+ Language.Fixpoint.Smt.Types: liftSym :: SymM a -> SmtM a
+ Language.Fixpoint.Smt.Types: type SmtM = StateT Context IO
+ Language.Fixpoint.Solver.Monad: [ssElabParam] :: SolverState ann -> !ElabParam
+ Language.Fixpoint.Solver.Monad: liftSMT :: SmtM a -> SolveM ann a
+ Language.Fixpoint.Solver.Monad: modifyContext :: (Context -> Context) -> SolveM ann ()
+ Language.Fixpoint.Solver.PLE: [icBindIds] :: ICtx -> IBindEnv
+ Language.Fixpoint.Solver.PLE: [icFreshExistentialCounter] :: ICtx -> Int
+ Language.Fixpoint.Solver.PLE: [icInitialLHSs] :: ICtx -> HashMap ExScope (HashSet Expr)
+ Language.Fixpoint.Solver.Solution: CEnv :: !Cid -> !BindEnv a -> !IBindEnv -> !SrcSpan -> !IBindEnv -> CombinedEnv a
+ Language.Fixpoint.Solver.Solution: [ceBEnv] :: CombinedEnv a -> !BindEnv a
+ Language.Fixpoint.Solver.Solution: [ceBindingsInSmt] :: CombinedEnv a -> !IBindEnv
+ Language.Fixpoint.Solver.Solution: [ceCid] :: CombinedEnv a -> !Cid
+ Language.Fixpoint.Solver.Solution: [ceIEnv] :: CombinedEnv a -> !IBindEnv
+ Language.Fixpoint.Solver.Solution: [ceSpan] :: CombinedEnv a -> !SrcSpan
+ Language.Fixpoint.Solver.Solution: alphaEq :: HashSet Symbol -> Expr -> Expr -> Bool
+ Language.Fixpoint.Solver.Solution: applyInSortedReft :: Config -> CombinedEnv ann -> Sol QBind -> (Symbol, SortedReft) -> (Symbol, SortedReft)
+ Language.Fixpoint.Solver.Solution: data CombinedEnv a
+ Language.Fixpoint.Solver.Solution: simplifyKVar :: HashSet Symbol -> Expr -> Expr
+ Language.Fixpoint.SortCheck: globalEnv :: forall (c :: Type -> Type) a. Config -> GInfo c a -> SEnv Sort
+ Language.Fixpoint.SortCheck: instance Language.Fixpoint.SortCheck.Elaborate Language.Fixpoint.Types.Constraints.DefinedFuns
+ Language.Fixpoint.SortCheck: theoryEnv :: forall (c :: Type -> Type) a. Config -> GInfo c a -> SEnv TheorySymbol
+ Language.Fixpoint.SortCheck: unElabFSetBagZ3 :: Expr -> Expr
+ Language.Fixpoint.Types.Config: [elabExplicitKvars] :: ElabFlags -> Bool
+ Language.Fixpoint.Types.Config: [explicitKvars] :: Config -> Bool
+ Language.Fixpoint.Types.Config: [inlineANFBinds] :: Config -> Bool
+ Language.Fixpoint.Types.Config: [noEnvReduction] :: Config -> Bool
+ Language.Fixpoint.Types.Config: [noStringTheory] :: Config -> Bool
+ Language.Fixpoint.Types.Config: [pleUndecGuards] :: Config -> Bool
+ Language.Fixpoint.Types.Config: [rwTermination] :: Config -> Bool
+ Language.Fixpoint.Types.Config: data ElabFlags
+ Language.Fixpoint.Types.Config: mkElabFlags :: SMTSolver -> Bool -> ElabFlags
+ Language.Fixpoint.Types.Constraints: Delayed :: a -> Delayed a
+ Language.Fixpoint.Types.Constraints: MkDefinedFuns :: [Equation] -> DefinedFuns
+ Language.Fixpoint.Types.Constraints: [forceDelayed] :: Delayed a -> a
+ Language.Fixpoint.Types.Constraints: [resSorts] :: Result a -> !ResultSorts
+ Language.Fixpoint.Types.Constraints: data Delayed a
+ Language.Fixpoint.Types.Constraints: eqnToHornSMT :: Doc -> Equation -> Doc
+ Language.Fixpoint.Types.Constraints: instance (GHC.Classes.Ord v, Language.Fixpoint.Types.PrettyPrint.Fixpoint v, Language.Fixpoint.Types.PrettyPrint.PPrint v) => Language.Fixpoint.Types.PrettyPrint.PPrint (Language.Fixpoint.Types.Constraints.QualifierV v)
+ Language.Fixpoint.Types.Constraints: instance Control.DeepSeq.NFData Language.Fixpoint.Types.Constraints.DefinedFuns
+ Language.Fixpoint.Types.Constraints: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Language.Fixpoint.Types.Constraints.Delayed a)
+ Language.Fixpoint.Types.Constraints: instance Data.Aeson.Types.ToJSON.ToJSON Language.Fixpoint.Types.Constraints.ScopedExpr
+ Language.Fixpoint.Types.Constraints: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Language.Fixpoint.Types.Constraints.KVarBind a)
+ Language.Fixpoint.Types.Constraints: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Language.Fixpoint.Types.Constraints.KVarMap a)
+ Language.Fixpoint.Types.Constraints: instance Data.Data.Data Language.Fixpoint.Types.Constraints.DefinedFuns
+ Language.Fixpoint.Types.Constraints: instance Data.Store.Impl.Store Language.Fixpoint.Types.Constraints.DefinedFuns
+ Language.Fixpoint.Types.Constraints: instance GHC.Base.Functor Language.Fixpoint.Types.Constraints.Delayed
+ Language.Fixpoint.Types.Constraints: instance GHC.Base.Monoid Language.Fixpoint.Types.Constraints.DefinedFuns
+ Language.Fixpoint.Types.Constraints: instance GHC.Base.Semigroup Language.Fixpoint.Types.Constraints.DefinedFuns
+ Language.Fixpoint.Types.Constraints: instance GHC.Classes.Eq Language.Fixpoint.Types.Constraints.DefinedFuns
+ Language.Fixpoint.Types.Constraints: instance GHC.Classes.Ord Language.Fixpoint.Types.Constraints.DefinedFuns
+ Language.Fixpoint.Types.Constraints: instance GHC.Generics.Generic (Language.Fixpoint.Types.Constraints.Delayed a)
+ Language.Fixpoint.Types.Constraints: instance GHC.Generics.Generic (Language.Fixpoint.Types.Constraints.KVarBind a)
+ Language.Fixpoint.Types.Constraints: instance GHC.Generics.Generic (Language.Fixpoint.Types.Constraints.KVarMap a)
+ Language.Fixpoint.Types.Constraints: instance GHC.Generics.Generic Language.Fixpoint.Types.Constraints.DefinedFuns
+ Language.Fixpoint.Types.Constraints: instance GHC.Generics.Generic Language.Fixpoint.Types.Constraints.ScopedExpr
+ Language.Fixpoint.Types.Constraints: instance GHC.Generics.Generic Language.Fixpoint.Types.Constraints.ScopedResult
+ Language.Fixpoint.Types.Constraints: instance GHC.Show.Show Language.Fixpoint.Types.Constraints.DefinedFuns
+ Language.Fixpoint.Types.Constraints: instance GHC.Show.Show Language.Fixpoint.Types.Constraints.ScopedExpr
+ Language.Fixpoint.Types.Constraints: instance GHC.Show.Show Language.Fixpoint.Types.Constraints.ScopedResult
+ Language.Fixpoint.Types.Constraints: instance GHC.Show.Show a => GHC.Show.Show (Language.Fixpoint.Types.Constraints.Delayed a)
+ Language.Fixpoint.Types.Constraints: instance GHC.Show.Show a => GHC.Show.Show (Language.Fixpoint.Types.Constraints.KVarBind a)
+ Language.Fixpoint.Types.Constraints: instance GHC.Show.Show a => GHC.Show.Show (Language.Fixpoint.Types.Constraints.KVarMap a)
+ Language.Fixpoint.Types.Constraints: instance Language.Fixpoint.Types.PrettyPrint.PPrint Language.Fixpoint.Types.Constraints.DefinedFuns
+ Language.Fixpoint.Types.Constraints: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Types.Constraints.QualParam
+ Language.Fixpoint.Types.Constraints: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Types.Constraints.Qualifier
+ Language.Fixpoint.Types.Constraints: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Types.Constraints.Rewrite
+ Language.Fixpoint.Types.Constraints: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Types.Constraints.ScopedExpr
+ Language.Fixpoint.Types.Constraints: newtype DefinedFuns
+ Language.Fixpoint.Types.Constraints: saveSInfo :: Fixpoint a => Config -> String -> SInfo a -> IO ()
+ Language.Fixpoint.Types.Constraints: type FixDelayedSolution = HashMap KVar Delayed Expr
+ Language.Fixpoint.Types.Constraints: type ResultSorts = HashMap KVar [(Symbol, Sort)]
+ Language.Fixpoint.Types.Names: bv16intName :: Symbol
+ Language.Fixpoint.Types.Names: bv8intName :: Symbol
+ Language.Fixpoint.Types.Names: ffldConName :: Symbol
+ Language.Fixpoint.Types.Names: intbv16Name :: Symbol
+ Language.Fixpoint.Types.Names: intbv8Name :: Symbol
+ Language.Fixpoint.Types.Names: renameSubstSymbol :: Symbol -> Int -> Symbol
+ Language.Fixpoint.Types.Refinements: ELet :: !Symbol -> !ExprV v -> !ExprV v -> ExprV v
+ Language.Fixpoint.Types.Refinements: instance Data.Aeson.Types.ToJSON.ToJSONKey Language.Fixpoint.Types.Refinements.KVar
+ Language.Fixpoint.Types.SMTPrint: class ToHornSMT a
+ Language.Fixpoint.Types.SMTPrint: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Types.Names.Symbol
+ Language.Fixpoint.Types.SMTPrint: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Types.Refinements.Expr
+ Language.Fixpoint.Types.SMTPrint: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Types.Refinements.KVar
+ Language.Fixpoint.Types.SMTPrint: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Types.Refinements.Subst
+ Language.Fixpoint.Types.SMTPrint: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Types.Sorts.DataCtor
+ Language.Fixpoint.Types.SMTPrint: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Types.Sorts.DataDecl
+ Language.Fixpoint.Types.SMTPrint: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Types.Sorts.DataField
+ Language.Fixpoint.Types.SMTPrint: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Types.Sorts.FTycon
+ Language.Fixpoint.Types.SMTPrint: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT Language.Fixpoint.Types.Sorts.Sort
+ Language.Fixpoint.Types.SMTPrint: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT a => Language.Fixpoint.Types.SMTPrint.ToHornSMT (Language.Fixpoint.Types.Names.Symbol, a)
+ Language.Fixpoint.Types.SMTPrint: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT a => Language.Fixpoint.Types.SMTPrint.ToHornSMT (Language.Fixpoint.Types.Spans.Located a)
+ Language.Fixpoint.Types.SMTPrint: instance Language.Fixpoint.Types.SMTPrint.ToHornSMT a => Language.Fixpoint.Types.SMTPrint.ToHornSMT [a]
+ Language.Fixpoint.Types.SMTPrint: toHornAbsApp :: Sort -> Doc
+ Language.Fixpoint.Types.SMTPrint: toHornAnd :: (a -> Doc) -> [a] -> Doc
+ Language.Fixpoint.Types.SMTPrint: toHornExpr :: Expr -> Doc
+ Language.Fixpoint.Types.SMTPrint: toHornFApp :: [Sort] -> Doc
+ Language.Fixpoint.Types.SMTPrint: toHornMany :: [Doc] -> Doc
+ Language.Fixpoint.Types.SMTPrint: toHornOp :: ToHornSMT a => Doc -> [a] -> Doc
+ Language.Fixpoint.Types.SMTPrint: toHornSMT :: ToHornSMT a => a -> Doc
+ Language.Fixpoint.Types.SMTPrint: toHornSort :: Sort -> Doc
+ Language.Fixpoint.Types.SMTPrint: toHornWithBinders :: (ToHornSMT a, ToHornSMT t) => Doc -> [(Symbol, t)] -> a -> Doc
+ Language.Fixpoint.Types.Solutions: QB :: [EQual] -> QBind
+ Language.Fixpoint.Types.Solutions: Sol :: !HashMap KVar a -> !HashMap KVar Hyp -> !HashMap KVar IBindEnv -> Sol a
+ Language.Fixpoint.Types.Solutions: [sHyp] :: Sol a -> !HashMap KVar Hyp
+ Language.Fixpoint.Types.Solutions: [sMap] :: Sol a -> !HashMap KVar a
+ Language.Fixpoint.Types.Solutions: [sScp] :: Sol a -> !HashMap KVar IBindEnv
+ Language.Fixpoint.Types.Solutions: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Language.Fixpoint.Types.Solutions.Sol a)
+ Language.Fixpoint.Types.Solutions: instance GHC.Base.Functor Language.Fixpoint.Types.Solutions.Sol
+ Language.Fixpoint.Types.Solutions: instance GHC.Base.Monoid (Language.Fixpoint.Types.Solutions.Sol a)
+ Language.Fixpoint.Types.Solutions: instance GHC.Base.Semigroup (Language.Fixpoint.Types.Solutions.Sol a)
+ Language.Fixpoint.Types.Solutions: instance GHC.Generics.Generic (Language.Fixpoint.Types.Solutions.Sol a)
+ Language.Fixpoint.Types.Solutions: instance Language.Fixpoint.Types.PrettyPrint.PPrint a => Language.Fixpoint.Types.PrettyPrint.PPrint (Language.Fixpoint.Types.Solutions.Sol a)
+ Language.Fixpoint.Types.Solutions: newtype QBind
+ Language.Fixpoint.Types.Sorts: FNatNum :: !Integer -> Sort
+ Language.Fixpoint.Types.Sorts: ffldFTyCon :: FTycon
+ Language.Fixpoint.Types.Sorts: finfieldSort :: Sort -> Sort
+ Language.Fixpoint.Types.Sorts: isFinfield :: Sort -> Bool
+ Language.Fixpoint.Types.Substitutions: extendSubst :: Subst -> Symbol -> Expr -> Subst
+ Language.Fixpoint.Types.Substitutions: rapierSubstExpr :: HashSet Symbol -> Subst -> Expr -> Expr
+ Language.Fixpoint.Types.Substitutions: substSymbolsSet :: Subst -> HashSet Symbol
+ Language.Fixpoint.Types.Theories: SFFld :: !Integer -> SmtSort
+ Language.Fixpoint.Types.Theories: [seApplsCur] :: SymEnv -> !HashMap FuncSort Int
+ Language.Fixpoint.Types.Theories: [seIx] :: SymEnv -> !Int
+ Language.Fixpoint.Types.Theories: coerceSort :: ElabFlags -> Sort -> Sort
+ Language.Fixpoint.Types.Theories: mergeTopAppls :: HashMap FuncSort Int -> Appls -> Appls
+ Language.Fixpoint.Types.Theories: peekAppls :: Appls -> Maybe (HashMap FuncSort Int)
+ Language.Fixpoint.Types.Theories: popAppls :: Appls -> Appls
+ Language.Fixpoint.Types.Theories: pushAppls :: Appls -> Appls
+ Language.Fixpoint.Types.Theories: symbolAtSortIndex :: Symbol -> Int -> Text
+ Language.Fixpoint.Types.Theories: type FuncSort = (SmtSort, SmtSort)
+ Language.Fixpoint.Types.Theories: type SymM a = State SymEnv a
+ Language.Fixpoint.Utils.Builder: quotes :: Builder -> Builder
+ Language.Fixpoint.Utils.Files: tempFileName :: FilePath -> FilePath
+ Language.Fixpoint.Utils.Progress: withProgressM :: (m a -> IO b) -> Int -> m a -> IO b
- Language.Fixpoint.Graph.Deps: decompose :: TaggedC c a => GInfo c a -> KVComps
+ Language.Fixpoint.Graph.Deps: decompose :: forall (c :: Type -> Type) a. TaggedC c a => GInfo c a -> KVComps
- Language.Fixpoint.Graph.Deps: elimDeps :: TaggedC c a => GInfo c a -> [CEdge] -> HashSet KVar -> HashSet Symbol -> CDeps
+ Language.Fixpoint.Graph.Deps: elimDeps :: forall (c :: Type -> Type) a. TaggedC c a => GInfo c a -> [CEdge] -> HashSet KVar -> CDeps
- Language.Fixpoint.Graph.Deps: elimVars :: TaggedC c a => Config -> GInfo c a -> ([CEdge], Elims KVar)
+ Language.Fixpoint.Graph.Deps: elimVars :: forall (c :: Type -> Type) a. TaggedC c a => Config -> GInfo c a -> ([CEdge], Elims KVar)
- Language.Fixpoint.Graph.Deps: graphStatistics :: TaggedC c a => Config -> GInfo c a -> IO ()
+ Language.Fixpoint.Graph.Deps: graphStatistics :: forall (c :: Type -> Type) a. TaggedC c a => Config -> GInfo c a -> IO ()
- Language.Fixpoint.Graph.Deps: kvEdges :: TaggedC c a => GInfo c a -> [CEdge]
+ Language.Fixpoint.Graph.Deps: kvEdges :: forall (c :: Type -> Type) a. TaggedC c a => GInfo c a -> [CEdge]
- Language.Fixpoint.Graph.Deps: slice :: TaggedC c a => Config -> GInfo c a -> GInfo c a
+ Language.Fixpoint.Graph.Deps: slice :: forall (c :: Type -> Type) a. TaggedC c a => Config -> GInfo c a -> GInfo c a
- Language.Fixpoint.Graph.Partition: CPart :: !HashMap KVar (WfC a) -> !HashMap Integer (c a) -> CPart c a
+ Language.Fixpoint.Graph.Partition: CPart :: !HashMap KVar (WfC a) -> !HashMap Integer (c a) -> CPart (c :: Type -> Type) a
- Language.Fixpoint.Graph.Partition: [pcm] :: CPart c a -> !HashMap Integer (c a)
+ Language.Fixpoint.Graph.Partition: [pcm] :: CPart (c :: Type -> Type) a -> !HashMap Integer (c a)
- Language.Fixpoint.Graph.Partition: [pws] :: CPart c a -> !HashMap KVar (WfC a)
+ Language.Fixpoint.Graph.Partition: [pws] :: CPart (c :: Type -> Type) a -> !HashMap KVar (WfC a)
- Language.Fixpoint.Graph.Partition: data CPart c a
+ Language.Fixpoint.Graph.Partition: data CPart (c :: Type -> Type) a
- Language.Fixpoint.Graph.Partition: dumpPartitions :: (Fixpoint (c a), Fixpoint a) => Config -> [GInfo c a] -> IO ()
+ Language.Fixpoint.Graph.Partition: dumpPartitions :: forall (c :: Type -> Type) a. (Fixpoint (c a), Fixpoint a) => Config -> [GInfo c a] -> IO ()
- Language.Fixpoint.Graph.Partition: partition :: (Fixpoint a, Fixpoint (c a), TaggedC c a) => Config -> GInfo c a -> IO (Result (Integer, a))
+ Language.Fixpoint.Graph.Partition: partition :: forall a (c :: Type -> Type). (Fixpoint a, Fixpoint (c a), TaggedC c a) => Config -> GInfo c a -> IO (Result (Integer, a))
- Language.Fixpoint.Graph.Partition: partition' :: TaggedC c a => Maybe MCInfo -> GInfo c a -> [GInfo c a]
+ Language.Fixpoint.Graph.Partition: partition' :: forall (c :: Type -> Type) a. TaggedC c a => Maybe MCInfo -> GInfo c a -> [GInfo c a]
- Language.Fixpoint.Graph.Partition: partitionN :: MCInfo -> GInfo c a -> [CPart c a] -> [GInfo c a]
+ Language.Fixpoint.Graph.Partition: partitionN :: forall (c :: Type -> Type) a. MCInfo -> GInfo c a -> [CPart c a] -> [GInfo c a]
- Language.Fixpoint.Graph.Reducible: isReducible :: TaggedC c a => GInfo c a -> Bool
+ Language.Fixpoint.Graph.Reducible: isReducible :: forall (c :: Type -> Type) a. TaggedC c a => GInfo c a -> Bool
- Language.Fixpoint.Graph.Types: SI :: !Sol b QBind -> !SInfo a -> !CDeps -> !HashSet KVar -> SolverInfo a b
+ Language.Fixpoint.Graph.Types: SI :: !Sol QBind -> !SInfo a -> !CDeps -> !HashSet KVar -> SolverInfo a
- Language.Fixpoint.Graph.Types: [siDeps] :: SolverInfo a b -> !CDeps
+ Language.Fixpoint.Graph.Types: [siDeps] :: SolverInfo a -> !CDeps
- Language.Fixpoint.Graph.Types: [siQuery] :: SolverInfo a b -> !SInfo a
+ Language.Fixpoint.Graph.Types: [siQuery] :: SolverInfo a -> !SInfo a
- Language.Fixpoint.Graph.Types: [siSol] :: SolverInfo a b -> !Sol b QBind
+ Language.Fixpoint.Graph.Types: [siSol] :: SolverInfo a -> !Sol QBind
- Language.Fixpoint.Graph.Types: [siVars] :: SolverInfo a b -> !HashSet KVar
+ Language.Fixpoint.Graph.Types: [siVars] :: SolverInfo a -> !HashSet KVar
- Language.Fixpoint.Graph.Types: data SolverInfo a b
+ Language.Fixpoint.Graph.Types: data SolverInfo a
- Language.Fixpoint.Horn.Types: Var :: !Symbol -> ![Symbol] -> Pred
+ Language.Fixpoint.Horn.Types: Var :: !Symbol -> ![Expr] -> Pred
- Language.Fixpoint.Parse: PState :: OpTable v -> [Fixity v] -> Maybe (Located () -> ExprV v) -> Maybe (Located () -> ExprV v -> ExprV v) -> !Integer -> LayoutStack -> !HashSet Symbol -> PStateV v
+ Language.Fixpoint.Parse: PState :: OpTable v -> [Fixity v] -> Maybe (Located () -> ExprV v) -> Maybe (Located () -> ExprV v -> ExprV v) -> !Integer -> LayoutStack -> !HashSet Symbol -> !Bool -> PStateV v
- Language.Fixpoint.Parse: type ParserV v = StateT (PStateV v) (Parsec Void String)
+ Language.Fixpoint.Parse: type ParserV v = StateT PStateV v Parsec Void String
- Language.Fixpoint.Smt.Interface: Ctx :: Solver -> ElabFlags -> IO () -> !Maybe Handle -> !Bool -> !SymEnv -> ![Equation] -> Context
+ Language.Fixpoint.Smt.Interface: Ctx :: Solver -> ElabFlags -> IO () -> !Maybe Handle -> !Bool -> !SymEnv -> ![Int] -> DefinedFuns -> !Bool -> !Config -> Context
- Language.Fixpoint.Smt.Interface: [ctxDefines] :: Context -> ![Equation]
+ Language.Fixpoint.Smt.Interface: [ctxDefines] :: Context -> DefinedFuns
- Language.Fixpoint.Smt.Interface: checkValid :: Config -> FilePath -> [(Symbol, Sort)] -> Expr -> Expr -> IO Bool
+ Language.Fixpoint.Smt.Interface: checkValid :: HasCallStack => Config -> FilePath -> [(Symbol, Sort)] -> Expr -> Expr -> IO Bool
- Language.Fixpoint.Smt.Interface: checkValid' :: Context -> [(Symbol, Sort)] -> Expr -> Expr -> IO Bool
+ Language.Fixpoint.Smt.Interface: checkValid' :: HasCallStack => [(Symbol, Sort)] -> Expr -> Expr -> SmtM Bool
- Language.Fixpoint.Smt.Interface: checkValidWithContext :: Context -> [(Symbol, Sort)] -> Expr -> Expr -> IO Bool
+ Language.Fixpoint.Smt.Interface: checkValidWithContext :: HasCallStack => [(Symbol, Sort)] -> Expr -> Expr -> SmtM Bool
- Language.Fixpoint.Smt.Interface: command :: Context -> Command -> IO Response
+ Language.Fixpoint.Smt.Interface: command :: HasCallStack => Command -> SmtM Response
- Language.Fixpoint.Smt.Interface: makeContextWithSEnv :: Config -> FilePath -> SymEnv -> [Equation] -> IO Context
+ Language.Fixpoint.Smt.Interface: makeContextWithSEnv :: Config -> FilePath -> SymEnv -> DefinedFuns -> IO Context
- Language.Fixpoint.Smt.Interface: smt2 :: SMTLIB2 a => SymEnv -> a -> Builder
+ Language.Fixpoint.Smt.Interface: smt2 :: SMTLIB2 a => a -> SymM Builder
- Language.Fixpoint.Smt.Interface: smtAssert :: Context -> Expr -> IO ()
+ Language.Fixpoint.Smt.Interface: smtAssert :: Expr -> SmtM ()
- Language.Fixpoint.Smt.Interface: smtAssertAxiom :: Context -> Triggered Expr -> IO ()
+ Language.Fixpoint.Smt.Interface: smtAssertAxiom :: Triggered Expr -> SmtM ()
- Language.Fixpoint.Smt.Interface: smtBracket :: Context -> String -> IO a -> IO a
+ Language.Fixpoint.Smt.Interface: smtBracket :: String -> SmtM a -> SmtM a
- Language.Fixpoint.Smt.Interface: smtBracketAt :: SrcSpan -> Context -> String -> IO a -> IO a
+ Language.Fixpoint.Smt.Interface: smtBracketAt :: SrcSpan -> String -> SmtM a -> SmtM a
- Language.Fixpoint.Smt.Interface: smtCheckUnsat :: Context -> IO Bool
+ Language.Fixpoint.Smt.Interface: smtCheckUnsat :: HasCallStack => SmtM Bool
- Language.Fixpoint.Smt.Interface: smtDecl :: Context -> Symbol -> Sort -> IO ()
+ Language.Fixpoint.Smt.Interface: smtDecl :: Symbol -> Sort -> SmtM ()
- Language.Fixpoint.Smt.Interface: smtDecls :: Context -> [(Symbol, Sort)] -> IO ()
+ Language.Fixpoint.Smt.Interface: smtDecls :: [(Symbol, Sort)] -> SmtM ()
- Language.Fixpoint.Smt.Interface: smtDefineFunc :: Context -> Symbol -> [(Symbol, Sort)] -> Sort -> Expr -> IO ()
+ Language.Fixpoint.Smt.Interface: smtDefineFunc :: Symbol -> [(Symbol, Sort)] -> Sort -> Expr -> SmtM ()
- Language.Fixpoint.Smt.Interface: smtDistinct :: Context -> [Expr] -> IO ()
+ Language.Fixpoint.Smt.Interface: smtDistinct :: [Expr] -> SmtM ()
- Language.Fixpoint.Smt.Interface: smtFuncDecl :: Context -> Text -> ([SmtSort], SmtSort) -> IO ()
+ Language.Fixpoint.Smt.Interface: smtFuncDecl :: Text -> ([SmtSort], SmtSort) -> SmtM ()
- Language.Fixpoint.Smt.Interface: smtPop :: Context -> IO ()
+ Language.Fixpoint.Smt.Interface: smtPop :: SmtM ()
- Language.Fixpoint.Smt.Interface: smtPush :: Context -> IO ()
+ Language.Fixpoint.Smt.Interface: smtPush :: SmtM ()
- Language.Fixpoint.Smt.Interface: smtSetMbqi :: Context -> IO ()
+ Language.Fixpoint.Smt.Interface: smtSetMbqi :: SmtM ()
- Language.Fixpoint.Smt.Serialize: smt2SortMono :: PPrint a => a -> SymEnv -> Sort -> Builder
+ Language.Fixpoint.Smt.Serialize: smt2SortMono :: PPrint a => a -> Sort -> SymM Builder
- Language.Fixpoint.Smt.Theories: axiomLiterals :: [(Symbol, Sort)] -> [Expr]
+ Language.Fixpoint.Smt.Theories: axiomLiterals :: Config -> [(Symbol, Sort)] -> [Expr]
- Language.Fixpoint.Smt.Theories: smt2App :: VarAs -> SymEnv -> Expr -> [Builder] -> Maybe Builder
+ Language.Fixpoint.Smt.Theories: smt2App :: VarAs -> Expr -> [Builder] -> SymM (Maybe Builder)
- Language.Fixpoint.Smt.Types: Ctx :: Solver -> ElabFlags -> IO () -> !Maybe Handle -> !Bool -> !SymEnv -> ![Equation] -> Context
+ Language.Fixpoint.Smt.Types: Ctx :: Solver -> ElabFlags -> IO () -> !Maybe Handle -> !Bool -> !SymEnv -> ![Int] -> DefinedFuns -> !Bool -> !Config -> Context
- Language.Fixpoint.Smt.Types: [ctxDefines] :: Context -> ![Equation]
+ Language.Fixpoint.Smt.Types: [ctxDefines] :: Context -> DefinedFuns
- Language.Fixpoint.Smt.Types: runSmt2 :: SMTLIB2 a => SymEnv -> a -> Builder
+ Language.Fixpoint.Smt.Types: runSmt2 :: SMTLIB2 a => a -> SymM Builder
- Language.Fixpoint.Smt.Types: smt2 :: SMTLIB2 a => SymEnv -> a -> Builder
+ Language.Fixpoint.Smt.Types: smt2 :: SMTLIB2 a => a -> SymM Builder
- Language.Fixpoint.Solver: simplifyFInfo :: (NFData a, Fixpoint a, Show a, Loc a) => Config -> FInfo a -> IO (SInfo a)
+ Language.Fixpoint.Solver: simplifyFInfo :: (NFData a, Fixpoint a, Show a, Loc a) => Config -> FInfo a -> IO (ElabParam, SInfo a)
- Language.Fixpoint.Solver: solve :: (PPrint a, NFData a, Fixpoint a, Show a, Loc a) => Solver a
+ Language.Fixpoint.Solver: solve :: (PPrint a, NFData a, Fixpoint a, Show a, Loc a) => Config -> FInfo a -> IO (Result (Integer, a))
- Language.Fixpoint.Solver.Common: askSMT :: Config -> Context -> [(Symbol, Sort)] -> Expr -> IO Bool
+ Language.Fixpoint.Solver.Common: askSMT :: HasCallStack => Config -> [(Symbol, Sort)] -> [(Symbol, Sort)] -> Expr -> SmtM Bool
- Language.Fixpoint.Solver.Common: toSMT :: String -> Config -> Context -> [(Symbol, Sort)] -> Expr -> Pred
+ Language.Fixpoint.Solver.Common: toSMT :: HasCallStack => String -> Config -> Context -> [(Symbol, Sort)] -> Expr -> Pred
- Language.Fixpoint.Solver.Eliminate: solverInfo :: Config -> SInfo a -> SolverInfo a b
+ Language.Fixpoint.Solver.Eliminate: solverInfo :: Config -> SInfo a -> SolverInfo a
- Language.Fixpoint.Solver.Interpreter: instInterpreter :: Loc a => Config -> SInfo a -> Maybe [SubcId] -> IO (SInfo a)
+ Language.Fixpoint.Solver.Interpreter: instInterpreter :: Loc a => Config -> SInfo a -> Maybe [SubcId] -> IO (BindEnv a)
- Language.Fixpoint.Solver.Monad: SS :: !Context -> !BindEnv ann -> !Stats -> SolverState ann
+ Language.Fixpoint.Solver.Monad: SS :: !Context -> !Stats -> !ElabParam -> SolverState ann
- Language.Fixpoint.Solver.Monad: runSolverM :: Config -> SolverInfo ann c -> SolveM ann a -> IO a
+ Language.Fixpoint.Solver.Monad: runSolverM :: Config -> SolverInfo ann -> ElabParam -> SolveM ann a -> IO a
- Language.Fixpoint.Solver.Monad: sendConcreteBindingsToSMT :: IBindEnv -> (IBindEnv -> SolveM ann a) -> SolveM ann a
+ Language.Fixpoint.Solver.Monad: sendConcreteBindingsToSMT :: IBindEnv -> BindEnv ann -> (IBindEnv -> SolveM ann a) -> SolveM ann a
- Language.Fixpoint.Solver.Monad: type SolveM ann = StateT (SolverState ann) IO
+ Language.Fixpoint.Solver.Monad: type SolveM ann = StateT SolverState ann IO
- Language.Fixpoint.Solver.PLE: ICtx :: HashSet Pred -> HashSet Expr -> EvEqualities -> !ConstMap -> Maybe SubcId -> [[(Symbol, SortedReft)]] -> LocalRewrites -> Bool -> Bool -> Bool -> ICtx
+ Language.Fixpoint.Solver.PLE: ICtx :: HashSet Pred -> HashMap ExScope (HashSet Expr) -> HashMap ExScope EvEqualities -> !ConstMap -> Maybe SubcId -> [[(Symbol, SortedReft)]] -> LocalRewrites -> IBindEnv -> Bool -> Bool -> Bool -> Int -> HashMap ExScope (HashSet Expr) -> ICtx
- Language.Fixpoint.Solver.PLE: KN :: Map Symbol [(Rewrite, IsUserDataSMeasure)] -> Map Symbol Equation -> Context -> (Context -> [(Symbol, Sort)] -> Expr -> IO Bool) -> ![(Symbol, Sort)] -> ![(Symbol, Int)] -> !HashSet Symbol -> !HashMap Symbol DataCtor -> !SelectorMap -> !ConstDCMap -> HashMap SubcId [AutoRewrite] -> RWTerminationOpts -> Knowledge
+ Language.Fixpoint.Solver.PLE: KN :: Map Symbol [(Rewrite, IsUserDataSMeasure)] -> Map Symbol Equation -> ([(Symbol, Sort)] -> [(Symbol, Sort)] -> Expr -> SmtM Bool) -> ![(Symbol, Sort)] -> ![(Symbol, Int)] -> !HashSet Symbol -> !HashMap Symbol DataCtor -> !SelectorMap -> !ConstDCMap -> HashMap SubcId [AutoRewrite] -> RWTerminationOpts -> Knowledge
- Language.Fixpoint.Solver.PLE: [icCands] :: ICtx -> HashSet Expr
+ Language.Fixpoint.Solver.PLE: [icCands] :: ICtx -> HashMap ExScope (HashSet Expr)
- Language.Fixpoint.Solver.PLE: [icEquals] :: ICtx -> EvEqualities
+ Language.Fixpoint.Solver.PLE: [icEquals] :: ICtx -> HashMap ExScope EvEqualities
- Language.Fixpoint.Solver.PLE: [knPreds] :: Knowledge -> Context -> [(Symbol, Sort)] -> Expr -> IO Bool
+ Language.Fixpoint.Solver.PLE: [knPreds] :: Knowledge -> [(Symbol, Sort)] -> [(Symbol, Sort)] -> Expr -> SmtM Bool
- Language.Fixpoint.Solver.PLE: instantiate :: Loc a => Config -> SInfo a -> Maybe [SubcId] -> IO (SInfo a)
+ Language.Fixpoint.Solver.PLE: instantiate :: Loc a => Config -> SInfo a -> Maybe Solution -> Maybe [SubcId] -> SmtM (BindEnv a)
- Language.Fixpoint.Solver.Rewrite: RWArgs :: (Expr -> IO Bool) -> RWTerminationOpts -> RewriteArgs
+ Language.Fixpoint.Solver.Rewrite: RWArgs :: (Expr -> SmtM Bool) -> RWTerminationOpts -> RewriteArgs
- Language.Fixpoint.Solver.Rewrite: [isRWValid] :: RewriteArgs -> Expr -> IO Bool
+ Language.Fixpoint.Solver.Rewrite: [isRWValid] :: RewriteArgs -> Expr -> SmtM Bool
- Language.Fixpoint.Solver.Rewrite: getRewrite :: OCAlgebra oc Expr IO -> RewriteArgs -> oc -> SubExpr -> AutoRewrite -> MaybeT IO ((Expr, Expr), Expr, oc)
+ Language.Fixpoint.Solver.Rewrite: getRewrite :: OCAlgebra oc Expr IO -> RewriteArgs -> oc -> SubExpr -> AutoRewrite -> MaybeT SmtM ((Expr, Expr), Expr, oc)
- Language.Fixpoint.Solver.Sanitize: symbolEnv :: Config -> SInfo a -> SymEnv
+ Language.Fixpoint.Solver.Sanitize: symbolEnv :: HasCallStack => Config -> SInfo a -> SymEnv
- Language.Fixpoint.Solver.Solution: init :: Fixpoint a => Config -> SInfo a -> HashSet KVar -> Solution
+ Language.Fixpoint.Solver.Solution: init :: Fixpoint a => Config -> SInfo a -> HashSet KVar -> HashMap KVar QBind
- Language.Fixpoint.Solver.Solution: lhsPred :: Loc a => IBindEnv -> BindEnv a -> Solution -> SimpC a -> ElabM Expr
+ Language.Fixpoint.Solver.Solution: lhsPred :: Loc a => Config -> IBindEnv -> BindEnv a -> Solution -> SimpC a -> Expr
- Language.Fixpoint.Solver.Solution: nonCutsResult :: BindEnv ann -> Sol a QBind -> ElabM (HashMap KVar Expr)
+ Language.Fixpoint.Solver.Solution: nonCutsResult :: Config -> BindEnv ann -> Sol QBind -> FixDelayedSolution
- Language.Fixpoint.Solver.Solution: update :: Sol a QBind -> [KVar] -> [(KVar, EQual)] -> (Bool, Sol a QBind)
+ Language.Fixpoint.Solver.Solution: update :: Sol QBind -> [(KVar, QBind)] -> (Bool, Sol QBind)
- Language.Fixpoint.Solver.Solve: solve :: (NFData a, Fixpoint a, Show a, Loc a) => Config -> SInfo a -> IO (Result (Integer, a))
+ Language.Fixpoint.Solver.Solve: solve :: (NFData a, Fixpoint a, Show a, Loc a) => Config -> ElabParam -> SInfo a -> IO (Result (Integer, a))
- Language.Fixpoint.Solver.Worklist: init :: SolverInfo a b -> Worklist a
+ Language.Fixpoint.Solver.Worklist: init :: SolverInfo a -> Worklist a
- Language.Fixpoint.SortCheck: elabExpr :: ElabParam -> Maybe Sort -> Expr -> Expr
+ Language.Fixpoint.SortCheck: elabExpr :: HasCallStack => ElabParam -> Maybe Sort -> Expr -> Expr
- Language.Fixpoint.Types.Config: Config :: FilePath -> Maybe Int -> Int -> Int -> SMTSolver -> Bool -> Bool -> Bool -> Bool -> Bool -> Eliminate -> Scrape -> Maybe Int -> Maybe Int -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> [Integer] -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe Int -> String -> Bool -> Config
+ Language.Fixpoint.Types.Config: Config :: FilePath -> Maybe Int -> Int -> Int -> SMTSolver -> Bool -> Bool -> Bool -> Bool -> Eliminate -> Scrape -> Maybe Int -> Maybe Int -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> [Integer] -> Bool -> Bool -> Bool -> Bool -> Maybe Int -> String -> Bool -> Bool -> Bool -> Config
- Language.Fixpoint.Types.Config: ElabFlags :: Bool -> ElabFlags
+ Language.Fixpoint.Types.Config: ElabFlags :: Bool -> Bool -> ElabFlags
- Language.Fixpoint.Types.Config: solverFlags :: SMTSolver -> ElabFlags
+ Language.Fixpoint.Types.Config: solverFlags :: Config -> ElabFlags
- 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
+ Language.Fixpoint.Types.Constraints: FI :: !HashMap SubcId (c a) -> !HashMap KVar (WfC a) -> !BindEnv a -> !SEnv Sort -> !SEnv Sort -> !Kuts -> ![Qualifier] -> !HashMap BindId a -> ![DataDecl] -> !HOInfo -> ![Triggered Expr] -> AxiomEnv -> LocalRewritesEnv -> DefinedFuns -> GInfo (c :: Type -> Type) a
- Language.Fixpoint.Types.Constraints: Result :: !FixResult a -> !FixSolution -> !FixSolution -> !GFixSolution -> Result a
+ Language.Fixpoint.Types.Constraints: Result :: !FixResult a -> !FixSolution -> !FixDelayedSolution -> !ResultSorts -> Result a
- Language.Fixpoint.Types.Constraints: [ae] :: GInfo c a -> AxiomEnv
+ Language.Fixpoint.Types.Constraints: [ae] :: GInfo (c :: Type -> Type) a -> AxiomEnv
- Language.Fixpoint.Types.Constraints: [asserts] :: GInfo c a -> ![Triggered Expr]
+ Language.Fixpoint.Types.Constraints: [asserts] :: GInfo (c :: Type -> Type) a -> ![Triggered Expr]
- Language.Fixpoint.Types.Constraints: [bindInfo] :: GInfo c a -> !HashMap BindId a
+ Language.Fixpoint.Types.Constraints: [bindInfo] :: GInfo (c :: Type -> Type) a -> !HashMap BindId a
- Language.Fixpoint.Types.Constraints: [bs] :: GInfo c a -> !BindEnv a
+ Language.Fixpoint.Types.Constraints: [bs] :: GInfo (c :: Type -> Type) a -> !BindEnv a
- Language.Fixpoint.Types.Constraints: [cm] :: GInfo c a -> !HashMap SubcId (c a)
+ Language.Fixpoint.Types.Constraints: [cm] :: GInfo (c :: Type -> Type) a -> !HashMap SubcId (c a)
- Language.Fixpoint.Types.Constraints: [dLits] :: GInfo c a -> !SEnv Sort
+ Language.Fixpoint.Types.Constraints: [dLits] :: GInfo (c :: Type -> Type) a -> !SEnv Sort
- Language.Fixpoint.Types.Constraints: [ddecls] :: GInfo c a -> ![DataDecl]
+ Language.Fixpoint.Types.Constraints: [ddecls] :: GInfo (c :: Type -> Type) a -> ![DataDecl]
- Language.Fixpoint.Types.Constraints: [defns] :: GInfo c a -> ![Equation]
+ Language.Fixpoint.Types.Constraints: [defns] :: GInfo (c :: Type -> Type) a -> DefinedFuns
- Language.Fixpoint.Types.Constraints: [gLits] :: GInfo c a -> !SEnv Sort
+ Language.Fixpoint.Types.Constraints: [gLits] :: GInfo (c :: Type -> Type) a -> !SEnv Sort
- Language.Fixpoint.Types.Constraints: [hoInfo] :: GInfo c a -> !HOInfo
+ Language.Fixpoint.Types.Constraints: [hoInfo] :: GInfo (c :: Type -> Type) a -> !HOInfo
- Language.Fixpoint.Types.Constraints: [kuts] :: GInfo c a -> !Kuts
+ Language.Fixpoint.Types.Constraints: [kuts] :: GInfo (c :: Type -> Type) a -> !Kuts
- Language.Fixpoint.Types.Constraints: [lrws] :: GInfo c a -> LocalRewritesEnv
+ Language.Fixpoint.Types.Constraints: [lrws] :: GInfo (c :: Type -> Type) a -> LocalRewritesEnv
- Language.Fixpoint.Types.Constraints: [quals] :: GInfo c a -> ![Qualifier]
+ Language.Fixpoint.Types.Constraints: [quals] :: GInfo (c :: Type -> Type) a -> ![Qualifier]
- Language.Fixpoint.Types.Constraints: [resNonCutsSolution] :: Result a -> !FixSolution
+ Language.Fixpoint.Types.Constraints: [resNonCutsSolution] :: Result a -> !FixDelayedSolution
- Language.Fixpoint.Types.Constraints: [wrft] :: WfC a -> !(Symbol, Sort, KVar)
+ Language.Fixpoint.Types.Constraints: [wrft] :: WfC a -> (Symbol, Sort, KVar)
- Language.Fixpoint.Types.Constraints: [ws] :: GInfo c a -> !HashMap KVar (WfC a)
+ Language.Fixpoint.Types.Constraints: [ws] :: GInfo (c :: Type -> Type) a -> !HashMap KVar (WfC a)
- Language.Fixpoint.Types.Constraints: allowHO :: GInfo c a -> Bool
+ Language.Fixpoint.Types.Constraints: allowHO :: forall (c :: Type -> Type) a. GInfo c a -> Bool
- Language.Fixpoint.Types.Constraints: allowHOquals :: GInfo c a -> Bool
+ Language.Fixpoint.Types.Constraints: allowHOquals :: forall (c :: Type -> Type) a. GInfo c a -> Bool
- Language.Fixpoint.Types.Constraints: class TaggedC c a
+ Language.Fixpoint.Types.Constraints: class TaggedC (c :: Type -> Type) a
- Language.Fixpoint.Types.Constraints: data GInfo c a
+ Language.Fixpoint.Types.Constraints: data GInfo (c :: Type -> Type) a
- Language.Fixpoint.Types.Constraints: fi :: [SubC a] -> [WfC a] -> BindEnv a -> SEnv Sort -> SEnv Sort -> Kuts -> [Qualifier] -> HashMap BindId a -> Bool -> Bool -> [Triggered Expr] -> AxiomEnv -> [DataDecl] -> [BindId] -> GInfo SubC a
+ Language.Fixpoint.Types.Constraints: fi :: [SubC a] -> [WfC a] -> BindEnv a -> SEnv Sort -> SEnv Sort -> Kuts -> [Qualifier] -> HashMap BindId a -> Bool -> Bool -> [Triggered Expr] -> AxiomEnv -> [DataDecl] -> GInfo SubC a
- Language.Fixpoint.Types.Constraints: strengthenBinds :: SInfo a -> HashMap BindId Expr -> SInfo a
+ Language.Fixpoint.Types.Constraints: strengthenBinds :: SInfo a -> HashMap BindId Expr -> BindEnv a
- Language.Fixpoint.Types.Constraints: strengthenHyp :: SInfo a -> [(Integer, Expr)] -> SInfo a
+ Language.Fixpoint.Types.Constraints: strengthenHyp :: SInfo a -> [(Integer, Expr)] -> BindEnv a
- Language.Fixpoint.Types.Constraints: toFixpoint :: (Fixpoint a, Fixpoint (c a)) => Config -> GInfo c a -> Doc
+ Language.Fixpoint.Types.Constraints: toFixpoint :: forall a (c :: Type -> Type). (Fixpoint a, Fixpoint (c a)) => Config -> GInfo c a -> Doc
- Language.Fixpoint.Types.Constraints: writeFInfo :: (Fixpoint a, Fixpoint (c a)) => Config -> GInfo c a -> FilePath -> IO ()
+ Language.Fixpoint.Types.Constraints: writeFInfo :: forall a (c :: Type -> Type). (Fixpoint a, Fixpoint (c a)) => Config -> GInfo c a -> FilePath -> IO ()
- Language.Fixpoint.Types.Errors: die :: Error -> a
+ Language.Fixpoint.Types.Errors: die :: HasCallStack => Error -> a
- Language.Fixpoint.Types.Errors: panic :: String -> a
+ Language.Fixpoint.Types.Errors: panic :: HasCallStack => String -> a
- Language.Fixpoint.Types.Solutions: data Sol b a
+ Language.Fixpoint.Types.Solutions: data Sol a
- Language.Fixpoint.Types.Solutions: lookup :: Sol a QBind -> KVar -> Either Hyp QBind
+ Language.Fixpoint.Types.Solutions: lookup :: Sol QBind -> KVar -> Either Hyp QBind
- Language.Fixpoint.Types.Solutions: lookupQBind :: Sol a QBind -> KVar -> QBind
+ Language.Fixpoint.Types.Solutions: lookupQBind :: Sol QBind -> KVar -> QBind
- Language.Fixpoint.Types.Solutions: qbPreds :: String -> Sol a QBind -> Subst -> QBind -> ElabM [(Pred, EQual)]
+ Language.Fixpoint.Types.Solutions: qbPreds :: Subst -> QBind -> [(Pred, EQual)]
- Language.Fixpoint.Types.Solutions: result :: Sol a QBind -> HashMap KVar Expr
+ Language.Fixpoint.Types.Solutions: result :: Sol QBind -> HashMap KVar Expr
- Language.Fixpoint.Types.Solutions: type Solution = Sol () QBind
+ Language.Fixpoint.Types.Solutions: type Solution = Sol QBind
- Language.Fixpoint.Types.Solutions: update :: Sol a QBind -> [KVar] -> [(KVar, EQual)] -> (Bool, Sol a QBind)
+ Language.Fixpoint.Types.Solutions: update :: Sol QBind -> [(KVar, QBind)] -> (Bool, Sol QBind)
- Language.Fixpoint.Types.Spans: data () => Pos
+ Language.Fixpoint.Types.Spans: data Pos
- Language.Fixpoint.Types.Spans: data () => SourcePos
+ Language.Fixpoint.Types.Spans: data SourcePos
- Language.Fixpoint.Types.Theories: SymEnv :: !SEnv Sort -> !SEnv TheorySymbol -> !SEnv DataDecl -> !SEnv Sort -> !HashMap FuncSort Int -> SymEnv
+ Language.Fixpoint.Types.Theories: SymEnv :: !SEnv Sort -> !SEnv TheorySymbol -> !SEnv DataDecl -> !SEnv Sort -> !Appls -> !HashMap FuncSort Int -> !Int -> SymEnv
- Language.Fixpoint.Types.Theories: [seAppls] :: SymEnv -> !HashMap FuncSort Int
+ Language.Fixpoint.Types.Theories: [seAppls] :: SymEnv -> !Appls
- Language.Fixpoint.Types.Theories: symbolAtName :: PPrint a => Symbol -> SymEnv -> a -> Sort -> Text
+ Language.Fixpoint.Types.Theories: symbolAtName :: Symbol -> Sort -> SymM Text
- Language.Fixpoint.Types.Utils: kvarDomain :: SInfo a -> KVar -> [Symbol]
+ Language.Fixpoint.Types.Utils: kvarDomain :: forall (c :: Type -> Type) a. GInfo c a -> KVar -> [Symbol]
- Language.Fixpoint.Types.Utils: sortedReftConcKVars :: Symbol -> SortedReft -> ([Pred], [KVSub], [KVSub])
+ Language.Fixpoint.Types.Utils: sortedReftConcKVars :: Symbol -> SortedReft -> ([Pred], [KVSub])
- Text.PrettyPrint.HughesPJ.Compat: data () => Doc
+ Text.PrettyPrint.HughesPJ.Compat: data Doc
- Text.PrettyPrint.HughesPJ.Compat: data () => Mode
+ Text.PrettyPrint.HughesPJ.Compat: data Mode
- Text.PrettyPrint.HughesPJ.Compat: data () => Style
+ Text.PrettyPrint.HughesPJ.Compat: data Style
- Text.PrettyPrint.HughesPJ.Compat: data () => TextDetails
+ Text.PrettyPrint.HughesPJ.Compat: data TextDetails
Files
- CHANGES.md +29/−0
- README.md +63/−26
- bin/Fixpoint.hs +2/−2
- liquid-fixpoint.cabal +10/−7
- src/Control/Exception/Compat.hs +28/−0
- src/Language/Fixpoint/Defunctionalize.hs +3/−5
- src/Language/Fixpoint/Graph/Deps.hs +16/−27
- src/Language/Fixpoint/Graph/Types.hs +2/−4
- src/Language/Fixpoint/Horn/Info.hs +22/−37
- src/Language/Fixpoint/Horn/Parse.hs +1/−2
- src/Language/Fixpoint/Horn/SMTParse.hs +14/−3
- src/Language/Fixpoint/Horn/Solve.hs +5/−5
- src/Language/Fixpoint/Horn/Transformations.hs +16/−67
- src/Language/Fixpoint/Horn/Types.hs +38/−169
- src/Language/Fixpoint/Minimize.hs +5/−0
- src/Language/Fixpoint/Parse.hs +101/−286
- src/Language/Fixpoint/Smt/Interface.hs +197/−135
- src/Language/Fixpoint/Smt/Serialize.hs +229/−151
- src/Language/Fixpoint/Smt/Theories.hs +116/−52
- src/Language/Fixpoint/Smt/Types.hs +44/−5
- src/Language/Fixpoint/Solver.hs +79/−160
- src/Language/Fixpoint/Solver/Common.hs +19/−10
- src/Language/Fixpoint/Solver/Eliminate.hs +40/−14
- src/Language/Fixpoint/Solver/EnvironmentReduction.hs +18/−15
- src/Language/Fixpoint/Solver/Extensionality.hs +4/−3
- src/Language/Fixpoint/Solver/GradualSolution.hs +0/−135
- src/Language/Fixpoint/Solver/GradualSolve.hs +0/−328
- src/Language/Fixpoint/Solver/Instantiate.hs +0/−816
- src/Language/Fixpoint/Solver/Interpreter.hs +8/−6
- src/Language/Fixpoint/Solver/Monad.hs +43/−81
- src/Language/Fixpoint/Solver/PLE.hs +471/−238
- src/Language/Fixpoint/Solver/Rewrite.hs +15/−5
- src/Language/Fixpoint/Solver/Sanitize.hs +21/−55
- src/Language/Fixpoint/Solver/Solution.hs +303/−287
- src/Language/Fixpoint/Solver/Solve.hs +183/−171
- src/Language/Fixpoint/Solver/UniqifyKVars.hs +5/−5
- src/Language/Fixpoint/Solver/Worklist.hs +6/−4
- src/Language/Fixpoint/SortCheck.hs +251/−75
- src/Language/Fixpoint/Types.hs +1/−0
- src/Language/Fixpoint/Types/Config.hs +36/−42
- src/Language/Fixpoint/Types/Constraints.hs +142/−105
- src/Language/Fixpoint/Types/Environments.hs +1/−1
- src/Language/Fixpoint/Types/Errors.hs +3/−2
- src/Language/Fixpoint/Types/Graduals.hs +0/−259
- src/Language/Fixpoint/Types/Names.hs +54/−63
- src/Language/Fixpoint/Types/Refinements.hs +23/−88
- src/Language/Fixpoint/Types/SMTPrint.hs +130/−0
- src/Language/Fixpoint/Types/Solutions.hs +47/−194
- src/Language/Fixpoint/Types/Sorts.hs +29/−8
- src/Language/Fixpoint/Types/Substitutions.hs +150/−31
- src/Language/Fixpoint/Types/Templates.hs +2/−2
- src/Language/Fixpoint/Types/Theories.hs +123/−119
- src/Language/Fixpoint/Types/Utils.hs +10/−9
- src/Language/Fixpoint/Types/Visitor.hs +13/−24
- src/Language/Fixpoint/Utils/Builder.hs +4/−0
- src/Language/Fixpoint/Utils/Files.hs +5/−5
- tests/neg/ebind-00.fq +0/−16
- tests/neg/ebind-01.fq +0/−17
- tests/neg/ebind-02.fq +0/−28
- tests/neg/ebind-03.fq +0/−45
- tests/neg/ebind-04.fq +0/−35
- tests/neg/ebind-elim2.fq +0/−26
- tests/neg/elim-dep-00.fq +3/−3
- tests/neg/qualif-template-00.fq +1/−1
- tests/neg/qualif-template-01.fq +1/−1
- tests/neg/qualif-template-02.fq +1/−1
- tests/neg/test00.fq +2/−2
- tests/neg/test00.hs.fq +60/−60
- tests/neg/test00a.fq +1/−1
- tests/neg/test1.fq +1/−1
- tests/neg/test2.fq +2/−2
- tests/neg/test3.fq +1/−1
- tests/pos/LogicCurry1.hs.fq +41/−41
- tests/pos/MergeSort.fq +49/−49
- tests/pos/T416.fq +2/−2
- tests/pos/T753A.fq +45/−0
- tests/pos/adt_qual.fq +2/−2
- tests/pos/bad-subst00.fq +2/−2
- tests/pos/bad-subst01.fq +2/−2
- tests/pos/bad-subst02.fq +1/−1
- tests/pos/bool00.fq +2/−2
- tests/pos/bool03.fq +1/−1
- tests/pos/bool04.fq +0/−20
- tests/pos/ebind-00.fq +0/−16
- tests/pos/ebind-01.fq +0/−17
- tests/pos/ebind-02.fq +0/−28
- tests/pos/ebind-03.fq +0/−45
- tests/pos/ebind-03a.fq +0/−55
- tests/pos/ebind-04.fq +0/−35
- tests/pos/ebind-05.fq +0/−31
- tests/pos/ebind-06.fq +0/−27
- tests/pos/elim00.fq +2/−2
- tests/pos/func00.fq +1/−1
- tests/pos/gfp00.fq +4/−4
- tests/pos/hex.ts.fq +78/−78
- tests/pos/kvar-param-poly-00.fq +1/−1
- tests/pos/len00-rename.fq +1/−1
- tests/pos/len00.fq +1/−1
- tests/pos/listqual.hs.fq +58/−58
- tests/pos/meas02.fq +2/−2
- tests/pos/min00.fq +4/−4
- tests/pos/num00.fq +1/−1
- tests/pos/numoverload00.fq +2/−2
- tests/pos/qualif-inst.fq +1/−1
- tests/pos/qualif-template-00.fq +1/−1
- tests/pos/qualif-template-01.fq +1/−1
- tests/pos/qualif-template-02.fq +1/−1
- tests/pos/sets.fq +1/−1
- tests/pos/test00.fq +2/−2
- tests/pos/test00.hs.fq +65/−65
- tests/pos/test000.hs.fq +70/−70
- tests/pos/test00a.fq +1/−1
- tests/pos/test1.fq +1/−1
- tests/pos/test2.fq +2/−2
- tests/pos/test3.fq +1/−1
- tests/pos/test4.fq +1/−1
- tests/pos/unexpected-ge.fq +1/−1
- tests/pos/wl00.fq +3/−3
- tests/pos/wl01.fq +1/−1
- tests/pos/wl02.fq +1/−1
- tests/tasty/Arbitrary.hs +2/−9
- tests/tasty/Main.hs +2/−0
- tests/tasty/ParserTests.hs +11/−59
- tests/tasty/SimplifyPLE.hs +6/−4
- tests/tasty/ghc-9.12.1/SimplifyKVarTests.hs +400/−0
- tests/tasty/ghc-before-9.12.1/SimplifyKVarTests.hs +12/−0
- tests/test.hs +21/−20
- unix/Language/Fixpoint/Utils/Progress.hs +17/−4
- win/Language/Fixpoint/Utils/Progress.hs +4/−0
CHANGES.md view
@@ -2,6 +2,35 @@ ## NEXT +## 0.9.6.3.4 (2026-01-14)++- Implement `--sortedsolution` to keep elaborated sorts in fqout/solution [#821](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/821)+- Retire old parser for horn queries [#820](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/820)+- Stop the parser from simplifying expressions during parsing [#819](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/819)+- Add `--explicitKvars` option and generalize horn syntax to accept expressions for kvars arguments [#818](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/818)+- Provide more comments in the SMT queries to relate them to the source code [#814](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/814)+- Remove `--no-lazy-ple` [#813](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/813)+- Allow PLE to unfold in kvar solutions [#811](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/811)+- Remove redundant question marks from expression [#807](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/807)+- Remove distinction of predicates and expressions in the parser [#805](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/805)+- Shrink kvar solutions [#799](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/799) [#809](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/809) [#821](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/821)+- Disable the progress bar when not on a terminal [#798](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/798)+- Retire existential binds [#797](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/797)+- Provide stack traces for more crashes [#794](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/794)+- Support string operators [#793](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/793)+- Apply kvar solutions to constraints before PLE [#792](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/792)+- Retire implementation of gradual refinement types [#789](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/789)+- Retire old PLE variations [#788](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/788)+- Add set cardinality support when using cvc5 [#774](https:://github.com/ucsd-progsys/liquid-fixpoint/pull/774)+- Have `--scrape` consider global constants and ADTs [#772](https://github.com/ucsd-progsys/liquid-fixpoint/pull/772)+- Shorten flags of a few flags and add git-version [#762](https://github.com/ucsd-progsys/liquid-fixpoint/pull/762)+- Add support/conversions for Bitv8 and Bitv16 [#759](https://github.com/ucsd-progsys/liquid-fixpoint/pull/759)+- Support the finite field theory of CVC5 [#755](https://github.com/ucsd-progsys/liquid-fixpoint/pull/755)+- Fix SMT crashes on reflected functions on polymorphic data types [#753](https://github.com/ucsd-progsys/liquid-fixpoint/pull/753)+- Allow function names to start with prefix mod [#751](https://github.com/ucsd-progsys/liquid-fixpoint/pull/751)+- Implement let bindings for Horn queries [#748](https://github.com/ucsd-progsys/liquid-fixpoint/pull/748)+- Fix elaboration of `define_fun` declarations [#747](https://github.com/ucsd-progsys/liquid-fixpoint/pull/747) [#749](https://github.com/ucsd-progsys/liquid-fixpoint/pull/749)+ ## 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).
README.md view
@@ -2,7 +2,7 @@ =============== -[](https://hackage.haskell.org/package/liquid-fixpoint) [](http://packdeps.haskellers.com/feed?needle=liquid-fixpoint) +[](https://hackage.haskell.org/package/liquid-fixpoint) [](http://packdeps.haskellers.com/feed?needle=liquid-fixpoint) [](https://circleci.com/gh/ucsd-progsys/liquid-fixpoint) [](https://github.com/ucsd-progsys/liquid-fixpoint/actions/workflows/hlint.yml) [](https://github.com/ucsd-progsys/liquid-fixpoint/actions/workflows/cabal.yml)@@ -15,7 +15,13 @@ + [Houdini](https://users.soe.ucsc.edu/~cormac/papers/fme01.pdf) + [Cartesian predicate abstraction](http://swt.informatik.uni-freiburg.de/berit/papers/boolean-and-cartesian-....pdf) +Algorithms implemented in liquid-fixpoint: ++ [FUSION](https://ranjitjhala.github.io/static/local_refinement_typing.pdf) Local refinement typing++ [PLE](https://ranjitjhala.github.io/static/refinement_reflection.pdf) Refinement Reflection: Complete Verification with SMT++ [REST](https://drops.dagstuhl.de/entities/document/10.4230/DARTS.8.2.12) REST: Integrating Term Rewriting with Program Verification++ Requirements ------------ @@ -23,6 +29,7 @@ - [Z3](https://github.com/Z3Prover/z3) - [CVC4](https://cvc4.github.io/)+- [CVC5](https://cvc5.github.io/) - [MathSat](http://mathsat.fbk.eu/download.html) If on Windows, please make sure to place the binary and any associated DLLs somewhere@@ -60,9 +67,10 @@ * Z3 * CVC4+ * CVC5 * MathSat -"Horn" Format +"Horn" Format ------------- See the examples in `tests/horn/{pos, neg}` eg@@ -73,8 +81,8 @@ For how to write VCs "by hand". -See [this tutorial](https://arxiv.org/abs/2010.07763) -with [accompanying code](https://github.com/ranjitjhala/sprite-lang) +See [this tutorial](https://arxiv.org/abs/2010.07763)+with [accompanying code](https://github.com/ranjitjhala/sprite-lang) for an example of how to generate Horn queries. The main datatypes are described in [src/Language/Fixpoint/Horn/Types.hs](src/Language/Fixpoint/Horn/Types.hs)@@ -145,7 +153,7 @@ ``` $ more tests/horn/pos/test01.smt2 | fixpoint --stdin -Liquid-Fixpoint Copyright 2013-21 Regents of the University of California.+Liquid-Fixpoint Copyright 2009-25 Regents of the University of California. All Rights Reserved. Working 166% [===============================================================]@@ -226,15 +234,20 @@ Then a single `IBindEnv` should only mention _at most_ one of `1` or `12`. -* There is also a "tree-shape" property that its a bit hard- to describe ... TODO +* [NOTE:TREE-LIKE] There is also a "tree-shape" property required by PLE: +```+ forall constraints c, c'.+ if i in c and i in c' then+ forall 0 <= j < i, j in c and j in c'+```+ ### LHS Each `slhs` of a constraint is a `SortedReft`. - Each `SortredReft` is basically a `Reft` -- a logical predicate.- The important bit is that a `KVar` i.e. terms of the formalized+ The important bit is that a `KVar` i.e. terms of the form ``` $k1[x1:=y1][x2:=y2]...[xn:=yn]@@ -271,16 +284,35 @@ is not. The exact definition is formalized in `Language.Fixpoint.SortCheck` - ### RHS Similarly each `rhs` of a `SubC` must either be a single `$k[...]` or an plain `$k`-free `Expr`. +### KVar occurrences++* Each `KVar` that appears in any binding or constraint must have exactly one+ associated wf constraint.++* Each `KVar` that appears in any binding or constraint must have an+ accompanying substitution whose domain has the same symbols as the environment+ of the corresponding wf constraint plus the symbol of its refinement type.++For example, if the wf constraint is+```+ x:int, y: int |- {v:int | $k_##42 }+```++any occurrence of `$k_##42` must be of the form++```+ $k_##42 [x:=e1][y:=e2][v:=e3]+```+ ### Global vs. Distinct Literals ``` , gLits :: !(SEnv Sort) -- ^ Global Constant symbols- , dLits :: !(SEnv Sort) + , dLits :: !(SEnv Sort) ``` The _global_ literals `gLits` are symbols that@@ -326,15 +358,10 @@ > What's the difference between an FTC and an FObj? -In early versions of fixpoint, there was support for -three sorts for expressions (`Expr`) that were sent -to the SMT solver:--1. `int`-2. `bool`-3. "other"--The `FObj` sort was introduced to represent essentially _all_ +In early versions of fixpoint, there was support for+three sorts for expressions (`Expr`) that were sent+to the SMT solver: `int`, `bool` and "other". The+`FObj` sort was introduced to represent essentially _all_ non-int and non-bool values (e.g. tuples, lists, trees, pointers...) However, we later realized that it is valuable to keep _more_@@ -351,17 +378,27 @@ > Does that then make FTC types that the SMT solver does > know about (bools, ints, lists, sets, etc.)? -The SMT solver knows about `bool`, `int` and `set` (also `bitvector` -and `map`) but _all_ other types are _currently_ represented as plain -`Int` inside the SMT solver. However, we _will be_ changing this +The SMT solvers we currently use know about following sorts:++* `bool`+* `int`+* `real`+* `string`+* `array` (aka `map`)+* `bitvector`+* `set` and `bag` (in Z3, they are both also represented internally as `array`s)+* `finitefield` (CVC5 only)++_All_ other types are _currently_ represented as plain+`Int` inside the SMT solver. However, we _will be_ changing this to make use of SMT support for ADTs ... -To sum up: the `FObj` is there for historical reasons; it has been -subsumed by `FTC` which is what I recomend you use. However `FObj` -is there if you want a simple "unitype" / "any" type for terms +To sum up: the `FObj` is there for historical reasons; it has been+subsumed by `FTC` which is what I recomend you use. However `FObj`+is there if you want a simple "unitype" / "any" type for terms that are not "interpreted". -## Qualifier Patterns +## Qualifier Patterns ```haskell λ> doParse' (qualParamP sortP) "" "z as (mon . $1) : int"
bin/Fixpoint.hs view
@@ -24,10 +24,10 @@ | otherwise = solveFQ isHorn :: F.Config -> Bool-isHorn cfg = F.isExtFile F.Smt2 file +isHorn cfg = F.isExtFile F.Smt2 file || F.isExtFile F.Json file || F.stdin cfg- where + where file = F.srcFile cfg errorExit :: F.Error -> IO ExitCode
liquid-fixpoint.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: liquid-fixpoint-version: 0.9.6.3.3+version: 0.9.6.3.4 synopsis: Predicate Abstraction-based Horn-Clause/Implication Constraint Solver description: This package implements an SMTLIB based Horn-Clause\/Logical Implication constraint@@ -56,6 +56,7 @@ library import: warnings exposed-modules: Data.ShareMap+ Control.Exception.Compat Language.Fixpoint.Conditional.Z3 Language.Fixpoint.Defunctionalize Language.Fixpoint.Graph@@ -82,9 +83,6 @@ Language.Fixpoint.Solver.Eliminate Language.Fixpoint.Solver.EnvironmentReduction Language.Fixpoint.Solver.Extensionality- Language.Fixpoint.Solver.GradualSolution- Language.Fixpoint.Solver.GradualSolve- Language.Fixpoint.Solver.Instantiate Language.Fixpoint.Solver.Interpreter Language.Fixpoint.Solver.Monad Language.Fixpoint.Solver.PLE@@ -105,8 +103,8 @@ Language.Fixpoint.Types.Constraints Language.Fixpoint.Types.Environments Language.Fixpoint.Types.Errors- Language.Fixpoint.Types.Graduals Language.Fixpoint.Types.Names+ Language.Fixpoint.Types.SMTPrint Language.Fixpoint.Types.PrettyPrint Language.Fixpoint.Types.Refinements Language.Fixpoint.Types.Solutions@@ -144,12 +142,12 @@ , directory , fgl , filepath+ , gitrev >= 1.3.1 , hashable , intern , lens-family , megaparsec >= 7.0.0 && < 10 , mtl- , parallel , parser-combinators , pretty >= 1.1.3.1 , process@@ -194,7 +192,7 @@ autogen-modules: Paths_liquid_fixpoint hs-source-dirs: bin ghc-options: -threaded -W -Wno-missing-methods- build-depends: base >= 4.9.1.0 && < 5, liquid-fixpoint+ build-depends: base >= 4.9.1.0 && < 5, liquid-fixpoint, gitrev >= 1.3.1 if flag(devel) ghc-options: -Werror default-language: Haskell98@@ -236,10 +234,15 @@ ShareMapReference ShareMapTests SimplifyInterpreter+ SimplifyKVarTests SimplifyPLE SimplifyTests UndoANFTests Paths_liquid_fixpoint+ if impl(ghc>=9.12.1)+ hs-source-dirs: tests/tasty/ghc-9.12.1+ else+ hs-source-dirs: tests/tasty/ghc-before-9.12.1 autogen-modules: Paths_liquid_fixpoint hs-source-dirs: tests/tasty ghc-options: -threaded
+ src/Control/Exception/Compat.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE CPP #-}+module Control.Exception.Compat+ ( ExceptionWithContext(..)+ , displayExceptionContext+ , wrapExceptionWithContext+ ) where++#if MIN_VERSION_base(4,20,0)++import Control.Exception (ExceptionWithContext(..))+import Control.Exception.Context (displayExceptionContext)++wrapExceptionWithContext :: ExceptionWithContext a -> ExceptionWithContext a+wrapExceptionWithContext = id++#else++data ExceptionWithContext a = ExceptionWithContext ExceptionContext a++data ExceptionContext = ExceptionContext++displayExceptionContext :: ExceptionContext -> String+displayExceptionContext _ = "Exception context not available in this version of ghc."++wrapExceptionWithContext :: a -> ExceptionWithContext a+wrapExceptionWithContext = ExceptionWithContext ExceptionContext+#endif+
src/Language/Fixpoint/Defunctionalize.hs view
@@ -85,6 +85,9 @@ (i2, e2') = go e2 in (max i1 i2, EApp e1' e2') go (ECst e s) = fmap (`ECst` s) (go e)+ go (ELet x e1 e2) = let (i1, e1') = go e1+ (i2, e2') = go e2+ in (max i1 i2, ELet x e1' e2') go (EIte e1 e2 e3) = let (i1, e1') = go e1 (i2, e2') = go e2 (i3, e3') = go e3@@ -152,11 +155,6 @@ let (x, t, k) = wrft wf t' <- defunc t return $ wf { wrft = (x, t', k) }- defunc wf@GWfC{} = do- let (x, t, k) = wrft wf- t' <- defunc t- e' <- defunc $ wexpr wf- return $ wf { wrft = (x, t', k), wexpr = e' } instance Defunc SortedReft where defunc (RR s r) = RR s <$> defunc r
src/Language/Fixpoint/Graph/Deps.hs view
@@ -205,12 +205,16 @@ edgeGraph es = KVGraph [(v, v, vs) | (v, vs) <- groupList es ] -- need to plumb list of ebinds++-- | Compute dependencies between constraints and kvars.+--+-- @(k, c)@ means that constraint @c@ uses kvar @k@ on the LHS.+-- @(c, k)@ means that constraint @c@ uses kvar @k@ on the RHS. {-# SCC kvEdges #-} kvEdges :: (F.TaggedC c a) => F.GInfo c a -> [CEdge]-kvEdges fi = selfes ++ concatMap (subcEdges bs) cs ++ concatMap (ebindEdges ebs bs) cs+kvEdges fi = selfes ++ concatMap (subcEdges bs) cs where bs = F.bs fi- ebs = F.ebinds fi cs = M.elems (F.cm fi) ks = fiKVars fi selfes = [(Cstr i , Cstr i) | c <- cs, let i = F.subcId c]@@ -220,21 +224,6 @@ fiKVars :: F.GInfo c a -> [F.KVar] fiKVars = M.keys . F.ws -ebindEdges :: (F.TaggedC c a) => [F.BindId] -> F.BindEnv a -> c a -> [CEdge]-ebindEdges ebs bs c = [(EBind k, Cstr i ) | k <- envEbinds xs bs c ]- ++ [(Cstr i, EBind k') | k' <- rhsEbinds xs c ]- where- i = F.subcId c- xs = fst3 . flip F.lookupBindEnv bs <$> ebs--envEbinds :: (F.TaggedC c a, Foldable t) =>- t F.Symbol -> F.BindEnv a -> c a -> [F.Symbol]-envEbinds xs be c = [ x | x <- envBinds , x `elem` xs ]- where envBinds = fst <$> F.clhs be c-rhsEbinds :: (Foldable t, F.TaggedC c a) =>- t F.Symbol -> c a -> [F.Symbol]-rhsEbinds xs c = [ x | x <- F.syms (F.crhs c) , x `elem` xs ]- subcEdges :: (F.TaggedC c a) => F.BindEnv a -> c a -> [CEdge] subcEdges bs c = [(KVar k, Cstr i ) | k <- V.envKVars bs c] ++ [(Cstr i, KVar k') | k' <- V.rhsKVars c ]@@ -245,10 +234,10 @@ -- | Eliminated Dependencies -------------------------------------------------------------------------------- {-# SCC elimDeps #-}-elimDeps :: (F.TaggedC c a) => F.GInfo c a -> [CEdge] -> S.HashSet F.KVar -> S.HashSet F.Symbol -> CDeps-elimDeps si es nonKutVs ebs = graphDeps si es'+elimDeps :: (F.TaggedC c a) => F.GInfo c a -> [CEdge] -> S.HashSet F.KVar -> CDeps+elimDeps si es nonKutVs = graphDeps si es' where- es' = graphElim es nonKutVs ebs+ es' = graphElim es nonKutVs _msg = "graphElim: " ++ show (length es') {- | `graphElim` "eliminates" a kvar k by replacing every "path"@@ -259,9 +248,8 @@ ki ------------> c -}-graphElim :: [CEdge] -> S.HashSet F.KVar -> S.HashSet F.Symbol -> [CEdge]-graphElim es ks _ebs = ikvgEdges $ -- elimEs (S.map EBind ebs) $- elimKs (S.map KVar ks) $ edgesIkvg es+graphElim :: [CEdge] -> S.HashSet F.KVar -> [CEdge]+graphElim es ks = ikvgEdges $ elimKs (S.map KVar ks) $ edgesIkvg es where elimKs = flip (S.foldl' elimK) _elimEs = flip (S.foldl' elimE)@@ -307,8 +295,10 @@ dCut v = Deps (S.singleton v) S.empty ----------------------------------------------------------------------------------- | Compute Dependencies and Cuts ------------------------------------------------------------------------------------------------------------------------------+-- | Compute Dependencies and Cuts+--+-- Computes greedily a set of kvars that make the dependency graph acyclic when+-- removed. Also yields the edges of the dependency graph. {-# SCC elimVars #-} elimVars :: (F.TaggedC c a) => Config -> F.GInfo c a -> ([CEdge], Elims F.KVar) --------------------------------------------------------------------------------@@ -581,9 +571,8 @@ nlks = nonLinearKVars si d = snd $ elimVars cfg si ---------------------------------------------------------------------------------+-- | KVars used more than once in the LHS of some constraint nonLinearKVars :: (F.TaggedC c a) => F.GInfo c a -> S.HashSet F.KVar--------------------------------------------------------------------------------- nonLinearKVars fi = S.unions $ nlKVarsC bs <$> cs where bs = F.bs fi
src/Language/Fixpoint/Graph/Types.hs view
@@ -66,13 +66,11 @@ data CVertex = KVar !KVar -- ^ real kvar vertex | DKVar !KVar -- ^ dummy to ensure each kvar has a successor- | EBind !F.Symbol -- ^ existentially bound "ghost paramter" to solve for | Cstr !Integer -- ^ constraint-id which creates a dependency deriving (Eq, Ord, Show, Generic) instance PPrint CVertex where pprintTidy _ (KVar k) = doubleQuotes $ pprint $ kv k- pprintTidy _ (EBind s) = doubleQuotes $ pprint s pprintTidy _ (Cstr i) = text "id_" <-> pprint i pprintTidy _ (DKVar k) = pprint k <-> text "*" @@ -192,8 +190,8 @@ -- | `SolverInfo` contains all the stuff needed to produce a result, and is the -- the essential ingredient of the state needed by solve_ ---------------------------------------------------------------------------------data SolverInfo a b = SI- { siSol :: !(F.Sol b F.QBind) -- ^ the initial solution+data SolverInfo a = SI+ { siSol :: !(F.Sol F.QBind) -- ^ the initial solution , siQuery :: !(F.SInfo a) -- ^ the whole input query , siDeps :: !CDeps -- ^ dependencies between constraints/ranks etc. , siVars :: !(S.HashSet F.KVar) -- ^ set of KVars to actually solve for
src/Language/Fixpoint/Horn/Info.hs view
@@ -5,12 +5,10 @@ hornFInfo ) where -import Control.Monad (forM) import Data.Ord (Down(..), comparing) import qualified Data.HashMap.Strict as M import qualified Data.List as L import qualified Data.Tuple as Tuple-import Data.Either (partitionEithers) import GHC.Generics (Generic) import qualified Language.Fixpoint.Misc as Misc import qualified Language.Fixpoint.Types as F@@ -22,7 +20,6 @@ hornFInfo cfg q = mempty { F.cm = cs , F.bs = be2- , F.ebinds = ebs , F.ws = kvEnvWfCs kve , F.quals = H.qQuals q ++ scrapeCstr (F.scrape cfg) hCst , F.gLits = F.fromMapSEnv $ H.qCon q@@ -30,12 +27,12 @@ , F.ae = axEnv cfg q cs , F.ddecls = H.qData q , F.hoInfo = F.cfgHoInfo cfg- , F.defns = H.qDefs q+ , F.defns = F.MkDefinedFuns (H.qDefs q) } where be0 = F.emptyBindEnv (be1, kve) = hornWfs be0 (H.qVars q)- (be2, ebs, cs) = hornSubCs be1 kve hCst+ (be2, cs) = hornSubCs be1 kve hCst hCst = H.qCstr q @@ -48,27 +45,26 @@ ---------------------------------------------------------------------------------- hornSubCs :: F.BindEnv a -> KVEnv a -> H.Cstr a- -> (F.BindEnv a, [F.BindId], M.HashMap F.SubcId (F.SubC a))+ -> (F.BindEnv a, M.HashMap F.SubcId (F.SubC a)) -----------------------------------------------------------------------------------hornSubCs be kve c = (be', ebs, M.fromList (F.addIds cs))+hornSubCs be kve c = (be', M.fromList (F.addIds cs)) where- (be', ebs, cs) = goS kve F.emptyIBindEnv be c+ (be', cs) = goS kve F.emptyIBindEnv be c -- lhs0 = bindSortedReft kve H.dummyBind -- | @goS@ recursively traverses the NNF constraint to build up a list -- of the vanilla @SubC@ constraints. goS :: KVEnv a -> F.IBindEnv -> F.BindEnv a -> H.Cstr a- -> (F.BindEnv a, [F.BindId], [F.SubC a])+ -> (F.BindEnv a, [F.SubC a]) -goS kve env be c = (be', mEbs, subcs)+goS kve env be c = (be', subcs) where- (be', ecs) = goS' kve env Nothing be c- (mEbs, subcs) = partitionEithers ecs+ (be', subcs) = goS' kve env Nothing be c goS' :: KVEnv a -> F.IBindEnv -> Maybe F.SortedReft -> F.BindEnv a -> H.Cstr a- -> (F.BindEnv a, [Either F.BindId (F.SubC a)])-goS' kve env lhs be (H.Head p l) = (be, [Right subc])+ -> (F.BindEnv a, [F.SubC a])+goS' kve env lhs be (H.Head p l) = (be, [subc]) where subc = myMkSubC env lhs rhs Nothing [] l rhs = updSortedReft kve lhs p@@ -84,13 +80,6 @@ bSR = bindSortedReft kve b env' = F.insertsIBindEnv [bId] env -goS' kve env _ be (H.Any b c) = (be'', Left bId : subcs)- where- (be'', subcs) = goS' kve env' (Just bSR) be' c- (bId, be') = F.insertBindEnv (H.bSym b) bSR (H.bMeta b) be- bSR = bindSortedReft kve b- env' = F.insertsIBindEnv [bId] env- myMkSubC :: F.IBindEnv -> Maybe F.SortedReft -> F.SortedReft -> Maybe Integer -> F.Tag -> a -> F.SubC a myMkSubC be lhsMb rhs x y z = F.mkSubC be lhs rhs x y z where@@ -114,10 +103,10 @@ go (H.Var k ys) = kvApp kve k ys go (H.PAnd ps) = F.PAnd (go <$> ps) -kvApp :: KVEnv a -> F.Symbol -> [F.Symbol] -> F.Expr+kvApp :: KVEnv a -> F.Symbol -> [F.Expr] -> F.Expr kvApp kve k ys = F.PKVar (F.KV k) su where- su = F.mkSubst (zip params (F.eVar <$> ys))+ su = F.mkSubst (zip params ys) params = maybe err1 kvParams (M.lookup k kve) err1 = F.panic ("Unknown Horn variable: " ++ F.showpp k) @@ -176,7 +165,6 @@ go senv (H.Head p _) = scrapePred senv p go senv (H.CAnd cs) = concatMap (go senv) cs go senv (H.All b c) = scrapeBind m senv' b <> go senv' c where senv' = insertBindEnv b senv- go senv (H.Any b c) = scrapeBind m senv' b <> go senv' c where senv' = insertBindEnv b senv scrapeBind :: F.Scrape -> BindEnv -> H.Bind a -> [F.Qualifier] scrapeBind F.Both senv b = scrapePred senv (H.bPred b)@@ -189,16 +177,17 @@ -- NOTE: Constraints.mkQual will do extra stuff like generalizing the sorts... mkQual :: BindEnv -> F.Expr -> [ F.Qualifier ]-mkQual env e = case qualParams env e of- Nothing -> []- Just xts -> [ mkScrapeQual xts' e | xts' <- shiftCycle xts ]+mkQual env e = [ mkScrapeQual xts' e | xts' <- shiftCycle xts ]+ where+ xts = qualParams env e mkScrapeQual :: [(F.Symbol, F.Sort)] -> F.Expr -> F.Qualifier-mkScrapeQual xts e = F.mkQual (F.symbol "AUTO") qParams (F.subst su e) (F.dummyPos "")+mkScrapeQual xts e = F.mkQual (F.symbol "AUTO") qParams body (F.dummyPos "") where qParams = [ F.QP {F.qpSym = y, F.qpPat = F.PatNone, F.qpSort = t} | (_, y, t) <- xyts ] xyts = zipWith (\i (x, t) -> (x, F.bindSymbol i, t)) [0..] xts su = F.mkSubst [ (x, F.expr y) | (x, y, _) <- xyts ]+ body = F.subst su e shiftCycle :: [(F.Symbol, F.Sort)] -> [[(F.Symbol, F.Sort)]]@@ -221,15 +210,11 @@ 2. Permute the args? -} -qualParams :: BindEnv -> F.Expr -> Maybe [(F.Symbol, F.Sort)]-qualParams env e = do- let xs = Misc.nubOrd (F.syms e)- ixts <- forM xs $ \x -> do- (t, i) <- lookupBindEnv x env- return (i, x, t)- return [ (x, t) | (_, x, t) <- L.sortBy (comparing Down) ixts ]-- -- ixts = [ (i, x, t) | x <- xs, (i, t) <- lookupBindEnv x env ]+qualParams :: BindEnv -> F.Expr -> [(F.Symbol, F.Sort)]+qualParams env e = [ (x, t) | (_, x, t) <- L.sortBy (comparing Down) ixts ]+ where+ xs = Misc.nubOrd (F.syms e)+ ixts = [ (i, x, t) | x <- xs, (t, i) <- Mb.maybeToList (lookupBindEnv x env) ] -------------------------------------------------------------------------------
src/Language/Fixpoint/Horn/Parse.hs view
@@ -84,7 +84,6 @@ where body = H.CAnd <$> (reserved "and" *> many hCstrP) <|> H.All <$> (reserved "forall" *> hBindP) <*> hCstrP- <|> H.Any <$> (reserved "exists" *> hBindP) <*> hCstrP <|> H.Head <$> (reserved "tag" *> hPredP) <*> (H.Tag <$> stringLiteral) <|> H.Head <$> hPredP <*> pure H.NoTag @@ -98,7 +97,7 @@ ------------------------------------------------------------------------------- hPredP = parens body where- body = H.Var <$> kvSymP <*> some symbolP+ body = H.Var <$> kvSymP <*> some predP <|> H.PAnd <$> (reserved "and" *> some hPredP) <|> H.Reft <$> predP
src/Language/Fixpoint/Horn/SMTParse.hs view
@@ -187,7 +187,6 @@ where body = H.CAnd <$> (reserved "and" *> many hCstrP) <|> H.All <$> (reserved "forall" *> hBindP) <*> hCstrP- <|> H.Any <$> (reserved "exists" *> hBindP) <*> hCstrP <|> H.Head <$> (reserved "tag" *> hPredP) <*> (H.Tag <$> stringLiteral) hBindP :: FParser (H.Bind H.Tag)@@ -200,7 +199,7 @@ ------------------------------------------------------------------------------- hPredP = parens body where- body = H.Var <$> kvSymP <*> some symbolP+ body = H.Var <$> kvSymP <*> some exprP <|> H.PAnd <$> (reserved "and" *> some hPredP) <|> H.Reft <$> exprP @@ -260,6 +259,16 @@ bindP :: FParser (F.Symbol, F.Sort) bindP = sPairP symbolP sortP +-- | We only support lets with a single binder, but we parse this as a "singleton list"+-- to be forward compatible with multiple binders. Note that the semantics of multiple+-- binders in smtlib is *simulatenous substitution*, so they cannot be desugared to nested+-- lets.+exprBindsP :: FParser (F.Symbol, F.Expr)+exprBindsP = parens exprBindP++exprBindP :: FParser (F.Symbol, F.Expr)+exprBindP = sPairP symbolP exprP+ defineP :: FParser F.Equation defineP = do name <- symbolP@@ -285,6 +294,7 @@ <|> try (parens (reserved "func" >> (mkFunc <$> fIntP <*> sMany sortP <*> sortP))) <|> try (parens (reserved "list" >> (mkList <$> sortP))) <|> parens (F.fAppTC <$> fTyConP <*> many sortP)+ <|> (F.FNatNum <$> natural) mkFunc :: Int -> [F.Sort] -> F.Sort -> F.Sort mkFunc n ss s = F.mkFFunc n (ss ++ [s])@@ -304,6 +314,7 @@ pExprP :: FParser F.Expr pExprP = (reserved "if" >> (F.EIte <$> exprP <*> exprP <*> exprP))+ <|> (reserved "let" >> (uncurry F.ELet <$> exprBindsP <*> exprP)) <|> (reserved "lit" >> (mkLit <$> stringLiteral <*> sortP)) <|> (reserved "cast" >> (F.ECst <$> exprP <*> sortP)) <|> (reserved "not" >> (F.PNot <$> exprP))@@ -335,7 +346,7 @@ <|> (sym "-" >> return F.Minus) <|> (sym "*" >> return F.Times) <|> (sym "/" >> return F.Div)- <|> (sym "mod" >> return F.Mod)+ <|> (reserved "mod" >> return F.Mod) <|> (sym "*." >> return F.RTimes) <|> (sym "/." >> return F.RDiv)
src/Language/Fixpoint/Horn/Solve.hs view
@@ -30,9 +30,9 @@ ---------------------------------------------------------------------------------- solveHorn :: F.Config -> IO ExitCode -----------------------------------------------------------------------------------solveHorn baseCfg = do- q <- parseQuery baseCfg-+solveHorn baseCfg0 = do+ q <- parseQuery baseCfg0+ let baseCfg = baseCfg0 { F.explicitKvars = True } -- If you want to set --eliminate=none, you better make it a pragma let cfgElim = if F.eliminate baseCfg == F.None then baseCfg { F.eliminate = F.Some }@@ -67,12 +67,12 @@ saveHornSMT2 cfg q saveHornJSON cfg q -saveHornSMT2 :: H.ToHornSMT a => F.Config -> a -> IO ()+saveHornSMT2 :: F.ToHornSMT a => F.Config -> a -> IO () saveHornSMT2 cfg q = do let hq = F.queryFile Files.HSmt2 cfg putStrLn $ "Saving Horn Query: " ++ hq ++ "\n" Misc.ensurePath hq- writeFile hq $ render ({- F.pprint -} H.toHornSMT q)+ writeFile hq $ render (F.toHornSMT q) saveHornJSON :: F.Config -> H.Query H.Tag -> IO () saveHornJSON cfg q = do
src/Language/Fixpoint/Horn/Transformations.hs view
@@ -147,10 +147,12 @@ (ns, formals, Just defC) -> (ns, formals, defC) (_, _, Nothing) -> error $ "pi variable " <> F.showpp k <> " has no defining constraint." + -- TODO: generalize the `expectVar` business below to handle arbitrary expressions+ -- https://github.com/ucsd-progsys/liquid-fixpoint/pull/818#discussion_r2643206366 go :: Cstr a -> ([F.Symbol], [[F.Symbol]], Maybe (Cstr a)) go (CAnd cs) = (\(as, bs, mcs) -> (concat as, concat bs, cAndMaybes mcs)) $ unzip3 $ go <$> cs go (All b@(Bind n _ (Var k' xs) _) c')- | k == k' = ([n], [S.toList $ S.fromList xs `S.difference` S.singleton n], Just c')+ | k == k' = ([n], [S.toList $ S.fromList (expectVar <$> xs) `S.difference` S.singleton n], Just c') | otherwise = map3 (fmap (All b)) (go c') go (All b c') = map3 (fmap (All b)) (go c') go _ = ([], [], Nothing)@@ -160,6 +162,10 @@ [] -> Nothing cs -> Just $ CAnd cs +expectVar :: F.Expr -> F.Symbol+expectVar (F.EVar s) = s+expectVar _ = error "expectVar: expected variable"+ map3 :: (c -> d) -> (a, b, c) -> (a, b, d) map3 f (x, y, z) = (x, y, f z) @@ -194,7 +200,6 @@ (eqs' <> eqs'', newVisited') go visited (All (Bind _ _ p _) c) = let (eqs, visited') = go visited c in (eqs <> collectEqualities p, visited')- go _ Any{} = error "exists should not be present in piSols" ------------------------------------------------------------------------------ {- | pokec skolemizes the EHC into an HC + side condition@@ -248,16 +253,7 @@ go _ (Head c l) = Head c l go xs (CAnd c) = CAnd (go xs <$> c) go xs (All b c2) = All b $ go (bSym b : xs) c2- go xs (Any b@(Bind x t p ann) c2) = CAnd [All b' $ CAnd [Head p l, go (x:xs) c2], Any b (Head pi' l)]- -- TODO: actually use the renamer?- where- b' = Bind x t pi' ann- pi' = piVar x xs- l = cLabel c2 -piVar :: F.Symbol -> [F.Symbol] -> Pred-piVar x xs = Var (piSym x) (x:xs)- piSym :: F.Symbol -> F.Symbol piSym s = fromString $ "π" ++ F.symbolString s @@ -332,7 +328,6 @@ where (nosides, sides) = unzip $ split <$> cs split (All b c) = (All b <$> c', All b <$> c'') where (c',c'') = split c-split c@Any{} = (Nothing, Just c) split c@Head{} = (Just c, Nothing) andMaybes :: [Maybe (Cstr a)] -> Maybe (Cstr a)@@ -407,8 +402,6 @@ = CAnd $ applyPi k bp <$> cs applyPi k bp (All b c) = All b (applyPi k bp c)-applyPi k bp (Any b c)- = Any b (applyPi k bp c) applyPi k defCstr (Head (Var k' _xs) a) | k == k' -- what happens when pi's appear inside the defs for other pis?@@ -475,18 +468,16 @@ = pure c defs x (All _ c) = defs x c defs _ (Head _ _) = Nothing-defs _ (Any _ _) = error "defs should be run only after noside and poke" cstrToExpr :: Cstr a -> F.Expr cstrToExpr (Head p _) = predToExpr p cstrToExpr (CAnd cs) = F.PAnd $ cstrToExpr <$> cs cstrToExpr (All (Bind x t p _) c) = F.PAll [(x,t)] $ F.PImp (predToExpr p) $ cstrToExpr c-cstrToExpr (Any (Bind x t p _) c) = F.PExist [(x,t)] $ F.PImp (predToExpr p) $ cstrToExpr c predToExpr :: Pred -> F.Expr predToExpr (Reft e) = e predToExpr (Var k xs) = F.PKVar (F.KV k) (F.Su $ M.fromList su)- where su = zip (kargs k) (F.EVar <$> xs)+ where su = zip (kargs k) xs predToExpr (PAnd ps) = F.PAnd $ predToExpr <$> ps ------------------------------------------------------------------------------@@ -573,7 +564,6 @@ foldE v c (CAnd cs) = CAnd <$> mapM (foldE v c) cs foldE v c (Head p a) = Head <$> foldE v c p <*> pure a foldE v ctx (All (Bind x t p l) c) = All <$> (Bind x t <$> foldE v ctx p <*> pure l) <*> foldE v ctx c- foldE v ctx (Any (Bind x t p l) c) = All <$> (Bind x t <$> foldE v ctx p <*> pure l) <*> foldE v ctx c ------------------------------------------------------------------------------ -- | Quantifier elimination for use with implicit solver@@ -700,27 +690,7 @@ substPiSols piSols (All (Bind x t p l) c) | Var k _ <- p = All (Bind x t (M.lookupDefault p k piSols) l) (substPiSols piSols c) | otherwise = All (Bind x t p l) (substPiSols piSols c)-substPiSols piSols (Any (Bind n _ p _) c)- | Head (Var pi' _) label <- c, Just sol <- M.lookup pi' piSols =- case findSol n sol of- Just e -> Head (flatten $ PAnd $ (\predFn -> F.subst1 predFn (n, e)) <$> [p, sol]) label- Nothing -> Head (Reft $ F.PAnd []) label- | otherwise = error "missing piSol" -findSol :: F.Symbol -> Pred -> Maybe F.Expr-findSol sym = go- where- go (Reft e) = findEq e- go Var{} = Nothing- go (PAnd ps) = case mapMaybe go ps of- [] -> Nothing- x:_ -> Just x-- findEq (F.PAtom F.Eq left right)- | F.EVar y <- left, y == sym = Just right- | F.EVar y <- right, y == sym = Just left- findEq _ = Nothing- ------------------------------------------------------------------------------ -- | uniq makes sure each binder has a unique name ------------------------------------------------------------------------------@@ -737,11 +707,6 @@ c2' <- uniq' c2 modify $ popName x pure $ All b' c2'-uniq' (Any b@(Bind x _ _ _) c2) = do- b' <- uBind b- c2' <- uniq' c2- modify $ popName x- pure $ Any b' c2' popName :: F.Symbol -> RenameMap -> RenameMap popName x m = M.adjust (second tail) x m@@ -764,18 +729,17 @@ rename :: Pred -> RenameMap -> Pred rename e m = substPred (M.mapMaybeWithKey (\k v -> case v of- (_, n:_) -> Just $ numSym k n+ (_, n:_) -> Just $ F.EVar $ numSym k n _ -> Nothing) m) e numSym :: IsString a => F.Symbol -> Integer -> a numSym s 0 = fromString $ F.symbolString s numSym s i = fromString $ F.symbolString s ++ "#" ++ show i -substPred :: M.HashMap F.Symbol F.Symbol -> Pred -> Pred-substPred su (Reft e) = Reft $ F.subst (F.Su $ F.EVar <$> su) e+substPred :: M.HashMap F.Symbol F.Expr -> Pred -> Pred+substPred su (Reft e) = Reft $ F.subst (F.Su su) e substPred su (PAnd ps) = PAnd $ substPred su <$> ps-substPred su (Var k xs) = Var k $ upd <$> xs- where upd x = M.lookupDefault x x su+substPred su (Var k xs) = Var k $ F.subst (F.Su su) <$> xs ------------------------------------------------------------------------------ -- | elim solves all of the KVars in a Cstr (assuming no cycles...)@@ -814,8 +778,6 @@ go (Head _ l) = Left l go c@(All (Bind _ _ p _) c') = if k `S.member` pKVars p then Right c else go c'- go Any{} = error "any should not appear after poke"- -- if kvar doesn't appear, then just return the left -- if kvar appears in one child, that is the lca -- but if kvar appear in multiple chlidren, this is the lca@@ -850,10 +812,9 @@ sol1 k (CAnd cs) = sol1 k =<< cs sol1 k (All b c) = first (b :) <$> sol1 k c sol1 k (Head (Var k' ys) _) | k == k'- = [([], zipWith (F.PAtom F.Eq) (F.EVar <$> xs) (F.EVar <$> ys))]+ = [([], zipWith (F.PAtom F.Eq) (F.EVar <$> xs) ys)] where xs = zipWith const (kargs k) ys sol1 _ (Head _ _) = []-sol1 _ (Any _ _) = error "ebinds don't work with old elim" kargs :: F.Symbol -> [F.Symbol] kargs k = fromString . (("κarg$" ++ F.symbolString k ++ "#") ++) . show <$> [1 :: Integer ..]@@ -871,9 +832,9 @@ Right _ -> All (Bind sym' sort' p l) (doelim sym bss cstr) Left (kvars, preds) -> demorgan sym' sort' l kvars preds (doelim sym bss cstr) bss where- demorgan :: F.Symbol -> F.Sort -> a -> [(F.Symbol, [F.Symbol])] -> [Pred] -> Cstr a -> [([Bind a], [F.Expr])] -> Cstr a+ demorgan :: F.Symbol -> F.Sort -> a -> [(F.Symbol, [F.Expr])] -> [Pred] -> Cstr a -> [([Bind a], [F.Expr])] -> Cstr a demorgan x t ann kvars preds cstr' bindExprs = mkAnd $ cubeSol <$> bindExprs- where su = F.Su $ M.fromList $ concatMap (\(k, xs) -> zip (kargs k) (F.EVar <$> xs)) kvars+ where su = F.Su $ M.fromList $ concatMap (\(k, xs) -> zip (kargs k) xs) kvars mkAnd [c] = c mkAnd cs = CAnd cs cubeSol (b:bs, eqs) = All b $ cubeSol (bs, eqs)@@ -883,14 +844,9 @@ = Head (Reft F.PTrue) a doelim _ _ (Head p a) = Head p a -doelim k bss (Any (Bind x t p l) c) =- case findKVarInGuard k p of- Right _ -> Any (Bind x t p l) (doelim k bss c)- Left (_, rights') -> Any (Bind x t (PAnd rights') l) (doelim k bss c) -- TODO: for now we set the kvar to true. not sure if this is correct- -- If k is in the guard then returns a Left list of that k and the remaining preds in the guard -- If k is not in the guard returns a Right of the pred-findKVarInGuard :: F.Symbol -> Pred -> Either ([(F.Symbol, [F.Symbol])], [Pred]) Pred+findKVarInGuard :: F.Symbol -> Pred -> Either ([(F.Symbol, [F.Expr])], [Pred]) Pred findKVarInGuard k (PAnd ps) = if null lefts then Right (PAnd ps) -- kvar not found@@ -923,7 +879,6 @@ boundKvars (Head p _) = pKVars p boundKvars (CAnd c) = mconcat $ boundKvars <$> c boundKvars (All (Bind _ _ p _) c) = pKVars p <> boundKvars c-boundKvars (Any (Bind _ _ p _) c) = pKVars p <> boundKvars c pKVars :: Pred -> S.Set F.Symbol pKVars (Var k _) = S.singleton k@@ -935,7 +890,6 @@ isNNF Head{} = True isNNF (CAnd cs) = all isNNF cs isNNF (All _ c) = isNNF c-isNNF Any{} = False calculateCuts :: (F.Fixpoint a, F.PPrint a) => F.Config -> Query a -> Cstr a -> S.Set F.Symbol calculateCuts cfg q@(Query {}) nnf = convert $ FG.depCuts deps@@ -949,7 +903,6 @@ forgetPiVars pis (All (Bind x t p l) c) | Var k _ <- p, k `S.member` pis = All (Bind x t (PAnd []) l) $ forgetPiVars pis c | otherwise = All (Bind x t p l) $ forgetPiVars pis c-forgetPiVars _ Any{} = error "shouldn't be present" ----------------------------------------------------------------------------------- -- | Cleanup Horn Constraint@@ -997,7 +950,6 @@ go (Head p a) = Just $ Head (flatten p) a go (CAnd cs) = mk . concatMap splitAnd $ mapMaybe flattenCstr cs go (All (Bind x t p l) c) = All (Bind x t (flatten p) l) <$> go c- go (Any (Bind x t p l) c) = Any (Bind x t (flatten p) l) <$> go c mk [] = Nothing mk [c] = Just c@@ -1062,7 +1014,6 @@ splitP kacc pacc [] = (kacc,pacc) hornify (Head h a) = Head h a hornify (All b c) = All b $ hornify c-hornify (Any b c) = Any b $ hornify c hornify (CAnd cs) = CAnd $ hornify <$> cs removeDuplicateBinders :: Cstr a -> Cstr a@@ -1071,7 +1022,6 @@ go _ c@Head{} = c go xs (CAnd cs) = CAnd $ go xs <$> cs go xs (All b@(Bind x _ _ _) c) = if x `S.member` xs then go xs c else All b $ go (S.insert x xs) c- go xs (Any b c) = Any b $ go xs c pruneTauts :: Cstr a -> Cstr a pruneTauts = fromMaybe (CAnd []) . go@@ -1084,7 +1034,6 @@ go (All b c) = do c' <- go c pure (All b c')- go c@Any{} = Just c goP (Reft e) = if F.isTautoPred e then Nothing else Just $ Reft e goP p@Var{} = Just p
src/Language/Fixpoint/Horn/Types.hs view
@@ -10,7 +10,6 @@ {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE ViewPatterns #-} module Language.Fixpoint.Horn.Types ( -- * Horn Constraints and their components@@ -34,8 +33,6 @@ -- * extract qualifiers , quals - -- * SMTLIB style render- , ToHornSMT (..) ) where @@ -63,19 +60,27 @@ } deriving (Eq, Ord, Data, Typeable, Generic, Functor, ToJSON, FromJSON) ++ ------------------------------------------------------------------------------- -- | @HPred@ is a Horn predicate that appears as LHS (body) or RHS (head) of constraints ------------------------------------------------------------------------------- data Pred = Reft !F.Expr -- ^ r- | Var !F.Symbol ![F.Symbol] -- ^ $k(y1..yn)+ | Var !F.Symbol ![F.Expr] -- ^ $k(y1..yn) | PAnd ![Pred] -- ^ p1 /\ .../\ pn deriving (Data, Typeable, Generic, Eq, ToJSON, FromJSON) +instance F.ToHornSMT (Var a) where+ toHornSMT (HVar k ts _) = P.parens ("var" P.<+> "$" P.<-> F.pprint k P.<+> F.toHornSMT ts)+instance F.ToHornSMT Pred where+ toHornSMT (Reft p) = P.parens (F.toHornSMT p)+ toHornSMT (Var k xs) = F.toHornMany (F.toHornSMT (F.KV k) : (F.toHornSMT <$> xs))+ toHornSMT (PAnd ps) = F.toHornMany ("and" : (F.toHornSMT <$> ps)) instance F.Subable Pred where syms (Reft e) = F.syms e- syms (Var _ xs) = xs+ syms (Var _ xs) = concatMap F.syms xs syms (PAnd ps) = concatMap F.syms ps substa f (Reft e) = Reft (F.substa f e)@@ -105,7 +110,6 @@ go env v (Head p _) = predQuals env v p go env v (CAnd cs) = concatMap (go env v) cs go env _ (All b c) = bindQuals env b c- go env _ (Any b c) = bindQuals env b c bindQuals :: F.SEnv F.Sort -> Bind a -> Cstr a -> [F.Qualifier] bindQuals env b c = predQuals env' bx (bPred b) ++ cstrQuals env' bx c@@ -155,6 +159,9 @@ } deriving (Data, Typeable, Generic, Functor, Eq, ToJSON, FromJSON) +instance F.ToHornSMT (Bind a) where+ toHornSMT (Bind x t p _) = P.parens (F.toHornSMT (x, t) P.<+> F.toHornSMT p)+ instance F.Subable (Bind a) where syms (Bind x _ p _) = x : F.syms p substa f (Bind v t p a) = Bind (f v) t (F.substa f p) a@@ -167,9 +174,17 @@ = Head !Pred !a -- ^ p | CAnd ![Cstr a] -- ^ c1 /\ ... /\ cn | All !(Bind a) !(Cstr a) -- ^ \all x:t. p => c- | Any !(Bind a) !(Cstr a) -- ^ \exi x:t. p /\ c or is it \exi x:t. p => c? deriving (Data, Typeable, Generic, Functor, Eq, ToJSON, FromJSON) +instance F.ToHornSMT (Cstr a) where+ toHornSMT = toHornCstr++toHornCstr :: Cstr a -> P.Doc+toHornCstr (Head p _) = F.toHornSMT p+toHornCstr (CAnd cs) = F.toHornAnd toHornCstr cs+toHornCstr (All b c) = P.parens (P.vcat ["forall" P.<+> F.toHornSMT b+ , P.nest 1 (toHornCstr c)])+ cLabel :: Cstr a -> a cLabel cstr = case go cstr of [] -> F.panic "everything is true!!!"@@ -178,13 +193,11 @@ go (Head _ l) = [l] go (CAnd cs) = mconcat $ go <$> cs go (All _ c) = go c- go (Any _ c) = go c -- We want all valid constraints to start with a binding at the top okCstr :: Cstr a -> Bool okCstr All {} = True-okCstr Any {} = True okCstr _ = False @@ -236,7 +249,9 @@ parseJSON (String t) = pure (Tag (T.unpack t)) parseJSON invalid = prependFailure "parsing `Tag` failed, " (typeMismatch "Object" invalid) -+instance F.ToHornSMT Tag where+ toHornSMT NoTag = mempty+ toHornSMT (Tag s) = P.text s @@ -284,13 +299,12 @@ instance Show Pred where show (Reft p) = parens $ F.showpp p- show (Var x xs) = parens $ "$" ++ unwords (F.symbolString <$> x:xs)+ show (Var x xs) = parens $ "$" ++ unwords (F.symbolString x : (parens . F.showpp <$> xs)) show (PAnd ps) = parens $ unwords $ "and": map show ps instance Show (Cstr a) where show (Head p _) = parens $ show p show (All b c) = parens $ unwords ["forall" , show b , show c]- show (Any b c) = parens $ unwords ["exists" , show b , show c] show (CAnd cs) = parens $ unwords $ "and" : map show cs instance Show (Bind a) where@@ -301,7 +315,7 @@ instance F.PPrint Pred where pprintPrec k t (Reft p) = P.parens $ F.pprintPrec k t p- pprintPrec _ _ (Var x xs) = P.parens $ P.ptext "$" <> P.hsep (P.ptext . F.symbolString <$> x:xs)+ pprintPrec k t (Var x xs) = P.parens $ P.ptext "$" <> P.hsep (P.ptext (F.symbolString x) : (P.parens. F.pprintPrec k t <$> xs)) pprintPrec k t (PAnd ps) = P.parens $ P.vcat $ P.ptext "and" : map (F.pprintPrec (k+2) t) ps instance F.PPrint (Cstr a) where@@ -309,170 +323,25 @@ pprintPrec k t (All b c) = P.parens $ P.vcat [ P.ptext "forall" P.<+> F.pprintPrec (k+2) t b , F.pprintPrec (k+1) t c ]- pprintPrec k t (Any b c) = P.parens $ P.vcat [P.ptext "exists" P.<+> F.pprintPrec (k+2) t b- , F.pprintPrec (k+1) t c- ] pprintPrec k t (CAnd cs) = P.parens $ P.vcat $ P.ptext "and" : map (F.pprintPrec (k+2) t) cs instance F.PPrint (Bind a) where pprintPrec _ _ b = P.ptext $ show b ---------------------------------------------------------------------------------------------------------------------- Human readable but robustly parseable SMT-LIB format pretty printer-------------------------------------------------------------------------------------------------------------------class ToHornSMT a where- toHornSMT :: a -> P.Doc--instance ToHornSMT Tag where- toHornSMT NoTag = mempty- toHornSMT (Tag s) = P.text s--instance ToHornSMT F.Symbol where- toHornSMT s = F.pprint s--instance ToHornSMT (Var a) where- toHornSMT (HVar k ts _) = P.parens ("var" P.<+> "$" P.<-> F.pprint k P.<+> toHornSMT ts)--instance ToHornSMT (Query a) where+instance F.ToHornSMT (Query a) where toHornSMT q = P.vcat $ L.intersperse " " [ P.vcat (toHornOpt <$> qOpts q) , P.vcat (toHornNum <$> qNums q)- , P.vcat (toHornSMT <$> qQuals q)- , P.vcat (toHornSMT <$> qVars q)+ , P.vcat (F.toHornSMT <$> qQuals q)+ , P.vcat (F.toHornSMT <$> qVars q) , P.vcat [toHornCon x t | (x, t) <- M.toList (qCon 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))])+ , P.vcat (F.eqnToHornSMT "define" <$> qEqns q)+ , P.vcat (F.eqnToHornSMT "define_fun" <$> qDefs q)+ , P.vcat (F.toHornSMT <$> qData q)+ , P.vcat (F.toHornSMT <$> qMats q)+ , P.parens (P.vcat ["constraint", P.nest 1 (F.toHornSMT (qCstr q))]) ] where- toHornNum x = toHornMany ["numeric", toHornSMT x]- toHornOpt str = toHornMany ["fixpoint", P.text ("\"" ++ str ++ "\"")]- toHornCon x t = toHornMany ["constant", toHornSMT x, toHornSMT t]--instance ToHornSMT F.Rewrite where- toHornSMT (F.SMeasure f d xs e) = P.parens ("match" P.<+> toHornSMT f P.<+> toHornSMT (d:xs) P.<+> toHornSMT e)--instance ToHornSMT F.Qualifier where- toHornSMT (F.Q n xts p _) = P.parens ("qualif" P.<+> F.pprint n P.<+> toHornSMT xts P.<+> toHornSMT p)--instance ToHornSMT F.QualParam where- toHornSMT qp = toHornSMT (F.qpSym qp, F.qpSort qp)--instance ToHornSMT a => ToHornSMT (F.Symbol, a) where- toHornSMT (x, t) = P.parens $ F.pprint x P.<+> toHornSMT t--instance ToHornSMT a => ToHornSMT [a] where- toHornSMT = toHornMany . fmap toHornSMT--toHornMany :: [P.Doc] -> P.Doc-toHornMany = P.parens . P.sep -- Misc.intersperse " "--toHornAnd :: (a -> P.Doc) -> [a] -> P.Doc-toHornAnd f xs = P.parens (P.vcat ("and" : (P.nest 1 . f <$> xs)))--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) =- P.parens $ P.vcat [- P.text "datatype" P.<+> P.parens (toHornSMT tc P.<+> P.int n)- , P.parens (P.vcat (toHornSMT <$> ctors))- ]--instance ToHornSMT F.FTycon where- toHornSMT c- | c == F.listFTyCon = "list"- | otherwise = toHornSMT (F.symbol c)--instance ToHornSMT a => ToHornSMT (F.Located a) where- toHornSMT = toHornSMT . F.val-instance ToHornSMT F.DataCtor where- toHornSMT (F.DCtor x flds) = P.parens (toHornSMT x P.<+> toHornSMT flds)--instance ToHornSMT F.DataField where- toHornSMT (F.DField x t) = toHornSMT (F.val x, t)--instance ToHornSMT F.Sort where- toHornSMT = toHornSort--toHornSort :: F.Sort -> P.Doc-toHornSort (F.FVar i) = "@" P.<-> P.parens (P.int i)-toHornSort F.FInt = "Int"-toHornSort F.FReal = "Real"-toHornSort F.FFrac = "Frac"-toHornSort (F.FObj x) = toHornSMT x -- P.parens ("obj" P.<+> toHornSMT x)-toHornSort F.FNum = "num"-toHornSort t@(F.FAbs _ _) = toHornAbsApp t-toHornSort t@(F.FFunc _ _)= toHornAbsApp t-toHornSort (F.FTC c) = toHornSMT c-toHornSort t@(F.FApp _ _) = toHornFApp (F.unFApp t)--toHornAbsApp :: F.Sort -> P.Doc-toHornAbsApp (F.functionSort -> Just (vs, ss, s)) = P.parens ("func" P.<+> P.int (length vs) P.<+> toHornSMT ss P.<+> toHornSMT s )-toHornAbsApp _ = error "Unexpected nothing function sort"--toHornFApp :: [F.Sort] -> P.Doc-toHornFApp [t] = toHornSMT t-toHornFApp ts = toHornSMT ts--instance ToHornSMT F.Subst where- toHornSMT (F.Su m) = toHornSMT (Misc.hashMapToAscList m)--instance ToHornSMT (Bind a) where- toHornSMT (Bind x t p _) = P.parens (toHornSMT (x, t) P.<+> toHornSMT p)--instance ToHornSMT Pred where- toHornSMT (Reft p) = P.parens (toHornSMT p)- toHornSMT (Var k xs) = toHornMany (toHornSMT (F.KV k) : (toHornSMT <$> xs))- toHornSMT (PAnd ps) = toHornMany ("and" : (toHornSMT <$> ps))--instance ToHornSMT F.KVar where- toHornSMT (F.KV k) = "$" P.<-> toHornSMT k--instance ToHornSMT F.Expr where- toHornSMT = toHornExpr--toHornExpr :: F.Expr -> P.Doc-toHornExpr (F.ESym c) = F.pprint c-toHornExpr (F.ECon c) = F.pprint c-toHornExpr (F.EVar s) = toHornSMT s-toHornExpr (F.ENeg e) = P.parens ("-" P.<+> toHornExpr e)-toHornExpr (F.EApp e1 e2) = toHornSMT [e1, e2]-toHornExpr (F.EBin o e1 e2) = toHornOp (F.toFix o) [e1, e2]-toHornExpr (F.EIte e1 e2 e3) = toHornOp "if" [e1, e2, e3]-toHornExpr (F.ECst e t) = toHornMany ["cast", toHornSMT e, toHornSMT t]-toHornExpr (F.PNot p) = toHornOp "not" [p]-toHornExpr (F.PImp e1 e2) = toHornOp "=>" [e1, e2]-toHornExpr (F.PIff e1 e2) = toHornOp "<=>" [e1, e2]-toHornExpr e@F.PTrue = F.pprint e-toHornExpr e@F.PFalse = F.pprint e-toHornExpr (F.PAnd es) = toHornOp "and" es-toHornExpr (F.POr es) = toHornOp "or" es-toHornExpr (F.PAtom r e1 e2) = toHornOp (F.toFix r) [e1, e2]-toHornExpr (F.PAll xts p) = toHornMany ["forall", toHornSMT xts, toHornSMT p]-toHornExpr (F.PExist xts p) = toHornMany ["exists", toHornSMT xts, toHornSMT p]-toHornExpr (F.ELam b e) = toHornMany ["lam", toHornSMT b, toHornSMT e]-toHornExpr (F.ECoerc a t e) = toHornMany ["coerce", toHornSMT a, toHornSMT t, toHornSMT e]-toHornExpr (F.PKVar k su) = toHornMany [toHornSMT k, toHornSMT su]-toHornExpr (F.ETApp e s) = toHornMany ["ETApp" , toHornSMT e, toHornSMT s]-toHornExpr (F.ETAbs e s) = toHornMany ["ETAbs" , toHornSMT e, toHornSMT s]-toHornExpr (F.PGrad k _ _ e) = toHornMany ["&&", toHornSMT e, toHornSMT k]--toHornOp :: ToHornSMT a => P.Doc -> [a] -> P.Doc-toHornOp op es = toHornMany (op : (toHornSMT <$> es))--instance ToHornSMT (Cstr a) where- toHornSMT = toHornCstr--toHornCstr :: Cstr a -> P.Doc-toHornCstr (Head p _) = toHornSMT p-toHornCstr (CAnd cs) = toHornAnd toHornCstr cs-toHornCstr (All b c) = P.parens (P.vcat ["forall" P.<+> toHornSMT b- , P.nest 1 (toHornCstr c)])-toHornCstr (Any b c) = P.parens (P.vcat ["exists" P.<+> toHornSMT b- , P.nest 1 (toHornCstr c)])+ toHornNum x = F.toHornMany ["numeric", F.toHornSMT x]+ toHornOpt str = F.toHornMany ["fixpoint", P.text ("\"" ++ str ++ "\"")]+ toHornCon x t = F.toHornMany ["constant", F.toHornSMT x, F.toHornSMT t]
src/Language/Fixpoint/Minimize.hs view
@@ -21,6 +21,11 @@ import Control.DeepSeq ---------------------------------------------------------------------------+-- | Top level Solvers ----------------------------------------------------+---------------------------------------------------------------------------+type Solver a = Config -> FInfo a -> IO (Result (Integer, a))++--------------------------------------------------------------------------- -- polymorphic delta debugging implementation --------------------------------------------------------------------------- deltaDebug :: Bool -> Oracle a c -> Config -> Solver a -> FInfo a -> [c] -> [c] -> IO [c]
src/Language/Fixpoint/Parse.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-}@@ -92,6 +91,7 @@ -- * Parsing Function , doParse'+ , doParse'' , parseTest' , parseFromFile , parseFromStdIn@@ -123,9 +123,7 @@ import qualified Data.IntMap.Strict as IM import qualified Data.HashMap.Strict as M import qualified Data.HashSet as S-#if !MIN_VERSION_base(4,20,0)-import Data.List (foldl')-#endif+import qualified Data.List as List import Data.List.NonEmpty (NonEmpty(..)) import qualified Data.Text as T import qualified Data.Text.IO as T@@ -231,6 +229,7 @@ , supply :: !Integer , layoutStack :: LayoutStack , numTyCons :: !(S.HashSet Symbol)+ , allowExists :: !Bool } type PState = PStateV Symbol @@ -476,6 +475,7 @@ , "func" , "autorewrite" , "rewrite"+ , "lit" -- reserved words used in liquid haskell , "forall"@@ -537,7 +537,7 @@ , "->" , ":=" , "&", "^", "<<", ">>", "--"- , "?", "Bexp"+ , "Bexp" , "'" , "_|_" , "|"@@ -677,7 +677,7 @@ -- * an error message to display if the final check fails. -- condIdR :: ParserV v Char -> (Char -> Bool) -> (String -> Bool) -> String -> ParserV v Symbol-condIdR initial okChars condition msg = do+condIdR initial okChars condition msg = try $ do s <- (:) <$> initial <*> takeWhileP Nothing okChars if condition s then pure (symbol s)@@ -789,28 +789,17 @@ -- This parser is reused by Liquid Haskell. -- expr0P :: ParseableV v => ParserV v (ExprV v)-expr0P- = trueP -- constant "true"- <|> falseP -- constant "false"- <|> (reservedOp "?" *> predP)- <|> fastIfP EIte exprP -- "if-then-else", starts with "if"- <|> coerceP exprP -- coercion, starts with "coerce"- <|> (ESym <$> symconstP) -- string literal, starts with double-quote- <|> (ECon <$> constantP) -- numeric literal, starts with a digit- <|> (reservedOp "_|_" >> return EBot) -- constant bottom, equivalent to "false"- <|> lamP -- lambda abstraction, starts with backslash- <|> try tupleP -- tuple expressions, starts with "("- <|> try (parens exprP) -- parenthesised expression, starts with "("- <|> try (parens exprCastP) -- explicit type annotation, starts with "(", TODO: should be an operator rather than require parentheses?- <|> EVar <$> parseV -- identifier, starts with any letter or underscore- <|> try (located (brackets (pure ())) >>= emptyListP) -- empty list, start with "["- <|> try (located (brackets exprP) >>= singletonListP) -- singleton list, starts with "["- --- -- Note:- --- -- In the parsers above, it is important that *all* parsers starting with "("- -- are prefixed with "try". This is because expr0P itself is chained with- -- additional parsers in funAppP ...+expr0P =+ botP+ <|> try (reserved "not") *> fmap PNot appliableExprP -- built-in prefix not+ <|> funAppP+ <|> existP+ <|> fastIfP EIte exprP -- "if-then-else", starts with "if"+ <|> try (coerceP exprP) -- coercion, starts with "coerce"+ <|> litP+ <|> lamP -- lambda abstraction, starts with backslash+ <|> (reservedOp "&&" >> PAnd <$> predsP) -- built-in prefix and+ <|> (reservedOp "||" >> POr <$> predsP) -- built-in prefix or emptyListP :: Located () -> ParserV v (ExprV v) emptyListP lx = do@@ -836,7 +825,7 @@ fastIfP :: ParseableV v => (ExprV v -> a -> a -> a) -> ParserV v a -> ParserV v a fastIfP f bodyP = do reserved "if"- p <- predP+ p <- exprP reserved "then" b1 <- bodyP reserved "else"@@ -848,35 +837,12 @@ (s, t) <- parens (pairP sortP (reservedOp "~") sortP) ECoerc s t <$> p ---{--qmIfP f bodyP- = parens $ do- p <- predP- reserved "?"- b1 <- bodyP- colon- b2 <- bodyP- return $ f p b1 b2--}---- | Parser for atomic expressions plus function applications.------ Base parser used in 'exprP' which adds in other operators.----expr1P :: ParseableV v => ParserV v (ExprV v)-expr1P- = try funAppP- <|> expr0P- -- | Expressions exprP :: ParseableV v => ParserV v (ExprV v)-exprP =- do+exprP = do table <- gets fixityTable- makeExprParser expr1P (flattenOpTable table)+ makeExprParser expr0P (flattenOpTable table) data Assoc = AssocNone | AssocLeft | AssocRight @@ -968,7 +934,7 @@ -- | Built-in operator table, parameterised over the composition function. bops :: forall v. ParseableV v => Maybe (Located String -> ExprV v) -> OpTable v-bops cmpFun = foldl' (flip addOperator) initOpTable builtinOps+bops cmpFun = List.foldl' (flip addOperator) initOpTable builtinOps where -- Built-in Haskell operators, see https://www.haskell.org/onlinereport/decls.html#fixity builtinOps :: [Fixity v]@@ -980,37 +946,55 @@ , FInfix (Just 5) "mod" (Just $ const $ EBin Mod) AssocLeft -- Haskell gives mod 7 , FInfix (Just 9) "." applyCompose AssocRight -- --- -- , FInfix (Just 4) "<" (Just $ PAtom Lt) AssocNone- -- , FInfix (Just 4) "==" (Just $ PAtom Eq) AssocNone- -- , FInfix (Just 4) "=" (Just $ PAtom Eq) AssocNone- -- , FInfix (Just 4) "~~" (Just $ PAtom Ueq) AssocNone- -- , FInfix (Just 4) "!=" (Just $ PAtom Ne) AssocNone- -- , FInfix (Just 4) "/=" (Just $ PAtom Ne) AssocNone- -- , FInfix (Just 4) "!~" (Just $ PAtom Une) AssocNone- -- , FInfix (Just 4) "<" (Just $ PAtom Lt) AssocNone- -- , FInfix (Just 4) "<=" (Just $ PAtom Le) AssocNone- -- , FInfix (Just 4) ">" (Just $ PAtom Gt) AssocNone- -- , FInfix (Just 4) ">=" (Just $ PAtom Ge) AssocNone+ , FInfix (Just 4) "==" (Just $ const $ PAtom Eq) AssocNone+ , FInfix (Just 4) "=" (Just $ const $ PAtom Eq) AssocNone+ , FInfix (Just 4) "~~" (Just $ const $ PAtom Ueq) AssocNone+ , FInfix (Just 4) "!=" (Just $ const $ PAtom Ne) AssocNone+ , FInfix (Just 4) "/=" (Just $ const $ PAtom Ne) AssocNone+ , FInfix (Just 4) "!~" (Just $ const $ PAtom Une) AssocNone+ , FInfix (Just 4) "<" (Just $ const $ PAtom Lt) AssocNone+ , FInfix (Just 4) "<=" (Just $ const $ PAtom Le) AssocNone+ , FInfix (Just 4) ">" (Just $ const $ PAtom Gt) AssocNone+ , FInfix (Just 4) ">=" (Just $ const $ PAtom Ge) AssocNone++ , FInfix (Just 3) "&&" (Just $ const $ \x y -> PAnd [x,y]) AssocRight+ , FInfix (Just 2) "||" (Just $ const $ \x y -> POr [x,y]) AssocRight+ , FInfix (Just 1) "=>" (Just $ const PImp) AssocRight+ , FInfix (Just 1) "==>" (Just $ const PImp) AssocRight+ , FInfix (Just 1) "<=>" (Just $ const PIff) AssocRight+ , FPrefix (Just 9) "~" (Just $ const PNot) ]+ applyCompose :: Maybe (Located String -> ExprV v -> ExprV v -> ExprV v) applyCompose = (\f lop x y -> f lop `eApps` [x,y]) <$> cmpFun -- | Parser for function applications.------ Andres, TODO: Why is this so complicated?--- funAppP :: ParseableV v => ParserV v (ExprV v)-funAppP = litP <|> exprFunP <|> simpleAppP- where- exprFunP = eApps <$> funSymbolP <*> funRhsP- funRhsP = some expr0P- <|> parens innerP- innerP = brackets (sepBy exprP semi)+funAppP = do+ f <- appliableExprP+ foldl EApp f <$> (<|>)+ (try $ parens $ brackets $ sepBy exprP semi) -- special form: f ([e1; e2; ...; en])+ (many appliableExprP) -- normal function application: f e1 e2 ... en - -- TODO:AZ the parens here should be superfluous, but it hits an infinite loop if removed- simpleAppP = EApp <$> parens exprP <*> parens exprP- funSymbolP = EVar <$> parseV+appliableExprP :: ParseableV v => ParserV v (ExprV v)+appliableExprP =+ trueP -- constant "true"+ <|> falseP -- constant "false"+ <|> (ESym <$> symconstP) -- string literal, starts with double-quote+ <|> (ECon <$> constantP) -- numeric literal, starts with a digit+ <|> botP+ <|> try tupleP -- tuple expressions, starts with "("+ <|> try (parens exprP) -- parenthesised expression, starts with "("+ <|> try (parens exprCastP) -- explicit type annotation, starts with "(", TODO: should be an operator rather than require parentheses?+ <|> EVar <$> parseV -- identifier, starts with any letter or underscore+ <|> try (located (brackets (pure ())) >>= emptyListP) -- empty list, start with "["+ <|> try (located (brackets exprP) >>= singletonListP) -- singleton list, starts with "["+ <|> kvarPredP +-- | constant bottom, equivalent to "false"+botP :: ParserV v (ExprV v)+botP = reservedOp "_|_" >> return EBot+ -- | Parser for tuple expressions (two or more components). tupleP :: ParseableV v => ParserV v (ExprV v) tupleP = do@@ -1035,9 +1019,10 @@ t <- sortP reservedOp "->" ELam (x, t) <$> exprP+ <?> "lambda abstraction" varSortP :: ParserV v Sort-varSortP = FVar <$> parens intP+varSortP = FVar <$> parens (fromInteger <$> integerP) -- | Parser for function sorts without the "func" keyword. funcSortP :: ParserV v Sort@@ -1072,6 +1057,7 @@ <|> (fAppTC listFTyCon . pure <$> brackets sortP) <|> (fAppTC <$> fTyConP <*> appArgsP) <|> (fApp <$> tvarP <*> appArgsP)+ <|> (FNatNum <$> natural) tvarP :: ParserV v Sort tvarP@@ -1100,31 +1086,6 @@ -- | Predicates ---------------------------------------------------------------- -------------------------------------------------------------------------------- --- | Parser for "atomic" predicates.------ This parser is reused by Liquid Haskell.----pred0P :: ParseableV v => ParserV v (ExprV v)-pred0P = trueP -- constant "true"- <|> falseP -- constant "false"- <|> (reservedOp "??" >> makeUniquePGrad)- <|> kvarPredP- <|> fastIfP pIte predP -- "if-then-else", starts with "if"- <|> try predrP -- binary relation, starts with anything that an expr can start with- <|> parens predP -- parenthesised predicate, starts with "("- <|> (reservedOp "?" *> exprP)- <|> try funAppP- <|> EVar <$> parseV -- identifier, starts with any letter or underscore- <|> (reservedOp "&&" >> pGAnds <$> predsP) -- built-in prefix and- <|> (reservedOp "||" >> POr <$> predsP) -- built-in prefix or--makeUniquePGrad :: ParserV v (ExprV v)-makeUniquePGrad- = do uniquePos <- getSourcePos- return $ PGrad (KV $ symbol $ show uniquePos) (Su mempty) (srcGradInfo uniquePos) PTrue---- qmP = reserved "?" <|> reserved "Bexp"- -- | Parser for the reserved constant "true". trueP :: ParserV v (ExprV v) trueP = reserved "true" >> return PTrue@@ -1150,53 +1111,23 @@ -- disjunction. -- predsP :: ParseableV v => ParserV v [ExprV v]-predsP = brackets $ sepBy predP semi+predsP = brackets $ sepBy exprP semi -- | Parses a predicate. ----- Unlike for expressions, there is a built-in operator list.--- predP :: ParseableV v => ParserV v (ExprV v)-predP = makeExprParser pred0P lops- where- lops = [ [Prefix (reservedOp "~" >> return PNot)]- , [Prefix (reserved "not" >> return PNot)]- , [InfixR (reservedOp "&&" >> return pGAnd)]- , [InfixR (reservedOp "||" >> return (\x y -> POr [x,y]))]- , [InfixR (reservedOp "=>" >> return PImp)]- , [InfixR (reservedOp "==>" >> return PImp)]- , [InfixR (reservedOp "=" >> return PIff)]- , [InfixR (reservedOp "<=>" >> return PIff)]- , [InfixR (reservedOp "!=" >> return pNotIff)]- , [InfixR (reservedOp "/=" >> return pNotIff)]- ]--pNotIff :: ExprV v -> ExprV v -> ExprV v-pNotIff x y = PNot (PIff x y)---- | Parses a relation predicate.------ Binary relations connect expressions and predicates.----predrP :: ParseableV v => ParserV v (ExprV v)-predrP =- (\ e1 r e2 -> r e1 e2) <$> exprP <*> brelP <*> exprP+predP = exprP --- | Parses a relation symbol.------ There is a built-in table of available relations.----brelP :: ParserV v (ExprV v -> ExprV v -> ExprV v)-brelP = (reservedOp "==" >> return (PAtom Eq))- <|> (reservedOp "=" >> return (PAtom Eq))- <|> (reservedOp "~~" >> return (PAtom Ueq))- <|> (reservedOp "!=" >> return (PAtom Ne))- <|> (reservedOp "/=" >> return (PAtom Ne))- <|> (reservedOp "!~" >> return (PAtom Une))- <|> (reservedOp "<" >> return (PAtom Lt))- <|> (reservedOp "<=" >> return (PAtom Le))- <|> (reservedOp ">" >> return (PAtom Gt))- <|> (reservedOp ">=" >> return (PAtom Ge))+existP :: ParseableV v => ParserV v (ExprV v)+existP = do+ allow <- gets allowExists+ if allow then do+ reserved "exists"+ bs <- brackets $ sepBy ((,) <$> bindP <*> sortP) comma+ _ <- dot+ PExist bs <$> exprP+ else+ empty -------------------------------------------------------------------------------- -- | BareTypes -----------------------------------------------------------------@@ -1204,8 +1135,8 @@ -- | Refa refaP :: ParseableV v => ParserV v (ExprV v)-refaP = try (pAnd <$> brackets (sepBy predP semi))- <|> predP+refaP = try (PAnd <$> brackets (sepBy exprP semi))+ <|> exprP -- | (Sorted) Refinements with configurable sub-parsers@@ -1260,8 +1191,7 @@ pos <- getSourcePos n <- upperIdP params <- parens $ sepBy1 (qualParamP tP) comma- _ <- colon- body <- predP+ body <- braces exprP return $ mkQual n params body pos qualParamP :: ParserV v Sort -> ParserV v QualParam@@ -1302,8 +1232,10 @@ _ <- spaces _ <- reserved "=" _ <- spaces- (lhs, rhs) <- braces $- pairP exprP (reserved "=") exprP+ e <- braces exprP+ (lhs, rhs) <- case e of+ PAtom Eq l r -> return (l, r)+ _ -> error "Expected rewrite rule of the form: LHS = RHS" return $ AutoRewrite args lhs rhs @@ -1312,9 +1244,7 @@ name <- symbolP params <- parens $ sepBy (symBindP sortP) comma sort <- colon *> sortP- body <- reserved "=" *> braces (- if sort == boolSort then predP else exprP- )+ body <- reserved "=" *> braces exprP return $ mkEquation name params body sort defineLocalP :: Parser (Int, [(Symbol, Expr)])@@ -1331,7 +1261,7 @@ return (x, e) matchP :: Parser Rewrite-matchP = SMeasure <$> symbolP <*> symbolP <*> many symbolP <*> (reserved "=" >> exprP)+matchP = SMeasure <$> symbolP <*> symbolP <*> many symbolP <*> braces exprP pairsP :: Parser a -> Parser b -> Parser [(a, b)] pairsP aP bP = brackets $ sepBy (pairP aP (reserved ":") bP) semi@@ -1444,20 +1374,23 @@ intP :: ParserV v Int intP = fromInteger <$> natural +integerP :: ParserV v Integer+integerP =+ (try (char '-') >> negate <$> natural)+ <|> natural+ boolP :: Parser Bool boolP = (reserved "True" >> return True) <|> (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 mempty+defsFInfo defs = {- SCC "defsFI" -} Types.FI cm ws bs lts dts kts qs binfo adts mempty mempty ae lrws mempty where cm = Misc.safeFromList "defs-cm" [(cid c, c) | Cst c <- defs] ws = Misc.safeFromList "defs-ws" [(i, w) | Wfc w <- defs, let i = Misc.thd3 (wrft w)]- bs = bindEnvFromList $ exBinds ++ [(n,(x,r,a)) | IBind n x r a <- defs]- ebs = [ n | (n,_) <- exBinds]- exBinds = [(n, (x, RR t trueReft, a)) | EBind n x t a <- defs]+ bs = bindEnvFromList [(n,(x,r,a)) | IBind n x r a <- defs] lts = fromListSEnv [(x, t) | Con x t <- defs] dts = fromListSEnv [(x, t) | Dis x t <- defs] kts = KS $ S.fromList [k | Kut k <- defs]@@ -1468,7 +1401,7 @@ rews = [r | Mat r <- defs] autoRWs = M.fromList [(arId , s) | AutoRW arId s <- defs] rwEntries = [(i, f) | RWMap fs <- defs, (i,f) <- fs]- rwMap = foldl' insert (M.fromList []) rwEntries+ rwMap = List.foldl' insert (M.fromList []) rwEntries where insert map' (cid', arId) = case M.lookup arId autoRWs of@@ -1498,28 +1431,6 @@ msg <- takeWhileP Nothing (const True) -- consume the rest of the input return $ Crash [(i, Nothing)] msg -predSolP :: Parser Expr-predSolP = parens (predP <* (comma >> iQualP))--iQualP :: Parser [Symbol]-iQualP = upperIdP >> parens (sepBy symbolP comma)--solution1P :: Parser (KVar, Expr)-solution1P = do- reserved "solution:"- k <- kvP- reservedOp ":="- ps <- brackets $ sepBy predSolP semi- return (k, simplify $ PAnd ps)- where- kvP = try kvarP <|> (KV <$> symbolP)--solutionP :: Parser (M.HashMap KVar Expr)-solutionP = M.fromList <$> sepBy solution1P spaces--solutionFileP :: Parser (FixResult Integer, M.HashMap KVar Expr)-solutionFileP = (,) <$> fixResultP natural <*> solutionP- -------------------------------------------------------------------------------- -- | Parse via the given parser, and obtain the rest of the input@@ -1547,6 +1458,7 @@ , supply = 0 , layoutStack = Empty , numTyCons = S.empty+ , allowExists = False } -- | Entry point for parsing, for testing.@@ -1555,8 +1467,11 @@ -- Fails with an exception on a parse error. -- doParse' :: Parser a -> SourceName -> String -> a-doParse' parser fileName input =- case runParser (evalStateT (spaces *> parser <* eof) (initPState Nothing)) fileName input of+doParse' = doParse'' False++doParse'' :: Bool -> Parser a -> SourceName -> String -> a+doParse'' allowEx parser fileName input =+ case runParser (evalStateT (spaces *> parser <* eof) ((initPState Nothing) { allowExists = allowEx})) fileName input of Left peb@(ParseErrorBundle errors posState) -> -- parse errors; we extract the first error from the error bundle let ((_, pos) :| _, _) = attachSourcePos errorOffset errors posState@@ -1600,7 +1515,7 @@ <|> (reserved "push" >> return Push) <|> (reserved "pop" >> return Pop) <|> (reserved "check" >> return CheckSat)- <|> (reserved "assert" >> (Assert Nothing <$> predP))+ <|> (reserved "assert" >> (Assert Nothing <$> exprP)) <|> (reserved "distinct" >> (Distinct <$> brackets (sepBy exprP comma))) cmdVarP :: Parser Command@@ -1632,9 +1547,6 @@ instance Inputable (FixResult Integer) where rr' = doParse' $ fixResultP natural -instance Inputable (FixResult Integer, FixSolution) where- rr' = doParse' solutionFileP- instance Inputable (FInfo ()) where rr' = {- SCC "fInfoP" -} doParse' fInfoP @@ -1647,100 +1559,3 @@ instance Inputable [Command] where rr' = doParse' commandsP -{--------------------------------------------------------------------------------------------- Testing ----------------------------------------------------------------------------------------------- A few tricky predicates for parsing--- myTest1 = "((((v >= 56320) && (v <= 57343)) => (((numchars a o ((i - o) + 1)) == (1 + (numchars a o ((i - o) - 1)))) && (((numchars a o (i - (o -1))) >= 0) && (((i - o) - 1) >= 0)))) && ((not (((v >= 56320) && (v <= 57343)))) => (((numchars a o ((i - o) + 1)) == (1 + (numchars a o (i - o)))) && ((numchars a o (i - o)) >= 0))))"------ myTest2 = "len x = len y - 1"--- myTest3 = "len x y z = len a b c - 1"--- myTest4 = "len x y z = len a b (c - 1)"--- myTest5 = "x >= -1"--- myTest6 = "(bLength v) = if n > 0 then n else 0"--- myTest7 = "(bLength v) = (if n > 0 then n else 0)"--- myTest8 = "(bLength v) = (n > 0 ? n : 0)"---sa = "0"-sb = "x"-sc = "(x0 + y0 + z0) "-sd = "(x+ y * 1)"-se = "_|_ "-sf = "(1 + x + _|_)"-sg = "f(x,y,z)"-sh = "(f((x+1), (y * a * b - 1), _|_))"-si = "(2 + f((x+1), (y * a * b - 1), _|_))"--s0 = "true"-s1 = "false"-s2 = "v > 0"-s3 = "(0 < v && v < 100)"-s4 = "(x < v && v < y+10 && v < z)"-s6 = "[(v > 0)]"-s6' = "x"-s7' = "(x <=> y)"-s8' = "(x <=> a = b)"-s9' = "(x <=> (a <= b && b < c))"--s7 = "{ v: Int | [(v > 0)] }"-s8 = "x:{ v: Int | v > 0 } -> {v : Int | v >= x}"-s9 = "v = x+y"-s10 = "{v: Int | v = x + y}"--s11 = "x:{v:Int | true } -> {v:Int | true }"-s12 = "y : {v:Int | true } -> {v:Int | v = x }"-s13 = "x:{v:Int | true } -> y:{v:Int | true} -> {v:Int | v = x + y}"-s14 = "x:{v:a | true} -> y:{v:b | true } -> {v:a | (x < v && v < y) }"-s15 = "x:Int -> Bool"-s16 = "x:Int -> y:Int -> {v:Int | v = x + y}"-s17 = "a"-s18 = "x:a -> Bool"-s20 = "forall a . x:Int -> Bool"--s21 = "x:{v : GHC.Prim.Int# | true } -> {v : Int | true }"--r0 = (rr s0) :: Pred-r0' = (rr s0) :: [Refa]-r1 = (rr s1) :: [Refa]---e1, e2 :: Expr-e1 = rr "(k_1 + k_2)"-e2 = rr "k_1"--o1, o2, o3 :: FixResult Integer-o1 = rr "SAT "-o2 = rr "UNSAT [1, 2, 9,10]"-o3 = rr "UNSAT []"---- sol1 = doParse solution1P "solution: k_5 := [0 <= VV_int]"--- sol2 = doParse solution1P "solution: k_4 := [(0 <= VV_int)]"--b0, b1, b2, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13 :: BareType-b0 = rr "Int"-b1 = rr "x:{v:Int | true } -> y:{v:Int | true} -> {v:Int | v = x + y}"-b2 = rr "x:{v:Int | true } -> y:{v:Int | true} -> {v:Int | v = x - y}"-b4 = rr "forall a . x : a -> Bool"-b5 = rr "Int -> Int -> Int"-b6 = rr "(Int -> Int) -> Int"-b7 = rr "({v: Int | v > 10} -> Int) -> Int"-b8 = rr "(x:Int -> {v: Int | v > x}) -> {v: Int | v > 10}"-b9 = rr "x:Int -> {v: Int | v > x} -> {v: Int | v > 10}"-b10 = rr "[Int]"-b11 = rr "x:[Int] -> {v: Int | v > 10}"-b12 = rr "[Int] -> String"-b13 = rr "x:(Int, [Bool]) -> [(String, String)]"---- b3 :: BareType--- b3 = rr "x:Int -> y:Int -> {v:Bool | ((v is True) <=> x = y)}"--m1 = ["len :: [a] -> Int", "len (Nil) = 0", "len (Cons x xs) = 1 + len(xs)"]-m2 = ["tog :: LL a -> Int", "tog (Nil) = 100", "tog (Cons y ys) = 200"]--me1, me2 :: Measure.Measure BareType Symbol-me1 = (rr $ intercalate "\n" m1)-me2 = (rr $ intercalate "\n" m2)--}
src/Language/Fixpoint/Smt/Interface.hs view
@@ -45,13 +45,14 @@ , smtDecls , smtDefineFunc , smtAssert+ , smtAssertDecl , smtFuncDecl , smtAssertAxiom , smtCheckUnsat- , smtCheckSat , smtBracket, smtBracketAt , smtDistinct , smtPush, smtPop+ , smtComment -- * Check Validity , checkValid@@ -59,10 +60,12 @@ , checkValidWithContext , checkValids + , funcSortVars+ ) where import Language.Fixpoint.Types.Config ( SMTSolver (..), solverFlags- , Config (solver, smtTimeout, gradual, stringTheory, save))+ , Config (solver, smtTimeout, noStringTheory, save, allowHO)) import qualified Language.Fixpoint.Misc as Misc import Language.Fixpoint.Types.Errors import Language.Fixpoint.Utils.Files@@ -73,6 +76,7 @@ import Language.Fixpoint.Smt.Serialize () import Control.Applicative ((<|>)) import Control.Monad+import Control.Monad.State import Control.Exception import Data.ByteString.Builder (Builder) import qualified Data.ByteString.Builder as BS@@ -80,6 +84,7 @@ import qualified Data.ByteString.Lazy.Char8 as Char8 import Data.Char import qualified Data.HashMap.Strict as M+import Data.List (uncons) import Data.Maybe (fromMaybe) import qualified Data.Text as T import qualified Data.Text.Encoding as TE@@ -102,6 +107,7 @@ import qualified SMTLIB.Backends.Process as Process import qualified Language.Fixpoint.Conditional.Z3 as Conditional.Z3 import Control.Concurrent.Async (async)+import GHC.Stack (HasCallStack) {- runFile f@@ -117,36 +123,43 @@ return zs -} -checkValidWithContext :: Context -> [(Symbol, Sort)] -> Expr -> Expr -> IO Bool-checkValidWithContext me xts p q =- smtBracket me "checkValidWithContext" $- checkValid' me xts p q+checkValidWithContext+ :: HasCallStack => [(Symbol, Sort)] -> Expr -> Expr -> SmtM Bool+checkValidWithContext xts p q =+ smtBracket "checkValidWithContext" $+ checkValid' xts p q -- | type ClosedPred E = {v:Pred | subset (vars v) (keys E) } -- checkValid :: e:Env -> ClosedPred e -> ClosedPred e -> IO Bool-checkValid :: Config -> FilePath -> [(Symbol, Sort)] -> Expr -> Expr -> IO Bool+checkValid+ :: HasCallStack+ => Config -> FilePath -> [(Symbol, Sort)] -> Expr -> Expr -> IO Bool checkValid cfg f xts p q = do me <- makeContext cfg f- checkValid' me xts p q+ evalStateT (checkValid' xts p q) me -checkValid' :: Context -> [(Symbol, Sort)] -> Expr -> Expr -> IO Bool-checkValid' me xts p q = do- smtDecls me xts- smtAssert me $ pAnd [p, PNot q]- smtCheckUnsat me+checkValid' :: HasCallStack => [(Symbol, Sort)] -> Expr -> Expr -> SmtM Bool+checkValid' xts p q = do+ smtDecls xts+ smtAssertDecl $ pAnd [p, PNot q]+ smtCheckUnsat -- | If you already HAVE a context, where all the variables have declared types -- (e.g. if you want to make MANY repeated Queries) -- checkValid :: e:Env -> [ClosedPred e] -> IO [Bool] checkValids :: Config -> FilePath -> [(Symbol, Sort)] -> [Expr] -> IO [Bool]-checkValids cfg f xts ps- = do me <- makeContext cfg f- smtDecls me xts- forM ps $ \p ->- smtBracket me "checkValids" $- smtAssert me (PNot p) >> smtCheckUnsat me+checkValids cfg f xts ps = do+ me <- makeContext cfg f+ evalStateT (checkValids' xts ps) me +checkValids' :: [(Symbol, Sort)] -> [Expr] -> SmtM [Bool]+checkValids' xts ps = do+ smtDecls xts+ forM ps $ \p ->+ smtBracket "checkValids" $+ smtAssert (PNot p) >> smtCheckUnsat+ -- debugFile :: FilePath -- debugFile = "DEBUG.smt2" @@ -154,42 +167,55 @@ -- | SMT IO -------------------------------------------------------------------- -------------------------------------------------------------------------------- +commandRaw :: Maybe Handle -> SMTLIB.Backends.Solver -> Bool -> Builder -> IO Response+commandRaw ctxLog ctxSolver ctxVerbose cmdBS = do+ resp <- SMTLIB.Backends.command ctxSolver cmdBS+ let respTxt =+ TE.decodeUtf8With (const $ const $ Just ' ') $+ LBS.toStrict resp+ case A.parseOnly responseP respTxt of+ Left e -> Misc.errorstar $ "SMTREAD:" ++ e+ Right r -> do+ let textResponse = "; SMT Says: " <> T.pack (show r)+ forM_ ctxLog $ \h ->+ Data.Text.IO.hPutStrLn h textResponse+ when ctxVerbose $+ Data.Text.IO.putStrLn textResponse+ return r+ -------------------------------------------------------------------------------- {-# SCC command #-}-command :: Context -> Command -> IO Response+command :: HasCallStack => Command -> SmtM Response ---------------------------------------------------------------------------------command Ctx{..} !cmd = do+command !cmd = do -- whenLoud $ do LTIO.appendFile debugFile (s <> "\n") -- LTIO.putStrLn ("CMD-RAW:" <> s <> ":CMD-RAW:DONE")- forM_ ctxLog $ \h -> do+ ctxLog <- gets ctxLog+ ctxSolver <- gets ctxSolver+ ctxVerbose <- gets ctxVerbose+ cmdBS <- liftSym $ runSmt2 cmd+ forM_ ctxLog $ \h -> lift $ do BS.hPutBuilder h cmdBS LBS.hPutStr h "\n"- case cmd of- CheckSat -> commandRaw- GetValue _ -> commandRaw+ lift $ case cmd of+ CheckSat -> commandRaw ctxLog ctxSolver ctxVerbose cmdBS+ GetValue _ -> commandRaw ctxLog ctxSolver ctxVerbose cmdBS _ -> SMTLIB.Backends.command_ ctxSolver cmdBS >> return Ok- where- commandRaw = do- resp <- SMTLIB.Backends.command ctxSolver cmdBS- let respTxt =- TE.decodeUtf8With (const $ const $ Just ' ') $- LBS.toStrict resp- parse respTxt- cmdBS = {-# SCC "Command-runSmt2" #-} runSmt2 ctxSymEnv cmd- parse resp = do- case A.parseOnly responseP resp of- Left e -> Misc.errorstar $ "SMTREAD:" ++ e- Right r -> do- let textResponse = "; SMT Says: " <> T.pack (show r)- forM_ ctxLog $ \h ->- Data.Text.IO.hPutStrLn h textResponse- when ctxVerbose $- Data.Text.IO.putStrLn textResponse- return r -smtSetMbqi :: Context -> IO ()-smtSetMbqi me = interact' me SetMbqi+-- | A variant of `command` that accepts a pre-built command+commandB :: Builder -> SmtM Response+--------------------------------------------------------------------------------+commandB cmdBS = do+ ctxLog <- gets ctxLog+ ctxSolver <- gets ctxSolver+ forM_ ctxLog $ \h -> lift $ do+ BS.hPutBuilder h cmdBS+ LBS.hPutStr h "\n"+ lift $ SMTLIB.Backends.command_ ctxSolver cmdBS >> return Ok +smtSetMbqi :: SmtM ()+smtSetMbqi = interact' SetMbqi+ type SmtParser a = Parser T.Text a responseP :: SmtParser Response@@ -254,12 +280,11 @@ where smtFile = extFileName Smt2 f -makeContextWithSEnv :: Config -> FilePath -> SymEnv -> [Equation] -> IO Context+makeContextWithSEnv :: Config -> FilePath -> SymEnv -> DefinedFuns -> IO Context makeContextWithSEnv cfg f env defns = do- ctx <- makeContext cfg f+ ctx <- makeContext cfg f let ctx' = ctx {ctxSymEnv = env, ctxDefines = defns}- declare ctx'- return ctx'+ execStateT declare ctx' makeContextNoLog :: Config -> IO Context makeContextNoLog cfg = do@@ -307,16 +332,22 @@ Cvc5 -> makeProcess ctxLog $ Process.defaultConfig { Process.exe = "cvc5"- , Process.args = ["-L", "smtlib2"] }+ , Process.args = ["-L", "smtlib2", "--arrays-exp"] } solver <- SMTLIB.Backends.initSolver SMTLIB.Backends.Queuing backend loud <- isLoud return Ctx { ctxSolver = solver- , ctxElabF = solverFlags slv+ , ctxElabF = solverFlags cfg , ctxClose = closeIO , ctxLog = ctxLog , ctxVerbose = loud , ctxSymEnv = mempty+ , ctxIxs = [] , ctxDefines = mempty+ -- This is a heurstic to avoid generating large sequences of unused `lam_arg` symbols+ -- when there's no higher-order reasoning. It might require some tuning on larger codebases+ -- if `unknown function/constant lam_arg$XXX` errors are encountered.+ , ctxLams = allowHO cfg+ , config = cfg } -- | Close file handles and release the solver backend's resources.@@ -333,9 +364,11 @@ | s == Z3 || s == Z3mem = do v <- getZ3Version me checkValidStringFlag Z3 v cfg- return $ makeMbqi cfg ++ makeTimeout cfg ++ Thy.preamble cfg Z3+ return $ makeMbqi ++ makeTimeout cfg ++ Thy.preamble cfg Z3 | otherwise = checkValidStringFlag s [] cfg >> return (Thy.preamble cfg s)+ where+ makeMbqi = ["\n(set-option :smt.mbqi false)"] getZ3Version :: Context -> IO [Int] getZ3Version me@@ -361,58 +394,59 @@ noString :: SMTSolver -> [Int] -> Config -> Bool noString smt v cfg- = stringTheory cfg- && not (smt == Z3 && (v >= [4, 4, 2]))-+ = not (noStringTheory cfg)+ && not (smt == Cvc5 || (smt == Z3 && (v >= [4, 4, 2]))) ----------------------------------------------------------------------------- -- | SMT Commands ----------------------------------------------------------- ----------------------------------------------------------------------------- -smtPush, smtPop :: Context -> IO ()-smtPush me = interact' me Push-smtPop me = interact' me Pop+smtPush, smtPop :: SmtM ()+smtPush = interact' Push+smtPop = interact' Pop -smtDecls :: Context -> [(Symbol, Sort)] -> IO ()-smtDecls = mapM_ . uncurry . smtDecl+smtComment :: T.Text -> SmtM ()+smtComment t = interact' (Comment t) -smtDecl :: Context -> Symbol -> Sort -> IO ()-smtDecl me x t = interact' me ({- notracepp msg $ -} Declare (symbolSafeText x) ins' out')+smtDecls :: [(Symbol, Sort)] -> SmtM ()+smtDecls = mapM_ $ uncurry smtDecl++smtDecl :: Symbol -> Sort -> SmtM ()+smtDecl x t = do+ me <- get+ let env = seData (ctxSymEnv me)+ let ins' = sortSmtSort False env <$> ins+ let out' = sortSmtSort False env out+ interact' (notracepp _msg $ Declare (symbolSafeText x) ins' out') where- ins' = sortSmtSort False env <$> ins- out' = sortSmtSort False env out (ins, out) = deconSort t- _msg = "smtDecl: " ++ showpp (x, t, ins, out)- env = seData (ctxSymEnv me)+ _msg = "smtDecl: " ++ showpp (x, t, ins, out) -smtFuncDecl :: Context -> T.Text -> ([SmtSort], SmtSort) -> IO ()-smtFuncDecl me x (ts, t) = interact' me (Declare x ts t)+smtFuncDecl :: T.Text -> ([SmtSort], SmtSort) -> SmtM ()+smtFuncDecl x (ts, t) = interact' (Declare x ts t) -smtDataDecl :: Context -> [DataDecl] -> IO ()-smtDataDecl me ds = interact' me (DeclData ds)+smtDataDecl :: [DataDecl] -> SmtM ()+smtDataDecl ds = interact' (DeclData ds) deconSort :: Sort -> ([Sort], Sort) deconSort t = case functionSort t of Just (_, ins, out) -> (ins, out) Nothing -> ([], t) --- hack now this is used only for checking gradual condition.-smtCheckSat :: Context -> Expr -> IO Bool-smtCheckSat me p- = smtAssert me p >> (ans <$> command me CheckSat)- where- ans Sat = True- ans _ = False+smtAssert :: Expr -> SmtM ()+smtAssert p = interact' (Assert Nothing p) -smtAssert :: Context -> Expr -> IO ()-smtAssert me p = interact' me (Assert Nothing p)+-- the following three functions will emit additional `apply`,+-- `coerce`, and `lambda` symbols for fresh function sorts as needed+smtAssertDecl :: HasCallStack => Expr -> SmtM ()+smtAssertDecl p = interactDecl' (Assert Nothing p) -smtDefineEqn :: Context -> Equation -> IO ()-smtDefineEqn me Equ {..} = smtDefineFunc me eqName eqArgs eqSort eqBody+smtDefineEqn :: Equation -> SmtM ()+smtDefineEqn Equ {..} = smtDefineFunc 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 $+smtDefineFunc :: Symbol -> [(Symbol, F.Sort)] -> F.Sort -> Expr -> SmtM ()+smtDefineFunc name symList rsort e =+ do env <- gets (seData . ctxSymEnv)+ interactDecl' $ DefineFunc name (map (sortSmtSort False env <$>) symList)@@ -421,34 +455,60 @@ ----------------------------------------------------------------- -smtAssertAxiom :: Context -> Triggered Expr -> IO ()-smtAssertAxiom me p = interact' me (AssertAx p)+smtAssertAxiom :: Triggered Expr -> SmtM ()+smtAssertAxiom p = interact' (AssertAx p) -smtDistinct :: Context -> [Expr] -> IO ()-smtDistinct me az = interact' me (Distinct az)+smtDistinct :: [Expr] -> SmtM ()+smtDistinct az = interact' (Distinct az) -smtCheckUnsat :: Context -> IO Bool-smtCheckUnsat me = respSat <$> command me CheckSat+smtCheckUnsat :: HasCallStack => SmtM Bool+smtCheckUnsat = respSat <$> command CheckSat -smtBracketAt :: SrcSpan -> Context -> String -> IO a -> IO a-smtBracketAt sp x y z = smtBracket x y z `catch` dieAt sp+smtBracketAt :: SrcSpan -> String -> SmtM a -> SmtM a+smtBracketAt sp _msg a =+ smtBracket _msg a `catchSMT` dieAt sp -smtBracket :: Context -> String -> IO a -> IO a-smtBracket me _msg a = do- smtPush me+-- | `smtBracket` adds a new level to the apply stack and saves the last fresh index+-- on the index stack before the action, and reverts these changes after the action.+smtBracket :: String -> SmtM a -> SmtM a+smtBracket msg a = do+ smtComment (T.pack $ "smtBracket - start: " ++ msg)+ smtPush+ modify $ \ctx ->+ let env = ctxSymEnv ctx in+ ctx { ctxSymEnv = env { seAppls = pushAppls (seAppls env) }+ , ctxIxs = seIx env : ctxIxs ctx} r <- a- smtPop me+ smtPop+ smtComment (T.pack $ "smtBracket - end: " ++ msg)+ modify $ \ctx ->+ let env = ctxSymEnv ctx+ (i , is) = fromMaybe (0, []) (uncons $ ctxIxs ctx)+ in+ ctx { ctxSymEnv = env {seAppls = popAppls (seAppls env) , seIx = i}+ , ctxIxs = is} return r -respSat :: Response -> Bool+respSat :: HasCallStack => Response -> Bool respSat Unsat = True respSat Sat = False respSat Unknown = False respSat r = die $ err dummySpan $ text ("crash: SMTLIB2 respSat = " ++ show r) -interact' :: Context -> Command -> IO ()-interact' me cmd = void $ command me cmd+interact' :: Command -> SmtM ()+interact' cmd = void $ command cmd +-- | a variant of `interact'` which also emits fresh+-- `apply`, `coerce`, and `lambda` symbols+interactDecl' :: HasCallStack => Command -> SmtM ()+interactDecl' cmd = do+ cmdBS <- liftSym $ runSmt2 cmd+ ctx <- get+ let env = ctxSymEnv ctx+ let ats = funcSortVars (ctxLams ctx) env+ forM_ ats $ uncurry smtFuncDecl+ put (ctx {ctxSymEnv = env {seAppls = mergeTopAppls (seApplsCur env) (seAppls env), seApplsCur = M.empty} })+ void $ commandB cmdBS makeTimeout :: Config -> [Builder] makeTimeout cfg@@ -456,36 +516,28 @@ | otherwise = [""] -makeMbqi :: Config -> [Builder]-makeMbqi cfg- | gradual cfg = [""]- | otherwise = ["\n(set-option :smt.mbqi false)"]-- ---------------------------------------------------------------------------------declare :: Context -> IO ()+declare :: SmtM () ---------------------------------------------------------------------------------declare me = do- forM_ dss $ smtDataDecl me- 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- env = ctxSymEnv me- dss = dataDeclarations env- lts = F.toListSEnv . F.seLits $ env- ess = distinctLiterals lts- axs = Thy.axiomLiterals lts- 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+declare = do+ me <- get+ let env = ctxSymEnv me+ let xts = symbolSorts (F.seSort env)+ let tx = elaborate (ElabParam (ctxElabF me) "declare" env)+ let lts = F.toListSEnv . F.seLits $ env+ let dss = dataDeclarations env+ let thyXTs = [ (x, t) | (x, t) <- xts, symKind env x == Just F.Uninterp ]+ let qryXTs = fmap tx <$> [ (x, t) | (x, t) <- xts, symKind env x == Nothing ]+ -- let isKind n = (n ==) . symKind env . fst+ let MkDefinedFuns defs = ctxDefines me+ let ess = distinctLiterals lts+ let axs = Thy.axiomLiterals (config me) lts+ forM_ dss smtDataDecl+ forM_ thyXTs $ uncurry smtDecl+ forM_ qryXTs $ uncurry smtDecl+ forM_ defs smtDefineEqn+ forM_ ess smtDistinct+ forM_ axs smtAssert symbolSorts :: F.SEnv F.Sort -> [(F.Symbol, F.Sort)] symbolSorts env = [(x, tx t) | (x, t) <- F.toListSEnv env ]@@ -496,14 +548,24 @@ dataDeclarations :: SymEnv -> [[DataDecl]] dataDeclarations = orderDeclarations . map snd . F.toListSEnv . F.seData -funcSortVars :: F.SymEnv -> [(T.Text, ([F.SmtSort], F.SmtSort))]-funcSortVars env = [(var applyName t , appSort t) | t <- ts]- ++ [(var coerceName t , ([t1],t2)) | t@(t1, t2) <- ts]- ++ [(var lambdaName t , lamSort t) | t <- ts]- ++ [(var (lamArgSymbol i) t , argSort t) | t@(_,F.SInt) <- ts, i <- [1..Thy.maxLamArg] ]+-- | See 'F.seApplsCur' for explanation.+funcSortVars :: Bool -> F.SymEnv -> [(T.Text, ([F.SmtSort], F.SmtSort))]+funcSortVars lams env =+ concatMap symbolsForTag $ M.toList $ F.seApplsCur env where- var n = F.symbolAtSmtName n env ()- ts = M.keys (F.seAppls env)+ symbolsForTag (t, i) =+ let applySym = symbolAtSortIndex applyName i+ coerceSym = symbolAtSortIndex coerceName i+ lamSym = symbolAtSortIndex lambdaName i+ argSyms = if lams && snd t == F.SInt+ then [ (symbolAtSortIndex (lamArgSymbol j) i, argSort t)+ | j <- [1..Thy.maxLamArg] ]+ else []+ in (applySym, appSort t)+ : (coerceSym, ([fst t], snd t))+ : (lamSym, lamSort t)+ : argSyms+ appSort (s,t) = ([F.SInt, s], t) lamSort (s,t) = ([s, t], F.SInt) argSort (s,_) = ([] , s)
src/Language/Fixpoint/Smt/Serialize.hs view
@@ -14,6 +14,7 @@ module Language.Fixpoint.Smt.Serialize (smt2SortMono) where +import Control.Monad.State import Data.ByteString.Builder (Builder) import Language.Fixpoint.SortCheck import Language.Fixpoint.Types@@ -27,47 +28,65 @@ -- import Debug.Trace (trace) instance SMTLIB2 (Symbol, Sort) where- smt2 env c@(sym, t) = -- build "({} {})" (smt2 env sym, smt2SortMono c env t)- parenSeqs [smt2 env sym, smt2SortMono c env t]+ smt2 c@(sym, t) =+ -- build "({} {})" (smt2 env sym, smt2SortMono c env t)+ do s <- smt2 sym+ ss <- smt2SortMono c t+ pure $ parenSeqs [s , ss] -smt2SortMono, smt2SortPoly :: (PPrint a) => a -> SymEnv -> Sort -> Builder+instance SMTLIB2 (Symbol, Expr) where+ smt2 (sym, e) =+ do s <- smt2 sym+ ss <- smt2 e+ pure $ parenSeqs [s, ss]++smt2SortMono, smt2SortPoly :: (PPrint a) => a -> Sort -> SymM Builder smt2SortMono = smt2Sort False smt2SortPoly = smt2Sort True -smt2Sort :: (PPrint a) => Bool -> a -> SymEnv -> Sort -> Builder-smt2Sort poly _ env t = smt2 env (Thy.sortSmtSort poly (seData env) t)+smt2Sort :: (PPrint a) => Bool -> a -> Sort -> SymM Builder+smt2Sort poly _ t =+ do env <- get+ smt2 (Thy.sortSmtSort poly (seData env) t) -smt2data :: SymEnv -> [DataDecl] -> Builder-smt2data env = smt2data' env . map padDataDecl+smt2data :: [DataDecl] -> SymM Builder+smt2data = smt2data' . map padDataDecl -smt2data' :: SymEnv -> [DataDecl] -> Builder-smt2data' env ds = seqs [ parens $ smt2many (smt2dataname env <$> ds)- , parens $ smt2many (smt2datactors env <$> ds)- ]+smt2data' :: [DataDecl] -> SymM Builder+smt2data' ds =+ do n <- traverse smt2dataname ds+ d <- traverse smt2datactors ds+ pure $ seqs [ parens $ smt2many n , parens $ smt2many d ] -smt2dataname :: SymEnv -> DataDecl -> Builder-smt2dataname env (DDecl tc as _) = parenSeqs [name, n]- where- name = smt2 env (symbol tc)- n = smt2 env as+smt2dataname :: DataDecl -> SymM Builder+smt2dataname (DDecl tc as _) =+ do name <- smt2 (symbol tc)+ n <- smt2 as+ pure $ parenSeqs [name, n] -smt2datactors :: SymEnv -> DataDecl -> Builder-smt2datactors env (DDecl _ as cs)- | as > 0 = parenSeqs ["par", parens tvars, parens ds]- | otherwise = parens ds+smt2datactors :: DataDecl -> SymM Builder+smt2datactors (DDecl _ as cs) =+ do ds <- traverse (smt2ctor as) cs+ if as > 0+ then do tvars <- traverse smt2TV [0..(as-1)]+ pure $ parenSeqs ["par", parens (smt2many tvars), parens (smt2many ds)]+ else pure $ parens (smt2many ds) where- tvars = smt2many (smt2TV <$> [0..(as-1)])- smt2TV = smt2 env . SVar- ds = smt2many (smt2ctor env as <$> cs)--smt2ctor :: SymEnv -> Int -> DataCtor -> Builder+ smt2TV = smt2 . SVar -smt2ctor env as (DCtor c fs) = parenSeqs (smt2 env c : (smt2field env as <$> fs))+smt2ctor :: Int -> DataCtor -> SymM Builder+smt2ctor as (DCtor c fs) =+ do h <- smt2 c+ t <- traverse (smt2field as) fs+ pure $ parenSeqs (h : t) -smt2field :: SymEnv -> Int -> DataField -> Builder-smt2field env as d@(DField x t) = parenSeqs [smt2 env x, smt2SortPoly d env $ mkPoly as t]+smt2field :: Int -> DataField -> SymM Builder+smt2field as d@(DField x t) =+ do s <- smt2 x+ ss <- smt2SortPoly d $ mkPoly as t+ pure $ parenSeqs [s , ss] -- | SMTLIB/Z3 don't like "unused" type variables; they get pruned away and -- cause wierd hassles. See tests/pos/adt_poly_dead.fq for an example.@@ -95,120 +114,153 @@ go is _ = is instance SMTLIB2 Symbol where- smt2 env s- | Just t <- Thy.smt2Symbol env s = t- smt2 _ s = symbolBuilder s-+ smt2 s = do env <- get+ case Thy.smt2Symbol env s of+ Just t -> pure t+ Nothing -> pure $ symbolBuilder s instance SMTLIB2 Int where- smt2 _ = Builder.fromString . show+ smt2 i = pure $ Builder.fromString $ show i instance SMTLIB2 LocSymbol where- smt2 env = smt2 env . val+ smt2 = smt2 . val instance SMTLIB2 SymConst where- smt2 env = smt2 env . symbol+ smt2 = smt2 . symbol instance SMTLIB2 Constant where- smt2 _ (I n) = bShow n- smt2 _ (R d) = bFloat d- smt2 _ (L t _) = fromText t+ smt2 (I n) = pure $ bShow n+ smt2 (R d) = pure $ bFloat d+ smt2 (L t s)+ | isString s = pure $ quotes $ fromText t+ | otherwise = pure $ fromText t instance SMTLIB2 Bop where- smt2 _ Plus = "+"- smt2 _ Minus = "-"- smt2 _ Times = symbolBuilder mulFuncName- smt2 _ Div = symbolBuilder divFuncName- smt2 _ RTimes = "*"- smt2 _ RDiv = "/"- smt2 _ Mod = "mod"+ smt2 Plus = pure "+"+ smt2 Minus = pure "-"+ smt2 Times = pure $ symbolBuilder mulFuncName+ smt2 Div = pure $ symbolBuilder divFuncName+ smt2 RTimes = pure "*"+ smt2 RDiv = pure "/"+ smt2 Mod = pure "mod" instance SMTLIB2 Brel where- smt2 _ Eq = "="- smt2 _ Ueq = "="- smt2 _ Gt = ">"- smt2 _ Ge = ">="- smt2 _ Lt = "<"- smt2 _ Le = "<="- smt2 _ _ = errorstar "SMTLIB2 Brel"+ smt2 Eq = pure "="+ smt2 Ueq = pure "="+ smt2 Gt = pure ">"+ smt2 Ge = pure ">="+ smt2 Lt = pure "<"+ smt2 Le = pure "<="+ smt2 _ = errorstar "SMTLIB2 Brel" -- NV TODO: change the way EApp is printed instance SMTLIB2 Expr where- smt2 env (ESym z) = smt2 env z- smt2 env (ECon c) = smt2 env c- smt2 env (EVar x) = smt2 env x- smt2 env e@(EApp _ _) = smt2App env e- smt2 env (ENeg e) = parenSeqs ["-", smt2 env e]- smt2 env (EBin o e1 e2) = parenSeqs [smt2 env o, smt2 env e1, smt2 env e2]- smt2 env (EIte e1 e2 e3) = parenSeqs ["ite", smt2 env e1, smt2 env e2, smt2 env e3]- smt2 env (ECst e t) = smt2Cast env e t- smt2 _ PTrue = "true"- smt2 _ PFalse = "false"- smt2 _ (PAnd []) = "true"- smt2 env (PAnd ps) = parenSeqs ["and", smt2s env ps]- smt2 _ (POr []) = "false"- smt2 env (POr ps) = parenSeqs ["or", smt2s env ps]- smt2 env (PNot p) = parenSeqs ["not", smt2 env p]- smt2 env (PImp p q) = parenSeqs ["=>", smt2 env p, smt2 env q]- smt2 env (PIff p q) = parenSeqs ["=", smt2 env p, smt2 env q]- smt2 env (PExist [] p) = smt2 env p- smt2 env (PExist xs p) = parenSeqs ["exists", parens (smt2s env xs), smt2 env p]- smt2 env (PAll [] p) = smt2 env p- smt2 env (PAll xs p) = parenSeqs ["forall", parens (smt2s env xs), smt2 env p]- smt2 env (PAtom r e1 e2) = mkRel env r e1 e2- smt2 env (ELam b e) = smt2Lam env b e- smt2 env (ECoerc t1 t2 e) = smt2Coerc env t1 t2 e- smt2 _ e = panic ("smtlib2 Pred " ++ show e)--+ smt2 (ESym z) = smt2 z+ smt2 (ECon c) = smt2 c+ smt2 (EVar x) = smt2 x+ smt2 e@(EApp _ _) = smt2App e+ smt2 (ENeg e) = do s <- smt2 e+ pure $ parenSeqs ["-", s]+ smt2 (EBin o e1 e2) = do so <- smt2 o+ s1 <- smt2 e1+ s2 <- smt2 e2+ pure $ parenSeqs [so, s1, s2]+ smt2 (ELet x e1 e2) = do s1 <- smt2 (x, e1)+ s2 <- smt2 e2+ pure $ parenSeqs ["let", parens s1, s2]+ smt2 (EIte e1 e2 e3) = do s1 <- smt2 e1+ s2 <- smt2 e2+ s3 <- smt2 e3+ pure $ parenSeqs ["ite", s1, s2, s3]+ smt2 (ECst e t) = smt2Cast e t+ smt2 PTrue = pure "true"+ smt2 PFalse = pure "false"+ smt2 (PAnd []) = pure "true"+ smt2 (PAnd ps) = do s <- smt2s ps+ pure $ parenSeqs ["and", s]+ smt2 (POr []) = pure "false"+ smt2 (POr ps) = do s <- smt2s ps+ pure $ parenSeqs ["or", s]+ smt2 (PNot p) = do s <- smt2 p+ pure $ parenSeqs ["not", s]+ smt2 (PImp p q) = do s1 <- smt2 p+ s2 <- smt2 q+ pure $ parenSeqs ["=>", s1, s2]+ smt2 (PIff p q) = do s1 <- smt2 p+ s2 <- smt2 q+ pure $ parenSeqs ["=", s1, s2]+ smt2 (PExist [] p) = smt2 p+ smt2 (PExist xs p) = do s <- smt2s xs+ s1 <- smt2 p+ pure $ parenSeqs ["exists", parens s, s1]+ smt2 (PAll [] p) = smt2 p+ smt2 (PAll xs p) = do s <- smt2s xs+ s1 <- smt2 p+ pure $ parenSeqs ["forall", parens s, s1]+ smt2 (PAtom r e1 e2) = mkRel r e1 e2+ smt2 (ELam b e) = smt2Lam b e+ smt2 (ECoerc t1 t2 e) = smt2Coerc t1 t2 e+ smt2 e = panic ("smtlib2 Pred " ++ show e) -- | smt2Cast uses the 'as x T' pattern needed for polymorphic ADT constructors -- like Nil, see `tests/pos/adt_list_1.fq` -smt2Cast :: SymEnv -> Expr -> Sort -> Builder-smt2Cast env (EVar x) t = smt2Var env x t-smt2Cast env e _ = smt2 env e--smt2Var :: SymEnv -> Symbol -> Sort -> Builder-smt2Var env x t- | isLamArgSymbol x = smtLamArg env x t- | Just s <- symEnvSort x env- , isPolyInst s t = smt2VarAs env x t- | otherwise = smt2 env x+smt2Cast :: Expr -> Sort -> SymM Builder+smt2Cast (EVar x) t = smt2Var x t+smt2Cast e _ = smt2 e -smtLamArg :: SymEnv -> Symbol -> Sort -> Builder-smtLamArg env x t = Builder.fromText $ symbolAtName x env () (FFunc t FInt)+smt2Var :: Symbol -> Sort -> SymM Builder+smt2Var x t+ | isLamArgSymbol x = smtLamArg x t+ | otherwise = do env <- get+ case symEnvSort x env of+ Just s | isPolyInst s t -> smt2VarAs x t+ _ -> smt2 x -smt2VarAs :: SymEnv -> Symbol -> Sort -> Builder-smt2VarAs env x t = parenSeqs ["as", smt2 env x, smt2SortMono x env t]+smt2VarAs :: Symbol -> Sort -> SymM Builder+smt2VarAs x t =+ do s <- smt2 x+ s1 <- smt2SortMono x t+ pure $ parenSeqs ["as", s, s1] -smt2Lam :: SymEnv -> (Symbol, Sort) -> Expr -> Builder-smt2Lam env (x, xT) full@(ECst _ eT) = parenSeqs [Builder.fromText lambda, x', smt2 env full]- where- x' = smtLamArg env x xT- lambda = symbolAtName lambdaName env () (FFunc xT eT)+-- the next four functions (ones containing a call to `symbolAtName`) can trigger+-- an expansion of the "nursery" tag table ('seApplsCur' in 'SymEnv') when processing+-- a fresh function sort+smtLamArg :: Symbol -> Sort -> SymM Builder+smtLamArg x t =+ do s <- symbolAtName x (FFunc t FInt)+ pure $ Builder.fromText s -smt2Lam _ _ e+smt2Lam :: (Symbol, Sort) -> Expr -> SymM Builder+smt2Lam (x, xT) full@(ECst _ eT) =+ do x' <- smtLamArg x xT+ lambda <- symbolAtName lambdaName (FFunc xT eT)+ f <- smt2 full+ pure $ parenSeqs [Builder.fromText lambda, x', f]+smt2Lam _ e = panic ("smtlib2: Cannot serialize unsorted lambda: " ++ showpp e) -smt2App :: SymEnv -> Expr -> Builder-smt2App env e@(EApp (EApp f e1) e2)+smt2App :: Expr -> SymM Builder+smt2App (EApp (EApp f e1) e2) | Just t <- unApplyAt f- = parenSeqs [Builder.fromText (symbolAtName applyName env e t), smt2s env [e1, e2]]-smt2App env e- | Just b <- Thy.smt2App smt2VarAs env f (smt2 env <$> es)- = b- | otherwise- = parenSeqs [smt2 env f, smt2s env es]+ = do a <- symbolAtName applyName t+ s <- smt2s [e1, e2]+ pure $ parenSeqs [Builder.fromText a, s]+smt2App e = do s0 <- traverse smt2 es+ s1 <- Thy.smt2App smt2VarAs f s0+ case s1 of+ Just b -> pure b+ Nothing -> do s2 <- smt2 f+ s3 <- smt2s es+ pure $ parenSeqs [s2, s3] where- (f, es) = splitEApp' e+ (f, es) = splitEApp' e -smt2Coerc :: SymEnv -> Sort -> Sort -> Expr -> Builder-smt2Coerc env t1 t2 e- | t1 == t2 = smt2 env e- | otherwise = parenSeqs [Builder.fromText coerceFn , smt2 env e]- where- coerceFn = symbolAtName coerceName env (ECoerc t1 t2 e) t- t = FFunc t1 t2+smt2Coerc :: Sort -> Sort -> Expr -> SymM Builder+smt2Coerc t1 t2 e+ | t1 == t2 = smt2 e+ | otherwise = do coerceFn <- symbolAtName coerceName (FFunc t1 t2)+ s <- smt2 e+ pure $ parenSeqs [Builder.fromText coerceFn , s] splitEApp' :: Expr -> (Expr, [Expr]) splitEApp' = go []@@ -217,50 +269,76 @@ -- go acc (ECst e _) = go acc e go acc e = (e, acc) -mkRel :: SymEnv -> Brel -> Expr -> Expr -> Builder-mkRel env Ne e1 e2 = mkNe env e1 e2-mkRel env Une e1 e2 = mkNe env e1 e2-mkRel env r e1 e2 = parenSeqs [smt2 env r, smt2 env e1, smt2 env e2]--mkNe :: SymEnv -> Expr -> Expr -> Builder-mkNe env e1 e2 = key "not" (parenSeqs ["=", smt2 env e1, smt2 env e2])+mkRel :: Brel -> Expr -> Expr -> SymM Builder+mkRel Ne e1 e2 = mkNe e1 e2+mkRel Une e1 e2 = mkNe e1 e2+mkRel r e1 e2 = do s <- smt2 r+ s1 <- smt2 e1+ s2 <- smt2 e2+ pure $ parenSeqs [s, s1, s2] +mkNe :: Expr -> Expr -> SymM Builder+mkNe e1 e2 = do s1 <- smt2 e1+ s2 <- smt2 e2+ pure $ key "not" (parenSeqs ["=", s1, s2]) instance SMTLIB2 Command where- smt2 env (DeclData ds) = key "declare-datatypes" (smt2data env ds)- smt2 env (Declare x ts t) = parenSeqs ["declare-fun", Builder.fromText x, parens (smt2many (smt2 env <$> ts)), smt2 env t]- smt2 env c@(Define t) = key "declare-sort" (smt2SortMono c env t)- smt2 env (DefineFunc name paramxs rsort e) =- let bParams = [ parenSeqs [smt2 env s, smt2 env t] | (s, t) <- paramxs]- in parenSeqs ["define-fun", smt2 env name, parenSeqs bParams, smt2 env rsort, smt2 env e]- smt2 env (Assert Nothing p) = {-# SCC "smt2-assert" #-} key "assert" (smt2 env p)- smt2 env (Assert (Just i) p) = {-# SCC "smt2-assert" #-} key "assert" (parens ("!"<+> smt2 env p <+> ":named p-" <> bShow i))- smt2 env (Distinct az)- | length az < 2 = ""- | otherwise = key "assert" (key "distinct" (smt2s env az))- smt2 env (AssertAx t) = key "assert" (smt2 env t)- smt2 _ Push = "(push 1)"- smt2 _ Pop = "(pop 1)"- smt2 _ CheckSat = "(check-sat)"- smt2 env (GetValue xs) = key "key-value" (parens (smt2s env xs))- smt2 env (CMany cmds) = smt2many (smt2 env <$> cmds)- smt2 _ Exit = "(exit)"- smt2 _ SetMbqi = "(set-option :smt.mbqi true)"+ smt2 (DeclData ds) = do s <- smt2data ds+ pure $ key "declare-datatypes" s+ smt2 (Declare x ts t) = do s <- smt2s ts+ s1 <- smt2 t+ pure $ parenSeqs ["declare-fun", Builder.fromText x, parens s, s1]+ smt2 c@(Define t) = do s <- smt2SortMono c t+ pure $ key "declare-sort" s+ smt2 (DefineFunc name paramxs rsort e) =+ do n <- smt2 name+ bParams <- traverse (\(s, t) -> do s0 <- smt2 s+ s1 <- smt2 t+ pure $ parenSeqs [s0 , s1]) paramxs+ r <- smt2 rsort+ e' <- smt2 e+ pure $ parenSeqs ["define-fun", n, parenSeqs bParams, r, e'] + smt2 (Assert Nothing p) = {-# SCC "smt2-assert" #-}+ do s <- smt2 p+ pure $ key "assert" s+ smt2 (Assert (Just i) p) = {-# SCC "smt2-assert" #-}+ do s <- smt2 p+ pure $ key "assert" (parens ("!"<+> s <+> ":named p-" <> bShow i))+ smt2 (Distinct az)+ | length az < 2 = pure ""+ | otherwise = do s <- smt2s az+ pure $ key "assert" $ key "distinct" s+ smt2 (AssertAx t) = do s <- smt2 t+ pure $ key "assert" s+ smt2 Push = pure "(push 1)"+ smt2 Pop = pure "(pop 1)"+ smt2 CheckSat = pure "(check-sat)"+ smt2 (GetValue xs) = do s <- smt2s xs+ pure $ key "key-value" (parens s)+ smt2 (CMany cmds) = smt2s cmds+ smt2 Exit = pure "(exit)"+ smt2 SetMbqi = pure "(set-option :smt.mbqi true)"+ smt2 (Comment t) = pure $ fromText ("; " <> t <> "\n")+ instance SMTLIB2 (Triggered Expr) where- smt2 env (TR NoTrigger e) = smt2 env e- smt2 env (TR _ (PExist [] p)) = smt2 env p- smt2 env t@(TR _ (PExist xs p)) = smtTr env "exists" xs p t- smt2 env (TR _ (PAll [] p)) = smt2 env p- smt2 env t@(TR _ (PAll xs p)) = smtTr env "forall" xs p t- smt2 env (TR _ e) = smt2 env e+ smt2 (TR NoTrigger e) = smt2 e+ smt2 (TR _ (PExist [] p)) = smt2 p+ smt2 t@(TR _ (PExist xs p)) = smtTr "exists" xs p t+ smt2 (TR _ (PAll [] p)) = smt2 p+ smt2 t@(TR _ (PAll xs p)) = smtTr "forall" xs p t+ smt2 (TR _ e) = smt2 e {-# INLINE smtTr #-}-smtTr :: SymEnv -> Builder -> [(Symbol, Sort)] -> Expr -> Triggered Expr -> Builder-smtTr env q xs p t = key q (parens (smt2s env xs) <+> key "!" (smt2 env p <+> ":pattern" <> parens (smt2s env (makeTriggers t))))+smtTr :: Builder -> [(Symbol, Sort)] -> Expr -> Triggered Expr -> SymM Builder+smtTr q xs p t =+ do s <- smt2s xs+ s1 <- smt2 p+ s2 <- smt2s (makeTriggers t)+ pure $ key q (parens s <+> key "!" (s1 <+> ":pattern" <> parens s2)) {-# INLINE smt2s #-}-smt2s :: SMTLIB2 a => SymEnv -> [a] -> Builder-smt2s env as = smt2many (smt2 env <$> as)+smt2s :: SMTLIB2 a => [a] -> SymM Builder+smt2s as = smt2many <$> traverse smt2 as {-# INLINE smt2many #-} smt2many :: [Builder] -> Builder
src/Language/Fixpoint/Smt/Theories.hs view
@@ -3,7 +3,6 @@ {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE PatternGuards #-} {-# LANGUAGE ViewPatterns #-} {-# OPTIONS_GHC -Wno-orphans #-}@@ -32,7 +31,7 @@ , dataDeclSymbols -- * Theories- , setEmpty, setEmp, setSng, setAdd, setMem+ , setEmpty, setEmp, setSng, setAdd, setMem, setCard , setCom, setCap, setCup, setDif, setSub , mapDef, mapSel, mapSto@@ -49,6 +48,9 @@ , arrConstB, arrStoreB, arrSelectB , arrMapPlusB, arrMapLeB, arrMapGtB, arrMapIteB + -- * CVC5 finite fields+ , ffVal, ffAdd, ffMul+ -- * Query Theories , isSmt2App , axiomLiterals@@ -56,6 +58,7 @@ ) where import Prelude hiding (map)+import Control.Monad.State import Data.ByteString.Builder (Builder) import Language.Fixpoint.Types.Sorts import Language.Fixpoint.Types.Config@@ -139,7 +142,8 @@ mapSel = "Map_select" mapSto = "Map_store" -setEmpty, setEmp, setCap, setSub, setAdd, setMem, setCom, setCup, setDif, setSng :: (IsString a) => a+setCard, setEmpty, setEmp, setCap, setSub, setAdd, setMem, setCom, setCup, setDif, setSng :: (IsString a) => a+setCard = "Set_card" setEmpty = "Set_empty" setEmp = "Set_emp" setCap = "Set_cap"@@ -195,20 +199,34 @@ arrMapGtB = "arr_map_gt" arrMapIteB = "arr_map_ite" -strLen, strSubstr, strConcat :: (IsString a) => a -- Symbol+-- Finite field operations+ffVal, ffAdd, ffMul :: (IsString a) => a -- Symbol+ffVal = "FF_val"+ffAdd = "FF_add"+ffMul = "FF_mul"++strLen, strSubstr, strConcat, strConcat', strPrefixOf, strSuffixOf, strContains :: (IsString a) => a -- Symbol strLen = "strLen" strSubstr = "subString" strConcat = "concatString"+strConcat' = "strConcat"+strPrefixOf = "strPrefixOf"+strSuffixOf = "strSuffixOf"+strContains = "strContains" -smtlibStrLen, smtlibStrSubstr, smtlibStrConcat :: Raw+smtlibStrLen, smtlibStrSubstr, smtlibStrConcat, smtlibStrPrefixOf, smtlibStrSuffixOf, smtlibStrContains :: Raw smtlibStrLen = "str.len" smtlibStrSubstr = "str.substr" smtlibStrConcat = "str.++"+smtlibStrPrefixOf = "str.prefixof"+smtlibStrSuffixOf = "str.suffixof"+smtlibStrContains = "str.contains" -strLenSort, substrSort, concatstrSort :: Sort+strLenSort, substrSort, concatstrSort, strCompareSort :: Sort strLenSort = FFunc strSort intSort substrSort = mkFFunc 0 [strSort, intSort, intSort, strSort] concatstrSort = mkFFunc 0 [strSort, strSort, strSort]+strCompareSort = mkFFunc 0 [strSort, strSort, boolSort] string :: Raw string = strConName@@ -256,6 +274,7 @@ , (SOnly [Cvc5], "(set-logic ALL)") , (SOnly [Cvc4, Cvc5], "(set-option :incremental true)") ]+ ++ setPreamble cfg ++ boolPreamble cfg ++ arithPreamble cfg ++ stringPreamble cfg@@ -265,6 +284,10 @@ data PreambleCondition = SAll | SOnly [SMTSolver] deriving (Eq, Show) +setPreamble :: Config -> [Preamble]+-- Z3 does not support cardinality on sets, which is defined to be uninterpreted function+setPreamble _+ = [ (SOnly [Z3, Z3mem], bFun' "set.card" ["(Array Int Bool)"] "Int") ] boolPreamble :: Config -> [Preamble] boolPreamble _@@ -277,7 +300,7 @@ ] stringPreamble :: Config -> [Preamble]-stringPreamble cfg | stringTheory cfg+stringPreamble cfg | not (noStringTheory cfg) = [ (SAll, bSort string "String") , (SAll, bFun strLen [("s", fromText string)] "Int" (key (fromText smtlibStrLen) "s")) , (SAll, bFun strSubstr [("s", fromText string), ("i", "Int"), ("j", "Int")] (fromText string) (key (fromText smtlibStrSubstr) "s i j"))@@ -298,7 +321,7 @@ smt2Symbol env x = fromText . tsRaw <$> symEnvTheory x env instance SMTLIB2 SmtSort where- smt2 _ = smt2SmtSort+ smt2 s = pure $ smt2SmtSort s smt2SmtSort :: SmtSort -> Builder smt2SmtSort SInt = "Int"@@ -308,6 +331,7 @@ smt2SmtSort (SSet a) = key "Set" (smt2SmtSort a) smt2SmtSort (SBag a) = key "Bag" (smt2SmtSort a) smt2SmtSort (SArray a b) = key2 "Array" (smt2SmtSort a) (smt2SmtSort b)+smt2SmtSort (SFFld n) = key "_ FiniteField" (bShow n) smt2SmtSort (SBitVec n) = key "_ BitVec" (bShow n) smt2SmtSort (SVar n) = "T" <> bShow n smt2SmtSort (SData c []) = symbolBuilder c@@ -318,37 +342,44 @@ smt2SmtSorts :: [SmtSort] -> Builder smt2SmtSorts = seqs . fmap smt2SmtSort -type VarAs = SymEnv -> Symbol -> Sort -> Builder+type VarAs = Symbol -> Sort -> SymM Builder ---------------------------------------------------------------------------------smt2App :: VarAs -> SymEnv -> Expr -> [Builder] -> Maybe Builder+smt2App :: VarAs -> Expr -> [Builder] -> SymM (Maybe Builder) ---------------------------------------------------------------------------------smt2App _ env ex@(dropECst -> EVar f) [d]- | f == arrConstS = Just (key (key "as const" (getTarget ex)) d)- | f == arrConstB = Just (key (key "as const" (getTarget ex)) d)- | f == arrConstM = Just (key (key "as const" (getTarget ex)) d)- | f == setEmpty = Just (key "as set.empty" (getTarget ex))- | f == bagEmpty = Just (key "as bag.empty" (getTarget ex))+smt2App _ ex@(dropECst -> EVar f) [d]+ | f == arrConstS || f == arrConstB || f == arrConstM =+ do env <- get+ pure $ Just $ key (key "as const" (getTarget env ex)) d+ | f == setEmpty =+ do env <- get+ pure $ Just $ key "as set.empty" (getTarget env ex)+ | f == bagEmpty =+ do env <- get+ pure $ Just $ key "as bag.empty" (getTarget env ex)+ | f == ffVal =+ do env <- get+ pure $ Just $ key ("as ff" <> d) (getTarget env ex) where- getTarget :: Expr -> Builder+ getTarget :: SymEnv -> Expr -> Builder -- const is a function, but SMT expects only the output sort- getTarget (ECst _ t) = smt2SmtSort $ sortSmtSort True (seData env) (ffuncOut t)- getTarget e = bShow e--smt2App k env ex (builder:builders)- | Just fb <- smt2AppArg k env ex- = Just $ key fb (builder <> mconcat [ " " <> d | d <- builders])--smt2App _ _ _ _ = Nothing+ getTarget env (ECst _ t) = smt2SmtSort $ sortSmtSort True (seData env) (ffuncOut t)+ getTarget _ e = bShow e -smt2AppArg :: VarAs -> SymEnv -> Expr -> Maybe Builder-smt2AppArg k env (ECst (dropECst -> EVar f) t)- | Just fThy <- symEnvTheory f env- = Just $ if isPolyCtor fThy t- then k env f (ffuncOut t)- else fromText (tsRaw fThy)+smt2App k ex (builder:builders) =+ do a <- smt2AppArg k ex+ pure $ (\fb -> key fb (builder <> mconcat [ " " <> d | d <- builders])) <$> a+smt2App _ _ [] = pure Nothing -smt2AppArg _ _ _- = Nothing+smt2AppArg :: VarAs -> Expr -> SymM (Maybe Builder)+smt2AppArg k (ECst (dropECst -> EVar f) t)+ = do env <- get+ case symEnvTheory f env of+ Just fThy -> if isPolyCtor fThy t+ then Just <$> k f (ffuncOut t)+ else pure $ Just $ fromText (tsRaw fThy)+ Nothing -> pure Nothing+smt2AppArg _ _+ = pure Nothing isPolyCtor :: TheorySymbol -> Sort -> Bool isPolyCtor fThy t = isPolyInst (tsSort fThy) t && tsInterp fThy == Ctor@@ -388,9 +419,13 @@ theorySymbols :: [DataDecl] -> SEnv TheorySymbol theorySymbols = fromListSEnv . concatMap dataDeclSymbols + instance TheorySymbols [Equation] where theorySymbols = fromListSEnv . fmap equationSymbol +instance TheorySymbols DefinedFuns where+ theorySymbols (MkDefinedFuns eqns) = theorySymbols eqns+ equationSymbol :: Equation -> (Symbol, TheorySymbol) equationSymbol eq = (sym, Thy sym (symbolRaw sym) sort Defined) where@@ -414,6 +449,7 @@ -- CVC5 sets + , interpSym setCard "set.card" (FAbs 0 $ FFunc (setSort $ FVar 0) intSort) , interpSym setEmp "set.is_empty" (FAbs 0 $ FFunc (setSort $ FVar 0) boolSort) , interpSym setEmpty "set.empty" (FAbs 0 $ FFunc intSort (setSort $ FVar 0)) , interpSym setSng "set.singleton" (FAbs 0 $ FFunc (FVar 0) (setSort $ FVar 0))@@ -435,14 +471,15 @@ , interpSym bagMin "bag.inter_min" bagBopSort , interpSym bagSub "bag.subbag" (FAbs 0 $ FFunc (bagSort $ FVar 0) $ FFunc (bagSort $ FVar 0) boolSort) - -- , interpSym bvOrName "bvor" bvBopSort- -- , interpSym bvAndName "bvand" bvBopSort- -- , interpSym bvAddName "bvadd" bvBopSort- -- , interpSym bvSubName "bvsub" bvBopSort+ -- Strings+ , interpSym strLen strLen strLenSort+ , interpSym strSubstr strSubstr substrSort+ , interpSym strConcat strConcat concatstrSort+ , interpSym strConcat' smtlibStrConcat concatstrSort+ , interpSym strPrefixOf smtlibStrPrefixOf strCompareSort+ , interpSym strSuffixOf smtlibStrSuffixOf strCompareSort+ , interpSym strContains smtlibStrContains strCompareSort - , interpSym strLen strLen strLenSort- , interpSym strSubstr strSubstr substrSort- , interpSym strConcat strConcat concatstrSort , interpSym boolInt boolInt (FFunc boolSort intSort) -- Function mappings for indexed identifier functions@@ -489,12 +526,18 @@ , interpBvCmp bvSLeName , interpBvCmp bvSGtName , interpBvCmp bvSGeName++ -- int to bv Conversions+ , interpSym intbv32Name "(_ int2bv 32)" (FFunc intSort bv32) , interpSym intbv64Name "(_ int2bv 64)" (FFunc intSort bv64)- , interpSym bv32intName (bv2i cfg 32) (FFunc bv32 intSort)- , interpSym bv64intName (bv2i cfg 64) (FFunc bv64 intSort)- -- , interpSym bv32intName "(_ bv2int 32)" (FFunc bv32 intSort)- -- , interpSym bv64intName "(_ bv2int 64)" (FFunc bv64 intSort)+ , interpSym bv32intName (bv2i cfg 32) (FFunc bv32 intSort)+ , interpSym bv64intName (bv2i cfg 64) (FFunc bv64 intSort)++ , interpSym intbv8Name "(_ int2bv 8)" (FFunc intSort bv8)+ , interpSym intbv16Name "(_ int2bv 16)" (FFunc intSort bv16)+ , interpSym bv8intName (bv2i cfg 32) (FFunc bv8 intSort)+ , interpSym bv16intName (bv2i cfg 64) (FFunc bv16 intSort) ] ++ if cfg == Z3 || cfg == Z3mem@@ -521,13 +564,22 @@ , interpSym arrMapLeB "(_ map (<= (Int Int) Bool))" (FAbs 0 $ FFunc bagArrSort $ FFunc bagArrSort setArrSort) , interpSym arrMapGtB "(_ map (> (Int Int) Bool))" (FAbs 0 $ FFunc bagArrSort $ FFunc bagArrSort setArrSort) , interpSym arrMapIteB "(_ map (ite (Bool Int Int) Int))" (FAbs 0 $ FFunc setArrSort $ FFunc bagArrSort $ FFunc bagArrSort bagArrSort)+ ] else if cfg == Cvc5+ then+ [+ -- CVC5 finite fields++ interpSym ffVal ffVal (FAbs 0 $ FFunc intSort (finfieldSort (FVar 0)))+ , interpSym ffAdd "ff.add" (FAbs 0 $ FFunc (finfieldSort (FVar 0)) $ FFunc (finfieldSort (FVar 0)) (finfieldSort (FVar 0)))+ , interpSym ffMul "ff.mul" (FAbs 0 $ FFunc (finfieldSort (FVar 0)) $ FFunc (finfieldSort (FVar 0)) (finfieldSort (FVar 0))) ] else [] where mapArrSort = arraySort (FVar 0) (FVar 1) setArrSort = arraySort (FVar 0) boolSort bagArrSort = arraySort (FVar 0) intSort- -- (sizedBitVecSort "Size1")+ bv8 = sizedBitVecSort "Size8"+ bv16 = sizedBitVecSort "Size16" bv32 = sizedBitVecSort "Size32" bv64 = sizedBitVecSort "Size64" boolInt = boolToIntName@@ -630,17 +682,29 @@ interpSym :: Symbol -> Raw -> Sort -> (Symbol, TheorySymbol) interpSym x n t = (x, Thy x n t Theory) --- This variable is uded to generate the lambda names `lam_arg$n` in+-- This variable is used to generate the lambda names `lam_arg$n` in -- `Interface.hs` that will be used during defunctionalization in--- `Defunctionalize.hs`, is a pretty gross hack as if the user typees in the--- program or ple generates a term that has more than `maxLamArg` lambda binders--- one inside the other, the smt will crash complaining that--- `lam_arg${maxLamArg}` was not declared.+-- `Defunctionalize.hs`, is a pretty gross hack as if the user types in the+-- program or PLE generates a term that has more than `maxLamArg` lambda binders+-- one inside the other, the SMT will crash complaining that+-- `lam_arg${maxLamArg + k}` was not declared. maxLamArg :: Int maxLamArg = 20 -axiomLiterals :: [(Symbol, Sort)] -> [Expr]-axiomLiterals lts = catMaybes [ lenAxiom l <$> litLen l | (l, t) <- lts, isString t ]+axiomLiterals :: Config -> [(Symbol, Sort)] -> [Expr]+axiomLiterals cfg+ | noStringTheory cfg = lenAxiomLiterals+ | otherwise = strAxiomLiterals++strAxiomLiterals :: [(Symbol, Sort)] -> [Expr]+strAxiomLiterals lts = catMaybes [ strAxiom l | (l, t) <- lts, isString t ]+ where+ strAxiom l = do+ sym <- unLitSymbol l+ pure (EEq (expr l) (ECon $ L (symbolText sym) strSort))++lenAxiomLiterals :: [(Symbol, Sort)] -> [Expr]+lenAxiomLiterals lts = catMaybes [ lenAxiom l <$> litLen l | (l, t) <- lts, isString t ] where lenAxiom l n = EEq (EApp (expr (strLen :: Symbol)) (expr l)) (expr n `ECst` intSort) litLen = fmap (Data.Text.length . symbolText) . unLitSymbol
src/Language/Fixpoint/Smt/Types.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TupleSections #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE OverloadedStrings #-}@@ -25,11 +26,18 @@ -- * SMTLIB2 Process Context , Context (..) - ) where+ -- * SMT monad+ , SmtM+ , liftSym+ , catchSMT+ , bracketSMT + ) where+import Control.Exception+import Control.Monad.State import Data.ByteString.Builder (Builder) import Language.Fixpoint.Types-import Language.Fixpoint.Types.Config (ElabFlags)+import Language.Fixpoint.Types.Config (ElabFlags, Config) import qualified Data.Text as T import Text.PrettyPrint.HughesPJ import qualified SMTLIB.Backends@@ -59,6 +67,7 @@ | Distinct [Expr] -- {v:[Expr] | 2 <= len v} | GetValue [Symbol] | CMany [Command]+ | Comment T.Text deriving (Eq, Show) instance PPrint Command where@@ -81,6 +90,7 @@ ppCmd Distinct {} = text "Distinct ..." ppCmd GetValue {} = text "GetValue ..." ppCmd CMany {} = text "CMany ..."+ppCmd (Comment t) = text ("; " ++ T.unpack t) -- | Responses received from SMT engine data Response = Ok@@ -102,15 +112,44 @@ , ctxLog :: !(Maybe Handle) , ctxVerbose :: !Bool , ctxSymEnv :: !SymEnv- , ctxDefines :: ![Equation]+ -- | The stack of sort indexes which were fresh at the corresponding level of push/pop stack.+ , ctxIxs :: ![Int]+ , ctxDefines :: DefinedFuns+ -- | Flag which controls the generation SMT placeholders for lambda arguments+ -- See also `L.F.Smt.Theories.maxLamArg`+ , ctxLams :: !Bool+ -- | Configuration options+ , config :: !Config } +-- | SMT monad, used to communicate with the SMT solver backend.+-- The `SymM` monad embeds into it, as the symbolic state has to be threaded+-- through for gnerating `apply`s and other function sort symbols.+type SmtM = StateT Context IO++liftSym :: SymM a -> SmtM a+liftSym s =+ do ctx <- get+ let (a, env') = runState s (ctxSymEnv ctx)+ put (ctx {ctxSymEnv = env'})+ pure a++catchSMT :: Exception e => SmtM a -> (e -> IO a) -> SmtM a+catchSMT action handler = StateT $ \s -> catch (runStateT action s) (fmap (, s) . handler)++bracketSMT :: SmtM a -> (a -> IO b) -> (a -> SmtM c) -> SmtM c+bracketSMT acquire release use = StateT $ \s ->+ bracket+ (runStateT acquire s)+ (\(resource, _) -> release resource)+ (\(resource, intermediateState) -> runStateT (use resource) intermediateState)+ -------------------------------------------------------------------------------- -- | AST Conversion: Types that can be serialized ------------------------------ -------------------------------------------------------------------------------- class SMTLIB2 a where- smt2 :: SymEnv -> a -> Builder+ smt2 :: a -> SymM Builder -runSmt2 :: (SMTLIB2 a) => SymEnv -> a -> Builder+runSmt2 :: (SMTLIB2 a) => a -> SymM Builder runSmt2 = smt2
src/Language/Fixpoint/Solver.hs view
@@ -8,7 +8,7 @@ module Language.Fixpoint.Solver ( -- * Invoke Solver on an FInfo- solve, Solver+ solve -- * Invoke Solver on a .fq file , solveFQ@@ -26,26 +26,28 @@ import Control.Concurrent (setNumCapabilities) import qualified Data.HashMap.Strict as HashMap+import qualified Data.HashSet as HashSet import qualified Data.Store as S import Data.Aeson (ToJSON, encode)-import qualified Data.List as L import qualified Data.Text.Lazy.IO as LT import qualified Data.Text.Lazy.Encoding as LT import System.Exit (ExitCode (..)) import System.Console.CmdArgs.Verbosity (whenNormal, whenLoud)-import Text.PrettyPrint.HughesPJ (render)-import Control.Monad (mplus, when)-import Control.Exception (catch)+import Control.Monad (when)+import Control.Exception (SomeException, catch)+import Control.Exception.Compat+ (ExceptionWithContext(..), displayExceptionContext, wrapExceptionWithContext) import Language.Fixpoint.Solver.EnvironmentReduction (reduceEnvironments, simplifyBindings) import Language.Fixpoint.Solver.Sanitize (symbolEnv, sanitize) import Language.Fixpoint.Solver.UniqifyBinds (renameAll) import Language.Fixpoint.Defunctionalize (defunctionalize)-import Language.Fixpoint.SortCheck (ElabParam (..), Elaborate (..), unElab)+import Language.Fixpoint.SortCheck (ElabParam (..), Elaborate (..), unElab, unElabFSetBagZ3) import Language.Fixpoint.Solver.Extensionality (expand) import Language.Fixpoint.Solver.Prettify (savePrettifiedQuery) import Language.Fixpoint.Solver.UniqifyKVars (wfcUniqify) import qualified Language.Fixpoint.Solver.Solve as Sol+import qualified Language.Fixpoint.Solver.Solution as Sol import Language.Fixpoint.Types.Config import Language.Fixpoint.Types.Errors import Language.Fixpoint.Utils.Files hiding (Result)@@ -56,10 +58,10 @@ import Language.Fixpoint.Types hiding (GInfo(..), fi) import qualified Language.Fixpoint.Types as Types (GInfo(..)) import Language.Fixpoint.Minimize (minQuery, minQuals, minKvars)-import Language.Fixpoint.Solver.Instantiate (instantiate) import Control.DeepSeq import qualified Data.ByteString as B-import Data.Maybe (catMaybes, mapMaybe)+import Data.Maybe (catMaybes)+import qualified Text.PrettyPrint.HughesPJ as PJ --------------------------------------------------------------------------- -- | Solve an .fq file ----------------------------------------------------@@ -86,7 +88,7 @@ jStr = LT.decodeUtf8 . encode $ r stat = resStatus $!! r eCode = resultExit . resStatus- statStr = render . resultDoc+ statStr = PJ.render . resultDoc ignoreQualifiers :: Config -> FInfo a -> FInfo a ignoreQualifiers cfg fi@@ -97,7 +99,9 @@ -------------------------------------------------------------------------------- -- | Solve FInfo system of horn-clause constraints ----------------------------- ---------------------------------------------------------------------------------solve :: (PPrint a, NFData a, Fixpoint a, Show a, Loc a) => Solver a+solve+ :: (PPrint a, NFData a, Fixpoint a, Show a, Loc a)+ => Config -> FInfo a -> IO (Result (Integer, a)) -------------------------------------------------------------------------------- solve cfg q | parts cfg = partition cfg $!! q@@ -107,15 +111,16 @@ | minimizeKs cfg = minKvars cfg solve' $!! q | otherwise = solve' cfg $!! q -solve' :: (PPrint a, NFData a, Fixpoint a, Show a, Loc a) => Solver a++solve'+ :: (PPrint a, NFData a, Fixpoint a, Show a, Loc a)+ => Config -> FInfo a -> IO (Result (Integer, a)) solve' cfg q = do when (save cfg) $ saveQuery cfg q- configSW cfg solveNative cfg q--configSW :: (NFData a, Fixpoint a, Show a, Loc a) => Config -> Solver a -> Solver a-configSW cfg- | multicore cfg = solveParWith- | otherwise = solveSeqWith+ if multicore cfg then+ solvePar cfg q+ else+ solveNative cfg (slice cfg q) -------------------------------------------------------------------------------- readFInfo :: FilePath -> IO (FInfo (), [String])@@ -140,17 +145,11 @@ -------------------------------------------------------------------------------- -- | Solve in parallel after partitioning an FInfo to indepdendant parts ---------------------------------------------------------------------------------solveSeqWith :: (Fixpoint a) => Solver a -> Solver a-solveSeqWith s c fi0 = {- withProgressFI fi $ -} s c fi- where- fi = slice c fi0------------------------------------------------------------------------------------- | Solve in parallel after partitioning an FInfo to indepdendant parts----------------------------------------------------------------------------------solveParWith :: (Fixpoint a) => Solver a -> Solver a+solvePar+ :: (Loc a, NFData a, PPrint a, Show a, Fixpoint a)+ => Config -> FInfo a -> IO (Result (Integer, a)) ---------------------------------------------------------------------------------solveParWith s c fi0 = do+solvePar c fi0 = do -- putStrLn "Using Parallel Solver \n" let fi = slice c fi0 mci <- mcInfo c@@ -161,10 +160,10 @@ writeLoud $ "maximum part size : " ++ show (maxPartSize c) case fis of [] -> errorstar "partiton' returned empty list!"- [onePart] -> s c onePart- _ -> inParallelUsing (f s c) $ zip [1..] fis+ [onePart] -> solveNative c onePart+ _ -> inParallelUsing (f c) $ zip [1..] fis where- f s' c' (j, fi) = s' (c {srcFile = queryFile (Part j) c'}) fi+ f c' (j, fi) = solveNative (c {srcFile = queryFile (Part j) c'}) fi -------------------------------------------------------------------------------- -- | Solve a list of FInfos using the provided solver function in parallel@@ -180,26 +179,35 @@ -------------------------------------------------------------------------------- -- | Native Haskell Solver ----------------------------------------------------- ---------------------------------------------------------------------------------solveNative, solveNative' :: (NFData a, Fixpoint a, Show a, Loc a, PPrint a) => Solver a+solveNative, solveNative'+ :: (NFData a, Fixpoint a, Show a, Loc a, PPrint a)+ => Config -> FInfo a -> IO (Result (Integer, a)) -------------------------------------------------------------------------------- solveNative !cfg !fi0 = solveNative' cfg fi0 `catch`- (return . crashResult (errorMap fi0))+ (return . crashResult (errorMap fi0) . wrapExceptionWithContext)+ `catch`+ (return . crashResultOther . wrapExceptionWithContext) -crashResult :: (PPrint a) => ErrorMap a -> Error -> Result (Integer, a)-crashResult m err' = Result res mempty mempty mempty+crashResult :: (PPrint a) => ErrorMap a -> ExceptionWithContext Error -> Result (Integer, a)+crashResult m (ExceptionWithContext ectx ex) = Result res mempty mempty mempty where- res = Crash es msg- es = catMaybes [ findError m e | e <- ers ]- ers = errs err'- msg | null ers = "Sorry, unexpected panic in liquid-fixpoint!"- -- {-dbgFalse-} True = "Sorry, unexpected panic in liquid-fixpoint!\n" ++ crashMessage es- | otherwise = showpp err'+ res = Crash es msg+ es = catMaybes [ findError m e | e <- ers ]+ ers = errs ex+ msg = displayExceptionContext ectx ++ "\n" ++ msg0+ msg0 | null ers = "Sorry, unexpected panic in liquid-fixpoint!\n"+ ++ showpp ex+ | otherwise = showpp ex -_crashMessage :: [((Integer, a), Maybe String) ] -> String-_crashMessage es = L.intercalate "\n" [ msg i s | ((i,_), Just s) <- es ]+crashResultOther+ :: ExceptionWithContext SomeException -> Result (Integer, a)+crashResultOther (ExceptionWithContext ectx ex) =+ Result res mempty mempty mempty where- msg i s = "Error in constraint " ++ show i ++ ":\n" ++ s+ res = Crash [] msg+ msg = displayExceptionContext ectx ++ "\n" ++ msg0+ msg0 = "Sorry, unexpected panic in liquid-fixpoint!\n" ++ show ex -- | Unpleasant hack to save meta-data that can be recovered from SrcSpan type ErrorMap a = HashMap.HashMap SrcSpan a@@ -207,7 +215,7 @@ findError :: ErrorMap a -> Error1 -> Maybe ((Integer, a), Maybe String) findError m e = do ann <- HashMap.lookup (errLoc e) m- let str = render (errMsg e)+ let str = PJ.render (errMsg e) return ((-1, ann), Just str) -- The order is important here: we want the "binders" to get the "precedence"@@ -219,13 +227,13 @@ ++ [ a | (_, (_,_, a)) <- bindEnvToList (Types.bs fi) ] loudDump :: (Fixpoint a) => Int -> Config -> SInfo a -> IO ()-loudDump i cfg si = when False (writeLoud $ msg ++ render (toFixpoint cfg si))+loudDump i cfg si = when False (writeLoud $ msg ++ PJ.render (toFixpoint cfg si)) where msg = "fq file after Uniqify & Rename " ++ show i ++ "\n" {-# SCC simplifyFInfo #-} simplifyFInfo :: (NFData a, Fixpoint a, Show a, Loc a)- => Config -> FInfo a -> IO (SInfo a)+ => Config -> FInfo a -> IO (ElabParam, SInfo a) simplifyFInfo !cfg !fi0 = do -- writeLoud $ "fq file in: \n" ++ render (toFixpoint cfg fi) -- rnf fi0 `seq` donePhase Loud "Read Constraints"@@ -250,13 +258,16 @@ -- writeLoud $ "fq file after defunc: \n" ++ render (toFixpoint cfg si4) -- putStrLn $ "AXIOMS: " ++ showpp (asserts si4) loudDump 2 cfg si4- let si5 = {- SCC "elaborate" -} elaborate (ElabParam (solverFlags $ solver cfg) (atLoc dummySpan "solver") (symbolEnv cfg si4)) si4+ let ef = solverFlags cfg+ elabParam = ElabParam+ ef+ (atLoc dummySpan "solver")+ (coerceEnv ef (symbolEnv cfg si4))+ si5 = elaborate elabParam si4 -- writeLoud $ "fq file after elaborate: \n" ++ render (toFixpoint cfg si5) loudDump 3 cfg si5 let si6 = if extensionality cfg then {- SCC "expand" -} expand cfg si5 else si5- if rewriteAxioms cfg && noLazyPLE cfg- then instantiate cfg si6 $!! Nothing- else return si6+ return (elabParam, si6){- SCC "elaborate" -} reduceFInfo :: Fixpoint a => Config -> FInfo a -> IO (FInfo a) reduceFInfo cfg fi = do@@ -264,15 +275,15 @@ reducedFi = {- SCC "reduceEnvironments" -} reduceEnvironments simplifiedFi when (save cfg) $ savePrettifiedQuery cfg reducedFi- if noEnvironmentReduction cfg then+ if noEnvReduction cfg then return fi else return reducedFi solveNative' !cfg !fi0 = do- si6 <- simplifyFInfo cfg fi0- res0 <- {- SCC "Sol.solve" -} Sol.solve cfg $!! si6- let res = simplifyResult res0+ (elabParam, si6) <- simplifyFInfo cfg fi0+ res0 <- {- SCC "Sol.solve" -} Sol.solve cfg elabParam $!! si6+ let res = simplifyResult cfg res0 -- rnf soln `seq` donePhase Loud "Solve2" --let stat = resStatus res -- saveSolution cfg res@@ -304,119 +315,27 @@ writeFile f $ unlines $ [ "" , "Solution:"- , showpp (resSolution res)+ , scopedRender (resSolution res) ] ++- ( if gradual cfg then- ["", "", showpp $ gresSolution res]- else- []- ) ++ [ "" , "" , "Non-cut kvars:" , ""- , showpp (HashMap.map unElab $ resNonCutsSolution res)+ , scopedRender (HashMap.map forceDelayed $ resNonCutsSolution res) ]+ where+ scopedRender = PJ.render . PJ.vcat . map ncDoc . scoped+ scoped sol = [ (k, scope k, e) | (k, e) <- HashMap.toList sol]+ scope k = HashMap.lookupDefault [] k $ resSorts res+ ncDoc (k, xts, e) = PJ.hsep [ pprint k PJ.<> pprint xts, ":=", pprint e ] -simplifyResult :: Result a -> Result a-simplifyResult res =+simplifyResult :: Config -> Result a -> Result a+simplifyResult cfg res = res- { resSolution = HashMap.map simplifyKVar (resSolution res)- , resNonCutsSolution = HashMap.map simplifyKVar (resNonCutsSolution res)+ { resSolution = HashMap.map simplifyKVar' (resSolution res)+ , resNonCutsSolution = HashMap.map (fmap 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+ simplifyKVar' = unElabSets . unElab . Sol.simplifyKVar HashSet.empty+ sets = elabSetBag . solverFlags $ cfg+ unElabSets = if sets then unElabFSetBagZ3 else id
src/Language/Fixpoint/Solver/Common.hs view
@@ -2,30 +2,39 @@ module Language.Fixpoint.Solver.Common (askSMT, toSMT) where -import Language.Fixpoint.Types.Config (Config, solver, solverFlags)+import Control.Monad.State+import Language.Fixpoint.Types.Config (Config, solverFlags) import Language.Fixpoint.Smt.Interface (Context(..), checkValidWithContext)+import Language.Fixpoint.Smt.Types (SmtM) import Language.Fixpoint.Types import Language.Fixpoint.Types.Visitor (kvarsExpr) import Language.Fixpoint.Defunctionalize (defuncAny) import Language.Fixpoint.SortCheck (ElabParam(..), elaborate)+import GHC.Stack (HasCallStack) mytracepp :: (PPrint a) => String -> a -> a mytracepp = notracepp -askSMT :: Config -> Context -> [(Symbol, Sort)] -> Expr -> IO Bool-askSMT cfg ctx xs e--- | isContraPred e = return False+askSMT+ :: HasCallStack+ => Config+ -> [(Symbol, Sort)] -- ^ symbols already declared in the SMT solver+ -> [(Symbol, Sort)] -- ^ symbols to declare in the SMT solver+ -> Expr+ -> SmtM Bool+askSMT cfg bsInSMT xs e | isTautoPred e = return True- | null (kvarsExpr e) = checkValidWithContext ctx xs PTrue e'+ | null (kvarsExpr e) =+ do ctx <- get+ let e' = toSMT "askSMT" cfg ctx (xs ++ bsInSMT) e+ checkValidWithContext xs PTrue e' | otherwise = return False- where- e' = toSMT "askSMT" cfg ctx xs e -toSMT :: String -> Config -> Context -> [(Symbol, Sort)] -> Expr -> Pred+toSMT :: HasCallStack => String -> Config -> Context -> [(Symbol, Sort)] -> Expr -> Pred toSMT msg cfg ctx xs e = defuncAny cfg symenv .- elaborate (ElabParam (solverFlags $ solver cfg) (dummyLoc msg) (elabEnv xs)) .- mytracepp ("toSMT from " ++ msg ++ showpp e) $+ elaborate (ElabParam (solverFlags cfg) (dummyLoc msg) (elabEnv xs)) .+ mytracepp ("toSMT from " ++ msg ++ " > " ++ showpp e) $ e where elabEnv = insertsSymEnv symenv
src/Language/Fixpoint/Solver/Eliminate.hs view
@@ -16,39 +16,61 @@ import Language.Fixpoint.Types.Visitor (kvarsExpr, isConcC) import Language.Fixpoint.Graph import Language.Fixpoint.Misc (safeLookup, group, errorstar)-import Language.Fixpoint.Solver.Sanitize -------------------------------------------------------------------------------- -- | `solverInfo` constructs a `SolverInfo` comprising the Solution and various -- indices needed by the worklist-based refinement loop+--+-- Computes the set of cut and non-cut kvars, computes the hypotheses common+-- to all of the usage sites of each kvar, then initializes the solutions of+-- the non-cut KVars (in the sHyp field).+--+-- This is part of the implementation of the FUSION algorithm described in:+--+-- "Local Refinement Typing", ICFP 2017, https://ranjitjhala.github.io/static/local_refinement_typing.pdf+-- -------------------------------------------------------------------------------- {-# SCC solverInfo #-}-solverInfo :: Config -> SInfo a -> SolverInfo a b+solverInfo :: Config -> SInfo a -> SolverInfo a -------------------------------------------------------------------------------- solverInfo cfg sI = SI sHyp sI' cD cKs where- cD = elimDeps sI es nKs ebs+ cD = elimDeps sI es nKs sI' = cutSInfo sI kI cKs- sHyp = Sol.fromList sE mempty mempty kHyps kS [] sEnv- sEnv = fromListSEnv [ (x, (i, sr_sort sr)) | (i, (x,sr, _)) <- bindEnvToList (bs sI)]+ sHyp = Sol.Sol+ { Sol.sMap = mempty+ , Sol.sHyp = M.fromList kHyps+ , Sol.sScp = kS+ } kHyps = nonCutHyps sI kI nKs kI = kIndex sI (es, cKs, nKs) = kutVars cfg sI kS = kvScopes sI es- sE = symbolEnv cfg sI- ebs = S.fromList [x | i <- ebinds sI, let (x, _, _) = lookupBindEnv i (bs sI) ] - --------------------------------------------------------------------------------+-- | For each KVar, provide the intersection of the binding environments+-- of all the constraints in which it appears.+--+-- See Section 2.4 of "Local Refinement Typing", ICFP 2017, for the motivation+-- to collect these. kvScopes :: SInfo a -> [CEdge] -> M.HashMap KVar IBindEnv-kvScopes sI es = is2env <$> kiM+kvScopes sI es = commonBindingsOfConstraints <$> kvarUses where- is2env = foldr1 intersectionIBindEnv . fmap (senv . getSubC sI)- kiM = group $ [(k, i) | (Cstr i, KVar k) <- es ] ++- [(k, i) | (KVar k, Cstr i) <- es ]+ -- | The common bindings of a list of constraints+ commonBindingsOfConstraints :: [Integer] -> IBindEnv+ commonBindingsOfConstraints =+ foldr1 intersectionIBindEnv . fmap (senv . getSubC sI) ---------------------------------------------------------------------------------+ -- | The constraints in which each KVar appears+ kvarUses :: M.HashMap KVar [Integer]+ kvarUses =+ group $ [(k, i) | (Cstr i, KVar k) <- es ] +++ [(k, i) | (KVar k, Cstr i) <- es ] +--------------------------------------------------------------------------------+-- | @cutSInfo si kI cKs@ drops well-formed constraints that don't refer to the+-- KVars in @cKs@. Also drops subtyping constraints that don't refer in their+-- RHS to any of the KVars in @cKs@ or which aren't concrete. cutSInfo :: SInfo a -> KIndex -> S.HashSet KVar -> SInfo a cutSInfo si kI cKs = si { ws = ws', cm = cm' } where@@ -57,13 +79,17 @@ cs = S.fromList (concatMap kCs cKs) kCs k = M.lookupDefault [] k kI +-- | Compute Dependencies and Cuts+--+-- Yields the edges of the dependency graph, then the set of KVars whose removal+-- makes the graph acyclic (cuts), and finally the rest of the KVars. kutVars :: Config -> SInfo a -> ([CEdge], S.HashSet KVar, S.HashSet KVar) kutVars cfg si = (es, depCuts ds, depNonCuts ds) where (es, ds) = elimVars cfg si ----------------------------------------------------------------------------------- | Map each `KVar` to the list of constraints on which it appears on RHS+-- | Map each 'KVar' to the list of constraints on which it appears on RHS -------------------------------------------------------------------------------- type KIndex = M.HashMap KVar [Integer]
src/Language/Fixpoint/Solver/EnvironmentReduction.hs view
@@ -33,9 +33,9 @@ import Data.HashSet (HashSet) import qualified Data.HashSet as HashSet #if MIN_VERSION_base(4,20,0)-import Data.List (nub, partition)+import Data.List (partition) #else-import Data.List (foldl', nub, partition)+import Data.List (foldl', partition) #endif import Data.Maybe (fromMaybe) import Data.ShareMap (ShareMap)@@ -153,7 +153,6 @@ { bs = bs' , cm = HashMap.fromList cm' , ws = ws'- , ebinds = updateEbinds bs' (ebinds finfo) , bindInfo = updateBindInfoKeys bs' $ bindInfo finfo } @@ -170,9 +169,6 @@ in HashMap.filterWithKey (\bId _ -> memberIBindEnv bId ibindEnv) be - -- Updates BindIds in an ebinds list- updateEbinds be = filter (`HashMap.member` beBinds be)- -- Updates BindId keys in a bindInfos map updateBindInfoKeys be oldBindInfos = HashMap.intersection oldBindInfos (beBinds be)@@ -310,10 +306,17 @@ filter relevantBind env where allSymbols =- reachableSymbols (HashSet.union extraSymbols envSymbols) aenvMap+ reachableSymbols (HashSet.unions [extraSymbols, envSymbols, withKVars]) aenvMap envSymbols = HashSet.unions $ map (\(_, _, sr,_) -> sortedReftSymbols sr) env + -- If there are bindings with KVars, we include them to be conservative.+ withKVars =+ HashSet.fromList $+ map fst $+ filter (not . HashMap.null . exprKVars . reftPred . sr_reft . snd) $+ map (\(x, _, sr, _) -> (x, sr)) env+ relevantBind (s, _, sr, _) | HashSet.member s allSymbols = True | otherwise = case reftPred (sr_reft sr) of@@ -470,15 +473,9 @@ in finfo { bs = bs' , cm = cm'- , ebinds = updateEbinds oldToNew (ebinds finfo) , bindInfo = updateBindInfoKeys oldToNew $ bindInfo finfo } where- updateEbinds :: HashMap BindId [BindId] -> [BindId] -> [BindId]- updateEbinds oldToNew ebs =- nub $- concat [ bId : fromMaybe [] (HashMap.lookup bId oldToNew) | bId <- ebs ]- updateBindInfoKeys :: HashMap BindId [BindId] -> HashMap BindId a -> HashMap BindId a updateBindInfoKeys oldToNew infoMap =@@ -516,7 +513,7 @@ mergedEnv = mergeDuplicatedBindings env undoANFEnv =- if inlineANFBindings cfg then undoANFOnlyModified mergedEnv else HashMap.empty+ if inlineANFBinds cfg then undoANFOnlyModified mergedEnv else HashMap.empty boolSimplEnv = simplifyBooleanRefts $ HashMap.union undoANFEnv mergedEnv @@ -749,7 +746,13 @@ dropLikelyIrrelevantBindings ss env = HashMap.filterWithKey relevant env where directlyUses = HashMap.map (exprSymbolsSet . reftPred . sr_reft) env- relatedSyms = relatedSymbols ss directlyUses+ relatedSyms = relatedSymbols (HashSet.union ss withKVars) directlyUses+ -- If there are bindings with KVars, we include them to be conservative.+ withKVars =+ HashSet.fromList $+ map fst $+ filter (not . HashMap.null . exprKVars . reftPred . sr_reft . snd) $+ HashMap.toList env relevant s _sr = (not (capitalizedSym s) || prefixOfSym s /= s) && s `HashSet.member` relatedSyms capitalizedSym = Text.all isUpper . Text.take 1 . symbolText
src/Language/Fixpoint/Solver/Extensionality.hs view
@@ -24,7 +24,7 @@ mytracepp = notracepp expand :: Config -> SInfo a -> SInfo a-expand cfg si = evalState (ext si) $ initST (symbolEnv cfg si) (ddecls si) (solverFlags $ solver cfg)+expand cfg si = evalState (ext si) $ initST (symbolEnv cfg si) (ddecls si) (solverFlags cfg) where ext :: SInfo a -> Ex a (SInfo a) ext = extend@@ -148,6 +148,8 @@ go p (PImp p1 p2) = f p =<< (PImp <$> go (negatePos p) p1 <*> go p p2) go p (PAnd ps) = f p . PAnd =<< (go p `traverse` ps) + go p (ELet x e1 e2) = f p =<< ELet x <$> go p e1 <*> go p e2+ -- The below cannot appear due to normalization go p (PNot e) = f p . PNot =<< go p e go p (PIff p1 p2) = f p =<< (PIff <$> go p p1 <*> go p p2 )@@ -160,7 +162,6 @@ go p (PExist xts e) = f p . PExist xts =<< go p e go p (ETApp e s) = f p . (`ETApp` s) =<< go p e go p (ETAbs e s) = f p . (`ETAbs` s) =<< go p e- go p (PGrad k s i e) = f p . PGrad k s i =<< go p e normalize :: Expr -> Expr normalize expr' = mytracepp ("normalize: " ++ showpp expr') $ go expr'@@ -181,12 +182,12 @@ go (EIte e e1 e2) = go $ PAnd [PImp e e1, PImp (PNot e) e2] go (PAnd ps) = pAnd (go <$> ps) go (POr ps) = foldl' (\x y -> PImp (PImp (go x) PFalse) y) PFalse ps+ go e@ELet{} = e go e@(PAll _ _) = e -- Cannot appear go e@(ELam _ _) = e -- Cannot appear go e@(PExist _ _) = e -- Cannot appear go e@(ETApp _ _) = e -- Cannot appear go e@(ETAbs _ _) = e -- Cannot appear- go e@PGrad{} = e -- Cannot appear type Ex a = State (ExSt a)
− src/Language/Fixpoint/Solver/GradualSolution.hs
@@ -1,135 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleInstances #-}--module Language.Fixpoint.Solver.GradualSolution- ( -- * Create Initial Solution- init- ) where--import Control.Parallel.Strategies-import Control.Monad.Reader-import qualified Data.HashMap.Strict as M-import qualified Data.List as L-import Data.Maybe (maybeToList, isNothing)-import Language.Fixpoint.Types.Config-import Language.Fixpoint.Types.PrettyPrint ()-import qualified Language.Fixpoint.SortCheck as So-import Language.Fixpoint.Misc-import qualified Language.Fixpoint.Types as F-import qualified Language.Fixpoint.Types.Solutions as Sol-import qualified Language.Fixpoint.Types.Constraints as Cons-import Prelude hiding (init, lookup)-import Language.Fixpoint.Solver.Sanitize (symbolEnv)-import Language.Fixpoint.SortCheck------------------------------------------------------------------------------------- | Initial Gradual Solution (from Qualifiers and WF constraints) -----------------------------------------------------------------------------------------------init :: (F.Fixpoint a) => Config -> F.SInfo a -> [(F.KVar, (F.GWInfo, [F.Expr]))]----------------------------------------------------------------------------------init cfg si = map elab (runReader (traverse (refineG si qs genv) gs) ef) `using` parList rdeepseq- where- qs = F.quals si- gs = snd <$> gs0- genv = instConstants si-- gs0 = L.filter (Cons.isGWfc . snd) $ M.toList (F.ws si)-- elab (k, (x,es)) = (k, (x, elaborate (ElabParam ef (F.atLoc F.dummySpan "init") (sEnv (Cons.gsym x) (Cons.gsort x))) <$> es))-- sEnv x s = isEnv {F.seSort = F.insertSEnv x s (F.seSort isEnv)}- isEnv = symbolEnv cfg si- ef = solverFlags $ solver cfg------------------------------------------------------------------------------------refineG :: F.SInfo a -> [F.Qualifier] -> F.SEnv F.Sort -> F.WfC a -> ElabM (F.KVar, (F.GWInfo, [F.Expr]))-refineG fi qs genv w =- do (k, qb) <- refine fi qs genv w- pure (k, (F.gwInfo w, Sol.qbExprs qb))--refine :: F.SInfo a -> [F.Qualifier] -> F.SEnv F.Sort -> F.WfC a -> ElabM (F.KVar, Sol.QBind)-refine fi qs genv w = refineK (Cons.allowHOquals fi) env qs $ F.wrft w- where- env = wenv <> genv- wenv = F.sr_sort <$> F.fromListSEnv (F.envCs (F.bs fi) (F.wenv w))--instConstants :: F.SInfo a -> F.SEnv F.Sort-instConstants = F.fromListSEnv . filter notLit . F.toListSEnv . F.gLits- where- notLit = not . F.isLitSymbol . fst---refineK :: Bool -> F.SEnv F.Sort -> [F.Qualifier] -> (F.Symbol, F.Sort, F.KVar) -> ElabM (F.KVar, Sol.QBind)-refineK ho env qs (v, t, k) =- do eqs' <- Sol.qbFilterM (okInst env v t) eqs- pure (k, eqs')- where- eqs = instK ho env v t qs------------------------------------------------------------------------------------instK :: Bool- -> F.SEnv F.Sort- -> F.Symbol- -> F.Sort- -> [F.Qualifier]- -> Sol.QBind----------------------------------------------------------------------------------instK ho env v t = Sol.qb . unique . concatMap (instKQ ho env v t)- where- unique = L.nubBy ((. Sol.eqPred) . (==) . Sol.eqPred)--instKQ :: Bool- -> F.SEnv F.Sort- -> F.Symbol- -> F.Sort- -> F.Qualifier- -> [Sol.EQual]-instKQ ho env v t q =- case Cons.qpSort <$> F.qParams q of- (qt:qts) -> do- (su0, v0) <- candidates senv [(t, [v])] qt- xs <- match senv tyss [v0] (So.apply su0 <$> qts)- return $ Sol.eQual q (reverse xs)- where- tyss = instCands ho env- senv = (`F.lookupSEnvWithDistance` env)- [] -> error "Empty qpSort of qParams q"--instCands :: Bool -> F.SEnv F.Sort -> [(F.Sort, [F.Symbol])]-instCands ho env = filter isOk tyss- where- tyss = groupList [(t, x) | (x, t) <- xts]- isOk = if ho then const True else isNothing . F.functionSort . fst- xts = F.toListSEnv env--match :: So.Env -> [(F.Sort, [F.Symbol])] -> [F.Symbol] -> [F.Sort] -> [[F.Symbol]]-match env tyss xs (t : ts)- = do (su, x) <- candidates env tyss t- match env tyss (x : xs) (So.apply su <$> ts)-match _ _ xs []- = return xs-----------------------------------------------------------------------------------candidates :: So.Env -> [(F.Sort, [F.Symbol])] -> F.Sort -> [(So.TVSubst, F.Symbol)]----------------------------------------------------------------------------------candidates env tyss tx =- [(su, y) | (t, ys) <- tyss- , su <- maybeToList $ So.unifyFast mono env tx t- , y <- ys ]- where- mono = So.isMono tx-----------------------------------------------------------------------------------okInst :: F.SEnv F.Sort -> F.Symbol -> F.Sort -> Sol.EQual -> ElabM Bool----------------------------------------------------------------------------------okInst env v t eq =- do tc <- So.checkSorted F.dummySpan env sr- pure $ isNothing tc- where- sr = F.RR t (F.Reft (v, p))- p = Sol.eqPred eq---
− src/Language/Fixpoint/Solver/GradualSolve.hs
@@ -1,328 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}------------------------------------------------------------------------------------- | Solve a system of horn-clause constraints --------------------------------------------------------------------------------------------------------------------module Language.Fixpoint.Solver.GradualSolve (solveGradual) where--{- COMMENTING OUT AS IT DOESNT BUILD!-import Control.Monad (when, filterM, foldM)-import Control.Monad.State.Strict (lift)-import Language.Fixpoint.Misc-import qualified Language.Fixpoint.Types.Solutions as Sol-import qualified Language.Fixpoint.SortCheck as So-import Language.Fixpoint.Types.PrettyPrint-import qualified Language.Fixpoint.Solver.GradualSolution as S-import qualified Language.Fixpoint.Solver.Worklist as W-import qualified Language.Fixpoint.Solver.Eliminate as E-import Language.Fixpoint.Solver.Monad-import Language.Fixpoint.Utils.Progress-import Language.Fixpoint.Graph-import Text.PrettyPrint.HughesPJ-import Text.Printf-import System.Console.CmdArgs.Verbosity (whenNormal, whenLoud)-import qualified Data.HashMap.Strict as M-import qualified Data.HashSet as S--}--import Control.DeepSeq-import qualified Language.Fixpoint.Types as F-import Language.Fixpoint.Types.Config hiding (stats)--solveGradual :: (NFData a, F.Fixpoint a) => Config -> F.SInfo a -> IO (F.Result (Integer, a))-solveGradual = undefined----{- COMMENTING OUT AS IT DOESNT BUILD!------------------------------------------------------------------------------------- | Progress Bar----------------------------------------------------------------------------------withProgressFI :: SolverInfo a b -> IO b -> IO b-withProgressFI = withProgress . fromIntegral . cNumScc . siDeps-----------------------------------------------------------------------------------printStats :: F.SInfo a -> W.Worklist a -> Stats -> IO ()-printStats fi w s = putStrLn "\n" >> ppTs [ ptable fi, ptable s, ptable w ]- where- ppTs = putStrLn . showpp . mconcat-----------------------------------------------------------------------------------solverInfo :: Config -> F.SInfo a -> SolverInfo a b----------------------------------------------------------------------------------solverInfo cfg fI- | useElim cfg = E.solverInfo cfg fI- | otherwise = SI mempty fI cD (siKvars fI)- where- cD = elimDeps fI (kvEdges fI) mempty--siKvars :: F.SInfo a -> S.HashSet F.KVar-siKvars = S.fromList . M.keys . F.ws-------------------------------------------------------------------------------------- | tidyResult ensures we replace the temporary kVarArg names introduced to--- ensure uniqueness with the original names in the given WF constraints.----------------------------------------------------------------------------------tidyResult :: F.Result a -> F.Result a-tidyResult r = r { F.resSolution = tidySolution (F.resSolution r)- , F.gresSolution = gtidySolution (F.gresSolution r)- }--tidySolution :: F.FixSolution -> F.FixSolution-tidySolution = fmap tidyPred--gtidySolution :: F.GFixSolution -> F.GFixSolution-gtidySolution = fmap tidyPred -- (\(e, es) -> (tidyPred e, tidyPred <$> es))--tidyPred :: F.Expr -> F.Expr-tidyPred = F.substf (F.eVar . F.tidySymbol)---predKs :: F.Expr -> [(F.KVar, F.Subst)]-predKs (F.PAnd ps) = concatMap predKs ps-predKs (F.PKVar k su) = [(k, su)]-predKs _ = []-------------------------------------------------------------------------------------minimizeResult :: Config -> M.HashMap F.KVar F.Expr- -> SolveM (M.HashMap F.KVar F.Expr)----------------------------------------------------------------------------------minimizeResult cfg s- | minimalSol cfg = mapM minimizeConjuncts s- | otherwise = return s--minimizeConjuncts :: F.Expr -> SolveM F.Expr-minimizeConjuncts p = F.pAnd <$> go (F.conjuncts p) []- where- go [] acc = return acc- go (p:ps) acc = do b <- isValid (F.pAnd (acc ++ ps)) p- if b then go ps acc- else go ps (p:acc)----showUnsat :: Bool -> Integer -> F.Pred -> F.Pred -> IO ()-showUnsat u i lP rP = {- when u $ -} do- putStrLn $ printf "UNSAT id %s %s" (show i) (show u)- putStrLn $ showpp $ "LHS:" <+> pprint lP- putStrLn $ showpp $ "RHS:" <+> pprint rP------------------------------------------------------------------------------------- | Predicate corresponding to RHS of constraint in current solution----------------------------------------------------------------------------------rhsPred :: F.SimpC a -> F.Expr----------------------------------------------------------------------------------rhsPred c- | isTarget c = F.crhs c- | otherwise = errorstar $ "rhsPred on non-target: " ++ show (F.sid c)--isValid :: F.Expr -> F.Expr -> SolveM Bool-isValid p q = (not . null) <$> filterValid p [(q, ())]------------------------------------------------------------------------------------- | solve with edits to allow Gradual types --------------------------------------------------------------------------------------------------------------------solveGradual :: (NFData a, F.Fixpoint a) => Config -> F.SInfo a -> IO (F.Result (Integer, a))--- solveGradual = undefined--solveGradual cfg fi = do- (res, stat) <- withProgressFI sI $ runSolverM cfg sI n act- when (solverStats cfg) $ printStats fi wkl stat- return res- where- act = solveGradual_ cfg fi s0 ks wkl- sI = solverInfo cfg fi- wkl = W.init sI- n = fromIntegral $ W.wRanks wkl- s0 = siSol sI- ks = siVars sI-----------------------------------------------------------------------------------solveGradual_ :: (NFData a, F.Fixpoint a)- => Config- -> F.SInfo a- -> Sol.GSolution- -> S.HashSet F.KVar- -> W.Worklist a- -> SolveM (F.Result (Integer, a), Stats)----------------------------------------------------------------------------------solveGradual_ cfg fi s0 ks wkl = do- let s1 = mappend s0 $ {- SCC "sol-init" #-} S.init cfg fi ks- s2 <- {- SCC "sol-local" #-} filterLocal s1- s <- {- SCC "sol-refine" #-} refine s2 wkl- res <- {- SCC "sol-result" #-} result cfg wkl s- st <- stats- let res' = {- SCC "sol-tidy" #-} tidyResult res- return $!! (res', st)--filterLocal :: Sol.GSolution -> SolveM Sol.GSolution-filterLocal sol = do- gs' <- mapM (initGBind sol) gs- return $ Sol.updateGMap sol $ M.fromList gs'- where- gs = M.toList $ Sol.gMap sol--initGBind :: Sol.GSolution -> (F.KVar, (((F.Symbol, F.Sort), F.Expr), Sol.GBind)) -> SolveM (F.KVar, (((F.Symbol, F.Sort), F.Expr), Sol.GBind))-initGBind sol (k, (e, gb)) = do- elems0 <- filterM (isLocal e) (Sol.gbEquals gb)- elems <- sortEquals elems0- lattice <- makeLattice [] (map (:[]) elems) elems- return $ ((k,) . (e,) . Sol.equalsGb) lattice- where- makeLattice acc new elems- | null new- = return acc- | otherwise- = do let cands = [e:es |e<-elems, es<-new]- localCans <- filterM (isLocal e) cands- newElems <- filterM (notTrivial (new ++ acc)) localCans- makeLattice (acc ++ new) newElems elems-- notTrivial [] _ = return True- notTrivial (x:xs) p = do v <- isValid (mkPred x) (mkPred p)- if v then return False- else notTrivial xs p-- mkPred eq = So.elaborate "initBGind.mkPred" (Sol.sEnv sol) (F.pAnd (Sol.eqPred <$> eq))- isLocal (v, e) eqs = do- let pp = So.elaborate "filterLocal" (Sol.sEnv sol) $ F.PExist [v] $ F.pAnd (e:(Sol.eqPred <$> eqs))- isValid mempty pp-- root = Sol.trueEqual- sortEquals xs = (bfs [0]) <$> makeEdges vs [] vs- where- vs = zip [0..] (root:(head <$> xs))-- bfs [] _ = []- bfs (i:is) es = (snd $ (vs!!i)) : bfs (is++map snd (filter (\(j,k) -> (j==i && notElem k is)) es)) es-- makeEdges _ acc [] = return acc- makeEdges vs acc (x:xs) = do ves <- concat <$> mapM (makeEdgesOne x) vs- if any (\(i,j) -> elem (j,i) acc) ves- then makeEdges (filter ((/= fst x) . fst) vs) (filter (\(i,j) -> ((i /= fst x) && (j /= fst x))) acc) xs- else makeEdges vs (mergeEdges (ves ++ acc)) xs-- makeEdgesOne (i,_) (j,_) | i == j = return []- makeEdgesOne (i,x) (j,y) = do- ij <- isValid (mkPred [x]) (mkPred [y])- return (if ij then [(j,i)] else [])-- mergeEdges es = filter (\(i,j) -> (not (any (\k -> ((i,k) `elem` es && (k,j) `elem` es)) (fst <$> es)))) es------------------------------------------------------------------------------------refine :: Sol.GSolution -> W.Worklist a -> SolveM Sol.GSolution----------------------------------------------------------------------------------refine s w- | Just (c, w', newScc, rnk) <- W.pop w = do- i <- tickIter newScc- (b, s') <- refineC i s c- lift $ writeLoud $ refineMsg i c b rnk- let w'' = if b then W.push c w' else w'- refine s' w''- | otherwise = return s- where- -- DEBUG- refineMsg i c b rnk = printf "\niter=%d id=%d change=%s rank=%d\n"- i (F.subcId c) (show b) rnk-------------------------------------------------------------------------------- | Single Step Refinement ----------------------------------------------------------------------------------------------------------------------------refineC :: Int -> Sol.GSolution -> F.SimpC a -> SolveM (Bool, Sol.GSolution)-----------------------------------------------------------------------------refineC _i s c- | null rhs = return (False, s)- | otherwise = do be <- getBinds- let lhss = snd <$> S.lhsPred be s c- kqs <- filterValidGradual lhss rhs- return $ S.update s ks kqs- where- _ci = F.subcId c- (ks, rhs) = rhsCands s c- -- msg = printf "refineC: iter = %d, sid = %s, soln = \n%s\n"- -- _i (show (F.sid c)) (showpp s)- _msg ks xs ys = printf "refineC: iter = %d, sid = %s, s = %s, rhs = %d, rhs' = %d \n"- _i (show _ci) (showpp ks) (length xs) (length ys)---rhsCands :: Sol.GSolution -> F.SimpC a -> ([F.KVar], Sol.Cand (F.KVar, Sol.EQual))-rhsCands s c = (fst <$> ks, kqs)- where- kqs = [ (p, (k, q)) | (k, su) <- ks, (p, q) <- cnd k su ]- ks = predKs . F.crhs $ c- cnd k su = Sol.qbPreds msg s su (Sol.lookupQBind s k)- msg = "rhsCands: " ++ show (F.sid c)------------------------------------------------------------------------------------- | Gradual Convert Solution into Result --------------------------------------------------------------------------------------------------------------------------------result :: (F.Fixpoint a) => Config -> W.Worklist a -> Sol.GSolution- -> SolveM (F.Result (Integer, a))----------------------------------------------------------------------------------result cfg wkl s = do- lift $ writeLoud "Computing Result"- stat <- result_ wkl s- lift $ whenNormal $ putStrLn $ "RESULT: " ++ show (F.sid <$> stat)- F.Result (ci <$> stat) <$> solResult cfg s <*> solResultGradual wkl cfg s- where- ci c = (F.subcId c, F.sinfo c)--result_ :: Fixpoint a => W.Worklist a -> Sol.GSolution -> SolveM (F.FixResult (F.SimpC a))-result_ w s = res <$> filterM (isUnsat s) cs- where- cs = W.unsatCandidates w- res [] = F.Safe- res cs' = F.Unsafe cs'--solResult :: Config -> Sol.GSolution -> SolveM (M.HashMap F.KVar F.Expr)-solResult cfg- = minimizeResult cfg . Sol.result---solResultGradual :: W.Worklist a -> Config -> Sol.GSolution -> SolveM F.GFixSolution-solResultGradual w _cfg sol- = F.toGFixSol . Sol.resultGradual <$> updateGradualSolution (W.unsatCandidates w) sol-----------------------------------------------------------------------------------updateGradualSolution :: [F.SimpC a] -> Sol.GSolution -> SolveM (Sol.GSolution)----------------------------------------------------------------------------------updateGradualSolution cs sol = foldM f (Sol.emptyGMap sol) cs- where- f s c = do- be <- getBinds- let lpi = S.lhsPred be sol c- let rp = rhsPred c- gbs <- firstValid rp lpi- return $ Sol.updateGMapWithKey gbs s---firstValid :: Monoid a => F.Expr -> [(a, F.Expr)] -> SolveM a-firstValid _ [] = return mempty-firstValid rhs ((y,lhs):xs) = do- v <- isValid lhs rhs- if v then return y else firstValid rhs xs------------------------------------------------------------------------------------isUnsat :: Fixpoint a => Sol.GSolution -> F.SimpC a -> SolveM Bool----------------------------------------------------------------------------------isUnsat s c = do- -- lift $ printf "isUnsat %s" (show (F.subcId c))- _ <- tickIter True -- newScc- be <- getBinds- let lpi = S.lhsPred be s c- let rp = rhsPred c- res <- (not . or) <$> mapM (`isValid` rp) (snd <$> lpi)- lift $ whenLoud $ showUnsat res (F.subcId c) (F.pOr (snd <$> lpi)) rp- return res----}
− src/Language/Fixpoint/Solver/Instantiate.hs
@@ -1,816 +0,0 @@------------------------------------------------------------------------------------ | This module implements "Proof by Logical Evaluation" where we--- unfold function definitions if they *must* be unfolded, to strengthen--- the environments with function-definition-equalities.--- The algorithm is discussed at length in:------ 1. "Refinement Reflection", POPL 2018, https://arxiv.org/pdf/1711.03842--- 2. "Reasoning about Functions", VMCAI 2018, https://ranjitjhala.github.io/static/reasoning-about-functions.pdf-----------------------------------------------------------------------------------{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE PartialTypeSignatures #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ExistentialQuantification #-}--module Language.Fixpoint.Solver.Instantiate (instantiate) where--import Language.Fixpoint.Types-import Language.Fixpoint.Types.Config as FC-import qualified Language.Fixpoint.Types.Visitor as Vis-import qualified Language.Fixpoint.Misc as Misc -- (mapFst)-import qualified Language.Fixpoint.Smt.Interface as SMT-import Language.Fixpoint.Defunctionalize-import qualified Language.Fixpoint.Utils.Trie as T-import Language.Fixpoint.Utils.Progress -- as T-import Language.Fixpoint.SortCheck-import Language.Fixpoint.Graph.Deps (isTarget)-import Language.Fixpoint.Solver.Sanitize (symbolEnv)-import qualified Language.Fixpoint.Solver.PLE as PLE (instantiate)-import qualified Language.Fixpoint.Solver.Common as Common (toSMT)-import Language.Fixpoint.Solver.Common (askSMT)-import Control.Monad ((>=>), foldM, forM, forM_, join)-import Control.Monad.State-import Data.Bifunctor (first, second)-import qualified Data.Text as T-import qualified Data.HashMap.Strict as M-import qualified Data.HashSet as S-import qualified Data.List as L-import qualified Data.Maybe as Mb -- (isNothing, catMaybes, fromMaybe)-import Data.Char (isDigit, isUpper)--- import Debug.Trace (trace)--- import Text.Printf (printf)--mytracepp :: (PPrint a) => String -> a -> a-mytracepp = notracepp------------------------------------------------------------------------------------- | Strengthen Constraint Environments via PLE----------------------------------------------------------------------------------instantiate :: (Loc a) => Config -> SInfo a -> Maybe [SubcId] -> IO (SInfo a)-instantiate cfg info subcIds- | not (oldPLE cfg)- = PLE.instantiate cfg info subcIds-- | noIncrPle cfg- = instantiate' cfg info subcIds-- | otherwise- = incrInstantiate' cfg info subcIds------------------------------------------------------------------------------------- | New "Incremental" PLE -- see [NOTE:TREE-LIKE]--{- | [NOTE:TREE-LIKE] incremental PLE relies crucially on the SInfo satisfying- a "tree like" invariant:- forall constraints c, c'.- if i in c and i in c' then- forall 0 <= j < i, j in c and j in c'-- -}----------------------------------------------------------------------------------incrInstantiate' :: (Loc a) => Config -> SInfo a -> Maybe [SubcId] -> IO (SInfo a)---------------------------------------------------------------------------------incrInstantiate' cfg info subcIds = do- let cs = [ (i, c) | (i, c) <- M.toList (cm info), isPleCstr aEnv i c- , maybe True (i `L.elem`) subcIds ]- let t = mkCTrie cs -- 1. BUILD the Trie- res <- withProgress (1 + length cs) $- 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"- sEnv = symbolEnv cfg info- aEnv = ae info-------------------------------------------------------------------------------------- | Step 1a: @instEnv@ sets up the incremental-PLE environment-instEnv :: (Loc a) => Config -> SInfo a -> [(SubcId, SimpC a)] -> SMT.Context -> InstEnv a-instEnv cfg info cs ctx = InstEnv cfg ctx bEnv aEnv (M.fromList cs) γ s0- where- bEnv = bs info- aEnv = ae info- γ = knowledge cfg ctx aEnv- s0 = EvalEnv 0 [] aEnv (SMT.ctxSymEnv ctx) cfg--------------------------------------------------------------------------------------------------- | Step 1b: @mkCTrie@ builds the @Trie@ of constraints indexed by their environments-mkCTrie :: [(SubcId, SimpC a)] -> CTrie-mkCTrie ics = mytracepp "TRIE" $ T.fromList [ (cBinds c, i) | (i, c) <- ics ]- where- cBinds = L.sort . elemsIBindEnv . senv--------------------------------------------------------------------------------------------------- | Step 2: @pleTrie@ walks over the @CTrie@ to actually do the incremental-PLE-pleTrie :: CTrie -> InstEnv a -> IO InstRes-pleTrie t env = loopT env ctx0 diff0 Nothing res0 t- where- diff0 = []- res0 = M.empty- ctx0 = initCtx es0- es0 = eqBody <$> L.filter (null . eqArgs) (aenvEqs . ieAenv $ env)--loopT :: InstEnv a -> ICtx -> Diff -> Maybe BindId -> InstRes -> CTrie -> IO InstRes-loopT env ctx delta i res t = case t of- T.Node [] -> return res- T.Node [b] -> loopB env ctx delta i res b- T.Node bs -> withAssms env ctx delta Nothing $ \ctx' -> do- (ctx'', res') <- ple1 env ctx' i Nothing res- foldM (loopB env ctx'' [] i) res' bs--loopB :: InstEnv a -> ICtx -> Diff -> Maybe BindId -> InstRes -> CBranch -> IO InstRes-loopB env ctx delta iMb res b = case b of- T.Bind i t -> loopT env ctx (i:delta) (Just i) res t- T.Val cid -> withAssms env ctx delta (Just cid) $ \ctx' -> do- progressTick- snd <$> ple1 env ctx' iMb (Just cid) res---withAssms :: InstEnv a -> ICtx -> Diff -> Maybe SubcId -> (ICtx -> IO b) -> IO b-withAssms env@InstEnv{..} ctx delta cidMb act = do- let ctx' = updCtx env ctx delta cidMb- let assms = mytracepp ("ple1-assms: " ++ show (cidMb, delta)) (icAssms ctx')- SMT.smtBracket ieSMT "PLE.evaluate" $ do- forM_ assms (SMT.smtAssert ieSMT)- act ctx'---- | @ple1@ performs the PLE at a single "node" in the Trie-ple1 :: InstEnv a -> ICtx -> Maybe BindId -> Maybe SubcId -> InstRes -> IO (ICtx, InstRes)-ple1 env@InstEnv{..} ctx i cidMb res = do- let cands = mytracepp ("ple1-cands: " ++ show cidMb) $ S.toList (icCands ctx)- -- unfolds <- evalCands ieKnowl ieEvEnv cands- unfolds <- evalCandsLoop ieCfg ieSMT ieKnowl ieEvEnv cands- return $ updCtxRes env ctx res i cidMb (mytracepp ("ple1-cands-unfolds: " ++ show cidMb) unfolds)--_evalCands :: Knowledge -> EvalEnv -> [Expr] -> IO [Unfold]-_evalCands _ _ [] = return []-_evalCands γ s0 cands = do eqs <- mapM (evalOne γ s0) cands- return $ mkUnfolds (zip (Just <$> cands) eqs)--unfoldPred :: Config -> SMT.Context -> [Unfold] -> Pred-unfoldPred cfg ctx = toSMT cfg ctx [] . pAnd . concatMap snd--evalCandsLoop :: Config -> SMT.Context -> Knowledge -> EvalEnv -> [Expr] -> IO [Unfold]-evalCandsLoop cfg ctx γ s0 = go []- where- go acc [] = return acc- go acc cands = do eqss <- SMT.smtBracket ctx "PLE.evaluate" $ do- SMT.smtAssert ctx (unfoldPred cfg ctx acc)- mapM (evalOne γ s0) cands- let us = zip (Just <$> cands) eqss- case mkUnfolds us of- [] -> return acc- us' -> do let acc' = acc ++ us'- let oks = S.fromList [ e | (Just e, _) <- us' ]- let cands' = [ e | e <- cands, not (S.member e oks) ]- go acc' cands'---------------------------------------------------------------------------------------------------- | Step 3: @resSInfo@ uses incremental PLE result @InstRes@ to produce the strengthened SInfo--resSInfo :: Config -> SymEnv -> SInfo a -> InstRes -> SInfo a-resSInfo cfg env info res = strengthenBinds info res'- where- res' = M.fromList $ mytracepp "ELAB-INST: " $ zip is ps''- ps'' = zipWith (\i -> elaborate (ElabParam (solverFlags $ solver cfg) (atLoc dummySpan ("PLE1 " ++ show i)) env)) is ps'- ps' = defuncAny cfg env ps- (is, ps) = unzip (M.toList res)--------------------------------------------------------------------------------------------------- | @InstEnv@ has the global information needed to do PLE-data InstEnv a = InstEnv- { ieCfg :: !Config- , ieSMT :: !SMT.Context- , ieBEnv :: !(BindEnv a)- , ieAenv :: !AxiomEnv- , ieCstrs :: !(M.HashMap SubcId (SimpC a))- , ieKnowl :: !Knowledge- , ieEvEnv :: !EvalEnv- }---- | @ICtx@ is the local information -- at each trie node -- obtained by incremental PLE-data ICtx = ICtx- { icAssms :: ![Pred] -- ^ Hypotheses, already converted to SMT format- , icCands :: S.HashSet Expr -- ^ "Candidates" for unfolding- , icEquals :: ![Expr] -- ^ "Known" equalities- , icSolved :: S.HashSet Expr -- ^ Terms that we have already expanded- }---- | @InstRes@ is the final result of PLE; a map from @BindId@ to the equations "known" at that BindId-type InstRes = M.HashMap BindId Expr---- | @Unfold is the result of running PLE at a single equality;--- (e, [(e1, e1')...]) is the source @e@ and the (possible empty)--- list of PLE-generated equalities (e1, e1') ...--- type Unfold = (Maybe Expr, [(Expr, Expr)])-type Unfold = (Maybe Expr, [Expr])-type CTrie = T.Trie SubcId-type CBranch = T.Branch SubcId-type Diff = [BindId] -- ^ in "reverse" order--initCtx :: [Expr] -> ICtx-initCtx es = ICtx- { icAssms = []- , icCands = mempty- , icEquals = mytracepp "INITIAL-STUFF-INCR" es- , icSolved = mempty- }--equalitiesPred :: [(Expr, Expr)] -> [Expr]-equalitiesPred eqs = [ EEq e1 e2 | (e1, e2) <- eqs, e1 /= e2 ]--updCtxRes :: InstEnv a -> ICtx -> InstRes -> Maybe BindId -> Maybe SubcId -> [Unfold] -> (ICtx, InstRes)-updCtxRes env ctx res iMb cidMb us- = -- trace _msg- ( ctx { {- icCands = cands', -} icSolved = solved', icEquals = mempty}- , res'- )- where- _msg = Mb.maybe "nuttin\n" (debugResult env res') cidMb- res' = updRes res iMb (pAnd solvedEqs)- _cands' = (icCands ctx `S.union` newCands) `S.difference` solved'- solved' = S.union (icSolved ctx) solvedCands- newCands = S.fromList (concatMap topApps newEqs)- solvedCands = S.fromList [ e | (Just e, _) <- okUnfolds ]- solvedEqs = icEquals ctx ++ newEqs- newEqs = concatMap snd okUnfolds- okUnfolds = mytracepp _str [ (eMb, ps) | (eMb, ps) <- us, {- let ps = equalitiesPred eqs, -} not (null ps) ]- _str = "okUnfolds " ++ showpp (iMb, cidMb)- -- cands' = S.difference (icCands ctx) (S.fromList solvedCands)- -- solvedEqs = icEquals ctx ++ concatMap snd us- -- solvedCands = [ e | (Just e, _) <- us]--mkUnfolds :: [(a, [(Expr, Expr)])] -> [(a, [Expr])]-mkUnfolds us = [ (eMb, ps) | (eMb, eqs) <- us- , let ps = equalitiesPred eqs- , not (null ps)- ]--debugResult :: InstEnv a -> InstRes -> SubcId -> String-debugResult InstEnv{..} res subId = msg- where- msg = "INCR-INSTANTIATE i = " ++ show subId ++ ": " ++ showpp cidEqs- cidEqs = pAnd [ e | i <- cBinds, e <- Mb.maybeToList $ M.lookup i res ]- cBinds = L.sort . elemsIBindEnv . senv . getCstr ieCstrs $ subId---updRes :: InstRes -> Maybe BindId -> Expr -> InstRes-updRes res (Just i) e = M.insert i e res-updRes res Nothing _ = res---- | @updCtx env ctx delta cidMb@ adds the assumptions and candidates from @delta@ and @cidMb@--- to the context.-updCtx :: InstEnv a -> ICtx -> Diff -> Maybe SubcId -> ICtx-updCtx InstEnv {..} ctx delta cidMb- = ctx { icAssms = ctxEqs- , icCands = cands <> icCands ctx- , icEquals = initEqs <> icEquals ctx }- where- initEqs = equalitiesPred (initEqualities ieSMT ieAenv bs)- cands = S.fromList (concatMap topApps es0) `S.difference` icSolved ctx- ctxEqs = toSMT ieCfg ieSMT [] <$>- (initEqs ++- [ expr xr- | xr@(_, r) <- bs- , null (Vis.kvarsExpr $ reftPred $ sr_reft r)- ])- (bs, es0) = (second unElabSortedReft <$> binds, unElab <$> es)- es = eRhs : (expr <$> binds)- eRhs = maybe PTrue crhs subMb- binds = [ (x, y) | i <- delta, let (x, y, _) = lookupBindEnv i ieBEnv ]- subMb = getCstr ieCstrs <$> cidMb--getCstr :: M.HashMap SubcId (SimpC a) -> SubcId -> SimpC a-getCstr env cid = Misc.safeLookup "Instantiate.getCstr" cid env------------------------------------------------------------------------------------- | "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 (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- cstrs = [ (i, c) | (i, c) <- M.toList (cm info) , isPleCstr aenv i c- , maybe True (i `L.elem`) subcIds ]- file = srcFile cfg ++ ".evals"- env = symbolEnv cfg info- aenv = {- mytracepp "AXIOM-ENV" -} ae info--sInfo :: Config -> SymEnv -> SInfo a -> [((SubcId, SrcSpan), Expr)] -> SInfo a-sInfo cfg env info ips = strengthenHyp info (mytracepp "ELAB-INST: " $ zip (fst <$> is) ps'')- where- (is, ps) = unzip ips- ps' = defuncAny cfg env ps- ps'' = zipWith (\(i, sp) -> elaborate (ElabParam (solverFlags $ solver cfg) (atLoc sp ("PLE1 " ++ show i)) env)) is ps'--instSimpC :: Config -> SMT.Context -> BindEnv a -> AxiomEnv -> SubcId -> SimpC a -> IO Expr-instSimpC cfg ctx bds aenv subId sub- | isPleCstr aenv subId sub = do- let is0 = mytracepp "INITIAL-STUFF" $ eqBody <$> L.filter (null . eqArgs) (aenvEqs aenv)- let (bs, es0) = cstrExprs bds sub- equalities <- evaluate cfg ctx aenv bs es0 subId- let evalEqs = [ EEq e1 e2 | (e1, e2) <- equalities, e1 /= e2 ]- return $ pAnd (is0 ++ evalEqs)- | otherwise = return PTrue--isPleCstr :: AxiomEnv -> SubcId -> SimpC a -> Bool-isPleCstr aenv subId c = isTarget c && M.lookupDefault False subId (aenvExpand aenv)--cstrExprs :: BindEnv a -> SimpC a -> ([(Symbol, SortedReft)], [Expr])-cstrExprs bds sub = (second unElabSortedReft <$> binds, unElab <$> es)- where- es = crhs sub : (expr <$> binds)- binds = envCs bds (senv sub)------------------------------------------------------------------------------------- | Symbolic Evaluation with SMT----------------------------------------------------------------------------------evaluate :: Config -> SMT.Context -> AxiomEnv -- ^ Definitions- -> [(Symbol, SortedReft)] -- ^ Environment of "true" facts- -> [Expr] -- ^ Candidates for unfolding- -> SubcId -- ^ Constraint Id- -> IO [(Expr, Expr)] -- ^ Newly unfolded equalities----------------------------------------------------------------------------------evaluate cfg ctx aenv facts es subId = do- let eqs = initEqualities ctx aenv facts- let γ = knowledge cfg ctx aenv- let cands = mytracepp ("evaluate-cands " ++ showpp subId) $ Misc.setNub (concatMap topApps es)- let s0 = EvalEnv 0 [] aenv (SMT.ctxSymEnv ctx) cfg- let ctxEqs = [ toSMT cfg ctx [] (EEq e1 e2) | (e1, e2) <- eqs ]- ++ [ toSMT cfg ctx [] (expr xr) | xr@(_, r) <- facts, null (Vis.kvarsExpr $ reftPred $ sr_reft r) ]- eqss <- _evalLoop cfg ctx γ s0 ctxEqs cands- return $ eqs ++ eqss----_evalLoop :: Config -> SMT.Context -> Knowledge -> EvalEnv -> [Pred] -> [Expr] -> IO [(Expr, Expr)]-_evalLoop cfg ctx γ s0 ctxEqs = loop 0 []- where- loop _ acc [] = return acc- loop i acc cands = do let eqp = toSMT cfg ctx [] $ pAnd $ equalitiesPred acc- eqss <- SMT.smtBracket ctx "PLE.evaluate" $ do- forM_ (eqp : ctxEqs) (SMT.smtAssert ctx)- mapM (evalOne γ s0) cands- case concat eqss of- [] -> return acc- eqs' -> do let acc' = acc ++ eqs'- let oks = S.fromList (fst <$> eqs')- let cands' = [ e | e <- cands, not (S.member e oks) ]- loop (i + 1 :: Integer) acc' cands'-------------------------------------------------------------------------------------data EvalEnv = EvalEnv- { evId :: !Int- , evSequence :: [(Expr,Expr)]- , _evAEnv :: !AxiomEnv- , evEnv :: !SymEnv- , _evCfg :: !Config- }--type EvalST a = StateT EvalEnv IO a-----------------------------------------------------------------------------------evalOne :: Knowledge -> EvalEnv -> Expr -> IO [(Expr, Expr)]-evalOne γ s0 e = do- (e', st) <- runStateT (eval γ initCS (mytracepp "evalOne: " e)) s0- if e' == e then return [] else return ((e, e') : evSequence st)--{- | [NOTE: Eval-Ite] We should not be doing any PLE/eval under if-then-else where- the guard condition does not provably hold. For example, see issue #387.- However, its ok and desirable to `eval` in this case, as long as one is not- unfolding recursive functions. To permit this, we track the "call-stack" and- whether or not, `eval` is occurring under an unresolved guard: if so, we do not- expand under any function that is already on the call-stack.- -}--data Recur = Ok | Stop deriving (Eq, Show)-type CStack = ([Symbol], Recur)--instance PPrint Recur where- pprintTidy _ = Misc.tshow--initCS :: CStack-initCS = ([], Ok)--pushCS :: CStack -> Symbol -> CStack-pushCS (fs, r) f = (f:fs, r)--recurCS :: CStack -> Symbol -> Bool-recurCS (_, Ok) _ = True--- recurCS (_, _ ) _ = False -- not (f `elem` fs)-recurCS (fs, _) f = f `notElem` fs--noRecurCS :: CStack -> CStack-noRecurCS (fs, _) = (fs, Stop)---- Don't evaluate under Lam, App, Ite, or Constants-topApps :: Expr -> [Expr]-topApps = go- where- go (PAnd es) = concatMap go es- go (POr es) = concatMap go es- go (PAtom _ e1 e2) = go e1 ++ go e2- go (PIff e1 e2) = go e1 ++ go e2- go (PImp e1 e2) = go e1 ++ go e2- go (EBin _ e1 e2) = go e1 ++ go e2- go (PNot e) = go e- go (ENeg e) = go e- go e@(EApp _ _) = [e]- go _ = []---- makeLam is the adjoint of splitEApp-makeLam :: Knowledge -> Expr -> Expr-makeLam γ e = L.foldl' (flip ELam) e (knLams γ)--eval :: Knowledge -> CStack -> Expr -> EvalST Expr-eval γ stk = go- where- go (ELam (x,s) e) = ELam (x, s) <$> eval γ' stk e where γ' = γ { knLams = (x, s) : knLams γ }- go e@(EIte b e1 e2) = go b >>= \b' -> evalIte γ stk e b' e1 e2- go (ECoerc s t e) = ECoerc s t <$> go e- go e@(EApp _ _) = evalArgs γ stk e >>= evalApp γ stk e- go e@(EVar _) = evalApp γ stk e (e, [])- go (PAtom r e1 e2) = PAtom r <$> go e1 <*> go e2- go (ENeg e) = ENeg <$> go e- go (EBin o e1 e2) = EBin o <$> go e1 <*> go e2- go (ETApp e t) = flip ETApp t <$> go e- go (ETAbs e s) = flip ETAbs s <$> go e- go (PNot e) = PNot <$> go e- go (PImp e1 e2) = PImp <$> go e1 <*> go e2- go (PIff e1 e2) = PIff <$> go e1 <*> go e2- go (PAnd es) = PAnd <$> (go `traverse` es)- go (POr es) = POr <$> (go `traverse` es)- go e = return e---- | `evalArgs` also evaluates all the partial applications for hacky reasons,--- suppose `foo g = id` then we want `foo g 10 = 10` and for that we need--- to `eval` the term `foo g` into `id` to tickle the `eval` on `id 10`.--- This seems a bit of a hack. At any rate, this can lead to divergence.--- TODO: distill a .fq test from the MOSSAKA-hw3 example.--evalArgs :: Knowledge -> CStack -> Expr -> EvalST (Expr, [Expr])-evalArgs γ stk = go []- where- go acc (EApp f e)- = do f' <- evalOk γ stk f- e' <- eval γ stk e- go (e':acc) f'- go acc e- = (,acc) <$> eval γ stk e---- | Minimal test case illustrating this `evalOk` hack is LH#tests/ple/pos/MossakaBug.hs--- too tired & baffled to generate simple .fq version. TODO:nuke and rewrite PLE!-evalOk :: Knowledge -> CStack -> Expr -> EvalST Expr-evalOk γ stk@(_, Ok) e = eval γ stk e-evalOk _ _ e = pure e--{--evalArgs :: Knowledge -> CStack -> Expr -> EvalST (Expr, [Expr])-evalArgs- | True = evalArgsOLD- | False = evalArgsNEW--evalArgsNEW :: Knowledge -> CStack -> Expr -> EvalST (Expr, [Expr])-evalArgsNEW γ stk e = do- let (e1, es) = splitEApp e- e1' <- eval γ stk e1- es' <- mapM (eval γ stk) es- return (e1', es')---}--evalApp :: Knowledge -> CStack -> Expr -> (Expr, [Expr]) -> EvalST Expr--- evalApp γ stk e (e1, es) = tracepp ("evalApp:END" ++ showpp (e1,es)) <$> (evalAppAc γ stk e (e1, es))-evalApp γ stk e (e1, es) = do- res <- evalAppAc γ stk e (e1, es)- let diff = res /= eApps e1 es- return $ mytracepp ("evalApp:END:" ++ showpp diff) res--evalAppAc :: Knowledge -> CStack -> Expr -> (Expr, [Expr]) -> EvalST Expr--{- MOSSAKA-}-evalAppAc γ stk e (EVar f, [ex])- | (EVar dc, es) <- splitEApp ex- , Just simp <- L.find (\simp -> (smName simp == f) && (smDC simp == dc)) (knSims γ)- , length (smArgs simp) == length es- = do let msg = "evalAppAc:ePop: " ++ showpp (f, dc, es)- let ePopIf = mytracepp msg $ substPopIf (zip (smArgs simp) es) (smBody simp)- e' <- eval γ stk ePopIf- (e, "Rewrite -" ++ showpp f) ~> e'--evalAppAc γ stk _ (EVar f, es)- -- we should move the lookupKnowledge stuff here into kmAms γ- | Just eq <- L.find (( == f) . eqName) (knAms γ)- , Just bd <- getEqBody eq- , length (eqArgs eq) == length es- , f `notElem` syms bd -- non-recursive equations << HACK! misses MUTUALLY RECURSIVE definitions!- , recurCS stk f- = do env <- gets (seSort . evEnv)- let ee = substEq env PopIf eq es bd- assertSelectors γ ee- eval γ (pushCS stk f) ee--evalAppAc γ stk _e (EVar f, es)- | Just eq <- L.find ((== f) . eqName) (knAms γ)- , Just bd <- getEqBody eq- , length (eqArgs eq) == length es -- recursive equations- , recurCS stk f- = do env <- gets (seSort . evEnv)- mytracepp ("EVAL-REC-APP" ++ showpp (stk, _e))- <$> evalRecApplication γ (pushCS stk f) (eApps (EVar f) es) (substEq env Normal eq es bd)--evalAppAc _ _ _ (f, es)- = return (eApps f es)------------------------------------------------------------------------------------- | 'substEq' unfolds or instantiates an equation at a particular list of--- argument values. We must also substitute the sort-variables that appear--- as coercions. See tests/proof/ple1.fq----------------------------------------------------------------------------------substEq :: SEnv Sort -> SubstOp -> Equation -> [Expr] -> Expr -> Expr-substEq env o eq es bd = substEqVal o eq es (substEqCoerce env eq es bd)--data SubstOp = PopIf | Normal--substEqVal :: SubstOp -> Equation -> [Expr] -> Expr -> Expr-substEqVal o eq es bd = case o of- PopIf -> substPopIf xes bd- Normal -> subst (mkSubst xes) bd- where- xes = zip xs es- xs = eqArgNames eq--substEqCoerce :: SEnv Sort -> Equation -> [Expr] -> Expr -> Expr-substEqCoerce env eq es bd = Vis.applyCoSub coSub bd- where- ts = snd <$> eqArgs eq- sp = panicSpan "mkCoSub"- eTs = sortExpr sp env <$> es- coSub = mytracepp ("substEqCoerce" ++ showpp (eqName eq, es, eTs, ts)) $ mkCoSub env eTs ts--mkCoSub :: SEnv Sort -> [Sort] -> [Sort] -> Vis.CoSub-mkCoSub env eTs xTs = M.fromList [ (x, unite ys) | (x, ys) <- Misc.groupList xys ]- where- unite ts = mytracepp ("UNITE: " ++ showpp ts) $ Mb.fromMaybe (uError ts) (unifyTo1 symToSearch ts)- symToSearch = mkSearchEnv env- uError ts = panic ("mkCoSub: cannot build CoSub for " ++ showpp xys ++ " cannot unify " ++ showpp ts)- xys = mytracepp "mkCoSubXXX" $ Misc.sortNub $ concat $ zipWith matchSorts _xTs _eTs- (_xTs,_eTs) = mytracepp "mkCoSub:MATCH" (xTs, eTs)--matchSorts :: Sort -> Sort -> [(Symbol, Sort)]-matchSorts sort1 sort2 = mytracepp ("matchSorts :" ++ showpp (sort1, sort2)) $ go sort1 sort2- where- go (FObj x) {-FObj-} y = [(x, y)]- go (FAbs _ t1) (FAbs _ t2) = go t1 t2- go (FFunc s1 t1) (FFunc s2 t2) = go s1 s2 ++ go t1 t2- go (FApp s1 t1) (FApp s2 t2) = go s1 s2 ++ go t1 t2- go _ _ = []-----------------------------------------------------------------------------------getEqBody :: Equation -> Maybe Expr-getEqBody (Equ x xts b _ _)- | Just (fxs, e) <- getEqBodyPred b- , (EVar f, es) <- splitEApp fxs- , f == x- , es == (EVar . fst <$> xts)- = Just e-getEqBody _- = Nothing--getEqBodyPred :: Expr -> Maybe (Expr, Expr)-getEqBodyPred (PAtom Eq fxs e)- = Just (fxs, e)-getEqBodyPred (PAnd ((PAtom Eq fxs e):_))- = Just (fxs, e)-getEqBodyPred _- = Nothing--eqArgNames :: Equation -> [Symbol]-eqArgNames = map fst . eqArgs--substPopIf :: [(Symbol, Expr)] -> Expr -> Expr-substPopIf xes expr' = L.foldl' go expr' xes- where- go e (x, EIte b e1 e2) = EIte b (subst1 e (x, e1)) (subst1 e (x, e2))- go e (x, ex) = subst1 e (x, ex)---- see [NOTE:Eval-Ite] the below is wrong; we need to guard other branches too. sigh.--evalRecApplication :: Knowledge -> CStack -> Expr -> Expr -> EvalST Expr-evalRecApplication γ stk e (EIte b e1 e2) = do- contra <- {- mytracepp ("CONTRA? " ++ showpp e) <$> -} liftIO (isValid γ PFalse)- if contra- then return e- else do b' <- eval γ stk (mytracepp "REC-APP-COND" b) -- <<<<<<<<<<<<<<<<<<<<< MOSSAKA-LOOP?- b1 <- liftIO (isValid γ b')- if b1- then addEquality γ e e1 >>- {- SCC "assertSelectors-1" -} assertSelectors γ e1 >>- eval γ stk (mytracepp ("evalREC-1: " ++ showpp stk) e1) >>=- ((e, "App1: ") ~>)- else do- b2 <- liftIO (isValid γ (PNot b'))- if b2- then addEquality γ e e2 >>- {- SCC "assertSelectors-2" -} assertSelectors γ e2 >>- eval γ stk (mytracepp ("evalREC-2: " ++ showpp stk) e2) >>=- ((e, "App2: " ++ showpp stk ) ~>)- else return e-evalRecApplication _ _ _ e- = return e--addEquality :: Knowledge -> Expr -> Expr -> EvalST ()-addEquality γ e1 e2 =- modify (\st -> st{evSequence = (makeLam γ e1, makeLam γ e2):evSequence st})--evalIte :: Knowledge -> CStack -> Expr -> Expr -> Expr -> Expr -> EvalST Expr-evalIte γ stk e b e1 e2 = mytracepp "evalIte:END: " <$>- evalIteAc γ stk e b e1 (mytracepp msg e2)- where- msg = "evalIte:BEGINS: " ++ showpp (stk, e)---evalIteAc :: Knowledge -> CStack -> Expr -> Expr -> Expr -> Expr -> EvalST Expr-evalIteAc γ stk e b e1 e2- = join $ evalIte' γ stk e b e1 e2 <$> liftIO (isValid γ b) <*> liftIO (isValid γ (PNot b))--evalIte' :: Knowledge -> CStack -> Expr -> Expr -> Expr -> Expr -> Bool -> Bool -> EvalST Expr-evalIte' γ stk e _ e1 _ b _- | b- = do e' <- eval γ stk e1- (e, "If-True of:" ++ showpp b) ~> e'-evalIte' γ stk e _ _ e2 _ b'- | b'- = do e' <- eval γ stk e2- (e, "If-False") ~> e'-evalIte' γ stk _ b e1 e2 _ _- -- see [NOTE:Eval-Ite] #387- = EIte b <$> eval γ stk' e1 <*> eval γ stk' e2- where stk' = mytracepp "evalIte'" $ noRecurCS stk------------------------------------------------------------------------------------- | Knowledge (SMT Interaction)----------------------------------------------------------------------------------data Knowledge = KN- { knSims :: ![Rewrite] -- ^ Measure info, asserted for each new Ctor ('assertSelectors')- , knAms :: ![Equation] -- ^ (Recursive) function definitions, used for PLE- , knContext :: SMT.Context- , knPreds :: SMT.Context -> [(Symbol, Sort)] -> Expr -> IO Bool- , knLams :: [(Symbol, Sort)]- }--isValid :: Knowledge -> Expr -> IO Bool-isValid γ e = mytracepp ("isValid: " ++ showpp e) <$>- knPreds γ (knContext γ) (knLams γ) e--isProof :: (a, SortedReft) -> Bool-isProof (_, RR s _) = showpp s == "Tuple"--knowledge :: Config -> SMT.Context -> AxiomEnv -> Knowledge-knowledge cfg ctx aenv = KN- { knSims = aenvSimpl aenv- , knAms = aenvEqs aenv- , knContext = ctx- , knPreds = askSMT cfg- , knLams = []- }---- | This creates the rewrite rule e1 -> e2, applied when:--- 1. when e2 is a DataCon and can lead to further reductions--- 2. when size e2 < size e1-initEqualities :: SMT.Context -> AxiomEnv -> [(Symbol, SortedReft)] -> [(Expr, Expr)]-initEqualities ctx aenv es = concatMap (makeSimplifications (aenvSimpl aenv)) dcEqs- where- dcEqs = Misc.setNub (Mb.catMaybes [getDCEquality symEnv' e1 e2 | EEq e1 e2 <- atoms])- atoms = splitPAnd . expr =<< filter isProof es- symEnv' = SMT.ctxSymEnv ctx---- AT: Non-obvious needed invariant: askSMT True is always the--- totality-effecting one.--- RJ: What does "totality effecting" mean?--toSMT :: Config -> SMT.Context -> [(Symbol, Sort)] -> Expr -> Pred-toSMT = Common.toSMT "Instantiate.toSMT"--makeSimplifications :: [Rewrite] -> (Symbol, [Expr], Expr) -> [(Expr, Expr)]-makeSimplifications sis (dc, es, e)- = go =<< sis- where- go (SMeasure f dc' xs bd)- | dc == dc', length xs == length es- = [(EApp (EVar f) e, subst (mkSubst $ zip xs es) bd)]- go _- = []--getDCEquality :: SymEnv -> Expr -> Expr -> Maybe (Symbol, [Expr], Expr)-getDCEquality sEnv e1 e2- | Just dc1 <- f1- , Just dc2 <- f2- = if dc1 == dc2- then Nothing- else error ("isDCEquality on" ++ showpp e1 ++ "\n" ++ showpp e2)- | Just dc1 <- f1- = Just (dc1, es1, e2)- | Just dc2 <- f2- = Just (dc2, es2, e1)- | otherwise- = Nothing- where- (f1, es1) = first (getDC sEnv) (splitEApp e1)- (f2, es2) = first (getDC sEnv) (splitEApp e2)---- TODO: Stringy hacks-getDC :: SymEnv -> Expr -> Maybe Symbol-getDC sEnv (EVar x)- | isUpperSymbol x && Mb.isNothing (symEnvTheory x sEnv)- = Just x-getDC _ _- = Nothing--isUpperSymbol :: Symbol -> Bool-isUpperSymbol x = (0 < lengthSym x') && isUpper (headSym x')- where- x' = dropModuleNames x--dropModuleNames :: Symbol -> Symbol-dropModuleNames = mungeNames (symbol . last) "."- where- mungeNames _ _ "" = ""- mungeNames f d s'@(symbolText -> s)- | isTupleSymbol s' = s'- | otherwise = f $ T.splitOn d $ stripParens s- stripParens t = Mb.fromMaybe t ((T.stripPrefix "(" >=> T.stripSuffix ")") t)-- -- TODO: Remove this code which is LH specific- isTupleSymbol :: Symbol -> Bool- isTupleSymbol s =- let t = symbolText s- in T.isPrefixOf "Tuple" t &&- T.all isDigit (T.drop 5 t)------------------------------------------------------------------------------------- | Creating Measure Info------------------------------------------------------------------------------------ AT@TODO do this for all reflected functions, not just DataCons--{- [NOTE:Datacon-Selectors] The 'assertSelectors' function- insert measure information for every constructor that appears- in the expression e.-- In theory, this is not required as the SMT ADT encoding takes- care of it. However, in practice, some constructors, e.g. from- GADTs cannot be directly encoded in SMT due to the lack of SMTLIB- support for GADT. Hence, we still need to hang onto this code.-- See tests/proof/ple2.fq for a concrete example.- -}--assertSelectors :: Knowledge -> Expr -> EvalST ()-assertSelectors γ expr' = do- sims <- gets (aenvSimpl . _evAEnv)- -- cfg <- gets evCfg- -- _ <- foldlM (\_ s -> Vis.mapMExpr (go s) e) (mytracepp "assertSelector" e) sims- forM_ sims $ \s -> Vis.mapMExpr (go s) expr'- where- go :: Rewrite -> Expr -> EvalST Expr- go (SMeasure f dc xs bd) e@(EApp _ _)- | (EVar dc', es) <- splitEApp e- , dc == dc'- , length xs == length es- = do let e1 = EApp (EVar f) e- let e2 = subst (mkSubst $ zip xs es) bd- addEquality γ e1 e2- return e- go _ e- = return e------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------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- return res--infixl 9 ~>-(~>) :: (Expr, String) -> Expr -> EvalST Expr-(e, _str) ~> e' = do- let msg = "PLE: " ++ _str ++ showpp (e, e')- modify (\st -> st {evId = mytracepp msg (evId st) + 1})- return e'
src/Language/Fixpoint/Solver/Interpreter.hs view
@@ -57,7 +57,7 @@ -------------------------------------------------------------------------------- -- | Strengthen Constraint Environments via PLE ---------------------------------------------------------------------------------instInterpreter :: (Loc a) => Config -> SInfo a -> Maybe [SubcId] -> IO (SInfo a)+instInterpreter :: (Loc a) => Config -> SInfo a -> Maybe [SubcId] -> IO (BindEnv a) instInterpreter cfg fi' subcIds = do let cs = M.filterWithKey (\i c -> isPleCstr aEnv i c && maybe True (i `L.elem`) subcIds)@@ -178,11 +178,11 @@ -- | Step 3: @resSInfo@ uses incremental PLE result @InstRes@ to produce the strengthened SInfo ---------------------------------------------------------------------------------------------- -resSInfo :: Config -> SymEnv -> SInfo a -> InstRes -> SInfo a+resSInfo :: Config -> SymEnv -> SInfo a -> InstRes -> BindEnv a resSInfo cfg env info res = strengthenBinds info res' where res' = M.fromList $ zip is ps''- ps'' = zipWith (\i -> elaborate (ElabParam (solverFlags $ solver cfg) (atLoc dummySpan ("PLE1 " ++ show i)) env)) is ps'+ ps'' = zipWith (\i -> elaborate (ElabParam (solverFlags cfg) (atLoc dummySpan ("PLE1 " ++ show i)) env)) is ps' ps' = defuncAny cfg env ps (is, ps) = unzip (M.toList res) @@ -358,6 +358,7 @@ EIte b _ _ -> go b $ e0 : acc ECoerc _ _ e -> go e acc ECst e _ -> go e acc+ ELet{} -> acc ESym _ -> acc ECon _ -> acc EVar _ -> acc@@ -367,7 +368,6 @@ PKVar _ _ -> acc PAll _ _ -> acc PExist _ _ -> acc- PGrad{} -> acc largestApps :: Expr -> [Expr] largestApps = flip go []@@ -388,13 +388,13 @@ ESym _ -> acc ECon _ -> acc EVar _ -> e0 : acc+ ELet{} -> acc ELam _ _ -> acc ETApp _ _ -> acc ETAbs _ _ -> acc PKVar _ _ -> acc PAll _ _ -> acc PExist _ _ -> acc- PGrad{} -> acc fastEval :: ConstMap -> Knowledge -> ICtx -> Expr -> EvalST Expr fastEval ienv γ ctx e@@ -554,9 +554,11 @@ interpret ie γ ctx env e@(PExist xss e1) = case xss of [] -> interpret' ie γ ctx env e1 _ -> e-interpret _ _ _ _ e@PGrad{} = e interpret ie γ ctx env (ECoerc s t e) = let e' = interpret' ie γ ctx env e in if s == t then e' else ECoerc s t e'+interpret ie γ ctx env (ELet x e1 e2) = let e1' = interpret' ie γ ctx env e1+ e2' = interpret' ie γ ctx env e2 in+ ELet x e1' e2' --------------------------------------------------------------------------------
src/Language/Fixpoint/Solver/Monad.hs view
@@ -5,19 +5,16 @@ module Language.Fixpoint.Solver.Monad ( -- * Type SolveM+ , liftSMT -- * Execution , runSolverM - -- * Get Binds- , getBinds , getContext -- * SMT Query , filterRequired , filterValid- , filterValidGradual- , checkSat , smtEnablembqi , sendConcreteBindingsToSMT @@ -27,10 +24,12 @@ , stats , numIter , SolverState(..)++ , modifyContext ) where -import Control.Monad (foldM, forM, forM_, when)+import Control.Monad (forM, forM_, when) import Language.Fixpoint.Utils.Progress import qualified Language.Fixpoint.Types.Config as C import Language.Fixpoint.Types.Config (Config)@@ -43,18 +42,20 @@ import Language.Fixpoint.Smt.Serialize () import Language.Fixpoint.Types.PrettyPrint () import Language.Fixpoint.Smt.Interface+import Language.Fixpoint.Smt.Types (SmtM) -- import qualified Language.Fixpoint.Smt.Theories as Thy import Language.Fixpoint.Solver.Sanitize import Language.Fixpoint.Solver.Stats import Language.Fixpoint.Graph.Types (SolverInfo (..)) -- import Language.Fixpoint.Solver.Solution -- import Data.Maybe (catMaybes)-import Data.List (partition) -- import Data.Char (isUpper)+import qualified Control.Monad.State as ST import Control.Monad.State.Strict import qualified Data.HashMap.Strict as M import Data.Maybe (catMaybes) import Control.Exception.Base (bracket)+import Language.Fixpoint.SortCheck (ElabParam) -------------------------------------------------------------------------------- -- | Solver Monadic API --------------------------------------------------------@@ -64,8 +65,8 @@ data SolverState ann = SS { ssCtx :: !Context -- ^ SMT Solver Context- , ssBinds :: !(F.BindEnv ann) -- ^ All variables and types , ssStats :: !Stats -- ^ Solver Statistics+ , ssElabParam :: !ElabParam -- ^ Elaboration Parameters } stats0 :: F.GInfo c b -> Stats@@ -74,31 +75,24 @@ nCs = M.size $ F.cm fi ---------------------------------------------------------------------------------runSolverM :: Config -> SolverInfo ann c -> SolveM ann a -> IO a+runSolverM :: Config -> SolverInfo ann -> ElabParam -> SolveM ann a -> IO a ---------------------------------------------------------------------------------runSolverM cfg sI act =+runSolverM cfg sI elabParam act = bracket acquire release $ \ctx -> do res <- runStateT act' (s0 ctx) return (fst res) where- s0 ctx = SS ctx be (stats0 fi)+ s0 ctx = SS ctx (stats0 fi) elabParam act' = assumesAxioms (F.asserts fi) >> act release = cleanupContext acquire = makeContextWithSEnv cfg file initEnv (F.defns fi) initEnv = symbolEnv cfg fi- be = F.bs fi file = C.srcFile cfg -- only linear arithmetic when: linear flag is on or solver /= Z3 -- lar = linear cfg || Z3 /= solver cfg fi = (siQuery sI) {F.hoInfo = F.cfgHoInfo cfg } - ---------------------------------------------------------------------------------getBinds :: SolveM ann (F.BindEnv ann)----------------------------------------------------------------------------------getBinds = ssBinds <$> get---------------------------------------------------------------------------------- getIter :: SolveM ann Int -------------------------------------------------------------------------------- getIter = numIter . ssStats <$> get@@ -115,8 +109,13 @@ incChck n = modifyStats $ \s -> s {numChck = n + numChck s} incVald n = modifyStats $ \s -> s {numVald = n + numVald s} -withContext :: (Context -> IO a) -> SolveM ann a-withContext k = (lift . k) =<< getContext+liftSMT :: SmtM a -> SolveM ann a+liftSMT k =+ do es <- get+ let ctx = ssCtx es+ (a, ctx') <- lift $ ST.runStateT k ctx+ put (es {ssCtx = ctx'})+ pure a getContext :: SolveM ann Context getContext = ssCtx <$> get@@ -124,6 +123,9 @@ modifyStats :: (Stats -> Stats) -> SolveM ann () modifyStats f = modify $ \s -> s { ssStats = f (ssStats s) } +modifyContext :: (Context -> Context) -> SolveM ann ()+modifyContext f = modify $ \s -> s { ssCtx = f (ssCtx s) }+ -------------------------------------------------------------------------------- -- | SMT Interface ------------------------------------------------------------- --------------------------------------------------------------------------------@@ -133,9 +135,8 @@ -- -- Yields the ids of bindings known to the SMT sendConcreteBindingsToSMT- :: F.IBindEnv -> (F.IBindEnv -> SolveM ann a) -> SolveM ann a-sendConcreteBindingsToSMT known act = do- be <- getBinds+ :: F.IBindEnv -> F.BindEnv ann -> (F.IBindEnv -> SolveM ann a) -> SolveM ann a+sendConcreteBindingsToSMT known be act = do let concretePreds = [ (i, F.subst1 p (v, F.EVar s)) | (i, (s, F.RR _ (F.Reft (v, p)),_)) <- F.bindEnvToList be@@ -144,12 +145,16 @@ , not (F.memberIBindEnv i known) ] st <- get- (a, st') <- withContext $ \me -> do- smtBracket me "" $ do+ (a, st'') <- liftSMT $+ smtBracket "sendConcreteBindingsToSMT" $ do forM_ concretePreds $ \(i, e) ->- smtDefineFunc me (F.bindSymbol (fromIntegral i)) [] F.boolSort e- flip runStateT st $ act $ F.unionIBindEnv known $ F.fromListIBindEnv $ map fst concretePreds- put st'+ smtDefineFunc (F.bindSymbol (fromIntegral i)) [] F.boolSort e+ ctx <- get+ let st' = st { ssCtx = ctx }+ (a, st'') <- liftIO $ flip runStateT st' $ act $ F.unionIBindEnv known $ F.fromListIBindEnv $ map fst concretePreds+ put (ssCtx st'')+ return (a, st'')+ modify $ \st''' -> st'' { ssCtx = ssCtx st''' } return a where isShortExpr F.PTrue = True@@ -170,9 +175,9 @@ filterValid :: F.SrcSpan -> F.Expr -> F.Cand a -> SolveM ann [a] -------------------------------------------------------------------------------- filterValid sp p qs = do- qs' <- withContext $ \me ->- smtBracket me "filterValidLHS" $- filterValid_ sp p qs me+ qs' <- liftSMT $+ smtBracket "filterValidLHS" $+ filterValid_ sp p qs -- stats incBrkt incChck (length qs)@@ -180,66 +185,23 @@ return qs' {-# SCC filterValid_ #-}-filterValid_ :: F.SrcSpan -> F.Expr -> F.Cand a -> Context -> IO [a]-filterValid_ sp p qs me = catMaybes <$> do- smtAssert me p+filterValid_ :: F.SrcSpan -> F.Expr -> F.Cand a -> SmtM [a]+filterValid_ sp p qs = catMaybes <$> do+ smtAssertDecl p forM qs $ \(q, x) ->- smtBracketAt sp me "filterValidRHS" $ do- smtAssert me (F.PNot q)- valid <- smtCheckUnsat me+ smtBracketAt sp "filterValidRHS" $ do+ smtAssertDecl (F.PNot q)+ valid <- smtCheckUnsat return $ if valid then Just x else Nothing ------------------------------------------------------------------------------------ | `filterValidGradual ps [(x1, q1),...,(xn, qn)]` returns the list `[ xi | p => qi]`--- | for some p in the list ps----------------------------------------------------------------------------------filterValidGradual :: [F.Expr] -> F.Cand a -> SolveM ann [a]----------------------------------------------------------------------------------filterValidGradual p qs = do- qs' <- withContext $ \me ->- smtBracket me "filterValidGradualLHS" $- filterValidGradual_ p qs me- -- stats- incBrkt- incChck (length qs)- incVald (length qs')- return qs'--filterValidGradual_ :: [F.Expr] -> F.Cand a -> Context -> IO [a]-filterValidGradual_ ps qs me- = map snd . fst <$> foldM partitionCandidates ([], qs) ps- where- partitionCandidates :: (F.Cand a, F.Cand a) -> F.Expr -> IO (F.Cand a, F.Cand a)- partitionCandidates (ok, candidates) p = do- (valids', invalids') <- partition snd <$> filterValidOne_ p candidates me- let (valids, invalids) = (fst <$> valids', fst <$> invalids')- return (ok ++ valids, invalids)--filterValidOne_ :: F.Expr -> F.Cand a -> Context -> IO [((F.Expr, a), Bool)]-filterValidOne_ p qs me = do- smtAssert me p- forM qs $ \(q, x) ->- smtBracket me "filterValidRHS" $ do- smtAssert me (F.PNot q)- valid <- smtCheckUnsat me- return ((q, x), valid)- smtEnablembqi :: SolveM ann () smtEnablembqi- = withContext smtSetMbqi-----------------------------------------------------------------------------------checkSat :: F.Expr -> SolveM ann Bool----------------------------------------------------------------------------------checkSat p- = withContext $ \me ->- smtBracket me "checkSat" $- smtCheckSat me p+ = liftSMT smtSetMbqi -------------------------------------------------------------------------------- assumesAxioms :: [F.Triggered F.Expr] -> SolveM ann () ---------------------------------------------------------------------------------assumesAxioms es = withContext $ \me -> forM_ es $ smtAssertAxiom me+assumesAxioms es = liftSMT $ forM_ es smtAssertAxiom ---------------------------------------------------------------------------
src/Language/Fixpoint/Solver/PLE.hs view
@@ -8,6 +8,7 @@ -- 2. "Reasoning about Functions", VMCAI 2018, https://ranjitjhala.github.io/static/reasoning-about-functions.pdf -------------------------------------------------------------------------------- +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE TupleSections #-}@@ -30,10 +31,11 @@ import Language.Fixpoint.Types hiding (simplify) import Language.Fixpoint.Types.Config as FC-import Language.Fixpoint.Types.Solutions (CMap)+import Language.Fixpoint.Types.Solutions (CMap, Solution) import qualified Language.Fixpoint.Types.Visitor as Vis import qualified Language.Fixpoint.Misc as Misc import qualified Language.Fixpoint.Smt.Interface as SMT+import Language.Fixpoint.Smt.Types (SmtM) import Language.Fixpoint.Defunctionalize import Language.Fixpoint.Solver.EnvironmentReduction (inlineInExpr, undoANF) import qualified Language.Fixpoint.Utils.Files as Files@@ -44,6 +46,7 @@ import Language.Fixpoint.Solver.Common (askSMT, toSMT) import Language.Fixpoint.Solver.Sanitize (symbolEnv) import Language.Fixpoint.Solver.Simplify+import Language.Fixpoint.Solver.Solution (CombinedEnv(..), applyInSortedReft) import Language.Fixpoint.Solver.Rewrite as Rewrite import Language.REST.OCAlgebra as OC@@ -51,7 +54,7 @@ import Language.REST.RuntimeTerm as RT import Language.REST.SMT (withZ3, SolverHandle) -import Control.Monad (filterM, foldM, forM_, when, replicateM)+import Control.Monad (filterM, foldM, forM_, when, replicateM, zipWithM) import Control.Monad.State import Control.Monad.Trans.Maybe import Data.Bifunctor (second)@@ -71,26 +74,31 @@ -------------------------------------------------------------------------------- -- | Strengthen Constraint Environments via PLE---------------------------------------------------------------------------------+--+-- @instantiate cfg fi subcIds@ yields @F.bs fi@ strengthened with the+-- unfoldings discovered by PLE on the constraints in @subcIds@ (or all+-- constraints if @subcIds == Nothing@). {-# SCC instantiate #-}-instantiate :: (Loc a) => Config -> SInfo a -> Maybe [SubcId] -> IO (SInfo a)-instantiate cfg fi' subcIds = do+instantiate :: (Loc a) => Config -> SInfo a -> Maybe Solution -> Maybe [SubcId] -> SmtM (BindEnv a)+instantiate cfg fi' mSol subcIds = do let cs = M.filterWithKey (\i c -> isPleCstr aEnv i c && maybe True (i `L.elem`) subcIds) (cm info) let t = mkCTrie (M.toList cs) -- 1. BUILD the Trie- res <- withRESTSolver $ \solver -> withProgress (1 + M.size cs) $- 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+ res <- withRESTSolver $ \solver -> do+ ctx <- get+ (res, ctx') <- liftIO $ withProgressM (`runStateT` ctx) (1 + M.size cs) $ do+ env <- instEnv cfg info mSol cs solver+ pleTrie t env -- 2. TRAVERSE Trie to compute InstRes+ put ctx'+ return res+ liftIO $ savePLEEqualities cfg info sEnv res return $ resSInfo cfg sEnv info res -- 3. STRENGTHEN SInfo using InstRes where- withRESTSolver :: (Maybe SolverHandle -> IO a) -> IO a+ withRESTSolver :: (Maybe SolverHandle -> SmtM a) -> SmtM a withRESTSolver f | all null (M.elems $ aenvAutoRW aEnv) = f Nothing withRESTSolver f = withZ3 (f . Just) - file = srcFile cfg ++ ".evals" sEnv = symbolEnv cfg info aEnv = ae info info = normalize fi'@@ -107,7 +115,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+ elabParam = ElabParam (solverFlags cfg) "savePLEEqualities" sEnv renderConstraintRewrite (cid, eqs) = "constraint id" <+> text (show cid ++ ":") $+$ nest 2@@ -122,10 +130,18 @@ ------------------------------------------------------------------------------- -- | Step 1a: @instEnv@ sets up the incremental-PLE environment-instEnv :: (Loc a) => Config -> SInfo a -> CMap (SimpC a) -> Maybe SolverHandle -> SMT.Context -> IO (InstEnv a)-instEnv cfg info cs restSolver ctx = do- refRESTCache <- newIORef mempty- refRESTSatCache <- newIORef mempty+instEnv+ :: Loc a+ => Config+ -> SInfo a+ -> Maybe Solution+ -> CMap (SimpC a)+ -> Maybe SolverHandle+ -> SmtM (InstEnv a)+instEnv cfg info s cs restSolver = do+ ctx <- get+ refRESTCache <- liftIO $ newIORef mempty+ refRESTSatCache <- liftIO $ newIORef mempty let restOrd = FC.restOC cfg oc0 = ordConstraints restOrd $ Mb.fromJust restSolver@@ -145,6 +161,8 @@ s0 = EvalEnv { evEnv = SMT.ctxSymEnv ctx , evElabF = ef+ , evKCtx = ctx+ , evExScope = [] , evPendingUnfoldings = mempty , evNewEqualities = mempty , evSMTCache = mempty@@ -157,16 +175,16 @@ } return $ InstEnv { ieCfg = cfg- , ieSMT = ctx- , ieBEnv = coerceBindEnv ef (bs info)+ , ieBEnv = bs info , ieAenv = ae info , ieCstrs = cs- , ieKnowl = knowledge cfg ctx info+ , ieKnowl = knowledge cfg info , ieEvEnv = s0 , ieLRWs = lrws info+ , ieSol = s } where- ef = solverFlags $ solver cfg+ ef = solverFlags cfg cachedNotStrongerThan refRESTCache oc a b = do m <- readIORef refRESTCache@@ -212,7 +230,7 @@ ---------------------------------------------------------------------------------------------- -- | Step 2: @pleTrie@ walks over the @CTrie@ to actually do the incremental-PLE-pleTrie :: CTrie -> InstEnv a -> IO InstRes+pleTrie :: Loc a => CTrie -> InstEnv a -> SmtM InstRes pleTrie t env = loopT env ctx0 diff0 Nothing res0 t where diff0 = []@@ -225,42 +243,54 @@ , icSubcId = Nothing , icANFs = [] , icLRWs = mempty+ , icBindIds = mempty , icEtaBetaFlag = etabeta $ ieCfg env , icExtensionalityFlag = extensionality $ ieCfg env , icLocalRewritesFlag = localRewrites $ ieCfg env+ , icFreshExistentialCounter = 0+ , icInitialLHSs = mempty } loopT- :: InstEnv a+ :: Loc a+ => InstEnv a -> ICtx -> Diff -- ^ The longest path suffix without forks in reverse order -> Maybe BindId -- ^ bind id of the branch ancestor of the trie if any. -- 'Nothing' when this is the top-level trie. -> InstRes -> CTrie- -> IO InstRes-loopT env ctx delta i res t = case t of+ -> SmtM InstRes+loopT env ictx delta i res t = case t of T.Node [] -> return res- T.Node [b] -> loopB env ctx delta i res b- T.Node bs -> withAssms env ctx delta Nothing $ \ctx' -> do- (ctx'', env'', res') <- ple1 env ctx' i res- foldM (loopB env'' ctx'' [] i) res' bs+ T.Node [b] -> loopB env ictx delta i res b+ T.Node bs -> withAssms env ictx delta Nothing (Just t) $ \ictx' -> do+ (ictx'', env'', res') <- ple1 env ictx' i res+ foldM (loopB env'' ictx'' [] i) res' bs loopB- :: InstEnv a+ :: Loc a+ => InstEnv a -> ICtx -> Diff -- ^ The longest path suffix without forks in reverse order -> Maybe BindId -- ^ bind id of the branch ancestor of the branch if any. -- 'Nothing' when this is a branch of the top-level trie. -> InstRes -> CBranch- -> IO InstRes-loopB env ctx delta iMb res b = case b of- T.Bind i t -> loopT env ctx (i:delta) (Just i) res t- T.Val cid -> withAssms env ctx delta (Just cid) $ \ctx' -> do- progressTick- (\(_, _, r) -> r) <$> ple1 env ctx' iMb res+ -> SmtM InstRes+loopB env ictx delta iMb res b = case b of+ T.Bind i t -> loopT env ictx (i:delta) (Just i) res t+ T.Val cid -> withAssms env ictx delta (Just cid) Nothing $ \ictx' -> do+ liftIO progressTick+ (\(_, _, r) -> r) <$> ple1 env ictx' iMb res +collectConstraints :: CTrie -> [SubcId]+collectConstraints = go+ where+ go (T.Node bs) = concatMap goB bs+ goB (T.Bind _ t) = go t+ goB (T.Val cid) = [cid]+ -- | Adds to @ctx@ candidate expressions to unfold from the bindings in @delta@ -- and the rhs of @cidMb@. --@@ -271,35 +301,59 @@ -- Pushes assumptions from the modified context to the SMT solver, runs @act@, -- and then pops the assumptions. ---withAssms :: InstEnv a -> ICtx -> Diff -> Maybe SubcId -> (ICtx -> IO b) -> IO b-withAssms env@InstEnv{..} ctx delta cidMb act = do- let ctx' = updCtx env ctx delta cidMb- let assms = icAssms ctx'+withAssms+ :: Loc a+ => InstEnv a+ -> ICtx+ -> Diff+ -> Maybe SubcId+ -> Maybe CTrie+ -> (ICtx -> SmtM b)+ -> SmtM b+withAssms env ctx delta cidMb mCTrie act = do+ sctx <- get+ let cfg = SMT.config sctx+ let (ictx', bs) = updCtx cfg env sctx ctx delta cidMb mCTrie+ let assms = icAssms ictx' - SMT.smtBracket ieSMT "PLE.evaluate" $ do- forM_ assms (SMT.smtAssert ieSMT)- act ctx' { icAssms = mempty }+ SMT.smtBracket "PLE.withAssms" $ do+ -- See Note [Existential quantification when unfolding]+ SMT.smtDecls $ elabBindings (ieEvEnv env) bs+ forM_ (S.toList assms) SMT.smtAssertDecl+ act $ ictx' { icAssms = mempty } + where+ elabBindings eenv bs =+ elaborate (ElabParam (evElabF eenv) "withAssms: PExist Args" (evEnv eenv)) bs+ -- | @ple1@ performs the PLE at a single "node" in the Trie -- -- It will generate equalities for all function invocations in the candidates -- in @ctx@ for which definitions are known. The function definitions are in -- @ieKnowl@.-ple1 :: InstEnv a -> ICtx -> Maybe BindId -> InstRes -> IO (ICtx, InstEnv a, InstRes)-ple1 ie@InstEnv{..} ctx i res = do- (ctx', env) <- runStateT (evalCandsLoop ieCfg ctx ieSMT ieKnowl) ieEvEnv- let pendings = collectPendingUnfoldings env (icSubcId ctx)- newEqs = pendings ++ S.toList (S.difference (icEquals ctx') (icEquals ctx))- return (ctx', ie { ieEvEnv = env }, updCtxRes res i newEqs)+ple1 :: InstEnv a -> ICtx -> Maybe BindId -> InstRes -> SmtM (ICtx, InstEnv a, InstRes)+ple1 ie@InstEnv{..} ictx i res = do+ ctx <- get+ (ictx', env) <- liftIO $ runStateT (evalCandsLoop ieCfg ictx ieKnowl) (ieEvEnv { evKCtx = ctx })+ put $ evKCtx env+ let pendings = collectPendingUnfoldings env (icSubcId ictx)+ newEqs =+ reconstructExistentials+ (M.intersectionWith S.union (icInitialLHSs ictx) $ -- add original predicates+ M.map (S.map equalitiesPred) $ -- construct equalities+ M.unionWith S.union pendings $ -- pending unfoldings if any+ M.unionWith S.difference (icEquals ictx') (icEquals ictx) -- new equalities only+ )+ return (ictx', ie { ieEvEnv = env }, updCtxRes res i newEqs) where -- Pending unfoldings (i.e. with undecided guards) are collected only -- when we reach a leaf in the Trie, and only if the user asked for them.- collectPendingUnfoldings env (Just _) | pleWithUndecidedGuards ieCfg =- M.toList (evPendingUnfoldings env)- collectPendingUnfoldings _ _ = []+ collectPendingUnfoldings env (Just _) | pleUndecGuards ieCfg =+ M.map (S.fromList . M.toList) (evPendingUnfoldings env)+ collectPendingUnfoldings _ _ = mempty -evalToSMT :: String -> Config -> SMT.Context -> (Expr, Expr) -> Pred-evalToSMT msg cfg ctx (e1,e2) = toSMT ("evalToSMT:" ++ msg) cfg ctx [] (EEq e1 e2)+evalToSMT :: String -> Config -> SMT.Context -> [(Symbol, Sort)] -> (Expr, Expr) -> Pred+evalToSMT msg cfg ctx bs (e1,e2) = toSMT ("evalToSMT:" ++ msg) cfg ctx bs (EEq e1 e2) -- | Generate equalities for all function invocations in the candidates -- in @ctx@ for which definitions are known. The function definitions are in@@ -316,44 +370,72 @@ -- > until no new equalities are discovered -- > or the environment becomes inconsistent ---evalCandsLoop :: Config -> ICtx -> SMT.Context -> Knowledge -> EvalST ICtx-evalCandsLoop cfg ictx0 ctx γ = go ictx0 0+evalCandsLoop :: Config -> ICtx -> Knowledge -> EvalST ICtx+evalCandsLoop cfg ictx0 γ = go ictx0 0 where- go ictx _ | S.null (icCands ictx) = return ictx+ go :: ICtx -> Int -> EvalST ICtx+ go ictx _ | all null (icCands ictx) = return ictx go ictx i = do inconsistentEnv <- testForInconsistentEnvironment if inconsistentEnv then return ictx- else do liftIO $ SMT.smtAssert ctx (pAndNoDedup (S.toList $ icAssms ictx))+ else do liftSMT $ SMT.smtAssertDecl $ pAndNoDedup $ S.toList $ icAssms ictx let ictx' = ictx { icAssms = mempty }- cands = S.toList $ icCands ictx- candss <- mapM (evalOne γ ictx' i) cands- us <- gets evNewEqualities- modify $ \st -> st { evNewEqualities = mempty }- let noCandidateChanged = and (zipWith eqCand candss cands)- unknownEqs = us `S.difference` icEquals ictx- if S.null unknownEqs && noCandidateChanged- then return ictx- else do let eqsSMT = evalToSMT "evalCandsLoop" cfg ctx `S.map` unknownEqs- let ictx'' = ictx' { icEquals = icEquals ictx <> unknownEqs- , icAssms = S.filter (not . isTautoPred) eqsSMT }- go (ictx'' { icCands = S.fromList (concat candss) }) (i + 1)+ (scopes, candSets) = unzip $ M.toList $ icCands ictx+ cands = map S.toList candSets+ (candss, uss) <- unzip <$> zipWithM (evalCand ictx' i) scopes cands+ let noCandidateChanged = all and $ zipWith (zipWith eqCand) candss cands+ unknownEqs = M.unionWith S.difference (M.fromList (zip scopes uss)) (icEquals ictx)+ if all null unknownEqs && noCandidateChanged then+ return ictx+ else do+ ctx' <- gets evKCtx+ let eqsSMT =+ S.unions $ M.elems $+ M.mapWithKey+ (\scope -> S.map $ evalToSMT "evalCandsLoop" cfg ctx' scope)+ unknownEqs+ ictx'' = ictx+ { icEquals = M.unionWith S.union (icEquals ictx) unknownEqs+ , icAssms = S.filter (not . isTautoPred) eqsSMT+ }+ go (ictx'' { icCands = M.fromList $ zip scopes (map (S.fromList . concat) candss) }) (i + 1) + testForInconsistentEnvironment :: EvalST Bool testForInconsistentEnvironment =- liftIO $ knPreds γ (knContext γ) (knLams γ) PFalse+ knPredsEvalST γ PFalse eqCand [e0] e1 = e0 == e1 eqCand _ _ = False + evalCand :: ICtx -> Int -> ExScope -> [Expr] -> EvalST ([[Expr]], S.HashSet (Expr, Expr))+ evalCand ictx i scope es = withExScope scope $ mapM (evalOne γ ictx i) es >>= collectEqs++ collectEqs :: [[Expr]] -> EvalST ([[Expr]], S.HashSet (Expr, Expr))+ collectEqs es = do+ env <- get+ let newEqs = evNewEqualities env+ modify $ \st -> st { evNewEqualities = mempty }+ return (es, newEqs)++ withExScope :: ExScope -> EvalST a -> EvalST a+ withExScope s m = do+ env <- get+ put $ env { evExScope = s }+ r <- m+ modify $ \st -> st { evExScope = evExScope env }+ return r++ ---------------------------------------------------------------------------------------------- -- | Step 3: @resSInfo@ uses incremental PLE result @InstRes@ to produce the strengthened SInfo ---------------------------------------------------------------------------------------------- -resSInfo :: Config -> SymEnv -> SInfo a -> InstRes -> SInfo a+resSInfo :: Config -> SymEnv -> SInfo a -> InstRes -> BindEnv a resSInfo cfg env info res = strengthenBinds info res' where res' = M.fromList $ zip is ps''- ps'' = zipWith (\i -> elaborate (ElabParam (solverFlags $ solver cfg) (atLoc dummySpan ("PLE1 " ++ show i)) env)) is ps'+ ps'' = zipWith (\i -> elaborate (ElabParam (solverFlags cfg) (atLoc dummySpan ("PLE1 " ++ show i)) env)) is ps' ps' = defuncAny cfg env ps (is, ps) = unzip (M.toList res) @@ -363,13 +445,13 @@ data InstEnv a = InstEnv { ieCfg :: !Config- , ieSMT :: !SMT.Context , ieBEnv :: !(BindEnv a) , ieAenv :: !AxiomEnv , ieCstrs :: !(CMap (SimpC a)) , ieKnowl :: !Knowledge , ieEvEnv :: !EvalEnv , ieLRWs :: LocalRewritesEnv+ , ieSol :: Maybe Solution } ----------------------------------------------------------------------------------------------@@ -378,18 +460,22 @@ data ICtx = ICtx { icAssms :: S.HashSet Pred -- ^ Equalities converted to SMT format- , icCands :: S.HashSet Expr -- ^ "Candidates" for unfolding- , icEquals :: EvEqualities -- ^ Accumulated equalities+ , icCands :: M.HashMap ExScope (S.HashSet Expr) -- ^ "Candidates" for unfolding+ , icEquals :: M.HashMap ExScope EvEqualities -- ^ Accumulated equalities , icSimpl :: !ConstMap -- ^ Map of expressions to constants , icSubcId :: Maybe SubcId -- ^ Current subconstraint ID , icANFs :: [[(Symbol, SortedReft)]] -- Hopefully contain only ANF things , icLRWs :: LocalRewrites -- ^ Local rewrites+ , icBindIds :: IBindEnv -- ^ Bind Ids in the current context , icEtaBetaFlag :: Bool -- ^ True if the etabeta flag is turned on, needed -- for the eta expansion reasoning as its going to -- generate ho constraints -- See Note [Eta expansion]. , icExtensionalityFlag :: Bool -- ^ True if the extensionality flag is turned on , icLocalRewritesFlag :: Bool -- ^ True if the local rewrites flag is turned on+ , icFreshExistentialCounter :: Int -- ^ Counter to generate fresh names for existentials+ , icInitialLHSs :: M.HashMap ExScope (S.HashSet Expr)+ -- ^ LHS candidates before any unfoldings } ----------------------------------------------------------------------------------------------@@ -408,11 +494,13 @@ type CBranch = T.Branch SubcId type Diff = [BindId] -- ^ in "reverse" order -equalitiesPred :: [(Expr, Expr)] -> [Expr]-equalitiesPred eqs = [ EEq e1 e2 | (e1, e2) <- eqs, e1 /= e2 ]+equalitiesPred :: (Expr, Expr) -> Expr+equalitiesPred (e1, e2)+ | e1 /= e2 = EEq e1 e2+ | otherwise = PTrue -updCtxRes :: InstRes -> Maybe BindId -> [(Expr, Expr)] -> InstRes-updCtxRes res iMb = updRes res iMb . pAndNoDedup . equalitiesPred+updCtxRes :: InstRes -> Maybe BindId -> [Expr] -> InstRes+updCtxRes res iMb = updRes res iMb . pAndNoDedup updRes :: InstRes -> Maybe BindId -> Expr -> InstRes@@ -422,41 +510,91 @@ ---------------------------------------------------------------------------------------------- -- | @updCtx env ctx delta cidMb@ adds the assumptions and candidates from @delta@ and @cidMb@ -- to the context.+--+-- Yields the new context and a list of existential binders found in @delta@.+-- See Note [Existential quantification when unfolding]. ---------------------------------------------------------------------------------------------- -updCtx :: InstEnv a -> ICtx -> Diff -> Maybe SubcId -> ICtx-updCtx InstEnv{..} ctx delta cidMb- = ctx { icAssms = S.fromList (filter (not . isTautoPred) ctxEqs)- , icCands = S.fromList deANFedCands <> icCands ctx- , icSimpl = icSimpl ctx <> econsts- , icSubcId = cidMb- , icANFs = anfBinds- , icLRWs = mconcat $ icLRWs ctx : newLRWs- }+updCtx+ :: Loc a+ => Config+ -> InstEnv a+ -> SMT.Context+ -> ICtx+ -> Diff+ -> Maybe SubcId+ -> Maybe CTrie+ -> (ICtx, [(Symbol, Sort)])+updCtx cfg InstEnv{..} ieSMT ictx delta cidMb mCTrie =+ ( ictx { icAssms = S.fromList ctxEqs+ , icCands = M.unionWith S.union candsPerExScope (icCands ictx)+ , icSimpl = icSimpl ictx <> econsts+ , icSubcId = cidMb+ , icANFs = anfBinds+ , icLRWs = mconcat $ icLRWs ictx : newLRWs+ , icBindIds = ibinds+ , icFreshExistentialCounter = existentialCounter+ , icInitialLHSs = M.unionWith S.union candsPerExScopeNoRHS (icInitialLHSs ictx)+ }+ , ebs+ ) where+ ebs = concat (M.keys candsPerExScope)+ ibinds = insertsIBindEnv delta (icBindIds ictx) cands = rhs:es- anfBinds = bs : icANFs ctx+ anfBinds = bs : icANFs ictx econsts = M.fromList $ findConstants ieKnowl es- ctxEqs = toSMT "updCtx" ieCfg ieSMT [] <$> L.nub- [ c | xr <- bs, c <- conjuncts (expr xr), null (Vis.kvarsExpr c) ]+ ctxEqs = toSMT "updCtx" ieCfg ieSMT ebs <$> L.nub+ [ c+ | (_, s) <- drop 1 deANFedCands+ , e <- S.toList s+ , c <- conjuncts e+ , not (isTautoPred c)+ ] bs = second unApplySortedReft <$> binds rhs = unApply eRhs es = expr <$> bs eRhs = maybe PTrue crhs subMb- binds = [ (x, y) | i <- delta, let (x, y, _) = lookupBindEnv i ieBEnv]++ (binds, existentialCounter) = renameExistentialsInSortedRefts binds0 (icFreshExistentialCounter ictx)++ binds0 = [ maybeApplyKVarSolutions (x, y)+ | i <- delta+ , let (x, y, _) = lookupBindEnv i ieBEnv+ ] subMb = getCstr ieCstrs <$> cidMb newLRWs = Mb.mapMaybe (`lookupLocalRewrites` ieLRWs) delta - deANFedCands =+ candsPerExScopeNoRHS = M.fromListWith S.union $ ([], S.empty) : drop 1 deANFedCands+ -- ebs expects all keys to contain disjoint sets of bindings+ candsPerExScope = M.unionWith S.union candsPerExScopeNoRHS $ M.fromListWith S.union (take 1 deANFedCands)++ deANFedCands = map (second S.singleton . prenexExistentials) $ -- We only call 'deANF' if necessary. if not (null (getAutoRws ieKnowl cidMb))- || icExtensionalityFlag ctx- || icEtaBetaFlag ctx then+ || icExtensionalityFlag ictx+ || icEtaBetaFlag ictx then deANF anfBinds cands else cands + maybeApplyKVarSolutions xsr =+ case ieSol of+ Just sol -> applyInSortedReft cfg g sol xsr+ Nothing -> xsr+ where+ gCid = case collectConstraints <$> mCTrie of+ Just (c:_) -> Just c+ _ -> Nothing+ g = CEnv+ { ceCid = gCid+ , ceBEnv = ieBEnv+ , ceIEnv = ibinds+ , ceSpan = maybe dummySpan srcSpan $ gCid >>= (`M.lookup` ieCstrs)+ , ceBindingsInSmt = emptyIBindEnv+ } + findConstants :: Knowledge -> [Expr] -> [(Expr, Expr)] findConstants γ es = [(EVar x, c) | (x,c) <- go [] (concatMap splitPAnd es)] where@@ -481,8 +619,15 @@ data EvalEnv = EvalEnv { evEnv :: !SymEnv , evElabF :: ElabFlags- -- | Equalities where we couldn't evaluate the guards- , evPendingUnfoldings :: M.HashMap Expr Expr+ , evKCtx :: SMT.Context+ -- | The current scope of existential variables.+ -- See Note [Existential quantification when unfolding].+ , evExScope :: ExScope+ -- | Equalities where we couldn't evaluate the guards, in a map which+ -- uses their existential scope as key.+ --+ -- See Note [Existential quantification when unfolding].+ , evPendingUnfoldings :: M.HashMap ExScope (M.HashMap Expr Expr) , evNewEqualities :: EvEqualities -- ^ Equalities discovered during a traversal of -- an expression , evSMTCache :: M.HashMap Expr Bool -- ^ Whether an expression is valid or its negation@@ -508,6 +653,15 @@ defFuelCount cfg = FC mempty (fuel cfg) type EvalST a = StateT EvalEnv IO a++liftSMT :: SmtM a -> EvalST a+liftSMT k =+ do es <- get+ let ctx = evKCtx es+ (a, ctx') <- lift $ runStateT k ctx+ put (es {evKCtx = ctx'})+ pure a+ -------------------------------------------------------------------------------- getAutoRws :: Knowledge -> Maybe SubcId -> [AutoRewrite]@@ -525,7 +679,7 @@ -- way. evalOne :: Knowledge -> ICtx -> Int -> Expr -> EvalST [Expr] evalOne γ ctx i e- | i > 0 || null (getAutoRws γ (icSubcId ctx)) = (:[]) . fst <$> eval γ ctx NoRW e+ | i > 0 || null (getAutoRws γ (icSubcId ctx)) = (:[]) <$> eval γ ctx NoRW e evalOne γ ctx _ e | isExprRewritable e = do env <- get let oc :: OCAlgebra OCType RuntimeTerm IO@@ -555,37 +709,7 @@ | RWNormal -- REST: Fully Expand Defs in the context of rewriting (similar to NoRW) deriving (Eq) --- Indicates whether or not the evaluation has expanded a function statement--- into a conditional branch.--- In this case, rewriting should stop--- It's unclear whether or not rewriting in either branch makes sense,--- since one branch could be an ill-formed expression.-newtype FinalExpand = FE Bool deriving (Show) -noExpand :: FinalExpand-noExpand = FE False--expand :: FinalExpand-expand = FE True--mapFE :: (Expr -> Expr) -> (Expr, FinalExpand) -> (Expr, FinalExpand)-mapFE f (e, fe) = (f e, fe)--feVal :: FinalExpand -> Bool-feVal (FE f) = f--feAny :: [FinalExpand] -> FinalExpand-feAny xs = FE $ any feVal xs--infixl 9 <|>-(<|>) :: FinalExpand -> FinalExpand -> FinalExpand-(<|>) (FE True) _ = expand-(<|>) _ f = f---feSeq :: [(Expr, FinalExpand)] -> ([Expr], FinalExpand)-feSeq xs = (map fst xs, feAny (map snd xs))- -- | Unfolds function invocations in expressions. -- -- Also reduces if-then-else when the boolean condition or the negation can be@@ -594,70 +718,55 @@ -- -- Also adds to the monad state all the unfolding equalities that have been -- discovered as necessary.-eval :: Knowledge -> ICtx -> EvalType -> Expr -> EvalST (Expr, FinalExpand)+eval :: Knowledge -> ICtx -> EvalType -> Expr -> EvalST Expr eval γ ctx et = go where go (ELam (x,s) e) = evalELam γ ctx et (x, s) e go e@EIte{} = evalIte γ ctx et e- go (ECoerc s t e) = mapFE (ECoerc s t) <$> go e+ go (ECoerc s t e) = ECoerc s t <$> go e go e@(EApp _ _) = case splitEAppThroughECst e of (f, es) | et == RWNormal -> -- Just evaluate the arguments first, to give rewriting a chance to step in -- if necessary do- (es', finalExpand) <- feSeq <$> mapM (eval γ ctx et) es+ es' <- mapM (eval γ ctx et) es if es /= es'- then return (eApps f es', finalExpand)+ then return (eApps f es') else do- (f', fe) <- case dropECst f of- EVar _ -> pure (f, noExpand)+ f' <- case dropECst f of+ EVar _ -> pure f _ -> go f- (me', fe') <- evalApp γ ctx f' es et- return (Mb.fromMaybe (eApps f' es') me', fe <|> fe')+ Mb.fromMaybe (eApps f' es') <$> evalApp γ ctx f' es et (f, es) -> do- (f', fe1) <- case dropECst f of- EVar _ -> pure (f, noExpand)+ f' <- case dropECst f of+ EVar _ -> pure f _ -> go f- (es', fe2) <- feSeq <$> mapM (eval γ ctx et) es- let fe = fe1 <|> fe2- (me', fe') <- evalApp γ ctx f' es' et- return (Mb.fromMaybe (eApps f' es') me', fe <|> fe')+ es' <- mapM (eval γ ctx et) es+ Mb.fromMaybe (eApps f' es') <$> evalApp γ ctx f' es' et - go (PAtom r e1 e2) = binOp (PAtom r) e1 e2- go (ENeg e) = do (e', fe) <- go e- return (ENeg e', fe)- go (EBin o e1 e2) = do (e1', fe1) <- go e1- (e2', fe2) <- go e2- return (EBin o e1' e2', fe1 <|> fe2)- go (ETApp e t) = mapFE (`ETApp` t) <$> go e- go (ETAbs e s) = mapFE (`ETAbs` s) <$> go e- go (PNot e') = mapFE PNot <$> go e'- go (PImp e1 e2) = binOp PImp e1 e2- go (PIff e1 e2) = binOp PIff e1 e2- go (PAnd es) = efAll PAnd (go `traverse` es)- go (POr es) = efAll POr (go `traverse` es)+ go (PAtom r e1 e2) = PAtom r <$> go e1 <*> go e2+ go (ENeg e) = ENeg <$> go e+ go (EBin o e1 e2) = EBin o <$> go e1 <*> go e2+ go (ETApp e t) = (`ETApp` t) <$> go e+ go (ETAbs e s) = (`ETAbs` s) <$> go e+ go (PNot e') = PNot <$> go e'+ go (PImp e1 e2) = PImp <$> go e1 <*> go e2+ go (PIff e1 e2) = PIff <$> go e1 <*> go e2+ go (PAnd es) = PAnd <$> traverse go es+ go (POr es) = POr <$> traverse go es go e | EVar _ <- dropECst e = do- (me', fe) <- evalApp γ ctx e [] et- return (Mb.fromMaybe e me', fe)- go (ECst e t) = do (e', fe) <- go e- return (ECst e' t, fe)- go e = return (e, noExpand)+ Mb.fromMaybe e <$> evalApp γ ctx e [] et+ go (ECst e t) = (`ECst` t) <$> go e+ go (ELet x e1 e2) = ELet x <$> go e1 <*> go e2 - binOp f e1 e2 = do- (e1', fe1) <- go e1- (e2', fe2) <- go e2- return (f e1' e2', fe1 <|> fe2)+ go e = return e - efAll f mes = do- xs <- mes- let (xs', fe) = feSeq xs- return (f xs', fe) --- | 'evalELamb' produces equations that preserve the context of a rewrite+-- | 'evalELam' produces equations that preserve the context of a rewrite -- so equations include any necessary lambda bindings.-evalELam :: Knowledge -> ICtx -> EvalType -> (Symbol, Sort) -> Expr -> EvalST (Expr, FinalExpand)+evalELam :: Knowledge -> ICtx -> EvalType -> (Symbol, Sort) -> Expr -> EvalST Expr evalELam γ ctx et (x, s) e | not $ isEtaSymbol x = do -- We need to refresh it as for some reason names bound by lambdas@@ -686,7 +795,7 @@ modify $ \st -> st { evEnv = insertSymEnv x s $ evEnv st } - (e', fe) <- eval (γ { knLams = (x, s) : knLams γ }) ctx et e+ e' <- eval (γ { knLams = (x, s) : knLams γ }) ctx et e let e2' = simplify γ ctx e' elam = ELam (x, s) e -- Discard the old equalities which miss the lambda binding@@ -696,7 +805,7 @@ -- Leaving the scope thus we need to get rid of it , evEnv = deleteSymEnv x $ evEnv st }- return (ELam (x, s) e', fe)+ return (ELam (x, s) e') data RESTParams oc = RP { oc :: OCAlgebra oc Expr IO@@ -795,21 +904,22 @@ evalRESTWithCache cacheRef γ ctx acc rp = do mexploredTerms <- gets explored+ ebs <- gets evExScope case mexploredTerms of Nothing -> return acc Just exploredTerms -> do- se <- liftIO (shouldExploreTerm exploredTerms exprs)+ se <- liftIO (shouldExploreTerm ebs exploredTerms exprs) if se then do- possibleRWs <- getRWs- rws <- notVisitedFirst exploredTerms <$> filterM (liftIO . allowed) possibleRWs+ possibleRWs <- liftSMT (getRWs ebs)+ rws <- notVisitedFirst exploredTerms <$> filterM (liftIO . allowed ebs) possibleRWs oldEqualities <- gets evNewEqualities modify $ \st -> st { evNewEqualities = mempty } -- liftIO $ putStrLn $ (show $ length possibleRWs) ++ " rewrites allowed at path length " ++ (show $ (map snd $ path rp))- (e', FE fe) <- do- r@(ec, _) <- eval γ ctx FuncNormal exprs+ e' <- do+ ec <- eval γ ctx FuncNormal exprs if ec /= exprs- then return r+ then return ec else eval γ ctx RWNormal exprs let evalIsNewExpr = e' `L.notElem` pathExprs@@ -834,8 +944,8 @@ } acc'' <- if evalIsNewExpr- then if fe && any isRW (path rp)- then (:[]) . fst <$> eval γ (addConst (exprs, e')) NoRW e'+ then if e' /= exprs && any isRW (path rp)+ then (:[]) <$> eval γ (addConst (exprs, e')) NoRW e' else evalRESTWithCache cacheRef γ (addConst (exprs, e')) acc' (rpEval newEqualities e') else return acc' @@ -843,17 +953,17 @@ else return acc where- shouldExploreTerm exploredTerms e | Vis.isConc e =- case rwTerminationOpts rwArgs of+ shouldExploreTerm ebs exploredTerms e | Vis.isConc e =+ case rwTerminationOpts (rwArgs ebs) of RWTerminationCheckDisabled -> return $ not $ ExploredTerms.visited (Rewrite.convert e) exploredTerms RWTerminationCheckEnabled -> ExploredTerms.shouldExplore (Rewrite.convert e) (c rp) exploredTerms- shouldExploreTerm _ _ = return False+ shouldExploreTerm _ _ _ = return False - allowed (_, rwE, _) | rwE `elem` pathExprs = return False- allowed (_, _, c) = termCheck c- termCheck c = Rewrite.passesTerminationCheck (oc rp) rwArgs c+ allowed _ebs (_, rwE, _) | rwE `elem` pathExprs = return False+ allowed ebs (_, _, c) = termCheck ebs c+ termCheck ebs c = Rewrite.passesTerminationCheck (oc rp) (rwArgs ebs) c notVisitedFirst exploredTerms rws = let@@ -879,21 +989,21 @@ exprs = last pathExprs autorws = getAutoRws γ (icSubcId ctx) - rwArgs = RWArgs (isValid cacheRef γ) $ knRWTerminationOpts γ+ rwArgs ebs = RWArgs (isValid cacheRef ebs γ) $ knRWTerminationOpts γ - getRWs =+ getRWs ebs = do -- Optimization: If we got here via rewriting, then the current constraints -- are satisfiable; otherwise double-check that rewriting is still allowed ok <- if isRW $ last (path rp) then return True- else liftIO $ termCheck (c rp)+ else liftIO $ termCheck ebs (c rp) if ok then do- let getRW e ar = Rewrite.getRewrite (oc rp) rwArgs (c rp) e ar- let getRWs' s = Mb.catMaybes <$> mapM (liftIO . runMaybeT . getRW s) autorws+ let getRW e ar = Rewrite.getRewrite (oc rp) (rwArgs ebs) (c rp) e ar+ let getRWs' s = Mb.catMaybes <$> mapM (runMaybeT . getRW s) autorws concat <$> mapM getRWs' (subExprs exprs) else return [] @@ -946,7 +1056,7 @@ -- | @evalApp kn ctx e es@ unfolds expressions in @eApps e es@ using rewrites -- and equations-evalApp :: Knowledge -> ICtx -> Expr -> [Expr] -> EvalType -> EvalST (Maybe Expr, FinalExpand)+evalApp :: Knowledge -> ICtx -> Expr -> [Expr] -> EvalType -> EvalST (Maybe Expr) evalApp γ ctx e0 es et | EVar f <- dropECst e0 , Just eq <- Map.lookup f (knAms γ)@@ -962,7 +1072,7 @@ then elaborateExpr "EvalApp unfold full: " newE else pure newE - (e', fe) <- evalIte γ ctx et newE' -- TODO:FUEL this is where an "unfolding" happens, CHECK/BUMP counter+ e' <- evalIte γ ctx et newE' -- TODO:FUEL this is where an "unfolding" happens, CHECK/BUMP counter let e2' = stripPLEUnfold e' let e3' = simplify γ ctx (eApps e2' es2) -- reduces a bit the equations @@ -972,17 +1082,18 @@ -- If evalIte does any modifications, though, we do unfold in order -- to allow analysis of the resulting expression modify $ \st -> st- { evPendingUnfoldings = M.insert (eApps e0 es) e3' (evPendingUnfoldings st)+ { evPendingUnfoldings =+ M.insertWith M.union (evExScope st) (M.singleton (eApps e0 es) e3') (evPendingUnfoldings st) }- return (Nothing, noExpand)+ return Nothing else do useFuel f modify $ \st -> st { evNewEqualities = S.insert (eApps e0 es, e3') (evNewEqualities st)- , evPendingUnfoldings = M.delete (eApps e0 es) (evPendingUnfoldings st)+ , evPendingUnfoldings = M.adjust (M.delete (eApps e0 es)) (evExScope st) (evPendingUnfoldings st) }- return (Just $ eApps e2' es2, fe)- else return (Nothing, noExpand)+ return (Just $ eApps e2' es2)+ else return Nothing where -- At the time of writing, any function application wrapping an -- if-statement would have the effect of unfolding the invocation.@@ -1016,7 +1127,7 @@ when (isUserDataSMeasure == NoUserDataSMeasure) $ modify $ \st -> st { evNewEqualities = S.insert (eApps e0 args, simplify γ ctx newE) (evNewEqualities st) }- return (Just newE, noExpand)+ return (Just newE) evalApp γ ctx e0 es _et | eqs@(_:_) <- noUserDataMeasureEqs γ (eApps e0 es)@@ -1024,7 +1135,7 @@ let eqs' = map (second $ simplify γ ctx) eqs modify $ \st -> st { evNewEqualities = foldr S.insert (evNewEqualities st) eqs' }- return (Nothing, noExpand)+ return Nothing evalApp γ ctx e0 es et | ELam (argName, _) body <- dropECst e0@@ -1037,13 +1148,13 @@ useFuel argName let argSubst = mkSubst [(argName, lambdaArg)] let body' = subst argSubst body- (body'', fe) <- evalIte γ ctx et body'+ body'' <- evalIte γ ctx et body' let simpBody = simplify γ ctx (eApps body'' remArgs) modify $ \st -> st { evNewEqualities = S.insert (eApps e0 es, simpBody) (evNewEqualities st) }- return (Just $ eApps body'' remArgs, fe)+ return (Just $ eApps body'' remArgs) else do- return (Nothing, noExpand)+ return Nothing evalApp _ ctx e0 es _ | icLocalRewritesFlag ctx@@ -1054,7 +1165,7 @@ let expandedTerm = eApps rw es modify $ \st -> st { evNewEqualities = S.insert (eApps e0 es, expandedTerm) (evNewEqualities st) }- return (Just expandedTerm, expand)+ return (Just expandedTerm) evalApp _γ ctx e0 es _et -- We check the annotation instead of the equations in γ for two reasons.@@ -1091,7 +1202,7 @@ -- is already handled by the previous case of evalApp modify $ \st -> st { evNewEqualities = S.insert (eApps e0 es, etaExpandedTerm) (evNewEqualities st) }- return (Just etaExpandedTerm, expand)+ return (Just etaExpandedTerm) where unpackFFuncs (FFunc t ts) = t : unpackFFuncs ts unpackFFuncs _ = []@@ -1099,22 +1210,21 @@ mkLams subject binds = foldr ELam subject binds evalApp _ _ctx _e0 _es _ = do- return (Nothing, noExpand)+ return Nothing -- | Evaluates if-then-else statements until they can't be evaluated anymore -- or some other expression is found.-evalIte :: Knowledge -> ICtx -> EvalType -> Expr -> EvalST (Expr, FinalExpand)+evalIte :: Knowledge -> ICtx -> EvalType -> Expr -> EvalST Expr evalIte γ ctx et (ECst e t) = do- (e', fe) <- evalIte γ ctx et e- return (ECst e' t, fe)+ (`ECst` t) <$> evalIte γ ctx et e evalIte γ ctx et (EIte i e1 e2) = do- (b, _) <- eval γ ctx et i+ b <- eval γ ctx et i b' <- mytracepp ("evalEIt POS " ++ showpp (i, b)) <$> isValidCached γ b case b' of Just True -> evalIte γ ctx et e1 Just False -> evalIte γ ctx et e2- _ -> return (EIte b e1 e2, expand)-evalIte _ _ _ e' = return (e', noExpand)+ _ -> return (EIte b e1 e2)+evalIte _ _ _ e' = return e' -- | Creates equations that explain how to rewrite a given constructor -- application with all measures that aren't user data measures@@ -1180,14 +1290,14 @@ case M.lookup e (evSMTCache env) of Nothing -> do let isFreeInE (s, _) = not (S.member s (exprSymbolsSet e))- b <- liftIO $ knPreds γ (knContext γ) (knLams γ) e+ b <- knPredsEvalST γ e if b then do when (all isFreeInE (knLams γ)) $ put (env { evSMTCache = M.insert e True (evSMTCache env) }) return (Just True) else do- b2 <- liftIO $ knPreds γ (knContext γ) (knLams γ) (PNot e)+ b2 <- knPredsEvalST γ (PNot e) if b2 then do when (all isFreeInE (knLams γ)) $@@ -1209,8 +1319,10 @@ -- user data declaration. knSims :: Map Symbol [(Rewrite, IsUserDataSMeasure)] , knAms :: Map Symbol Equation -- ^ All function definitions- , knContext :: SMT.Context- , knPreds :: SMT.Context -> [(Symbol, Sort)] -> Expr -> IO Bool+ -- | @knPreds γ bsInSMT xs e@ checks whether @e@ is valid under the+ -- assumptions that all variables in @bsInSMT@ are in the SMT solver,+ -- and that all variables in @xs@ need tp be declared in the SMT solver.+ , knPreds :: [(Symbol, Sort)] -> [(Symbol, Sort)] -> Expr -> SmtM Bool , knLams :: ![(Symbol, Sort)] , knSummary :: ![(Symbol, Int)] -- ^ summary of functions to be evaluates (knSims and knAsms) with their arity , knDCs :: !(S.HashSet Symbol) -- ^ data constructors drawn from Rewrite@@ -1226,25 +1338,29 @@ data IsUserDataSMeasure = NoUserDataSMeasure | UserDataSMeasure deriving (Eq, Show) -isValid :: IORef (M.HashMap Expr Bool) -> Knowledge -> Expr -> IO Bool-isValid cacheRef γ e = do- smtCache <- readIORef cacheRef+knPredsEvalST :: Knowledge -> Expr -> EvalST Bool+knPredsEvalST γ e = do+ env <- get+ liftSMT $ knPreds γ (evExScope env) (knLams γ) e++isValid :: IORef (M.HashMap Expr Bool) -> [(Symbol, Sort)] -> Knowledge -> Expr -> SmtM Bool+isValid cacheRef bs γ e = do+ smtCache <- liftIO $ readIORef cacheRef case M.lookup e smtCache of Nothing -> do- b <- knPreds γ (knContext γ) (knLams γ) e+ b <- knPreds γ bs (knLams γ) e when b $- writeIORef cacheRef (M.insert e True smtCache)+ liftIO $ writeIORef cacheRef (M.insert e True smtCache) return b- mb -> return (mb == Just True)+ Just b -> return b -knowledge :: Config -> SMT.Context -> SInfo a -> Knowledge-knowledge cfg ctx si = KN+knowledge :: Config -> SInfo a -> Knowledge+knowledge cfg si = KN { knSims = Map.fromListWith (++) $ [ (smDC rw, [(rw, NoUserDataSMeasure)]) | rw <- sims ] ++ [ (smDC rw, [(rw, UserDataSMeasure)]) | rw <- dataSims ] , knAms = Map.fromList [(eqName eq, eq) | eq <- aenvEqs aenv]- , knContext = ctx- , knPreds = askSMT cfg+ , knPreds = askSMT cfg , knLams = [] , knSummary = ((\s -> (smName s, 1)) <$> sims) ++ ((\s -> (eqName s, length (eqArgs s))) <$> aenvEqs aenv)@@ -1255,7 +1371,7 @@ , knConsts = Mb.mapMaybe makeCons sims , knAutoRWs = aenvAutoRW aenv , knRWTerminationOpts =- if rwTerminationCheck cfg+ if rwTermination cfg then RWTerminationCheckEnabled else RWTerminationCheckDisabled }@@ -1335,15 +1451,6 @@ -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -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- return res-- -- (sel_i, D, i), meaning sel_i (D x1 .. xn) = xi, -- i.e., sel_i selects the ith value for the data constructor D type SelectorMap = [(Symbol, (Symbol, Int))]@@ -1466,7 +1573,8 @@ elaborateExpr :: String -> Expr -> EvalST Expr elaborateExpr msg e = do let elabSpan = atLoc dummySpan msg- symEnv' <- gets evEnv+ env <- get+ let symEnv' = insertsSymEnv (evEnv env) (evExScope env) ef <- gets evElabF pure $ unApply $ elaborate (ElabParam ef elabSpan symEnv') e @@ -1478,3 +1586,128 @@ case (M.lookup f (fcMap fc), fcMax fc) of (Just fk, Just n) -> pure (fk <= n) _ -> pure True+++-- Note [Existential quantification when unfolding]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+--+-- After FUSION is performed, some predicates, which previously used kvars, may+-- contain existential quantifications.+--+-- When the unfoldings are searched by PLE in expressions with existentials,+-- we make sure that the produced unfoldings still have the existential+-- bindings in scope.+--+-- The procedure is as follows:+-- 1. First, we rename the existential variables in the predicates of the bindings+-- to make them unique ('renameExistentialsInSortedRefts').+--+-- @exists x y. f x y || (exists x. g x y)@+--+-- becomes+--+-- @exists v0 v1. f v0 v1 || (exists v2. g v2 v1)@+--+-- 2. We extract the nested existentials to prenex form, and we store the bodies of+-- the existentials in a map with the existential binders as keys+-- ('prenexExistentials' and 'updCtx').+--+-- @exists v0 v1. f v0 v1 || (exists v2. g v2 v1)@+--+-- produces the map+--+-- @[v0, v1, v2] -> f v0 v1 || g v2 v1@+--+-- 3. We declare to the SMT solver the existential variables in every scope+-- (in 'withAssms').+--+-- 4. We then look for unfoldings in each of the subexpressions. Whenever+-- we find an unfolding, we record the scope in which it was found.+--+-- @[v0, v1, v3] -> (f v0 v1 = v0 < v1) && (g v2 = v2 > v1)@+--+-- 5. When PLE is finished, we create for every scope an existential+-- quantification whose body contains all the corresponding unfoldings+-- and the original subexpressions in the scope ('reconstructExistentials').+--+-- @exists v0 v1 v0.+-- (f v0 v 1 = v0 < v1) && (g v2 = v2 > v1) &&+-- (f v0 v1 || g v2 v1)@+--+-- This is the expression that PLE returns.+++-- | Renames existential variables in the predicates of the given bindings to+-- make them unique.+--+-- Rather than looking for all existential bindings, this function only renames+-- the superficial existentials which can be introduced by KVar solutions.+--+-- These superficial existentials appear in conjunctions, disjunctions and in the+-- body of other existentials only.+renameExistentialsInSortedRefts+ :: [(Symbol, SortedReft)]+ -> Int+ -> ([(Symbol, SortedReft)], Int)+renameExistentialsInSortedRefts binds0 existentialCounter =+ let+ binds = [ (x, sr { sr_reft = mapPredReft (const p) (sr_reft sr) }) | ((x, sr), p) <- zip binds0 preds ]+ (preds, existentialCounter') =+ renameKVarExistentials (map (reftPred . sr_reft . snd) binds0) existentialCounter+ in+ (binds, existentialCounter')++renameKVarExistentials :: [Expr] -> Int -> ([Expr], Int)+renameKVarExistentials = runState . mapM go+ where+ go (POr es) = POr <$> mapM go es+ go (PAnd es) = PAnd <$> mapM go es+ go (PExist bs e0) = do+ i1 <- get+ let i2 = i1 + length bs+ put i2+ let vs = map fst bs+ vs' = [ existSymbol v (fromIntegral i) | (v, i) <- zip vs [i1..] ]+ bs' = zip vs' (map snd bs)+ su = mkSubst $ zip vs (map EVar vs')+ PExist bs' <$> go (rapierSubstExpr (S.fromList vs') su e0)+ go e = pure e++-- ^ Scopes of existential binders identifying the location of sub-expressions+type ExScope = [(Symbol, Sort)]+++-- | Extracts nested existentials from an expression.+--+-- For example, the expression+--+-- > exists [x1 : t1]. e1 == e2 &&+-- > exists [x2 : t2]. e3 == 2 &&+-- > exists [x3 : t3]. e3 < e4+--+-- would be flattened into+--+-- > (e1 == e2 && e3 == 2 && e3 < e4, [x1 : t1, x2 : t2, x3 : t3])+--+-- Precondition: the existential binding names are unique.+--+prenexExistentials :: Expr -> (ExScope, Expr)+prenexExistentials = go+ where+ go :: Expr -> (ExScope, Expr)+ go (PExist bs e) =+ let (bs', e') = go e+ in (bs ++ bs', e')+ go (PAnd es) =+ let (bss, es') = unzip (map go es)+ in (concat bss, PAnd es')+ go (POr es) =+ let (bss, es') = unzip (map go es)+ in (concat bss, POr es')+ go e = ([], e)+++-- | Reconstructs expressions with existentials from a map+-- of existential scopes to their bodies.+reconstructExistentials :: M.HashMap ExScope (S.HashSet Expr) -> [Expr]+reconstructExistentials m = [ pExist s (pAndNoDedup $ S.toList es) | (s, es) <- M.toList m, not (null es) ]
src/Language/Fixpoint/Solver/Rewrite.hs view
@@ -30,6 +30,7 @@ import Text.PrettyPrint (text) import Language.Fixpoint.Types.Config (RESTOrdering(..)) import Language.Fixpoint.Types hiding (simplify)+import Language.Fixpoint.Smt.Types (SmtM) import Language.REST import Language.REST.KBO (kbo) import Language.REST.LPO (lpo)@@ -54,7 +55,7 @@ | RWTerminationCheckDisabled data RewriteArgs = RWArgs- { isRWValid :: Expr -> IO Bool+ { isRWValid :: Expr -> SmtM Bool , rwTerminationOpts :: RWTerminationOpts } @@ -128,7 +129,7 @@ -> oc -> SubExpr -> AutoRewrite- -> MaybeT IO ((Expr, Expr), Expr, oc)+ -> MaybeT SmtM ((Expr, Expr), Expr, oc) getRewrite aoc rwArgs c (subE, toE) (AutoRewrite args lhs rhs) = do su <- MaybeT $ return $ unify freeVars lhs subE@@ -145,7 +146,7 @@ (eqn, expr', c') RWTerminationCheckDisabled -> (eqn, expr', c) where- check :: Expr -> MaybeT IO ()+ check :: Expr -> MaybeT SmtM () check e = do valid <- MaybeT $ Just <$> isRWValid rwArgs e guard valid@@ -225,6 +226,15 @@ subExprs' (POr es) = [ (e, POr . f) | (e, f) <- subs es ] +subExprs' (ELet x e1 e2) = e1'' ++ e2''+ where+ e1' = subExprs e1+ e2' = subExprs e2+ e1'' :: [SubExpr]+ e1'' = map (\(e, f) -> (e, \e' -> ELet x (f e') e2)) e1'+ e2'' :: [SubExpr]+ e2'' = map (\(e, f) -> (e, \e' -> ELet x e1 (f e'))) e2'+ subExprs' _ = [] -- | Computes the subexpressions of a list of expressions.@@ -304,8 +314,8 @@ unify freeVars rw seen (PExist _ rw, PExist _ seen) -> unify freeVars rw seen- (PGrad _ _ _ rw, PGrad _ _ _ seen) ->- unify freeVars rw seen (ECoerc _ _ rw, ECoerc _ _ seen) -> unify freeVars rw seen+ (ELet _ rw1 rw2, ELet _ seen1 seen2) ->+ unifyAll freeVars [rw1, rw2] [seen1, seen2] _ -> Nothing
src/Language/Fixpoint/Solver/Sanitize.hs view
@@ -2,7 +2,6 @@ -- 1. Each binder must be associated with a UNIQUE sort {-# LANGUAGE TupleSections #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE PatternGuards #-} module Language.Fixpoint.Solver.Sanitize ( -- * Transform FInfo to enforce invariants@@ -17,7 +16,7 @@ import Language.Fixpoint.Types.PrettyPrint import Language.Fixpoint.Types.Visitor-import Language.Fixpoint.SortCheck (ElabParam(..), elaborate, applySorts, isFirstOrder)+import Language.Fixpoint.SortCheck (ElabParam(..), theoryEnv, elaborate, applySorts, isFirstOrder) -- import Language.Fixpoint.Defunctionalize import Language.Fixpoint.Misc ((==>)) import qualified Language.Fixpoint.Misc as Misc@@ -34,7 +33,9 @@ import qualified Data.Text as T import Data.Maybe (isNothing, mapMaybe, fromMaybe) import Control.Monad ((>=>))+import GHC.Stack (HasCallStack) import Text.PrettyPrint.HughesPJ hiding ((<>))+import qualified Language.Fixpoint.SortCheck as SortCheck type SanitizeM a = Either E.Error a @@ -45,9 +46,9 @@ >=> Misc.fM dropFuncSortedShadowedBinders >=> Misc.fM sanitizeWfC >=> Misc.fM replaceDeadKvars- >=> Misc.fM (dropDeadSubsts . restrictKVarDomain)+ >=> Misc.fM (dropDeadSubsts . restrictKVarDomain cfg) >=> banMixedRhs- >=> banQualifFreeVars+ >=> banQualifFreeVars cfg >=> banConstraintFreeVars cfg >=> Misc.fM addLiterals >=> Misc.fM (eliminateEta cfg)@@ -88,42 +89,12 @@ -------------------------------------------------------------------------------- eliminateEta cfg si | Cfg.etaElim cfg- , Cfg.oldPLE cfg- = si { F.ae = ae' }- | Cfg.etaElim cfg = si { F.ae = (ae {F.aenvEqs = etaElimNEW `fmap` F.aenvEqs ae }) } | otherwise = si where- ae' = ae {F.aenvEqs = eqs} ae = F.ae si- eqs = fmap etaElim (F.aenvEqs ae) - etaElim eq = F.notracepp "Eliminating" $- case body of- F.PAtom F.Eq e0 e1 ->- let (f0, args0) = fapp e0- (f1, args1) = F.notracepp "f1" $ fapp e1 in- if reverse args0 == args- then let commonArgs = F.notracepp "commonArgs" .- fmap fst .- takeWhile (uncurry (==)) $- zip args0 args1- commonLength = length commonArgs- (newArgsAndSorts, elimedArgsAndSorts) =- splitAt (length args - commonLength) argsAndSorts- args0' = F.eVar <$> reverse (drop commonLength args0)- args1' = F.eVar <$> reverse (drop commonLength args1) in- eq { F.eqArgs = newArgsAndSorts- , F.eqSort = foldr F.FFunc sort- (snd <$> elimedArgsAndSorts)- , F.eqBody = F.PAtom F.Eq (F.eApps f0 args0') (F.eApps f1 args1')}- else eq- _ -> eq- where argsAndSorts = F.eqArgs eq- args = fst <$> argsAndSorts- body = F.eqBody eq- sort = F.eqSort eq etaElimNEW eq = F.notracepp "Eliminating" $ let (f1, args1) = fapp (F.eqBody eq) in let commonArgs = F.notracepp "commonArgs" .@@ -160,11 +131,6 @@ | 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,@@ -235,10 +201,12 @@ -- `x` which appear in substitutions of the form `K[x := y]` where `y` -- is not in the env. ---------------------------------------------------------------------------------restrictKVarDomain :: F.SInfo a -> F.SInfo a-restrictKVarDomain si = si { F.ws = M.mapWithKey (restrictWf kvm) (F.ws si) }+restrictKVarDomain :: Config -> F.SInfo a -> F.SInfo a+restrictKVarDomain cfg si+ | Cfg.explicitKvars cfg = si+ | otherwise = si { F.ws = M.mapWithKey (restrictWf kvm) (F.ws si) } where- kvm = safeKvarEnv si+ kvm = safeKvarEnv si -- | `restrictWf kve k w` restricts the env of `w` to the parameters in `kve k`. restrictWf :: KvDom -> F.KVar -> F.WfC a -> F.WfC a@@ -248,20 +216,21 @@ kis = S.fromList [ i | (_, i) <- F.toListSEnv kEnv ] kEnv = M.lookupDefault mempty k kve +type KvDom = M.HashMap F.KVar (F.SEnv F.BindId)+type KvBads = M.HashMap F.KVar [F.Symbol]+ -- | `safeKvarEnv` computes the "real" domain of each kvar, which is -- a SUBSET of the input domain, in which we KILL the parameters -- `x` which appear in substitutions of the form `K[x := y]` -- where `y` is not in the env. -type KvDom = M.HashMap F.KVar (F.SEnv F.BindId)-type KvBads = M.HashMap F.KVar [F.Symbol]- safeKvarEnv :: F.SInfo a -> KvDom safeKvarEnv si = L.foldl' (dropKvarEnv si) env0 cs where cs = M.elems (F.cm si) env0 = initKvarEnv si + dropKvarEnv :: F.SInfo a -> KvDom -> F.SimpC a -> KvDom dropKvarEnv si kve c = M.mapWithKey (dropBadParams kBads) kve where@@ -353,15 +322,13 @@ -------------------------------------------------------------------------------- -- | check that no qualifier has free variables ---------------------------------------------------------------------------------banQualifFreeVars :: F.SInfo a -> SanitizeM (F.SInfo a)+banQualifFreeVars :: Config -> F.SInfo a -> SanitizeM (F.SInfo a) ---------------------------------------------------------------------------------banQualifFreeVars fi = Misc.applyNonNull (Right fi) (Left . badQuals) bads+banQualifFreeVars cfg fi = Misc.applyNonNull (Right fi) (Left . badQuals) bads where bads = [ (q, xs) | q <- F.quals fi, let xs = free q, not (null xs) ]- free q = filter (not . isLit) (F.syms q)- isLit x = F.memberSEnv x (F.gLits fi)- -- lits = fst <$> F.toListSEnv (F.gLits fi)- -- free q = S.toList $ F.syms (F.qBody q) `nubDiff` (lits ++ F.prims ++ F.syms (F.qpSym <$> F.qParams q))+ free q = filter (not . isGlobal) (F.syms q)+ isGlobal x = F.memberSEnv x (SortCheck.globalEnv cfg fi) badQuals :: Misc.ListNE (F.Qualifier, Misc.ListNE F.Symbol) -> E.Error badQuals bqs = E.catErrors [ E.errFreeVarInQual q xs | (q, xs) <- bqs]@@ -393,7 +360,7 @@ -- function definitions inside the `AxiomEnv` which cannot be elaborated as -- it makes it hard to actually find the fundefs within (breaking PLE.) ---------------------------------------------------------------------------------symbolEnv :: Config -> F.SInfo a -> F.SymEnv+symbolEnv :: HasCallStack => Config -> F.SInfo a -> F.SymEnv symbolEnv cfg si = F.symEnv sEnv thyEnv ds lits (ts ++ ts') where ts' = applySorts ae'@@ -403,8 +370,7 @@ ds = F.ddecls si ts = Misc.setNub (applySorts si ++ [t | (_, t) <- F.toListSEnv sEnv]) sEnv = F.coerceSortEnv ef $ (F.tsSort <$> thyEnv) `mappend` F.fromListSEnv xts- slv = Cfg.solver cfg- ef = solverFlags slv+ ef = solverFlags cfg xts = symbolSorts cfg si ++ alits lits = F.dLits si `F.unionSEnv'` F.fromListSEnv alits alits = litsAEnv $ F.ae si@@ -412,7 +378,7 @@ litsAEnv :: F.AxiomEnv -> [(F.Symbol, F.Sort)] litsAEnv ae = zip (F.symbol <$> symConsts ae) (repeat F.strSort) -symbolSorts :: Config -> F.GInfo c a -> [(F.Symbol, F.Sort)]+symbolSorts :: HasCallStack => Config -> F.GInfo c a -> [(F.Symbol, F.Sort)] symbolSorts cfg fi = either E.die id $ symbolSorts' cfg fi symbolSorts' :: Config -> F.GInfo c a -> SanitizeM [(F.Symbol, F.Sort)]
src/Language/Fixpoint/Solver/Solution.hs view
@@ -1,7 +1,8 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE TupleSections #-}+{-# OPTIONS_GHC -Wwarn #-} module Language.Fixpoint.Solver.Solution ( -- * Create Initial Solution@@ -10,21 +11,27 @@ -- * Update Solution , Sol.update + -- * Apply Solution+ , applyInSortedReft+ , CombinedEnv(..)+ -- * Lookup Solution , lhsPred , nonCutsResult++ -- * Exported for Testing+ , simplifyKVar+ , alphaEq ) where -import Control.Parallel.Strategies import Control.Arrow (second, (***))-import Control.Monad (void)+import Control.Monad (guard, mplus) import Control.Monad.Reader import qualified Data.HashSet as S import qualified Data.HashMap.Strict as M-import qualified Data.List as L-import Data.Maybe (fromMaybe, maybeToList, isNothing)-import qualified Data.Bifunctor as Bifunctor (second)+import qualified Data.List as List+import Data.Maybe (maybeToList, isJust, isNothing) import Language.Fixpoint.Types.PrettyPrint () import Language.Fixpoint.Types.Visitor as V import Language.Fixpoint.SortCheck (ElabM)@@ -32,35 +39,30 @@ import qualified Language.Fixpoint.Misc as Misc import Language.Fixpoint.Types.Config import qualified Language.Fixpoint.Types as F-import Language.Fixpoint.Types ((&.&)) import qualified Language.Fixpoint.Types.Solutions as Sol import Language.Fixpoint.Types.Constraints hiding (ws, bs) import Prelude hiding (init, lookup)-import Language.Fixpoint.Solver.Sanitize --- DEBUG-import Text.Printf (printf)--- import Debug.Trace (trace) - -------------------------------------------------------------------------------- -- | Initial Solution (from Qualifiers and WF constraints) --------------------- ---------------------------------------------------------------------------------init :: (F.Fixpoint a) => Config -> F.SInfo a -> S.HashSet F.KVar -> Sol.Solution+init :: (F.Fixpoint a) => Config -> F.SInfo a -> S.HashSet F.KVar -> M.HashMap F.KVar Sol.QBind ---------------------------------------------------------------------------------init cfg si ks_ = Sol.fromList symEnv mempty keqs [] mempty ebs xEnv+init cfg si ks =+ runReader (traverse (refine si qcs genv) ws) (solverFlags cfg) where- keqs = runReader (traverse (refine si qcs genv) ws) (solverFlags $ solver cfg) `using` parList rdeepseq- qcs = {- trace ("init-qs-size " ++ show (length ws, length qs_, M.keys qcs_)) $ -} qcs_- qcs_ = mkQCluster qs_- qs_ = F.quals si- ws = [ w | (k, w) <- M.toList (F.ws si), not (isGWfc w), k `S.member` ks ]- ks = {- trace ("init-ks-size" ++ show (S.size ks_)) $ -} ks_- genv = instConstants si- symEnv = symbolEnv cfg si- ebs = ebindInfo si- xEnv = F.fromListSEnv [ (x, (i, F.sr_sort sr)) | (i,(x,sr,_)) <- F.bindEnvToList (F.bs si)]+ qcs = mkQCluster (F.quals si)+ ws = M.intersection (F.ws si) (S.toMap ks)+ genv = initQualifierEnv cfg si +initQualifierEnv :: (F.Fixpoint a) => Config -> F.SInfo a -> F.SEnv F.Sort+initQualifierEnv cfg si+ | scraping = So.globalEnv cfg si <> instConstants si+ | otherwise = instConstants si+ where+ scraping = scrape cfg /= No+ -------------------------------------------------------------------------------- -- | [NOTE:qual-cluster] It is wasteful to perform instantiation *individually* -- on each qualifier, as many qualifiers have "equivalent" parameters, and@@ -82,7 +84,7 @@ -------------------------------------------------------------------------------- -refine :: F.SInfo a -> QCluster -> F.SEnv F.Sort -> F.WfC a -> ElabM (F.KVar, Sol.QBind)+refine :: F.SInfo a -> QCluster -> F.SEnv F.Sort -> F.WfC a -> ElabM Sol.QBind refine info qs genv w = refineK (allowHOquals info) env qs (F.wrft w) where env = wenvSort <> genv@@ -94,14 +96,10 @@ notLit = not . F.isLitSymbol . fst -refineK :: Bool -> F.SEnv F.Sort -> QCluster -> (F.Symbol, F.Sort, F.KVar) -> ElabM (F.KVar, Sol.QBind)-refineK ho env qs (v, t, k) =- do eqs' <- Sol.qbFilterM (okInst env v t) eqs- pure $ F.notracepp _msg (k, eqs')+refineK :: Bool -> F.SEnv F.Sort -> QCluster -> (F.Symbol, F.Sort, F.KVar) -> ElabM Sol.QBind+refineK ho env qs (v, t, _k) = Sol.qbFilterM (okInst env v t) eqs where- eqs = instK ho env v t qs-- _msg = printf "\n\nrefineK: k = %s, eqs = %s" (F.showpp k) (F.showpp eqs)+ eqs = instK ho env v t qs -------------------------------------------------------------------------------- instK :: Bool@@ -253,14 +251,15 @@ {-# SCC lhsPred #-} lhsPred :: (F.Loc a)- => F.IBindEnv+ => Config+ -> F.IBindEnv -> F.BindEnv a -> Sol.Solution -> F.SimpC a- -> ElabM F.Expr-lhsPred bindingsInSmt be s c =- do ap <- apply g s bs- pure $ F.notracepp _msg $ fst ap+ -> F.Expr+lhsPred cfg bindingsInSmt be s c =+ let ap = apply cfg g s bs+ in F.notracepp _msg $ fst ap where g = CEnv ci be bs (F.srcSpan c) bindingsInSmt bs = F.senv c@@ -278,91 +277,67 @@ , ceBindingsInSmt :: !F.IBindEnv } -instance F.Loc (CombinedEnv a) where- srcSpan = ceSpan- type Cid = Maybe Integer type ExprInfo = (F.Expr, KInfo) -apply :: CombinedEnv ann -> Sol.Sol a Sol.QBind -> F.IBindEnv -> ElabM ExprInfo-apply g s bs =- -- Clear the "known" bindings for applyKVars, since it depends on- -- using the fully expanded representation of the predicates to bind their- -- variables with quantifiers.- do (ps, ks, _) <- envConcKVars g s bs- (pks, kI) <- applyKVars g {ceBindingsInSmt = F.emptyIBindEnv} s ks- pure (F.conj (pks:ps), kI) -- see [NOTE: pAnd-SLOW]+apply :: Config -> CombinedEnv ann -> Sol.Sol Sol.QBind -> F.IBindEnv -> ExprInfo+apply cfg g s bs =+ -- Clear the "known" bindings for applyKVars, since it depends on+ -- using the fully expanded representation of the predicates to bind their+ -- variables with quantifiers.+ let xrs = map (lookupBindEnvExt g) (F.elemsIBindEnv bs)+ (ps, ks) = envConcKVars xrs+ (pks, kI) = applyKVars cfg g {ceBindingsInSmt = F.emptyIBindEnv} s ks+ in (F.conj (pks:ps), kI) -- see [NOTE: pAnd-SLOW] +-- | @applyInSortedReft@ applies the solution to a single sorted reft+applyInSortedReft+ :: Config+ -> CombinedEnv ann+ -> Sol.Sol Sol.QBind+ -> (F.Symbol, F.SortedReft)+ -> (F.Symbol, F.SortedReft)+applyInSortedReft cfg g s xsr@(x, sr) =+ let (ps, ks) = envConcKVars [xsr]+ (pks, _) = applyKVars cfg g {ceBindingsInSmt = F.emptyIBindEnv} s ks+ in (x, sr { F.sr_reft = F.Reft (x, F.conj (pks : ps)) }) -envConcKVars :: CombinedEnv ann -> Sol.Sol a Sol.QBind -> F.IBindEnv -> ElabM ([F.Expr], [F.KVSub], [F.KVSub])-envConcKVars g s bs =- do xrs <- traverse (lookupBindEnvExt g s) is- let (pss, kss, gss) = unzip3 [ F.notracepp ("sortedReftConcKVars" ++ F.showpp sr) $ F.sortedReftConcKVars x sr | (x, sr) <- xrs ]- pure (concat pss, concat kss, L.nubBy (\x y -> F.ksuKVar x == F.ksuKVar y) $ concat gss)- where- is = F.elemsIBindEnv bs+-- | Produces conjuncts of each sorted reft in the IBindEnv, separated+-- into concrete conjuncts and kvars.+envConcKVars :: [(F.Symbol, F.SortedReft)] -> ([F.Expr], [F.KVSub])+envConcKVars xrs =+ let (pss, kss) = unzip [ F.sortedReftConcKVars x sr | (x, sr) <- xrs ]+ in (concat pss, concat kss) -lookupBindEnvExt :: CombinedEnv ann -> Sol.Sol a Sol.QBind -> F.BindId -> ElabM (F.Symbol, F.SortedReft)-lookupBindEnvExt g s i =- do msol <- ebSol (g {ceBindingsInSmt = F.emptyIBindEnv}) s i- pure (x, case msol of- Just p -> sr { F.sr_reft = F.Reft (x, p) }- Nothing -> if F.memberIBindEnv i (ceBindingsInSmt g)- then sr { F.sr_reft = F.Reft (x, F.EVar (F.bindSymbol (fromIntegral i)))}- else sr)+lookupBindEnvExt+ :: CombinedEnv ann -> F.BindId -> (F.Symbol, F.SortedReft)+lookupBindEnvExt g i =+ (,) x $+ if F.memberIBindEnv i (ceBindingsInSmt g)+ then sr { F.sr_reft = F.Reft (x, F.EVar (F.bindSymbol (fromIntegral i)))}+ else sr where (x, sr, _) = F.lookupBindEnv i (ceBEnv g) -ebSol :: CombinedEnv ann -> Sol.Sol a Sol.QBind -> F.BindId -> ElabM (Maybe F.Expr)-ebSol g sol bindId = case M.lookup bindId sebds of- Just (Sol.EbSol p) -> pure $ Just p- Just (Sol.EbDef cs _) ->- do let cSol c = if sid c == ceCid g- then pure F.PFalse- else do p <- ebindReft g s' c- pure $ exElim (Sol.sxEnv s') (senv c) bindId p- exps <- traverse cSol cs- pure $ Just $ F.PAnd exps- _ -> pure Nothing- where- sebds = Sol.sEbd sol- s' = sol { Sol.sEbd = M.insert bindId Sol.EbIncr sebds }--ebindReft :: CombinedEnv ann -> Sol.Sol a Sol.QBind -> F.SimpC () -> ElabM F.Pred-ebindReft g s c =- do a <- apply g' s bs- pure $ F.pAnd [ fst a , F.crhs c ]- where- g' = g { ceCid = sid c, ceIEnv = bs }- bs = F.senv c--exElim :: F.SEnv (F.BindId, F.Sort) -> F.IBindEnv -> F.BindId -> F.Pred -> F.Pred-exElim env ienv xi p = F.notracepp msg (F.pExist yts p)- where- msg = "exElim" -- printf "exElim: ix = %d, p = %s" xi (F.showpp p)- yts = [ (y, yt) | y <- F.syms p- , (yi, yt) <- maybeToList (F.lookupSEnv y env)- , xi < yi- , yi `F.memberIBindEnv` ienv ]--applyKVars :: CombinedEnv ann -> Sol.Sol a Sol.QBind -> [F.KVSub] -> ElabM ExprInfo-applyKVars g s ks =- mrExprInfosM (applyKVar g s) F.pAndNoDedup mconcat ks+applyKVars :: Config -> CombinedEnv ann -> Sol.Sol Sol.QBind -> [F.KVSub] -> ExprInfo+applyKVars cfg g s ks =+ let bcs = map (applyKVar cfg g s) ks+ (es, is) = unzip bcs+ in (F.pAndNoDedup es, mconcat is) -applyKVar :: CombinedEnv ann -> Sol.Sol a Sol.QBind -> F.KVSub -> ElabM ExprInfo-applyKVar g s ksu = case Sol.lookup s (F.ksuKVar ksu) of- Left cs -> hypPred g s ksu cs- Right eqs -> do qbp <- Sol.qbPreds msg s (F.ksuSubst ksu) eqs- pure (F.pAndNoDedup $ fst <$> qbp, mempty) -- TODO: don't initialize kvars that have a hyp solution- where- msg = "applyKVar: " ++ show (ceCid g)+applyKVar :: Config -> CombinedEnv ann -> Sol.Sol Sol.QBind -> F.KVSub -> ExprInfo+applyKVar cfg g s ksu = case Sol.lookup s (F.ksuKVar ksu) of+ Left cs -> hypPred cfg g s ksu cs+ Right eqs -> let qbp = Sol.qbPreds (F.ksuSubst ksu) eqs+ in (F.pAndNoDedup $ fst <$> qbp, mempty) -- TODO: don't initialize kvars that have a hyp solution -mkNonCutsExpr :: CombinedEnv ann -> Sol.Sol a Sol.QBind -> F.KVar -> Sol.Hyp -> ElabM F.Expr-mkNonCutsExpr ce s k cs = do bcps <- traverse (bareCubePred ce s k) cs- pure $ F.pOr bcps+mkNonCutsExpr :: Config -> CombinedEnv ann -> Sol.Sol Sol.QBind -> F.KVar -> Sol.Hyp -> F.Expr+mkNonCutsExpr cfg ce s k cs =+ let bcps = map (bareCubePred cfg ce s k) cs+ in F.pOr bcps -nonCutsResult :: F.BindEnv ann -> Sol.Sol a Sol.QBind -> ElabM (M.HashMap F.KVar F.Expr)-nonCutsResult be s = M.traverseWithKey (mkNonCutsExpr g s) $ Sol.sHyp s+nonCutsResult :: Config -> F.BindEnv ann -> Sol.Sol Sol.QBind -> FixDelayedSolution+nonCutsResult cfg be s = M.mapWithKey (\k -> Delayed . mkNonCutsExpr cfg g s k) $ Sol.sHyp s where g = CEnv Nothing be F.emptyIBindEnv F.dummySpan F.emptyIBindEnv @@ -373,35 +348,57 @@ -- differences since the result of 'cubePred' is fed to the verification -- pipeline and @bareCubePred@ is meant for human inspection. ----- 1) Only one existential quantifier is introduced at the top of the--- expression.--- 2) @bareCubePred@ doesn't elaborate the expression, so it avoids calling--- 'elabExist'. 'apply' is invoked to eliminate other kvars though, and--- apply will invoke 'elabExist', so 'Liquid.Fixpoint.SortCheck.unElab'--- might need to be called on the output to remove the elaboration.--- 3) The expression is created from its defining constraints only, while--- @cubePred@ does expect the caller to supply the substitution at a--- particular use of the KVar. Thus @cubePred@ produces a different--- expression for every use site of the kvar, while here we produce one--- expression for all the uses.-bareCubePred :: CombinedEnv ann -> Sol.Sol a Sol.QBind -> F.KVar -> Sol.Cube -> ElabM F.Expr-bareCubePred g s k c =- do (xts, psu) <- substElim (Sol.sEnv s) sEnv g' k su- (p, _kI) <- apply g' s bs'- pure $ F.pExist (xts ++ yts) (psu &.& p)+-- The expression is created from its defining constraints only, while+-- @cubePred@ does expect the caller to supply the substitution at a+-- particular use of the KVar. Thus @cubePred@ produces a different+-- expression for every use site of the kvar, while here we produce one+-- expression for all the uses.+--+-- Where the cube rhs is @k[params:=xts]@, we keep the parameters free in the+-- final predicate. e.g. @params == xts && exists yts . ...@+-- That is, we only quantify out the `yts` as we want to make+-- explicit what equalities those parameters have in each cube.+--+-- Issue https://github.com/ucsd-progsys/liquid-fixpoint/issues/808 discusses+-- an example where the equalities are essential to keep.++bareCubePred :: Config -> CombinedEnv ann -> Sol.Sol Sol.QBind -> F.KVar -> Sol.Cube -> F.Expr+bareCubePred cfg g s k c =+ let psu = F.pAnd [ F.EEq (F.expr x) e | (x, e) <- M.toList m ]+ (p, _kI) = apply cfg g' s bs+ in F.pExist yts (p F.&.& psu) where bs = Sol.cuBinds c- su = Sol.cuSubst c+ F.Su m = dropUnsortedExprs cfg g' (Sol.cuSubst c) g' = addCEnv g bs- bs' = delCEnv s k bs+ bs' = F.diffIBindEnv bs (Misc.safeLookup "sScp" k (Sol.sScp s)) yts = symSorts g bs'- sEnv = F.seSort (Sol.sEnv s) -hypPred :: CombinedEnv ann -> Sol.Sol a Sol.QBind -> F.KVSub -> Sol.Hyp -> ElabM ExprInfo-hypPred g s ksu hyp =- do cs <- traverse (cubePred g s ksu) hyp- pure $ F.pOr *** mconcatPlus $ unzip cs+-- | At the moment, the liquid-fixpoint implementation allows for unsorted+-- expressions in substitutions. See the discussion in+-- https://github.com/ucsd-progsys/liquid-fixpoint/issues/800+-- The `explicitKvars` flag is meant for Horn-style constraints, which must+-- have well-formed (expressions) as arguments, and so we *disable* the+-- filtering of unsorted expressions when that flag is set.+dropUnsortedExprs :: Config -> CombinedEnv ann -> F.Subst -> F.Subst+dropUnsortedExprs cfg g su@(F.Su m)+ | explicitKvars cfg = su+ | otherwise = F.Su $+ M.filter+ (\e -> isJust $ do+ t <- So.checkSortExpr sp env e+ guard (not (isClass t))+ )+ m+ where+ sp = ceSpan g+ env = combinedSEnv g +hypPred :: Config -> CombinedEnv ann -> Sol.Sol Sol.QBind -> F.KVSub -> Sol.Hyp -> ExprInfo+hypPred cfg g s ksu hyp =+ let cs = map (cubePred cfg g s ksu) hyp+ in F.pOr *** mconcatPlus $ unzip cs+ {- | `cubePred g s k su c` returns the predicate for (k . su)@@ -410,120 +407,48 @@ c := [b1,...,bn] |- (k . su') - in the binder environment `g`.-- bs' := the subset of "extra" binders in [b1...bn] that are *not* in `g`- p' := the predicate corresponding to the "extra" binders-+ in the binder environment `g`. The binders in `sScp s k` are not included+ in the final predicate. They are considered redundant conjuncts as per+ section 2.4 of "Local Refinement Typing", ICFP 2017. -}--elabExist :: F.SrcSpan -> Sol.Sol a Sol.QBind -> [(F.Symbol, F.Sort)] -> F.Expr -> ElabM F.Expr-elabExist sp s xts p =- do ef <- ask- let elab = So.elaborate (So.ElabParam ef (F.atLoc sp "elabExist") env)- let xts' = [ (x, elab t) | (x, t) <- xts]- pure $ F.pExist xts' p- where- env = Sol.sEnv s--cubePred :: CombinedEnv ann -> Sol.Sol a Sol.QBind -> F.KVSub -> Sol.Cube -> ElabM ExprInfo-cubePred g s ksu c =- do ((xts,psu,p), kI) <- cubePredExc g s ksu c bs'- e <- F.notracepp "cubePred" <$> elabExist sp s xts (psu &.& p)- pure (e , kI)+cubePred :: Config -> CombinedEnv ann -> Sol.Sol Sol.QBind -> F.KVSub -> Sol.Cube -> ExprInfo+cubePred cfg g s ksu c =+ let (p, kI) = cubePredExc cfg g s c bs'+ -- Free variables in p should not colide with those generated by+ -- the rapier substitution. If that were the case, perhaps we would+ -- need to include @combinedSEnv g@ in the scope set.+ in (F.rapierSubstExpr (F.substSymbolsSet su) su p, kI) where- sp = F.srcSpan g- bs' = delCEnv s k bs+ bs' = F.diffIBindEnv bs (Misc.safeLookup "sScp" k (Sol.sScp s)) bs = Sol.cuBinds c k = F.ksuKVar ksu--type Binders = [(F.Symbol, F.Sort)]+ su = dropUnsortedExprs cfg g (F.ksuSubst ksu) -- | @cubePredExc@ computes the predicate for the subset of binders bs'.--- The output is a tuple, `(xts, psu, p, kI)` such that the actual predicate--- we want is `Exists xts. (psu /\ p)`.--cubePredExc :: CombinedEnv ann -> Sol.Sol a Sol.QBind -> F.KVSub -> Sol.Cube -> F.IBindEnv- -> ElabM ((Binders, F.Pred, F.Pred), KInfo)-cubePredExc g s ksu c bs' =- do (xts, psu) <- substElim (Sol.sEnv s) sEnv g k su- (_ , psu') <- substElim (Sol.sEnv s) sEnv g' k su'- (p', kI) <- apply g' s bs'- cubeE <- elabExist sp s yts' (F.pAndNoDedup [p', psu'])- let cubeP = (xts, psu, cubeE)- pure (cubeP, extendKInfo kI (Sol.cuTag c))- where-- sp = F.srcSpan g- yts' = symSorts g bs'- g' = addCEnv g bs- su' = Sol.cuSubst c- bs = Sol.cuBinds c- k = F.ksuKVar ksu- su = F.ksuSubst ksu- sEnv = F.insertSEnv (F.ksuVV ksu) (F.ksuSort ksu) (F.seSort $ Sol.sEnv s)---- TODO: SUPER SLOW! Decorate all substitutions with Sorts in a SINGLE pass.--{- | @substElim@ returns the binders that must be existentially quantified,- and the equality predicate relating the kvar-"parameters" and their- actual values. i.e. given-- K[x1 := e1]...[xn := en]-- where e1 ... en have types t1 ... tn- we want to quantify out-- x1:t1 ... xn:tn-- and generate the equality predicate && [x1 ~~ e1, ... , xn ~~ en]- we use ~~ because the param and value may have different sorts, see:-- tests/pos/kvar-param-poly-00.hs-- Finally, we filter out binders if they are-- 1. "free" in e1...en i.e. in the outer environment.- (Hmm, that shouldn't happen...?)-- 2. are binders corresponding to sorts (e.g. `a : num`, currently used- to hack typeclasses current.)- -}-substElim :: F.SymEnv -> F.SEnv F.Sort -> CombinedEnv a -> F.KVar -> F.Subst -> ElabM ([(F.Symbol, F.Sort)], F.Pred)-substElim syEnv sEnv g _ (F.Su m) =- do p <- traverse (\(x, e ,t) -> mkSubst sp syEnv x (substSort sEnv x) e t) xets- pure (xts, F.pAnd p)- where- xts = [ (x, t) | (x, _, t) <- xets, not (S.member x frees) ]- xets = [ (x, e, t) | (x, e) <- xes, t <- sortOf e, not (isClass t)]- frees = S.fromList (concatMap (F.syms . snd) xes)- sortOf = maybeToList . So.checkSortExpr sp env- sp = F.srcSpan g- xes = M.toList m- env = combinedSEnv g--substSort :: F.SEnv F.Sort -> F.Symbol -> F.Sort-substSort sEnv sym = fromMaybe (err sym) $ F.lookupSEnv sym sEnv- where- err x = error $ "Solution.substSort: unknown binder " ++ F.showpp x----- LH #1091-mkSubst :: F.SrcSpan -> F.SymEnv -> F.Symbol -> F.Sort -> F.Expr -> F.Sort -> ElabM F.Expr-mkSubst sp env x tx ey ty- | tx == ty = pure $ F.EEq ex ey- | otherwise = do ex' <- elabToInt sp env ex tx- ey' <- elabToInt sp env ey ty- pure $ {- F.tracepp _msg $ -} F.EEq ex' ey'+--+-- Schematically, the result is+--+-- > Exists (bindsOf bs'). (pAnd (predicatesOf bs'))[Sol.cuSubst c]+--+-- but we also preserve the information about which variables are being+-- substituted:+--+-- > Exists (bindsOf bs'). pAnd (predicatesOf bs') && x1=e1 && ... && xn=en+--+-- where @Sol.cuSubst c = [x1:=e1;...;xn:=en]@.+--+cubePredExc :: Config -> CombinedEnv ann -> Sol.Sol Sol.QBind -> Sol.Cube -> F.IBindEnv+ -> (F.Pred, KInfo)+cubePredExc cfg g s c bs' =+ let psu' = F.pAnd [ F.EEq (F.expr x) e | (x, e) <- M.toList m ]+ (p', kI) = apply cfg g' s bs'+ cubeE = F.pExist yts' (F.pAndNoDedup [p', psu'])+ in (cubeE, extendKInfo kI (Sol.cuTag c)) where- -- _msg = "mkSubst-DIFF: tx = " ++ F.showpp tx ++ " ty = " ++ F.showpp ty- -- ++ " ex' = " ++ F.showpp ex' ++ " ey' = " ++ F.showpp ey'- ex = F.expr x--elabToInt :: F.SrcSpan -> F.SymEnv -> F.Expr -> F.Sort -> ElabM F.Expr-elabToInt sp env e s =- do ef <- ask- pure $ So.elaborate (So.ElabParam ef (F.atLoc sp "elabToInt") env) (So.toInt env e s)+ yts' = symSorts g bs'+ g' = addCEnv g bs+ F.Su m = dropUnsortedExprs cfg g' (Sol.cuSubst c)+ bs = Sol.cuBinds c isClass :: F.Sort -> Bool isClass F.FNum = True@@ -539,12 +464,6 @@ addCEnv :: CombinedEnv a -> F.IBindEnv -> CombinedEnv a addCEnv g bs' = g { ceIEnv = F.unionIBindEnv (ceIEnv g) bs' } --delCEnv :: Sol.Sol a Sol.QBind -> F.KVar -> F.IBindEnv -> F.IBindEnv-delCEnv s k bs = F.diffIBindEnv bs _kbs- where- _kbs = Misc.safeLookup "delCEnv" k (Sol.sScp s)- symSorts :: CombinedEnv a -> F.IBindEnv -> [(F.Symbol, F.Sort)] symSorts g bs = second F.sr_sort <$> F.envCs (ceBEnv g) bs @@ -570,11 +489,11 @@ mempty = KI [] 0 1 mappend = (<>) -mplus :: KInfo -> KInfo -> KInfo-mplus ki ki' = (mappend ki ki') { kiCubes = kiCubes ki + kiCubes ki'}+mplusKInfo :: KInfo -> KInfo -> KInfo+mplusKInfo ki ki' = (mappend ki ki') { kiCubes = kiCubes ki + kiCubes ki'} mconcatPlus :: [KInfo] -> KInfo-mconcatPlus = foldr mplus mempty+mconcatPlus = foldr mplusKInfo mempty appendTags :: [Tag] -> [Tag] -> [Tag] appendTags ts ts' = Misc.sortNub (ts ++ ts')@@ -583,48 +502,145 @@ extendKInfo ki t = ki { kiTags = appendTags [t] (kiTags ki) , kiDepth = 1 + kiDepth ki } -mrExprInfosM :: Monad m => (a -> m (b, c)) -> ([b] -> b1) -> ([c] -> c1) -> [a] -> m (b1, c1)-mrExprInfosM mF erF irF xs =- do bcs <- traverse mF xs- let (es, is) = unzip bcs- pure (erF es, irF is)+-- | Simplifies existential expressions with unused or inconsequential bindings.+--+-- Simplification is helpful for human readability of solutions. It makes easier+-- reporting errors. Sometimes it can be useful for debugging if run on queries+-- sent to the SMT solver. We don't do that by default because some benchmarks+-- show a slowdown in some cases.+--+-- 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"+--+-- Therefore we eliminate variables that appear in equalities via substitutions.+--+-- > simplifyKVar "exists x y. x == C && P && Q y"+-- > ==+-- > "exists y. (P && Q y)[x:=C]"+--+-- The first parameter is the set of symbols that can appear free in the input+-- expression. At the moment, this only needs to include the free variables that+-- start with the @subst$@ prefix.+--+simplifyKVar :: S.HashSet F.Symbol -> F.Expr -> F.Expr+simplifyKVar s0 = F.conj . dedupByAlphaEq s0 . floatPExistConjuncts . go s0+ where+ go s (F.POr es) = disj $ map (F.conj . floatPExistConjuncts . go s) es+ go s (F.PAnd es) = F.conj $ dedupByAlphaEq S.empty $ concatMap (floatPExistConjuncts . go s) es+ go s (F.PExist bs e0) =+ let es = concatMap (floatPExistConjuncts . go (S.union s $ S.fromList $ map fst bs)) (F.conjuncts e0)+ in elimExistentialBinds (F.PExist bs (F.conj es))+ go _ e = e ------------------------------------------------------------------------------------ | `ebindInfo` constructs the information about the "ebind-definitions".----------------------------------------------------------------------------------ebindInfo :: F.SInfo a -> [(F.BindId, Sol.EbindSol)]-ebindInfo si = group [((bid, x), cons cid) | (bid, cid, x) <- ebindDefs si]- where cons cid = void (Misc.safeLookup "ebindInfo" cid cs)- cs = F.cm si- cmpByFst x y = fst ( fst x ) == fst ( fst y )- group xs = (\ys -> Bifunctor.second (Sol.EbDef (snd <$> ys)) (fst $ head ys))- <$> L.groupBy cmpByFst xs+ dedupByAlphaEq :: S.HashSet F.Symbol -> [F.Expr] -> [F.Expr]+ dedupByAlphaEq s = List.nubBy (\e1 e2 -> alphaEq s e1 e2) -ebindDefs :: F.SInfo a -> [(F.BindId, F.SubcId, F.Symbol)]-ebindDefs si = [ (bid, cid, x) | (cid, x) <- cDefs- , bid <- maybeToList (M.lookup x ebSyms)]- where- ebSyms = ebindSyms si- cDefs = cstrDefs si+ disj :: [F.Expr] -> F.Expr+ disj [] = F.PFalse+ disj [e] = e+ disj es = F.POr es -ebindSyms :: F.SInfo a -> M.HashMap F.Symbol F.BindId-ebindSyms si = M.fromList [ (xi, bi) | bi <- ebinds si- , let (xi,_,_) = F.lookupBindEnv bi be ]- where- be = F.bs si+ elimExistentialBinds (F.PExist bs0 (F.PExist bs1 p)) =+ let bs0' = filter (\(x,_) -> x `notElem` map fst bs1) bs0+ in elimExistentialBinds (F.PExist (bs0' ++ bs1) p)+ elimExistentialBinds (F.PExist bs e0) =+ let es = F.conjuncts e0+ esv = map (isVarEq (map fst bs)) es+ -- Eliminating multiple variables at once can be difficult if the+ -- equalities define cyclic dependencies, so we only eliminate one+ -- variable at a time.+ esvElim = take 1 [ (x, v) | (Just (x, v), _) <- esv ]+ esvKeep =+ let (xs, ys) = break (isJust . fst) esv+ in map snd (xs ++ drop 1 ys)+ su = F.mkSubst esvElim+ e' = F.rapierSubstExpr (F.substSymbolsSet su) su $ F.conj esvKeep+ bs' = filter ((`S.member` F.exprSymbolsSet e') . fst) bs+ e'' = F.pExist bs' e'+ in+ if null esvElim then e'' else elimExistentialBinds e''+ elimExistentialBinds e = e -cstrDefs :: F.SInfo a -> [(F.SubcId, F.Symbol)]-cstrDefs si = [(cid, x) | (cid, c) <- M.toList (cm si)- , x <- maybeToList (cstrDef be c) ]+ -- | Float out conjuncts from an existential expression that does not+ -- depend on the existentially bound variables.+ floatPExistConjuncts :: F.Expr -> [F.Expr]+ floatPExistConjuncts e0@(F.PExist bs es0) =+ let es = F.conjuncts es0+ (floatable, nonFloatable) =+ List.partition (isFloatableConjunct (S.fromList (map fst bs))) es+ in+ if null floatable then+ [e0]+ else+ elimExistentialBinds (F.pExist bs (F.conj nonFloatable)) : floatable+ where+ isFloatableConjunct :: S.HashSet F.Symbol -> F.Expr -> Bool+ isFloatableConjunct s e = S.null $ S.intersection (F.exprSymbolsSet e) s+ floatPExistConjuncts e = [e]++-- | Determine if two expressions are alpha-equivalent.+--+-- Takes as first parameter the set of variables that might appear free+-- in the expressions to compare.+--+-- Doesn't handle all cases, just enough for simplifying KVars which requires+-- alpha-equivalence checking of existentially quantified expressions.+alphaEq :: S.HashSet F.Symbol -> F.Expr -> F.Expr -> Bool+alphaEq s0 = go s0 (F.mkSubst []) where- be = F.bs si+ go :: S.HashSet F.Symbol -> F.Subst -> F.Expr -> F.Expr -> Bool+ go s su (F.PExist bs1 x1) (F.PExist bs2 x2) =+ let su' =+ List.foldl'+ (\su1 (v1, v2) -> F.extendSubst su1 v1 (F.EVar v2))+ su+ (zip (map fst bs1) (map fst bs2))+ in go (S.union s (S.fromList $ map fst bs2)) su' x1 x2+ go s su (F.PAnd es1) (F.PAnd es2) =+ length es1 == length es2 && and (zipWith (go s su) es1 es2)+ go s su (F.POr es1) (F.POr es2) =+ length es1 == length es2 && and (zipWith (go s su) es1 es2)+ go s su e1 e2 =+ F.rapierSubstExpr s su e1 == e2 -cstrDef :: F.BindEnv a -> F.SimpC a -> Maybe F.Symbol-cstrDef be c- | Just (F.EVar x) <- e = Just x- | otherwise = Nothing+-- | Determine if the expression is an equality that sets the value of+-- a variable in the given set.+--+-- @isVarEq fvs e@ yields @(Just (v, e'), e)@ if @v@ is in @fvs@, and @e@ has+-- the form @v == e'@.+isVarEq :: [F.Symbol] -> F.Expr -> (Maybe (F.Symbol, F.Expr), F.Expr)+isVarEq fvs ei0 = case ei0 of+ F.PAtom brel e0 e1+ | isEqRel brel ->+ let m :: Maybe (F.Symbol, F.Expr)+ m = do+ (v, ei) <- ((,e1) <$> isVarIn e0 fvs) `mplus`+ ((,e0) <$> isVarIn e1 fvs)+ () <- guard (not (S.member v (F.exprSymbolsSet ei)))+ return (v, ei)+ in (m, ei0)+ _ ->+ (Nothing, ei0) where- (v,_,_) = F.lookupBindEnv (cbind c) be- e = F.notracepp _msg $ F.isSingletonExpr v rhs- _msg = "cstrDef: " ++ show (stag c) ++ " crhs = " ++ F.showpp rhs- rhs = V.stripCasts (crhs c)+ -- | Tells if the binary relation is an equality.+ isEqRel :: F.Brel -> Bool+ isEqRel F.Eq = True+ isEqRel F.Ueq = True+ isEqRel _ = False++ -- | @isVarIn s fvs@ yields @Just s@ if @s@ is a variable and it is in+ -- @fvs@.+ isVarIn :: F.Expr -> [F.Symbol] -> Maybe F.Symbol+ isVarIn (F.EVar s) vs+ | elem s vs = Just s+ isVarIn _ _vs = Nothing
src/Language/Fixpoint/Solver/Solve.hs view
@@ -2,6 +2,8 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-} {-# OPTIONS_GHC -Wno-name-shadowing #-} @@ -9,18 +11,18 @@ -- | Solve a system of horn-clause constraints --------------------------------- -------------------------------------------------------------------------------- -module Language.Fixpoint.Solver.Solve (solve, solverInfo) where+module Language.Fixpoint.Solver.Solve (solve) where -import Control.Monad (when, filterM)+import Control.Monad (forM, when, filterM) import Control.Monad.Reader-import Control.Monad.State.Strict (modify) import Language.Fixpoint.Misc import qualified Language.Fixpoint.Misc as Misc import qualified Language.Fixpoint.Types as F import qualified Language.Fixpoint.Types.Solutions as Sol import Language.Fixpoint.Types.PrettyPrint import Language.Fixpoint.Types.Config hiding (stats)-import Language.Fixpoint.SortCheck (ElabM)+import Language.Fixpoint.SortCheck (ElabParam(..), elaborate)+import Language.Fixpoint.Solver.Sanitize (symbolEnv) import qualified Language.Fixpoint.Solver.Solution as S import qualified Language.Fixpoint.Smt.Types as T import qualified Language.Fixpoint.Solver.Worklist as W@@ -37,37 +39,67 @@ -- import qualified Data.Maybe as Mb import qualified Data.List as L import Language.Fixpoint.Types (resStatus, FixResult(Unsafe))-import qualified Language.Fixpoint.Types.Config as C+import Language.Fixpoint.Smt.Interface (smtComment) import Language.Fixpoint.Solver.Interpreter (instInterpreter)-import Language.Fixpoint.Solver.Instantiate (instantiate)---import Debug.Trace (trace)+import qualified Language.Fixpoint.Solver.PLE as PLE (instantiate)+import Data.Maybe (maybeToList) mytrace :: String -> a -> a-mytrace _ x = {- trace s -} x+mytrace+ -- s x = trace s x+ _ x = x+{-+solve_ :: (NFData a, F.Fixpoint a, F.Loc a)+ => Config+ -> F.SInfo a+ -> Sol.Solution+ -> W.Worklist a+ -> SolveM a (F.Result (Integer, a), Stats)+ -}+-------------------------------------------------------------------------------- ---------------------------------------------------------------------------------solve :: (NFData a, F.Fixpoint a, Show a, F.Loc a) => Config -> F.SInfo a -> IO (F.Result (Integer, a))+solve+ :: forall a. (NFData a, F.Fixpoint a, Show a, F.Loc a)+ => Config -> ElabParam -> F.SInfo a -> IO (F.Result (Integer, a)) -------------------------------------------------------------------------------- -solve cfg fi = do+solve cfg elabParam fi = do whenLoud $ donePhase Misc.Loud "Worklist Initialize" vb <- getVerbosity- (res, stat) <- (if Quiet == vb || gradual cfg then id else withProgressFI sI) $ runSolverM cfg sI act+ (res, stat) <- (if Quiet == vb then id else withProgressFI sI) $ runSolverM cfg sI elabParam act when (solverStats cfg) $ printStats fi wkl stat -- print (numIter stat) return res where- act = solve_ cfg fi s0 ks wkl+ act :: SolveM a (F.Result (Integer, a), Stats)+ act = do+ ctx <- getContext+ let sEnv = symbolEnv cfg fi+ s1 = s0{Sol.sMap = M.map (elabQBind ctx "solve" sEnv) (Sol.sMap s0)}+ solve_ cfg fi s1 wkl+ -- solverInfo computes the set of cut and non-cut kvars, then initializes+ -- the solutions of the non-cut KVars (in the sHyp field)+ --+ -- S.init provides an initial solution for the cut KVars sI = solverInfo cfg fi wkl = W.init sI- s0 = siSol sI+ s0 = (siSol sI) { Sol.sMap = S.init cfg fi ks } ks = siVars sI+ elabQBind ctx msg env (Sol.QB xs) = Sol.QB (map elabEQual xs)+ where+ elabEQual eq =+ eq { Sol.eqPred =+ elaborate+ (ElabParam (T.ctxElabF ctx) (F.atLoc F.dummySpan msg) env)+ (Sol.eqPred eq)+ } -------------------------------------------------------------------------------- -- | Progress Bar ---------------------------------------------------------------------------------withProgressFI :: SolverInfo a b -> IO b -> IO b+withProgressFI :: SolverInfo a -> IO b -> IO b withProgressFI = withProgress . (+ 1) . fromIntegral . cNumScc . siDeps -------------------------------------------------------------------------------- @@ -77,38 +109,19 @@ ppTs = putStrLn . showpp . mconcat ---------------------------------------------------------------------------------solverInfo :: Config -> F.SInfo a -> SolverInfo a b+solverInfo :: Config -> F.SInfo a -> SolverInfo a -------------------------------------------------------------------------------- solverInfo cfg fI | useElim cfg = E.solverInfo cfg fI | otherwise = SI mempty fI cD (siKvars fI) where- cD = elimDeps fI (kvEdges fI) mempty mempty+ cD = elimDeps fI (kvEdges fI) mempty siKvars :: F.SInfo a -> S.HashSet F.KVar siKvars = S.fromList . M.keys . F.ws -doInterpret :: (F.Loc a) => Config -> F.SInfo a -> [F.SubcId] -> SolveM a (F.SInfo a)-doInterpret cfg fi0 subcIds = do- fi <- liftIO $ instInterpreter cfg fi0 (Just subcIds)- modify $ update' fi- return fi- where- update' fi ss = ss{ssBinds = F.bs fi'}- where- fi' = (siQuery sI) {F.hoInfo = F.HOI (C.allowHO cfg) (C.allowHOqs cfg)}- sI = solverInfo cfg fi--{-# SCC doPLE #-}-doPLE :: (F.Loc a) => Config -> F.SInfo a -> [F.SubcId] -> SolveM a ()-doPLE cfg fi0 subcIds = do- fi <- liftIO $ instantiate cfg fi0 (Just subcIds)- modify $ update' fi- where- update' fi ss = ss{ssBinds = F.bs fi'}- where- fi' = (siQuery sI) {F.hoInfo = F.HOI (C.allowHO cfg) (C.allowHOqs cfg)}- sI = solverInfo cfg fi+doInterpret :: (F.Loc a) => Config -> F.SInfo a -> [F.SubcId] -> SolveM a (F.BindEnv a)+doInterpret cfg fi subcIds = liftIO $ instInterpreter cfg fi (Just subcIds) -------------------------------------------------------------------------------- {-# SCC solve_ #-}@@ -116,39 +129,43 @@ => Config -> F.SInfo a -> Sol.Solution- -> S.HashSet F.KVar -> W.Worklist a -> SolveM a (F.Result (Integer, a), Stats) ---------------------------------------------------------------------------------solve_ cfg fi s0 ks wkl = do- let s1 = F.notracepp "solve_ " $ {-# SCC "sol-init" #-} S.init cfg fi ks- let s2 = mappend s0 s1- (s3, res0) <- sendConcreteBindingsToSMT F.emptyIBindEnv $ \bindingsInSmt -> do+solve_ cfg fi s2 wkl = do+ liftSMT $ smtComment "solve: start"+ (s3, res0) <- sendConcreteBindingsToSMT F.emptyIBindEnv (F.bs fi) $ \bindingsInSmt -> do -- let s3 = solveEbinds fi s2- s3 <- {- SCC "sol-refine" -} refine bindingsInSmt s2 wkl- res0 <- {- SCC "sol-result" -} result bindingsInSmt cfg wkl s3+ s3 <- {- SCC "sol-refine" -} refine bindingsInSmt (F.bs fi) s2 wkl+ res0 <- {- SCC "sol-result" -} result bindingsInSmt cfg fi (W.unsatCandidates wkl) s3 return (s3, res0) - (fi1, s4, res1) <- case resStatus res0 of {- first run the interpreter -}- Unsafe _ bads | not (noLazyPLE cfg) && rewriteAxioms cfg && interpreter cfg -> do- fi1 <- doInterpret cfg fi (map fst $ mytrace ("before the Interpreter " ++ show (length bads) ++ " constraints remain") bads)- (s4, res1) <- sendConcreteBindingsToSMT F.emptyIBindEnv $ \bindingsInSmt -> do- s4 <- {- SCC "sol-refine" -} refine bindingsInSmt s3 wkl- res1 <- {- SCC "sol-result" -} result bindingsInSmt cfg wkl s4- return (s4, res1)- return (fi1, s4, res1)- _ -> return (fi, s3, mytrace "all checked before interpreter" res0)+ (fi1, res1) <- case resStatus res0 of {- first run the interpreter -}+ Unsafe _ bads | rewriteAxioms cfg && interpreter cfg -> do+ liftSMT $ smtComment "solve: interpreter"+ bs <- doInterpret cfg fi (map fst $ mytrace ("before the Interpreter " ++ show (length bads) ++ " constraints remain") bads)+ let fi1 = fi { F.bs = bs }+ badCs = lookupCMap (F.cm fi) <$> map fst bads+ liftSMT $ smtComment "solve: pos-interpreter check"+ fmap (fi1,) $ sendConcreteBindingsToSMT F.emptyIBindEnv bs $ \bindingsInSmt ->+ result bindingsInSmt cfg fi1 badCs s3+ _ -> return (fi, mytrace "all checked before interpreter" res0) res2 <- case resStatus res1 of {- then run normal PLE on remaining unsolved constraints -}- Unsafe _ bads2 | not (noLazyPLE cfg) && rewriteAxioms cfg -> do- doPLE cfg fi1 (map fst $ mytrace ("before z3 PLE " ++ show (length bads2) ++ " constraints remain") bads2)- sendConcreteBindingsToSMT F.emptyIBindEnv $ \bindingsInSmt -> do- s5 <- {- SCC "sol-refine" -} refine bindingsInSmt s4 wkl- result bindingsInSmt cfg wkl s5+ Unsafe _ bads2 | rewriteAxioms cfg -> do+ liftSMT $ smtComment "solve: ple"+ bs <- liftSMT $ PLE.instantiate cfg fi1 (Just s3) (Just $ map fst bads2)+ -- Check the constraints one last time after PLE+ let fi2 = fi { F.bs = bs }+ badsCs2 = lookupCMap (F.cm fi) <$> map fst bads2+ liftSMT $ smtComment "solve: pos-ple check"+ sendConcreteBindingsToSMT F.emptyIBindEnv bs $ \bindingsInSmt ->+ result bindingsInSmt cfg fi2 badsCs2 s3 _ -> return $ mytrace "all checked with interpreter" res1 + liftSMT $ smtComment "solve: finished" st <- stats- let res3 = {- SCC "sol-tidy" -} tidyResult res2+ let res3 = {- SCC "sol-tidy" -} tidyResult cfg res2 return $!! (res3, st) @@ -156,78 +173,103 @@ -- | tidyResult ensures we replace the temporary kVarArg names introduced to -- ensure uniqueness with the original names in the given WF constraints. ---------------------------------------------------------------------------------tidyResult :: F.Result a -> F.Result a-tidyResult r = r+tidyResult :: Config -> F.Result a -> F.Result a+tidyResult _ r = r { F.resSolution = tidySolution (F.resSolution r)- , F.resNonCutsSolution = tidySolution (F.resNonCutsSolution r)+ , F.resNonCutsSolution = M.map (fmap tidyPred) (F.resNonCutsSolution r)+ , F.resSorts = fmap tidyBind <$> F.resSorts r } tidySolution :: F.FixSolution -> F.FixSolution tidySolution = fmap tidyPred +tidyBind :: (F.Symbol, F.Sort) -> (F.Symbol, F.Sort)+tidyBind (x, t) = (F.tidySymbol x, t)+ tidyPred :: F.Expr -> F.Expr-tidyPred = F.substf (F.eVar . F.tidySymbol)+tidyPred = go+ where+ ts = F.tidySymbol+ tb = tidyBind+ go (F.EApp s e) = F.EApp (go s) (go e)+ go (F.ELam (x,t) e) = F.ELam (ts x, t) (go e)+ go (F.ECoerc a t e) = F.ECoerc a t (go e)+ go (F.ENeg e) = F.ENeg (go e)+ go (F.EBin op e1 e2) = F.EBin op (go e1) (go e2)+ go (F.ELet x e1 e2) = F.ELet (ts x) (go e1) (go e2)+ go (F.EIte p e1 e2) = F.EIte (go p) (go e1) (go e2)+ go (F.ECst e so) = F.ECst (go e) so+ go (F.EVar x) = F.EVar (ts x)+ go (F.PAnd ps) = F.PAnd $ map go ps+ go (F.POr ps) = F.POr $ map go ps+ go (F.PNot p) = F.PNot $ go p+ go (F.PImp p1 p2) = F.PImp (go p1) (go p2)+ go (F.PIff p1 p2) = F.PIff (go p1) (go p2)+ go (F.PAtom r e1 e2) = F.PAtom r (go e1) (go e2)+ go (F.PExist xts e) = F.PExist (tb <$> xts) (go e)+ go (F.PAll xts e) = F.PAll (tb <$> xts) (go e)+ go p = p -------------------------------------------------------------------------------- {-# SCC refine #-}+-- | Implementation of the inference algorithm from:+--+-- "Liquid Types", PLDI 2008, https://ranjitjhala.github.io/static/liquid_types.pdf+-- refine- :: (F.Loc a)+ :: forall a. F.Loc a => F.IBindEnv+ -> F.BindEnv a -> Sol.Solution -> W.Worklist a -> SolveM a Sol.Solution ---------------------------------------------------------------------------------refine bindingsInSmt s w- | Just (c, w', newScc, rnk) <- W.pop w = do- i <- tickIter newScc- (b, s') <- refineC bindingsInSmt i s c- lift $ writeLoud $ refineMsg i c b rnk (showpp s')- let w'' = if b then W.push c w' else w'- refine bindingsInSmt s' w''- | otherwise = return s+refine bindingsInSmt be0 s0 w0 = go be0 s0 w0 where- -- DEBUG- refineMsg i c b rnk s = printf "\niter=%d id=%d change=%s rank=%d s=%s\n"- i (F.subcId c) (show b) rnk s+ go :: F.BindEnv a -> Sol.Solution -> W.Worklist a -> SolveM a Sol.Solution+ go be s w+ | Just (c, w', newScc, rnk) <- W.pop w = do+ i <- tickIter newScc+ (b, s') <- refineC bindingsInSmt be i s c+ lift $ writeLoud $ refineMsg i c b rnk (showpp s')+ let w'' = if b then W.push c w' else w'+ go be s' w''+ | otherwise = return s+ where+ -- DEBUG+ refineMsg i c b rnk s = printf "\niter=%d id=%d change=%s rank=%d s=%s\n"+ i (F.subcId c) (show b) rnk s --------------------------------------------------------------------------- -- | Single Step Refinement ----------------------------------------------- --------------------------------------------------------------------------- {-# SCC refineC #-} refineC- :: (F.Loc a)+ :: forall a. (F.Loc a) => F.IBindEnv+ -> F.BindEnv a -> Int -> Sol.Solution -> F.SimpC a -> SolveM a (Bool, Sol.Solution) ----------------------------------------------------------------------------refineC bindingsInSmt _i s c =- do ef <- T.ctxElabF <$> getContext- let (ks, rhs) = runReader (rhsCands s c) ef- if null rhs+refineC bindingsInSmt be _i s c =+ do let krhs = rhsCands s+ cfg <- T.config <$> getContext+ if all (null . snd) krhs then return (False, s)- else do be <- getBinds- let lhs = runReader (S.lhsPred bindingsInSmt (F.coerceBindEnv ef be) s c) ef- kqs <- filterValid (cstrSpan c) lhs rhs- return $ S.update s ks kqs- where- _ci = F.subcId c- -- msg = printf "refineC: iter = %d, sid = %s, soln = \n%s\n"- -- _i (show (F.sid c)) (showpp s)- _msg ks xs ys = printf "refineC: iter = %d, sid = %s, s = %s, rhs = %d, rhs' = %d \n"- _i (show _ci) (showpp ks) (length xs) (length ys)--rhsCands :: Sol.Solution -> F.SimpC a -> ElabM ([F.KVar], Sol.Cand (F.KVar, Sol.EQual))-rhsCands s c =- do pq <- traverse cnd ks- pure (fst <$> ks, concat pq)+ else do+ let lhs = S.lhsPred cfg bindingsInSmt be s c+ kqs <- forM krhs $ \(k, rhs) ->+ (,) k . Sol.QB <$> filterValid (cstrSpan c) lhs rhs+ return $ S.update s kqs where- cnd :: (F.KVar, F.Subst) -> ElabM [(F.Pred, (F.KVar, Sol.EQual))]- cnd (k, su) = map (\(p , q) -> (p , (k , q))) <$> Sol.qbPreds msg s su (Sol.lookupQBind s k)- ks = predKs . F.crhs $ c-- msg = "rhsCands: " ++ show (F.sid c)+ rhsCands :: Sol.Solution -> [(F.KVar, Sol.Cand Sol.EQual)]+ rhsCands s = M.toList $ M.fromList $ map cnd ks+ where+ ks = predKs . F.crhs $ c+ cnd :: (F.KVar, F.Subst) -> (F.KVar , Sol.Cand Sol.EQual)+ cnd (k, su) = (k, Sol.qbPreds su (Sol.lookupQBind s k)) predKs :: F.Expr -> [(F.KVar, F.Subst)] predKs (F.PAnd ps) = concatMap predKs ps@@ -242,42 +284,59 @@ :: (F.Fixpoint a, F.Loc a, NFData a) => F.IBindEnv -> Config- -> W.Worklist a+ -> F.SInfo a+ -> [F.SimpC a] -> Sol.Solution -> SolveM a (F.Result (Integer, a)) ---------------------------------------------------------------------------------result bindingsInSmt cfg wkl s =- sendConcreteBindingsToSMT bindingsInSmt $ \bindingsInSmt2 -> do- lift $ writeLoud "Computing Result"- stat <- result_ bindingsInSmt2 cfg wkl s- lift $ whenLoud $ putStrLn $ "RESULT: " ++ show (F.sid <$> stat)-- F.Result (ci <$> stat) <$> solResult cfg s <*> solNonCutsResult s <*> return mempty+result bindingsInSmt cfg fi cs s =+ sendConcreteBindingsToSMT bindingsInSmt be $ \bindingsInSmt2 -> do+ lift $ writeLoud "Computing Result"+ stat <- result_ bindingsInSmt2 be cfg cs s+ lift $ whenLoud $ putStrLn $ "RESULT: " ++ show (F.sid <$> stat)+ resCut <- solResult cfg s+ let resNonCut = S.nonCutsResult cfg be s+ resSorts = resultSorts fi (M.keys resCut ++ M.keys resNonCut) be+ return $ F.Result (ci <$> stat) resCut resNonCut resSorts where ci c = (F.subcId c, F.sinfo c)+ be = F.bs fi +resultSorts :: F.SInfo a -> [F.KVar] -> F.BindEnv a -> F.ResultSorts+resultSorts fi ks be = M.fromList+ [(k, xts)+ | k <- ks+ , xts <- maybeToList (kvarScope fi be k) ]++kvarScope :: F.SInfo a -> F.BindEnv a -> F.KVar -> Maybe [(F.Symbol, F.Sort)]+kvarScope fi be k = do+ w <- M.lookup k (F.ws fi)+ let bs = F.wenv w+ let (v, t, _) = F.wrft w+ return $ (v, t) : [ bindInfo be i | i <- L.sort (F.elemsIBindEnv bs) ]++bindInfo :: F.BindEnv a -> F.BindId -> (F.Symbol, F.Sort)+bindInfo be i = (x, F.sr_sort sr)+ where+ (x, sr, _) = F.lookupBindEnv i be+ solResult :: Config -> Sol.Solution -> SolveM ann (M.HashMap F.KVar F.Expr) solResult cfg = minimizeResult cfg . Sol.result -solNonCutsResult :: Sol.Solution -> SolveM ann (M.HashMap F.KVar F.Expr)-solNonCutsResult s = do- be <- getBinds- ef <- T.ctxElabF <$> getContext- pure $ runReader (S.nonCutsResult be s) ef- result_ :: (F.Loc a, NFData a) => F.IBindEnv+ -> F.BindEnv a -> Config- -> W.Worklist a+ -> [F.SimpC a] -> Sol.Solution -> SolveM a (F.FixResult (F.SimpC a))-result_ bindingsInSmt cfg w s = do- filtered <- filterM (isUnsat bindingsInSmt s) cs+result_ bindingsInSmt be cfg cs0 s = do+ unsatisfiedConstraints <- filterM (isUnsat bindingsInSmt be s) cs sts <- stats- pure $ res sts filtered+ pure $ res sts unsatisfiedConstraints where- cs = isChecked cfg (W.unsatCandidates w)+ cs = isChecked cfg cs0 res sts [] = F.Safe sts res sts cs' = F.Unsafe sts cs' @@ -314,15 +373,14 @@ -------------------------------------------------------------------------------- isUnsat- :: (F.Loc a, NFData a) => F.IBindEnv -> Sol.Solution -> F.SimpC a -> SolveM a Bool+ :: (F.Loc a, NFData a) => F.IBindEnv -> F.BindEnv a -> Sol.Solution -> F.SimpC a -> SolveM a Bool ---------------------------------------------------------------------------------isUnsat bindingsInSmt s c = do+isUnsat bindingsInSmt be s c = do -- lift $ printf "isUnsat %s" (show (F.subcId c)) _ <- tickIter True -- newScc- be <- getBinds- ef <- T.ctxElabF <$> getContext- let lp = runReader (S.lhsPred bindingsInSmt (F.coerceBindEnv ef be) s c) ef- let rp = rhsPred c+ cfg <- T.config <$> getContext+ let lp = S.lhsPred cfg bindingsInSmt be s c+ rp = rhsPred c res <- not <$> isValid (cstrSpan c) lp rp lift $ whenLoud $ showUnsat res (F.subcId c) lp rp return res@@ -359,49 +417,3 @@ putBlankLn donePhase Loud msg -}----- NV TODO Move to a new file----------------------------------------------------------------------------------- | Interaction with the user when Solving ---------------------------------------------------------------------------------------------------------------------_iMergePartitions :: [(Int, F.SInfo a)] -> IO [(Int, F.SInfo a)]-_iMergePartitions ifis = do- putStrLn "Current Partitions are: "- putStrLn $ unlines (partitionInfo <$> ifis)- putStrLn "Merge Partitions? Y/N"- c <- getChar- if c == 'N'- then do putStrLn "Solving Partitions"- return ifis- else do- (i, j) <- getMergePartition (length ifis)- _iMergePartitions (mergePartitions i j ifis)--getMergePartition :: Int -> IO (Int, Int)-getMergePartition n = do- putStrLn "Which two partition to merge? (i, j)"- ic <- getLine- let (i,j) = read ic :: (Int, Int)- if i < 1 || n < i || j < 1 || n < j- then do putStrLn ("Invalid Partition numbers, write (i,j) with 1 <= i <= " ++ show n)- getMergePartition n- else return (i,j)--mergePartitions :: Int -> Int -> [(Int, F.SInfo a)] -> [(Int, F.SInfo a)]-mergePartitions i j fis- = zip [1..] ((takei i `mappend` (takei j){F.bs = mempty}):rest)- where- takei i = snd (fis L.!! (i - 1))- rest = snd <$> filter (\(k,_) -> k /= i && k /= j) fis--partitionInfo :: (Int, F.SInfo a) -> String-partitionInfo (i, fi)- = "Partition number " ++ show i ++ "\n" ++- "Defined ?? " ++ show defs ++ "\n" ++- "Used ?? " ++ show uses- where- gs = F.wloc . snd <$> L.filter (F.isGWfc . snd) (M.toList (F.ws fi))- defs = L.nub (F.gsrc <$> gs)- uses = L.nub (F.gused <$> gs)
src/Language/Fixpoint/Solver/UniqifyKVars.hs view
@@ -39,6 +39,7 @@ import Language.Fixpoint.Types import Language.Fixpoint.Types.Visitor (mapKVarSubsts) import qualified Data.HashMap.Strict as M+import qualified Data.List as L #if !MIN_VERSION_base(4,20,0) import Data.Foldable (foldl') #endif@@ -78,13 +79,11 @@ updateWfc :: SInfo a -> WfC a -> SInfo a updateWfc fi w = fi'' { ws = M.insert k w' (ws fi) } where- w' = updateWfCExpr (subst su) w''- w'' = w { wenv = insertsIBindEnv newIds mempty, wrft = (v', t, k) }+ w' = w { wenv = insertsIBindEnv newIds mempty, wrft = (v', t, k) } (_, fi'') = newTopBind v' (trueSortedReft t) a fi'- (fi', newIds) = foldl' (accumBindsIfValid k a) (fi, []) (elemsIBindEnv $ wenv w)+ (fi', newIds) = foldl' (accumBindsIfValid k a) (fi, []) (L.sort $ elemsIBindEnv $ wenv w) (v, t, k) = wrft w v' = kArgSymbol v (kv k)- su = mkSubst ((v, EVar v'):[(x, eVar $ kArgSymbol x (kv k)) | x <- kvarDomain fi k]) a = winfo w accumBindsIfValid :: KVar -> a -> (SInfo a, [BindId]) -> BindId -> (SInfo a, [BindId])@@ -118,5 +117,6 @@ isValidInRefinements (FVar _) = True isValidInRefinements (FFunc _ _) = True -- False isValidInRefinements (FAbs _ t) = isValidInRefinements t-isValidInRefinements (FTC _) = True --TODO is this true? seems to be required for e.g. ResolvePred.hs+isValidInRefinements (FTC _) = True -- TODO is this true? seems to be required for e.g. ResolvePred.hs isValidInRefinements (FApp _ _) = True+isValidInRefinements (FNatNum _) = True -- TODO probably?
src/Language/Fixpoint/Solver/Worklist.hs view
@@ -24,8 +24,8 @@ import Prelude hiding (init) import Language.Fixpoint.Types.PrettyPrint import qualified Language.Fixpoint.Types as F+import Language.Fixpoint.Types.Visitor (isConcC) import Language.Fixpoint.Graph.Types-import Language.Fixpoint.Graph (isTarget) import Control.Arrow (first) import qualified Data.HashMap.Strict as M@@ -87,7 +87,7 @@ -------------------------------------------------------------------------------- -- | Initialize worklist and slice out irrelevant constraints ------------------ ---------------------------------------------------------------------------------init :: SolverInfo a b -> Worklist a+init :: SolverInfo a -> Worklist a -------------------------------------------------------------------------------- init sI = WL { wCs = items , wPend = addPends M.empty kvarCs@@ -104,9 +104,11 @@ cd = siDeps sI rankm = cRank cd items = S.fromList $ workItemsAt rankm 0 <$> kvarCs- concCs = fst <$> ics+ concCs = fst <$> filter (isNonTriv . snd) ics kvarCs = fst <$> iks- (ics,iks) = L.partition (isTarget . snd) (M.toList cm)+ (ics,iks) = L.partition (isConcC . snd) (M.toList cm)++ isNonTriv = not . F.isTautoPred . F.crhs --------------------------------------------------------------------------- -- | Candidate Constraints to be checked AFTER computing Fixpoint ---------
src/Language/Fixpoint/SortCheck.hs view
@@ -8,6 +8,7 @@ {-# LANGUAGE PatternGuards #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE InstanceSigs #-} -- | This module has the functions that perform sort-checking, and related -- operations on Fixpoint expressions and predicates.@@ -17,6 +18,8 @@ TVSubst , Env , mkSearchEnv+ , globalEnv+ , theoryEnv -- * Checking Well-Formedness , checkSorted@@ -55,6 +58,7 @@ , elabNumeric , unApply , unElab+ , unElabFSetBagZ3 , unElabSortedReft , unApplySortedReft , unApplyAt@@ -72,13 +76,13 @@ import Control.Monad import Control.Monad.Reader -import Data.Bifunctor (first)+import Data.Bifunctor (first, second) import qualified Data.IntMap.Strict as M import qualified Data.HashSet as S import Data.IORef import qualified Data.List as L import Data.Maybe (mapMaybe, fromMaybe, isJust)-+import qualified Data.HashMap.Strict as HashMap import Language.Fixpoint.Types.PrettyPrint import Language.Fixpoint.Misc import Language.Fixpoint.Types hiding (subst, GInfo(..), senv)@@ -91,6 +95,7 @@ import GHC.Stack import qualified Language.Fixpoint.Types as F import System.IO.Unsafe (unsafePerformIO)+import Language.Fixpoint.Types.Config (ElabFlags(elabExplicitKvars)) --import Debug.Trace as Debug @@ -133,14 +138,17 @@ } class Elaborate a where- elaborate :: ElabParam -> a -> a+ elaborate :: HasCallStack => ElabParam -> a -> a instance (Loc a) => Elaborate (SInfo a) where elaborate ep si = si { F.cm = elaborate ep <$> F.cm si , F.bs = elaborate ep $ F.bs si+ , F.gLits = coerceSort (epFlags ep) <$> F.gLits si+ , F.dLits = coerceSort (epFlags ep) <$> F.dLits si , F.asserts = elaborate ep <$> F.asserts si+ , F.defns = elaborate ep $ F.defns si , F.ddecls = coerceDataDecl (epFlags ep) <$> F.ddecls si } @@ -152,7 +160,7 @@ elaborate ep t = elaborate ep <$> t instance Elaborate Sort where- elaborate _ = go+ elaborate ep = coerceSort (epFlags ep) . go where go s | isString s = strSort go (FAbs i s) = FAbs i (go s)@@ -173,19 +181,34 @@ where ep' = ep { epEnv = insertsSymEnv (epEnv ep) undefined } + instance Elaborate Equation where elaborate ep eq = eq { eqBody = skipElabExpr ep' (eqBody eq) } where ep' = ep { epEnv = insertsSymEnv (epEnv ep) (eqArgs eq) } ++instance Elaborate DefinedFuns where+ elaborate ep (MkDefinedFuns eqs) = MkDefinedFuns (elabDefinedEqn ep <$> eqs)++elabDefinedEqn :: ElabParam -> Equation -> Equation+elabDefinedEqn ep eq = eq { eqBody = elaborateExpr ep' (eqBody eq) (Just t')+ , eqArgs = [(x, tx t) | (x, t) <- eqArgs eq ]+ , eqSort = t'+ }+ where+ ep' = ep { epEnv = insertsSymEnv (epEnv ep) (eqArgs eq) }+ tx = coerceSort (epFlags ep)+ t' = tx (eqSort eq)+ instance Elaborate Expr where elaborate p e = elaborateExpr p e Nothing -elaborateExpr :: ElabParam -> Expr -> Maybe Sort -> Expr+elaborateExpr :: HasCallStack => 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+ elabNumeric . elabApply env' . elabExpr (ElabParam ef msg env') t . elabSorts ef . 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 Nothing e of@@ -213,7 +236,7 @@ = e instance Elaborate SortedReft where- elaborate ep (RR s (Reft (v, e))) = RR s (Reft (v, e'))+ elaborate ep (RR s (Reft (v, e))) = RR (coerceSort (epFlags ep) s) (Reft (v, e')) where e' = elaborateExpr ep' e (Just boolSort) -- check that a SortedReft is in fact a bool ep' = ep { epEnv = insertSymEnv v s (epEnv ep) }@@ -248,6 +271,7 @@ elabFMap (EApp e1 e2) = EApp (elabFMap e1) (elabFMap e2) elabFMap (ENeg e) = ENeg (elabFMap e) elabFMap (EBin b e1 e2) = EBin b (elabFMap e1) (elabFMap e2)+elabFMap (ELet x e1 e2) = ELet x (elabFMap e1) (elabFMap e2) elabFMap (EIte e1 e2 e3) = EIte (elabFMap e1) (elabFMap e2) (elabFMap e3) elabFMap (ECst e t) = ECst (elabFMap e) t elabFMap (ELam b e) = ELam b (elabFMap e)@@ -261,79 +285,184 @@ elabFMap (PAtom r e1 e2) = PAtom r (elabFMap e1) (elabFMap e2) elabFMap (PAll bs e) = PAll bs (elabFMap e) elabFMap (PExist bs e) = PExist bs (elabFMap e)-elabFMap (PGrad k su i e) = PGrad k su i (elabFMap e) elabFMap (ECoerc a t e) = ECoerc a t (elabFMap e)+elabFMap (PKVar k (Su m)) = PKVar k (Su (elabFMap <$> m)) elabFMap e = e + elabFSetBagZ3 :: Expr -> Expr-elabFSetBagZ3 (EApp h@(EVar f) e)- | f == Thy.setEmpty = EApp (EVar Thy.arrConstS) PFalse- | f == Thy.setEmp = PAtom Eq (EApp (EVar Thy.arrConstS) PFalse) (elabFSetBagZ3 e)- | f == Thy.setSng = EApp (EApp (EApp (EVar Thy.arrStoreS) (EApp (EVar Thy.arrConstS) PFalse)) (elabFSetBagZ3 e)) PTrue- | f == Thy.setCom = EApp (EVar Thy.arrMapNotS) (elabFSetBagZ3 e)- | f == Thy.bagEmpty = EApp (EVar Thy.arrConstB) (ECon (I 0))- | otherwise = EApp (elabFSetBagZ3 h) (elabFSetBagZ3 e)-elabFSetBagZ3 (EApp (EApp h@(EVar f) e1) e2)- | f == Thy.setMem = EApp (EApp (EVar Thy.arrSelectS) (elabFSetBagZ3 e2)) (elabFSetBagZ3 e1)- | f == Thy.setCup = EApp (EApp (EVar Thy.arrMapOrS) (elabFSetBagZ3 e1)) (elabFSetBagZ3 e2)- | f == Thy.setCap = EApp (EApp (EVar Thy.arrMapAndS) (elabFSetBagZ3 e1)) (elabFSetBagZ3 e2)- | f == Thy.setAdd = EApp (EApp (EApp (EVar Thy.arrStoreS) (elabFSetBagZ3 e2)) (elabFSetBagZ3 e1)) PTrue- -- A \ B == A /\ ~B == ~(A => B)- | f == Thy.setDif = EApp (EApp (EVar Thy.arrMapAndS) (elabFSetBagZ3 e1)) (EApp (EVar Thy.arrMapNotS) (elabFSetBagZ3 e2))- | f == Thy.setSub = PAtom Eq (EApp (EVar Thy.arrConstS) PTrue) (EApp (EApp (EVar Thy.arrMapImpS) (elabFSetBagZ3 e1)) (elabFSetBagZ3 e2))- | f == Thy.bagCount = EApp (EApp (EVar Thy.arrSelectB) (elabFSetBagZ3 e2)) (elabFSetBagZ3 e1)- | f == Thy.bagSng = EApp (EApp (EApp (EVar Thy.arrStoreB) (EApp (EVar Thy.arrConstB) (ECon (I 0)))) (elabFSetBagZ3 e1)) (elabFSetBagZ3 e2)- | f == Thy.bagCup = EApp (EApp (EVar Thy.arrMapPlusB) (elabFSetBagZ3 e1)) (elabFSetBagZ3 e2)- | f == Thy.bagSub = PAtom Eq (EApp (EVar Thy.arrConstS) PTrue) (EApp (EApp (EVar Thy.arrMapLeB) (elabFSetBagZ3 e1)) (elabFSetBagZ3 e2))- | f == Thy.bagMax = EApp (EApp (EApp (EVar Thy.arrMapIteB) (EApp (EApp (EVar Thy.arrMapGtB) (elabFSetBagZ3 e1)) (elabFSetBagZ3 e2))) (elabFSetBagZ3 e1)) (elabFSetBagZ3 e2)- | f == Thy.bagMin = EApp (EApp (EApp (EVar Thy.arrMapIteB) (EApp (EApp (EVar Thy.arrMapLeB) (elabFSetBagZ3 e1)) (elabFSetBagZ3 e2))) (elabFSetBagZ3 e1)) (elabFSetBagZ3 e2)- | otherwise = EApp (EApp (elabFSetBagZ3 h) (elabFSetBagZ3 e1)) (elabFSetBagZ3 e2)-elabFSetBagZ3 (EApp e1 e2) = EApp (elabFSetBagZ3 e1) (elabFSetBagZ3 e2)-elabFSetBagZ3 (ENeg e) = ENeg (elabFSetBagZ3 e)-elabFSetBagZ3 (EBin b e1 e2) = EBin b (elabFSetBagZ3 e1) (elabFSetBagZ3 e2)-elabFSetBagZ3 (EIte e1 e2 e3) = EIte (elabFSetBagZ3 e1) (elabFSetBagZ3 e2) (elabFSetBagZ3 e3)-elabFSetBagZ3 (ECst e t) = ECst (elabFSetBagZ3 e) t-elabFSetBagZ3 (ELam b e) = ELam b (elabFSetBagZ3 e)-elabFSetBagZ3 (ETApp e t) = ETApp (elabFSetBagZ3 e) t-elabFSetBagZ3 (ETAbs e t) = ETAbs (elabFSetBagZ3 e) t-elabFSetBagZ3 (PAnd es) = PAnd (elabFSetBagZ3 <$> es)-elabFSetBagZ3 (POr es) = POr (elabFSetBagZ3 <$> es)-elabFSetBagZ3 (PNot e) = PNot (elabFSetBagZ3 e)-elabFSetBagZ3 (PImp e1 e2) = PImp (elabFSetBagZ3 e1) (elabFSetBagZ3 e2)-elabFSetBagZ3 (PIff e1 e2) = PIff (elabFSetBagZ3 e1) (elabFSetBagZ3 e2)-elabFSetBagZ3 (PAtom r e1 e2) = PAtom r (elabFSetBagZ3 e1) (elabFSetBagZ3 e2)-elabFSetBagZ3 (PAll bs e) = PAll bs (elabFSetBagZ3 e)-elabFSetBagZ3 (PExist bs e) = PExist bs (elabFSetBagZ3 e)-elabFSetBagZ3 (PGrad k su i e) = PGrad k su i (elabFSetBagZ3 e)-elabFSetBagZ3 (ECoerc a t e) = ECoerc a t (elabFSetBagZ3 e)-elabFSetBagZ3 e = e+elabFSetBagZ3 = go+ where+ go (EApp h@(EVar f) e)+ | f == Thy.setEmpty = EApp (EVar Thy.arrConstS) PFalse+ | f == Thy.setEmp = PAtom Eq (EApp (EVar Thy.arrConstS) PFalse) (go e)+ | f == Thy.setSng = EApp (EApp (EApp (EVar Thy.arrStoreS) (EApp (EVar Thy.arrConstS) PFalse)) (go e)) PTrue+ | f == Thy.setCom = EApp (EVar Thy.arrMapNotS) (go e)+ | f == Thy.bagEmpty = EApp (EVar Thy.arrConstB) (ECon (I 0))+ | otherwise = EApp (go h) (go e)+ go (EApp (EApp h@(EVar f) e1) e2)+ | f == Thy.setMem = EApp (EApp (EVar Thy.arrSelectS) (go e2)) (go e1)+ | f == Thy.setCup = EApp (EApp (EVar Thy.arrMapOrS) (go e1)) (go e2)+ | f == Thy.setCap = EApp (EApp (EVar Thy.arrMapAndS) (go e1)) (go e2)+ | f == Thy.setAdd = EApp (EApp (EApp (EVar Thy.arrStoreS) (go e2)) (go e1)) PTrue+ -- A \ B == A /\ ~B == ~(A => B)+ | f == Thy.setDif = EApp (EApp (EVar Thy.arrMapAndS) (go e1)) (EApp (EVar Thy.arrMapNotS) (go e2))+ | f == Thy.setSub = PAtom Eq (EApp (EVar Thy.arrConstS) PTrue) (EApp (EApp (EVar Thy.arrMapImpS) (go e1)) (go e2))+ | f == Thy.bagCount = EApp (EApp (EVar Thy.arrSelectB) (go e2)) (go e1)+ | f == Thy.bagSng = EApp (EApp (EApp (EVar Thy.arrStoreB) (EApp (EVar Thy.arrConstB) (ECon (I 0)))) (go e1)) (go e2)+ | f == Thy.bagCup = EApp (EApp (EVar Thy.arrMapPlusB) (go e1)) (go e2)+ | f == Thy.bagSub = PAtom Eq (EApp (EVar Thy.arrConstS) PTrue) (EApp (EApp (EVar Thy.arrMapLeB) (go e1)) (go e2))+ | f == Thy.bagMax = EApp (EApp (EApp (EVar Thy.arrMapIteB) (EApp (EApp (EVar Thy.arrMapGtB) (go e1)) (go e2))) (go e1)) (go e2)+ | f == Thy.bagMin = EApp (EApp (EApp (EVar Thy.arrMapIteB) (EApp (EApp (EVar Thy.arrMapLeB) (go e1)) (go e2))) (go e1)) (go e2)+ | otherwise = EApp (EApp (go h) (go e1)) (go e2)+ go (EApp e1 e2) = EApp (go e1) (go e2)+ go (ENeg e) = ENeg (go e)+ go (EBin b e1 e2) = EBin b (go e1) (go e2)+ go (ELet x e1 e2) = ELet x (go e1) (go e2)+ go (EIte e1 e2 e3) = EIte (go e1) (go e2) (go e3)+ go (ECst e t) = ECst (go e) t+ go (ELam b e) = ELam b (go e)+ go (ETApp e t) = ETApp (go e) t+ go (ETAbs e t) = ETAbs (go e) t+ go (PAnd es) = PAnd (go <$> es)+ go (POr es) = POr (go <$> es)+ go (PNot e) = PNot (go e)+ go (PImp e1 e2) = PImp (go e1) (go e2)+ go (PIff e1 e2) = PIff (go e1) (go e2)+ go (PAtom r e1 e2) = PAtom r (go e1) (go e2)+ go (PAll bs e) = PAll bs (go e)+ go (PExist bs e) = PExist bs (go e)+ go (ECoerc a t e) = ECoerc a t (go e)+ go (PKVar k (Su m)) = PKVar k (Su (go <$> m))+ go e = e +-- | Reverse transformation of elabFSetBagZ3: converts array representations back to set/bag operations+unElabFSetBagZ3 :: Expr -> Expr+unElabFSetBagZ3 = go+ where+ -- arr_const_s false -> Set_empty+ go (EApp (EVar f) PFalse)+ | f == Thy.arrConstS = EVar Thy.setEmpty+ -- arr_const_s false == e -> Set_emp e+ go (PAtom Eq (EApp (EVar f) PFalse) e)+ | f == Thy.arrConstS = EApp (EVar Thy.setEmp) (go e)+ -- arr_store_s (arr_const_s false) e true -> Set_sng e+ go (EApp (EApp (EApp (EVar f1) (EApp (EVar f2) PFalse)) e) PTrue)+ | f1 == Thy.arrStoreS && f2 == Thy.arrConstS = EApp (EVar Thy.setSng) (go e)+ -- arr_map_not_s e -> Set_com e+ go (EApp (EVar f) e)+ | f == Thy.arrMapNotS = EApp (EVar Thy.setCom) (go e)+ -- arr_const_b 0 -> Bag_empty+ go (EApp (EVar f) (ECon (I 0)))+ | f == Thy.arrConstB = EVar Thy.bagEmpty+ -- arr_select_s e2 e1 -> Set_mem e1 e2+ go (EApp (EApp (EVar f) e2) e1)+ | f == Thy.arrSelectS = EApp (EApp (EVar Thy.setMem) (go e1)) (go e2)+ -- arr_map_or_s e1 e2 -> Set_cup e1 e2+ go (EApp (EApp (EVar f) e1) e2)+ | f == Thy.arrMapOrS = EApp (EApp (EVar Thy.setCup) (go e1)) (go e2)+ -- arr_map_and_s e1 e2 -> Set_cap e1 e2+ go (EApp (EApp (EVar f) e1) e2)+ | f == Thy.arrMapAndS = EApp (EApp (EVar Thy.setCap) (go e1)) (go e2)+ -- arr_store_s e2 e1 true -> Set_add e1 e2+ go (EApp (EApp (EApp (EVar f) e2) e1) PTrue)+ | f == Thy.arrStoreS = EApp (EApp (EVar Thy.setAdd) (go e1)) (go e2)+ -- arr_map_and_s e1 (arr_map_not_s e2) -> Set_dif e1 e2+ go (EApp (EApp (EVar f1) e1) (EApp (EVar f2) e2))+ | f1 == Thy.arrMapAndS && f2 == Thy.arrMapNotS = EApp (EApp (EVar Thy.setDif) (go e1)) (go e2)+ -- arr_const_s true == arr_map_imp_s e1 e2 -> Set_sub e1 e2+ go (PAtom Eq (EApp (EVar f1) PTrue) (EApp (EApp (EVar f2) e1) e2))+ | f1 == Thy.arrConstS && f2 == Thy.arrMapImpS = EApp (EApp (EVar Thy.setSub) (go e1)) (go e2)+ -- arr_select_b e2 e1 -> Bag_count e1 e2+ go (EApp (EApp (EVar f) e2) e1)+ | f == Thy.arrSelectB = EApp (EApp (EVar Thy.bagCount) (go e1)) (go e2)+ -- arr_store_b (arr_const_b 0) e1 e2 -> Bag_sng e1 e2+ go (EApp (EApp (EApp (EVar f1) (EApp (EVar f2) (ECon (I 0)))) e1) e2)+ | f1 == Thy.arrStoreB && f2 == Thy.arrConstB = EApp (EApp (EVar Thy.bagSng) (go e1)) (go e2)+ -- arr_map_plus_b e1 e2 -> Bag_cup e1 e2+ go (EApp (EApp (EVar f) e1) e2)+ | f == Thy.arrMapPlusB = EApp (EApp (EVar Thy.bagCup) (go e1)) (go e2)+ -- arr_const_s true == arr_map_le_b e1 e2 -> Bag_sub e1 e2+ go (PAtom Eq (EApp (EVar f1) PTrue) (EApp (EApp (EVar f2) e1) e2))+ | f1 == Thy.arrConstS && f2 == Thy.arrMapLeB = EApp (EApp (EVar Thy.bagSub) (go e1)) (go e2)+ -- arr_map_ite_b (arr_map_gt_b e1 e2) e1 e2 -> Bag_max e1 e2+ go (EApp (EApp (EApp (EVar f1) (EApp (EApp (EVar f2) e1a) e2a)) e1b) e2b)+ | f1 == Thy.arrMapIteB && f2 == Thy.arrMapGtB && e1a == e1b && e2a == e2b+ = EApp (EApp (EVar Thy.bagMax) (go e1a)) (go e2a)+ -- arr_map_ite_b (arr_map_le_b e1 e2) e1 e2 -> Bag_min e1 e2+ go (EApp (EApp (EApp (EVar f1) (EApp (EApp (EVar f2) e1a) e2a)) e1b) e2b)+ | f1 == Thy.arrMapIteB && f2 == Thy.arrMapLeB && e1a == e1b && e2a == e2b+ = EApp (EApp (EVar Thy.bagMin) (go e1a)) (go e2a)+ -- Recursive cases+ go (EApp e1 e2) = EApp (go e1) (go e2)+ go (ENeg e) = ENeg (go e)+ go (EBin b e1 e2) = EBin b (go e1) (go e2)+ go (ELet x e1 e2) = ELet x (go e1) (go e2)+ go (EIte e1 e2 e3) = EIte (go e1) (go e2) (go e3)+ go (ECst e t) = ECst (go e) t+ go (ELam b e) = ELam b (go e)+ go (ETApp e t) = ETApp (go e) t+ go (ETAbs e t) = ETAbs (go e) t+ go (PAnd es) = PAnd (go <$> es)+ go (POr es) = POr (go <$> es)+ go (PNot e) = PNot (go e)+ go (PImp e1 e2) = PImp (go e1) (go e2)+ go (PIff e1 e2) = PIff (go e1) (go e2)+ go (PAtom r e1 e2) = PAtom r (go e1) (go e2)+ go (PAll bs e) = PAll bs (go e)+ go (PExist bs e) = PExist bs (go e)+ go (ECoerc a t e) = ECoerc a t (go e)+ go (PKVar k (Su m)) = PKVar k (Su (go <$> m))+ go e = e+++elabSorts :: Cfg.ElabFlags -> Expr -> Expr+elabSorts ef (EApp e1 e2) = EApp (elabSorts ef e1) (elabSorts ef e2)+elabSorts ef (ENeg e) = ENeg (elabSorts ef e)+elabSorts ef (EBin b e1 e2) = EBin b (elabSorts ef e1) (elabSorts ef e2)+elabSorts ef (ELet x e1 e2) = ELet x (elabSorts ef e1) (elabSorts ef e2)+elabSorts ef (EIte e1 e2 e3) = EIte (elabSorts ef e1) (elabSorts ef e2) (elabSorts ef e3)+elabSorts ef (ECst e s) = ECst (elabSorts ef e) (coerceSort ef s)+elabSorts ef (ELam b e) = ELam b (elabSorts ef e)+elabSorts ef (ETApp e s) = ETApp (elabSorts ef e) (coerceSort ef s)+elabSorts ef (ETAbs e t) = ETAbs (elabSorts ef e) t+elabSorts ef (PAnd es) = PAnd (elabSorts ef <$> es)+elabSorts ef (POr es) = POr (elabSorts ef <$> es)+elabSorts ef (PNot e) = PNot (elabSorts ef e)+elabSorts ef (PImp e1 e2) = PImp (elabSorts ef e1) (elabSorts ef e2)+elabSorts ef (PIff e1 e2) = PIff (elabSorts ef e1) (elabSorts ef e2)+elabSorts ef (PAtom r e1 e2) = PAtom r (elabSorts ef e1) (elabSorts ef e2)+elabSorts ef (PAll bs e) = PAll bs (elabSorts ef e)+elabSorts ef (PExist bs e) = PExist bs (elabSorts ef e)+elabSorts ef (ECoerc s1 s2 e) = ECoerc (coerceSort ef s1) (coerceSort ef s2) (elabSorts ef e)+elabSorts ef (PKVar k (Su m)) = PKVar k (Su (elabSorts ef <$> m))+elabSorts _ e = e+ -------------------------------------------------------------------------------- -- | 'elabExpr' adds "casts" to decorate polymorphic instantiation sites. ---------------------------------------------------------------------------------elabExpr :: ElabParam -> Maybe Sort -> Expr -> Expr+elabExpr :: HasCallStack => 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' -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 ()+validateSort :: Env -> Sort -> Maybe Sort -> CheckM ()+-- validateSort f t (Just t') = void (unifys f (tracepp ("validateSort" ++ show (t, t')) Nothing) [t] [t'])+validateSort f t (Just t') = void (unifys f Nothing [t] [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', eSort) <- elab (env, envLookup) e- validateSort eSort t+ validateSort envLookup 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'))- Right s -> Right s+ Right elab_e -> Right elab_e where sEnv = seSort env envLookup = (`lookupSEnvWithDistance` sEnv)@@ -359,6 +488,7 @@ step (POr []) = PFalse step (ENeg e) = ENeg (go e) step (EBin o e1 e2) = EBin o (go e1) (go e2)+ step (ELet x e1 e2) = ELet x (go e1) (go e2) step (EIte e1 e2 e3) = EIte (go e1) (go e2) (go e3) step (ECst e t) = ECst (go e) t step (PAnd ps) = PAnd (go <$> ps)@@ -372,8 +502,7 @@ step e@EApp {} = go e step (ELam b e) = ELam b (go e) step (ECoerc a t e) = ECoerc a t (go e)- step (PGrad k su i e) = PGrad k su i (go e)- step e@PKVar{} = e+ step (PKVar k (Su m)) = PKVar k (Su (go <$> m)) step e@ESym{} = e step e@ECon{} = e step e@EVar{} = e@@ -465,7 +594,7 @@ runCM0 :: SrcSpan -> Maybe Cfg.ElabFlags -> CheckM a -> Either ChError a runCM0 sp mef act = unsafePerformIO $ do ref <- newIORef Nothing- try (runReaderT act (ChS varCounterRef sp (fromMaybe (Cfg.ElabFlags False) mef) ref))+ try (runReaderT act (ChS varCounterRef sp (fromMaybe (Cfg.ElabFlags False False) mef) ref)) fresh :: CheckM Int fresh = do@@ -568,6 +697,7 @@ checkExpr f (EVar x) = checkSym f x checkExpr f (ENeg e) = checkNeg f e checkExpr f (EBin o e1 e2) = checkOp f e1 o e2+checkExpr f (ELet x e1 e2) = checkLet f x e1 e2 checkExpr f (EIte p e1 e2) = checkIte f p e1 e2 checkExpr f (ECst e t) = checkCst f t e checkExpr f (EApp g e) = checkApp f Nothing g e@@ -578,7 +708,6 @@ checkExpr f (POr ps) = mapM_ (checkPred f) ps >> return boolSort checkExpr f (PAtom r e e') = checkRel f r e e' >> return boolSort checkExpr _ PKVar{} = return boolSort-checkExpr f (PGrad _ _ _ e) = checkPred f e >> return boolSort checkExpr f (PAll bs e ) = checkExpr (addEnv f bs) e checkExpr f (PExist bs e) = checkExpr (addEnv f bs) e@@ -606,6 +735,10 @@ let !result = EBin o (eCst e1' s1) (eCst e2' s2) return (result, s) +elab !f (ECst (EApp !e1 !e2) t) = do+ ee <- elabAppAs f t e1 e2+ return (eCst ee t, t)+ elab !f (EApp !e1 !e2) = do (!e1', !s1, !e2', !s2, !s) <- elabEApp f e1 e2 let !e = eAppC s (eCst e1' s1) (eCst e2' s2)@@ -623,12 +756,19 @@ elab !_ e@(ECon (L _ !s)) = return (e, s) -elab !_ e@(PKVar _ _) =- return (e, boolSort)--elab !f (PGrad !k !su !i !e) = do- (!e', !_) <- elab f e- return (PGrad k su i e', boolSort)+-- TODO: the guard below is because some LH tests generate PKVar with ill-sorted substitutions.+-- However, a cleaner solution could be to modify `Sanitize.restrictKVarDomain` to simply+-- those ill-sorted substitutions right up at the outset.+elab !f e@(PKVar k (Su m)) = do+ expKvars <- asks (elabExplicitKvars . chElabF)+ if expKvars+ then do+ xargs' <- forM (HashMap.toList m) $ \(x, arg) -> do+ (arg', _) <- elab f arg+ return (x, arg')+ return (PKVar k (Su (HashMap.fromList xargs')), boolSort)+ else+ return (e, boolSort) elab (!_, !f) e@(EVar !x) = do !cs <- checkSym f x@@ -653,6 +793,11 @@ !s <- checkIteTy g p e1' e2' s1 s2 return (EIte p' (eCst e1' s) (eCst e2' s), s) +elab f (ELet !x !e1 !e2) = do+ (!e1', !t1) <- elab f e1+ (!e2', !t2) <- elab (elabAddEnv f [(x, t1)]) e2+ return (ELet x e1' e2', t2)+ elab !f (ECst !e !t) = do (!e', !_) <- elab f e return (eCst e' t, t)@@ -729,11 +874,11 @@ -- | 'eCstAtom' is to support tests like `tests/pos/undef00.fq` eCstAtom :: ElabEnv -> Expr -> Sort -> CheckM Expr-eCstAtom f@(sym,g) (EVar x) t+eCstAtom f@(sym,g) (ECst (EVar x) _) t | Found s <- g x , isUndef s- , not (isNum sym t) = (`ECst` t) <$> elabAs f t (EApp (eVar tyCastName) (eVar x))-eCstAtom _ e t = return (ECst e t)+ , not (isNum sym t) = (`eCst` t) <$> elabAppAs f t (eVar tyCastName) (eVar x)+eCstAtom _ e t = return (eCst e t) isUndef :: Sort -> Bool isUndef s = case bkAbs s of@@ -747,8 +892,8 @@ elabAs f t e = notracepp _msg <$> go e where _msg = "elabAs: t = " ++ showpp t ++ "; e = " ++ showpp e- go (EApp e1 e2) = elabAppAs f t e1 e2- go e' = fst <$> elab f e'+ go (EApp e1 e2) = elabAppAs f t e1 e2+ go e' = fst <$> elab f (eCst e' t) -- DUPLICATION with `checkApp'` elabAppAs :: ElabEnv -> Sort -> Expr -> Expr -> CheckM Expr@@ -762,7 +907,7 @@ g' <- elabAs env tg g let te = apply su eT e' <- elabAs env te e- pure $ EApp (ECst g' tg) (ECst e' te)+ pure $ EApp (eCst g' tg) (eCst e' te) elabEApp :: ElabEnv -> Expr -> Expr -> CheckM (Expr, Sort, Expr, Sort, Sort) elabEApp f@(_, g) e1 e2 = do@@ -845,6 +990,7 @@ go (ECst (EApp (EApp f e1) e2) _) | Just _ <- unApplyAt f = EApp e1 e2 go (ELam (x,s) e) = ELam (x, Vis.mapSort go' s) e+ go (PExist bs e) = PExist (map (second (Vis.mapSort go')) bs) e go e = e go' (FApp (FApp fs t1) t2) | fs == funcSort@@ -1048,6 +1194,12 @@ negSort (FApp s1 s2) = negSort s1 `S.union` negSort s2 negSort _ = S.empty +-- | Helper for checking let expressions+checkLet :: Env -> Symbol -> Expr -> Expr -> CheckM Sort+checkLet f x e1 e2 = do+ t <- checkExpr f e1+ checkExpr (addEnv f [(x, t)]) e2+ -- | Helper for checking if-then-else expressions checkIte :: Env -> Expr -> Expr -> Expr -> CheckM Sort checkIte f p e1 e2 = do@@ -1212,6 +1364,19 @@ checkRelTy f e Ne t1 t2 = void (unifys f (Just e) [t1] [t2] `withError` errRel e t1 t2) checkRelTy _ e _ t1 t2 = unless (t1 == t2) (throwErrorAt $ errRel e t1 t2) +-- | @a ~~ b@ is translated to @(= a b)@ when producing SMTLIB.+-- But this is only valid if @a@ and @b@ have the same sort in SMTLIB.+-- It turns out that most types are represented with sort Int, so comparing+-- values of different types is not rejected in general by SMT solvers.+--+-- There are at least two exceptions though. The first of them is the type+-- Bool, which is represented with the sort Bool. Therefore, @a ~~ b@ is fine+-- if both arguments have Bool sort, or if neither of them has.+--+-- The other exception is functions, which have a function sort in SMTLIB.+-- But at the moment no @~~@ equalities are produced with function sorts, so+-- that case isn't considered in this function.+-- checkURel :: Expr -> Sort -> Sort -> CheckM () checkURel e s1 s2 = unless (b1 == b2) (throwErrorAt $ errRel e s1 s2) where@@ -1544,3 +1709,14 @@ errBoolSort :: Expr -> Sort -> String errBoolSort e s = printf "Expressions %s should have bool sort, but has %s" (showpp e) (showpp s)++globalEnv :: Cfg.Config -> F.GInfo c a -> SEnv Sort+globalEnv cfg finfo = F.gLits finfo <> dataEnv+ where+ dataEnv = F.tsSort <$> theoryEnv cfg finfo++theoryEnv :: Cfg.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)
src/Language/Fixpoint/Types.hs view
@@ -5,6 +5,7 @@ module Language.Fixpoint.Types (module X) where +import Language.Fixpoint.Types.SMTPrint as X import Language.Fixpoint.Types.PrettyPrint as X import Language.Fixpoint.Types.Names as X import Language.Fixpoint.Types.Errors as X
src/Language/Fixpoint/Types/Config.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE TemplateHaskell #-} module Language.Fixpoint.Types.Config ( Config (..)@@ -13,7 +14,7 @@ -- * SMT Solver options , SMTSolver (..)- , solverFlags+ , solverFlags, mkElabFlags , ElabFlags (..) -- REST Options@@ -45,7 +46,9 @@ import qualified Language.Fixpoint.Conditional.Z3 as Conditional.Z3 import Language.Fixpoint.Utils.Files-+import Development.GitRev (gitHash)+import Data.Version (showVersion)+import Paths_liquid_fixpoint (version) -------------------------------------------------------------------------------- withPragmas :: Config -> [String] -> IO Config@@ -75,7 +78,6 @@ , maxPartSize :: Int -- ^ Maximum size of a partition. Overrides minPartSize , solver :: SMTSolver -- ^ which SMT solver to use , linear :: Bool -- ^ not interpret div and mul in SMT- , stringTheory :: Bool -- ^ interpretation of string theory by SMT , defunction :: Bool -- ^ defunctionalize (use 'apply' for all uninterpreted applications) , allowHO :: Bool -- ^ allow higher order binders in the logic environment , allowHOqs :: Bool -- ^ allow higher order qualifiers@@ -94,30 +96,27 @@ , minimizeKs :: Bool -- ^ min .fq by delta debug (sat with min kvars) , minimalSol :: Bool -- ^ shrink final solution by pruning redundant qualfiers from fixpoint , etaElim :: Bool -- ^ eta eliminate function definitions- , gradual :: Bool -- ^ solve "gradual" constraints- , ginteractive :: Bool -- ^ interactive gradual solving , autoKuts :: Bool -- ^ ignore given kut variables , nonLinCuts :: Bool -- ^ Treat non-linear vars as cuts , noslice :: Bool -- ^ Disable non-concrete KVar slicing , rewriteAxioms :: Bool -- ^ Allow axiom instantiation via rewriting- , pleWithUndecidedGuards :: Bool -- ^ Unfold invocations with undecided guards in PLE+ , pleUndecGuards :: Bool -- ^ Unfold invocations with undecided guards in PLE , etabeta :: Bool -- ^ Eta expand and beta reduce terms to aid PLE , localRewrites :: Bool -- ^ Eta expand and beta reduce terms to aid PLE , interpreter :: Bool -- ^ Do not use the interpreter to assist PLE- , oldPLE :: Bool -- ^ Use old version of PLE- , noIncrPle :: Bool -- ^ Use incremental PLE- , noEnvironmentReduction :: Bool -- ^ Don't use environment reduction- , inlineANFBindings :: Bool -- ^ Inline ANF bindings.+ , noEnvReduction :: Bool -- ^ Don't use environment reduction+ , inlineANFBinds :: Bool -- ^ Inline ANF bindings. -- Sometimes improves performance and sometimes worsens it. , checkCstr :: [Integer] -- ^ Only check these specific constraints , extensionality :: Bool -- ^ Enable extensional interpretation of function equality- , rwTerminationCheck :: Bool -- ^ Enable termination checking for rewriting+ , rwTermination :: Bool -- ^ Enable termination checking for rewriting , stdin :: Bool -- ^ Read input query from stdin , json :: Bool -- ^ Render output in JSON format- , noLazyPLE :: Bool , fuel :: Maybe Int -- ^ Maximum PLE "fuel" (unfold depth) (default=infinite) , restOrdering :: String -- ^ Term ordering for use in REST , noSmtHorn :: Bool -- ^ Do not use (new) SMTLIB horn parser+ , noStringTheory :: Bool -- ^ disable interpretation of string theory by SMT+ , explicitKvars :: Bool -- ^ use explicitly declared kvars (horn style) which disables several "defensive simplifications" } deriving (Eq,Data,Typeable,Show,Generic) instance Default Config where@@ -151,13 +150,18 @@ data SMTSolver = Z3 | Z3mem | Cvc4 | Cvc5 | Mathsat deriving (Eq, Data, Typeable, Generic) -newtype ElabFlags = ElabFlags { elabSetBag :: Bool }+data ElabFlags = ElabFlags { elabSetBag :: Bool, elabExplicitKvars :: Bool } -solverFlags :: SMTSolver -> ElabFlags-solverFlags Z3 = ElabFlags True-solverFlags Z3mem = ElabFlags True-solverFlags _ = ElabFlags False+mkElabFlags :: SMTSolver -> Bool -> ElabFlags+mkElabFlags slv expKvars = ElabFlags (setBag slv) expKvars+ where+ setBag Z3 = True+ setBag Z3mem = True+ setBag _ = False +solverFlags :: Config -> ElabFlags+solverFlags cfg = mkElabFlags (solver cfg) (explicitKvars cfg)+ instance Default SMTSolver where def = if Conditional.Z3.builtWithZ3AsALibrary then Z3mem else Z3 @@ -172,9 +176,9 @@ --------------------------------------------------------------------------------------- -- | `Scrape` describes which (Horn) constraints to scrape qualifiers from--- None = do not scrape, only use the supplied qualifiers+-- No = do not scrape, only use the supplied qualifiers -- Head = scrape only from the constraint heads (i.e. "rhs")--- All = scrape all concrete predicates (i.e. "rhs" + "lhs")+-- Both = scrape all concrete predicates (i.e. "rhs" + "lhs") data Scrape = No | Head | Both deriving (Eq, Data, Typeable, Generic)@@ -234,7 +238,7 @@ , defunction = False &= help "Allow higher order binders into fixpoint environment" , solver = def &= help "Name of SMT Solver" , linear = False &= help "Use uninterpreted integer multiplication and division"- , stringTheory = False &= help "Interpretation of String Theory by SMT"+ , noStringTheory = False &= help "Disable use of string theory by SMT" , allowHO = False &= help "Allow higher order binders into fixpoint environment" , allowHOqs = False &= help "Allow higher order qualifiers" , eliminate = None &= help "Eliminate KVars [none = quals for all-kvars, cuts = quals for cut-kvars, all = eliminate all-kvars (TRUE for cuts)]"@@ -255,13 +259,11 @@ , minimizeQs = False &= help "Delta debug to minimize fq file (sat with min qualifiers)" , minimizeKs = False &= help "Delta debug to minimize fq file (sat with max kvars replaced by True)" , minimalSol = False &= help "Shrink fixpoint by removing implied qualifiers"- , gradual = False &= help "Solve gradual-refinement typing constraints"- , ginteractive = False &= help "Interactive Gradual Solving" , autoKuts = False &= help "Ignore given Kut vars, compute from scratch" , nonLinCuts = False &= help "Treat non-linear kvars as cuts" , noslice = False &= help "Disable non-concrete KVar slicing" , rewriteAxioms = False &= name "ple" &= help "Allow axiom instantiation via rewriting (PLE)"- , pleWithUndecidedGuards =+ , pleUndecGuards = False &= name "ple-with-undecided-guards" &= help "Unfold invocations with undecided guards in PLE"@@ -270,44 +272,36 @@ False &= name "interpreter" &= help "Use the interpreter to assist PLE"- , oldPLE = False &= help "Use old version of PLE" , etabeta = False &= help "Use eta expansion and beta reduction to aid PLE"- , localRewrites = False &= name "local-rewrites" &= help "Perform local rewrites inside PLE"- , noIncrPle = False &= help "Don't use incremental PLE"- , noEnvironmentReduction =- False- &= name "no-environment-reduction"- &= help "Don't perform environment reduction"- , inlineANFBindings =- False- &= name "inline-anf-bindings"- &= help (unwords+ , localRewrites = False &= help "Perform local rewrites inside PLE"+ , noEnvReduction = False &= help "Don't perform environment reduction"+ , inlineANFBinds = False &= help (unwords [ "Inline ANF bindings." , "Sometimes improves performance and sometimes worsens it."- , "Disabled by --no-environment-reduction"+ , "Disabled by --noenvreduction" ]) , checkCstr = [] &= help "Only check these specific constraint-ids" , extensionality = False &= help "Allow extensional interpretation of extensionality"- , rwTerminationCheck = False &= help "Enable rewrite divergence checker"+ , rwTermination = False &= help "Enable rewrite divergence checker" , stdin = False &= help "Read input query from stdin" , json = False &= help "Render result in JSON"- , noLazyPLE = False &= help "Don't use lazy PLE" , fuel = Nothing &= help "Maximum fuel (per-function unfoldings) for PLE"- , restOrdering = "rpo"- &= name "rest-ordering"- &= help "Ordering Constraint Algebra to use for REST"+ , restOrdering = "rpo" &= help "Ordering Constraint Algebra to use for REST" , noSmtHorn = False &= help "Do not use SMTLIB horn format"+ , explicitKvars = False &= help "Use explicitly declared kvars (horn style) which disables several defensive simplifications" } &= verbosity &= program "fixpoint" &= help "Predicate Abstraction Based Horn-Clause Solver"- &= summary "fixpoint Copyright 2009-15 Regents of the University of California."+ &= summary summaryInfo &= details [ "Predicate Abstraction Based Horn-Clause Solver" , "" , "To check a file foo.fq type:" , " fixpoint foo.fq" ] +summaryInfo :: String+summaryInfo = "fixpoint " ++ showVersion version ++ " " ++ "(" ++ $(gitHash) ++ ")" config :: Mode (CmdArgs Config) config = cmdArgsMode defConfig @@ -318,7 +312,7 @@ return md banner :: String-banner = "\n\nLiquid-Fixpoint Copyright 2013-21 Regents of the University of California.\n"+banner = "\n\nLiquid-Fixpoint Copyright 2009-25 Regents of the University of California.\n" ++ "All Rights Reserved.\n" restOC :: Config -> RESTOrdering
src/Language/Fixpoint/Types/Constraints.hs view
@@ -13,6 +13,7 @@ {-# LANGUAGE PatternGuards #-} {-# OPTIONS_GHC -Wno-name-shadowing #-}+{-# LANGUAGE RecordWildCards #-} -- | This module contains the top-level QUERY data types and elements, -- including (Horn) implication & well-formedness constraints and sets.@@ -22,18 +23,18 @@ FInfo, SInfo, GInfo (..), FInfoWithOpts(..) , convertFormat , sinfoToFInfo- , Solver -- * Serializing , toFixpoint , writeFInfo , saveQuery+ , saveSInfo -- * Constructing Queries , fi -- * Constraints- , WfC (..), isGWfc, updateWfCExpr+ , WfC (..) , SubC, SubcId , mkSubC, subcId, sid, senv, updateSEnv, slhs, srhs, stag, subC, wfC , SimpC (..)@@ -47,7 +48,6 @@ , addIds , sinfo , shiftVV- , gwInfo, GWInfo (..) -- * Qualifiers , Qualifier@@ -63,8 +63,9 @@ -- * Results , FixSolution- , GFixSolution, toGFixSol- , Result (..)+ , FixDelayedSolution+ , Delayed (..)+ , Result (..), ResultSorts , unsafe, isUnsafe, isSafe ,safe -- * Cut KVars@@ -80,6 +81,7 @@ -- * Axioms , AxiomEnv (..) , Equation+ , DefinedFuns (..) , EquationV (..) , mkEquation , Rewrite (..)@@ -90,11 +92,13 @@ , lookupRewrite , lookupLocalRewrites , insertRewrites+ , eqnToHornSMT -- * Misc [should be elsewhere but here due to dependencies] , substVars , sortVars , gSorts+ ) where import qualified Data.Store as S@@ -109,6 +113,7 @@ import Control.DeepSeq import Control.Monad (when, void) import Language.Fixpoint.Types.PrettyPrint+import Language.Fixpoint.Types.SMTPrint import qualified Language.Fixpoint.Types.Config as C import Language.Fixpoint.Types.Triggers import Language.Fixpoint.Types.Names@@ -142,38 +147,8 @@ , wrft :: (Symbol, Sort, KVar) , winfo :: !a }- | GWfC { wenv :: !IBindEnv- , wrft :: !(Symbol, Sort, KVar)- , winfo :: !a- , wexpr :: !Expr- , wloc :: !GradInfo- } deriving (Eq, Generic, Functor) -data GWInfo = GWInfo { gsym :: Symbol- , gsort :: Sort- , gexpr :: Expr- , ginfo :: GradInfo- }- deriving (Eq, Generic)--gwInfo :: WfC a -> GWInfo-gwInfo (GWfC _ (x,s,_) _ e i)- = GWInfo x s e i-gwInfo _- = errorstar "gwInfo"--updateWfCExpr :: (Expr -> Expr) -> WfC a -> WfC a-updateWfCExpr _ w@WfC{} = w-updateWfCExpr f w@GWfC{} = w{wexpr = f (wexpr w)}--isGWfc :: WfC a -> Bool-isGWfc GWfC{} = True-isGWfc WfC{} = False--instance HasGradual (WfC a) where- isGradual = isGWfc- type SubcId = Integer data SubC a = SubC@@ -199,7 +174,7 @@ instance Loc a => Loc (SimpC a) where srcSpan = srcSpan . _cinfo -strengthenHyp :: SInfo a -> [(Integer, Expr)] -> SInfo a+strengthenHyp :: SInfo a -> [(Integer, Expr)] -> BindEnv a strengthenHyp si ies = strengthenBinds si bindExprs where bindExprs = safeFromList "strengthenHyp" [ (subcBind si i, e) | (i, e) <- ies ]@@ -212,8 +187,8 @@ = errorstar $ "Unknown subcId in subcBind: " ++ show i -strengthenBinds :: SInfo a -> M.HashMap BindId Expr -> SInfo a-strengthenBinds si m = si { bs = mapBindEnv f (bs si) }+strengthenBinds :: SInfo a -> M.HashMap BindId Expr -> BindEnv a+strengthenBinds si m = mapBindEnv f (bs si) where f i (x, sr, l) = case M.lookup i m of Nothing -> (x, sr, l)@@ -272,37 +247,87 @@ -- | Solutions and Results --------------------------------------------------------------------------- -type GFixSolution = GFixSol Expr+-- | Since some solutions are expensive to compute, we wrap them in a+-- "Delayed" type to compute them only if needed.+{- HLINT ignore Delayed "Use newtype instead of data" -}+data Delayed a = Delayed+ { forceDelayed :: a+ }+ deriving (Generic, Show, Functor) -type FixSolution = M.HashMap KVar Expr+instance (NFData a) => NFData (Delayed a) -newtype GFixSol e = GSol (M.HashMap KVar (e, [e]))- deriving (Generic, Semigroup, Monoid, Functor) -toGFixSol :: M.HashMap KVar (e, [e]) -> GFixSol e-toGFixSol = GSol-+type FixSolution = M.HashMap KVar Expr+type FixDelayedSolution = M.HashMap KVar (Delayed Expr) data Result a = Result { resStatus :: !(FixResult a) , resSolution :: !FixSolution- , resNonCutsSolution :: !FixSolution- , gresSolution :: !GFixSolution+ , resNonCutsSolution :: !FixDelayedSolution+ , resSorts :: !ResultSorts } deriving (Generic, Show, Functor) +type ResultSorts = M.HashMap KVar [(Symbol, Sort)] +data ScopedResult = MkScopedResult+ { scCuts :: KVarMap ScopedExpr+ , scNonCuts :: KVarMap ScopedExpr+ }+ deriving (Generic, Show) +newtype KVarMap a = MkKVarMap { unKVarMap :: M.HashMap KVar a }+ deriving (Generic, Show)++newtype KVarBind a = MkKVarBind { unKVarBind :: (KVar, a) }+ deriving (Generic, Show)+data ScopedExpr = MkScopedExpr+ { seParams :: [(Symbol, Sort)]+ , seBody :: !Expr+ }+ deriving (Generic, Show)++instance ToHornSMT ScopedExpr where+ toHornSMT (MkScopedExpr xts p) = toHornWithBinders "lambda" xts p+++scopedResult :: Result a -> ScopedResult+scopedResult res = MkScopedResult cuts nonCuts+ where+ cuts = scoped $ resSolution res+ nonCuts = scoped $ M.map forceDelayed $ resNonCutsSolution res+ scoped sol = MkKVarMap $ M.fromList [ (k, MkScopedExpr (scope k) e) | (k, e) <- M.toList sol]+ scope k = M.lookupDefault [] k $ resSorts res+ instance ToJSON a => ToJSON (Result a) where- toJSON = toJSON . resStatus+ toJSON r@(Result {..}) = object+ [ "status" .= resStatus+ , "solution" .= scCuts scopedSolution+ , "nonCutsSolution" .= scNonCuts scopedSolution+ ]+ where+ scopedSolution = scopedResult r +instance ToJSON a => ToJSON (KVarBind a) where+ toJSON (MkKVarBind (k, v)) = object+ [ "kvar" .= k+ , "val" .= v+ ]++instance ToJSON a => ToJSON (KVarMap a) where+ toJSON = toJSON . map MkKVarBind . M.toList . unKVarMap++instance ToJSON ScopedExpr where+ toJSON = toJSON . render . toHornSMT+ instance Semigroup (Result a) where- r1 <> r2 = Result stat soln nonCutsSoln gsoln+ r1 <> r2 = Result stat soln nonCutsSoln sorts where stat = resStatus r1 <> resStatus r2 soln = resSolution r1 <> resSolution r2 nonCutsSoln = resNonCutsSolution r1 <> resNonCutsSolution r2- gsoln = gresSolution r1 <> gresSolution r2+ sorts = M.unionWith L.union (resSorts r1) (resSorts r2) instance Monoid (Result a) where mempty = Result mempty mempty mempty mempty@@ -370,7 +395,6 @@ -- NOTE: this next line is printed this way for compatability with the OCAML solver $+$ text "reft" <+> toFix (RR t (Reft (v, PKVar k mempty))) $+$ toFixMeta (text "wf") (toFix (winfo w))- $+$ if isGWfc w then toFixMeta (text "expr") (toFix (wexpr w)) else mempty (v, t, k) = wrft w toFixMeta :: Doc -> Doc -> Doc@@ -380,31 +404,12 @@ pprId (Just i) = "id" <+> tshow i pprId _ = "" -instance PPrint GFixSolution where- pprintTidy k (GSol xs) = vcat $ punctuate "\n\n" (pprintTidyGradual k <$> M.toList xs)--pprintTidyGradual :: Tidy -> (KVar, (Expr, [Expr])) -> Doc-pprintTidyGradual _ (x, (e, es)) = ppLocOfKVar x <+> text ":=" <+> (ppNonTauto " && " e <-> pprint es)--ppLocOfKVar :: KVar -> Doc-ppLocOfKVar = text. dropWhile (/='(') . symbolString .kv--ppNonTauto :: Doc -> Expr -> Doc-ppNonTauto d e- | isTautoPred e = mempty- | otherwise = pprint e <-> d--instance Show GFixSolution where- show = showpp- ---------------------------------------------------------------- instance S.Store QualPattern instance S.Store QualParam instance S.Store Qualifier instance S.Store Kuts instance S.Store HOInfo-instance S.Store GWInfo-instance S.Store GFixSolution instance (S.Store a) => S.Store (SubC a) instance (S.Store a) => S.Store (WfC a) instance (S.Store a) => S.Store (SimpC a)@@ -415,8 +420,6 @@ instance NFData v => NFData (QualifierV v) instance NFData Kuts instance NFData HOInfo-instance NFData GFixSolution-instance NFData GWInfo instance (NFData a) => NFData (SubC a) instance (NFData a) => NFData (WfC a)@@ -443,22 +446,16 @@ -- NV TO RJ This tests fails with [LT:=GHC.Types.LT][EQ:=GHC.Types.EQ][GT:=GHC.Types.GT]] -- NV TO RJ looks like a resolution issue then [WfC be (v, sr_sort sr, k) x | k <- ks ]- ++ [GWfC be (v, sr_sort sr, k) x e i | (k, e, i) <- gs ] else errorstar msg where- msg = "wfKvar: malformed wfC " ++ show sr ++ "\n" ++ show (sus ++ gsus)+ msg = "wfKvar: malformed wfC " ++ show sr ++ "\n" ++ show sus Reft (v, ras) = sr_reft sr (ks, sus) = unzip $ go ras- (gs, gsus) = unzip $ go' ras go (PKVar k su) = [(k, su)] go (PAnd es) = [(k, su) | PKVar k su <- es] go _ = [] - go' (PGrad k su i e) = [((k, e, i), su)]- go' (PAnd es) = concatMap go' es- go' _ = []- mkSubC :: IBindEnv -> SortedReft -> SortedReft -> Maybe Integer -> Tag -> a -> SubC a mkSubC = SubC @@ -508,6 +505,10 @@ } deriving (Eq, Ord, Show, Data, Typeable, Generic) +instance ToHornSMT QualParam where+ toHornSMT qp = toHornSMT (qpSym qp, qpSort qp)++ data QualPattern = PatNone -- ^ match everything | PatPrefix !Symbol !Int -- ^ str . $i i.e. match prefix 'str' with suffix bound to $i@@ -526,6 +527,11 @@ instance ToJSON Rewrite where instance FromJSON Rewrite where +instance ToHornSMT Qualifier where+ toHornSMT (Q n qps p _) = toHornWithBinders name xts p+ where+ name = "qualif" <+> pprint n+ xts = [(qpSym qp, qpSort qp) | qp <- qps] trueQual :: Qualifier trueQual = Q (symbol ("QTrue" :: String)) [] PTrue (dummyPos "trueQual")@@ -564,11 +570,15 @@ instance Fixpoint Qualifier where toFix = pprQual -instance PPrint (QualifierV v) where- pprintTidy k q = "qualif" <+> pprintTidy k (qName q) <+> "defined at" <+> pprintTidy k (qPos q)+instance (Ord v, Fixpoint v, PPrint v) => PPrint (QualifierV v) where+ pprintTidy k q =+ "qualif" <+> pprintTidy k (qName q) <+>+ parens (hsep $ punctuate comma (pprintTidy k <$> qParams q)) <+>+ braces (pprintTidy k (qBody q)) <+> "//defined at" <+> pprintTidy k (qPos q) + pprQual :: Qualifier -> Doc-pprQual (Q n xts p l) = text "qualif" <+> text (symbolString n) <-> parens args <-> colon <+> parens (toFix p) <+> text "//" <+> toFix l+pprQual (Q n xts p l) = text "qualif" <+> text (symbolString n) <-> parens args <-> braces (toFix p) <+> text "//" <+> toFix l where args = intersperse comma (toFix <$> xts) @@ -681,12 +691,11 @@ -> [Triggered Expr] -> AxiomEnv -> [DataDecl]- -> [BindId] -> GInfo SubC a-fi cs ws binds ls ds ks qs bi aHO aHOq es axe adts ebs+fi cs ws binds ls ds ks qs bi aHO aHOq es axe adts = FI { cm = M.fromList $ addIds cs , ws = M.fromListWith err [(k, w) | w <- ws, let (_, _, k) = wrft w]- , bs = foldr (adjustBindEnv stripReft) binds ebs+ , bs = binds , gLits = ls , dLits = ds , kuts = ks@@ -696,14 +705,12 @@ , asserts = es , ae = axe , ddecls = adts- , ebinds = ebs , lrws = mempty , defns = mempty } where --TODO handle duplicates gracefully instead (merge envs by intersect?) err = errorstar "multiple WfCs with same kvar"- stripReft (sym, reft) = (sym, reft { sr_reft = trueReft }) ------------------------------------------------------------------------ -- | Top-level Queries@@ -733,8 +740,7 @@ data GInfo c a = FI { cm :: !(M.HashMap SubcId (c a)) -- ^ cst id |-> Horn Constraint , ws :: !(M.HashMap KVar (WfC a)) -- ^ Kvar |-> WfC defining its scope/args- , bs :: !(BindEnv a) -- ^ Bind |-> (Symbol, SortedReft)- , ebinds :: ![BindId] -- ^ Subset of existential binders+ , bs :: !(BindEnv a) -- ^ BindId |-> (Symbol, SortedReft) , gLits :: !(SEnv Sort) -- ^ Global Constant symbols , dLits :: !(SEnv Sort) -- ^ Distinct Constant symbols , kuts :: !Kuts -- ^ Set of KVars *not* to eliminate@@ -745,13 +751,10 @@ , 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+ , defns :: DefinedFuns -- ^ `define_fun` definitions to be passed to SMT } deriving (Eq, Show, Functor, Generic) -instance HasGradual (GInfo c a) where- isGradual info = any isGradual (M.elems $ ws info)- instance Semigroup HOInfo where i1 <> i2 = HOI { hoBinds = hoBinds i1 || hoBinds i2 , hoQuals = hoQuals i1 || hoQuals i2@@ -764,7 +767,6 @@ i1 <> i2 = FI { cm = cm i1 <> cm i2 , ws = ws i1 <> ws i2 , bs = bs i1 <> bs i2- , ebinds = ebinds i1 <> ebinds i2 , gLits = gLits i1 <> gLits i2 , dLits = dLits i1 <> dLits i2 , kuts = kuts i1 <> kuts i2@@ -783,7 +785,6 @@ mempty = FI { cm = M.empty , ws = mempty , bs = mempty- , ebinds = mempty , gLits = mempty , dLits = mempty , kuts = mempty@@ -830,9 +831,7 @@ kutsDoc = toFix . kuts -- packsDoc = toFix . packs declsDoc = vcat . map ((text "data" <+>) . toFix) . L.sort . ddecls- (ubs, ebs) = splitByQuantifiers (bs x') (ebinds x')- bindsDoc = toFix ubs- $++$ toFix ebs+ bindsDoc = toFix (bs x') qualsDoc = vcat . map toFix . L.sort . quals aeDoc = toFix . ae lrwsDoc = toFix . lrws@@ -909,11 +908,6 @@ where (b, sr, _) = lookupBindEnv (cbind s) env ------------------------------------------------------------------------------- | Top level Solvers ---------------------------------------------------------------------------------------------------------------------------------type Solver a = C.Config -> FInfo a -> IO (Result (Integer, a))- -------------------------------------------------------------------------------- saveQuery :: (Fixpoint a) => C.Config -> FInfo a -> IO () --------------------------------------------------------------------------------@@ -936,6 +930,26 @@ ensurePath fq T.writeFile fq $ T.pack $ render (toFixpoint cfg fi) +-- | Used for debugging to inspect intermediate 'SInfo' files.+--+-- Takes a suffix to put in the name of the written file, whose name+-- is still derived from the input file name in `cfg`.+--+-- Usage example:+--+-- > when (save cfg) $+-- > saveSInfo cfg ".sinfo" si+--+-- This will write a file like `.liquid/Test.hs.sinfo.fq` when the+-- `--save` flag is used.+--+saveSInfo :: Fixpoint a => C.Config -> String -> SInfo a -> IO ()+saveSInfo cfg sfx si = do+ let fq = Files.tempFileName (C.srcFile cfg ++ sfx ++ ".fq")+ putStrLn $ "Saving Text Query: " ++ fq ++ "\n"+ ensurePath fq+ T.writeFile fq $ T.pack $ render (toFixpoint cfg si)+ --------------------------------------------------------------------------- -- | Axiom Instantiation Information -------------------------------------- ---------------------------------------------------------------------------@@ -966,10 +980,12 @@ instance S.Store AxiomEnv instance S.Store Rewrite instance S.Store Equation+instance S.Store DefinedFuns instance NFData AutoRewrite instance NFData AxiomEnv instance NFData Rewrite instance NFData Equation+instance NFData DefinedFuns dedupAutoRewrites :: M.HashMap SubcId [AutoRewrite] -> [AutoRewrite] dedupAutoRewrites = Set.toList . Set.unions . map Set.fromList . M.elems@@ -989,6 +1005,19 @@ instance PPrint AxiomEnv where pprintTidy _ = text . show ++newtype DefinedFuns = MkDefinedFuns [Equation]+ deriving (Data, Eq, Ord, Show, Generic)++instance Semigroup DefinedFuns where+ MkDefinedFuns eq1 <> MkDefinedFuns eq2 = MkDefinedFuns (eq1 <> eq2)++instance Monoid DefinedFuns where+ mempty = MkDefinedFuns []++instance PPrint DefinedFuns where+ pprintTidy k (MkDefinedFuns eqs) = pprintTidy k eqs+ type Equation = EquationV Symbol data EquationV v = Equ { eqName :: !Symbol -- ^ name of reflected function@@ -999,6 +1028,10 @@ } deriving (Data, Eq, Ord, Show, Generic, Functor) +eqnToHornSMT :: Doc -> Equation -> Doc+eqnToHornSMT keyword (Equ f xs e s _) = parens (keyword <+> pprint f <+> toHornSMT xs <+> toHornSMT s <+> toHornSMT e)++ mkEquation :: Symbol -> [(Symbol, Sort)] -> Expr -> Sort -> Equation mkEquation f xts e out = Equ f xts e out (f `elem` syms e) @@ -1062,6 +1095,11 @@ } deriving (Data, Eq, Ord, Show, Generic) +instance ToHornSMT Rewrite where+ toHornSMT (SMeasure f d xs e) = parens ("match" <+> toHornSMT f <+> toHornSMT (d:xs) <+> toHornSMT e)+++ instance Fixpoint AxiomEnv where toFix axe = vcat ((toFix <$> L.sort (aenvEqs axe)) ++ (toFix <$> L.sort (aenvSimpl axe))) $+$ renderExpand (pairdoc <$> L.sort (M.toList $ aenvExpand axe))@@ -1086,8 +1124,7 @@ = text "match" <+> toFix f <+> toFix d <+> hsep (toFix <$> xs)- <+> text " = "- <+> parens (toFix e)+ <+> braces (toFix e) instance PPrint Rewrite where pprintTidy _ = toFix
src/Language/Fixpoint/Types/Environments.hs view
@@ -318,7 +318,7 @@ mappend = (<>) envCs :: BindEnv a -> IBindEnv -> [(Symbol, SortedReft)]-envCs be env = [(x, y) | i <- elemsIBindEnv env, let (x, y, _) = lookupBindEnv i be]+envCs be (FB s) = [(x, y) | (x, y, _) <- M.elems (M.intersection (beBinds be) (S.toMap s))] instance Fixpoint IBindEnv where toFix (FB ids) = text "env" <+> toFix ids
src/Language/Fixpoint/Types/Errors.hs view
@@ -62,6 +62,7 @@ -- import Data.Hashable import qualified Data.Store as S import GHC.Generics (Generic)+import GHC.Stack (HasCallStack) import Language.Fixpoint.Types.PrettyPrint import Language.Fixpoint.Types.Spans import Language.Fixpoint.Misc@@ -137,7 +138,7 @@ err sp d = Error [Error1 sp d] ----------------------------------------------------------------------panic :: String -> a+panic :: HasCallStack => String -> a --------------------------------------------------------------------- panic = die . err dummySpan . text . (panicMsg ++) @@ -145,7 +146,7 @@ panicMsg = "PANIC: Please file an issue at https://github.com/ucsd-progsys/liquid-fixpoint \n" ----------------------------------------------------------------------die :: Error -> a+die :: HasCallStack => Error -> a --------------------------------------------------------------------- die = throw
− src/Language/Fixpoint/Types/Graduals.hs
@@ -1,259 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TupleSections #-}--{-# OPTIONS_GHC -Wno-name-shadowing #-}---- | This module contains the top-level SOLUTION data types,--- including various indices used for solving.--module Language.Fixpoint.Types.Graduals (- uniquify,-- makeSolutions,-- GSol,-- Gradual (..)- ) where--import Language.Fixpoint.Types.Refinements-import Language.Fixpoint.Types.Constraints-import Language.Fixpoint.Types.Config-import Language.Fixpoint.Types.PrettyPrint-import Language.Fixpoint.Types.Environments-import Language.Fixpoint.Types.Substitutions-import Language.Fixpoint.Types.Visitor-import Language.Fixpoint.Types.Spans-import Language.Fixpoint.Types.Theories-import Language.Fixpoint.Types.Names (gradIntSymbol, tidySymbol)-import Language.Fixpoint.Misc (allCombinations, errorstar)--import Control.DeepSeq--import qualified Data.HashMap.Strict as M-import qualified Data.List as L--import Control.Monad.State.Lazy-import Data.Maybe (fromMaybe)-import qualified Language.Fixpoint.SortCheck as So-import Language.Fixpoint.Solver.Sanitize (symbolEnv)---data GSol = GSol !SymEnv !(M.HashMap KVar (Expr, GradInfo))--instance Semigroup GSol where- (GSol e1 m1) <> (GSol e2 m2) = GSol (e1 <> e2) (m1 <> m2)--instance Monoid GSol where- mempty = GSol mempty mempty--instance Show GSol where- show (GSol _ m) = "GSOL = \n" ++ unlines ((\(k,(e, i)) -> showpp k ++ showInfo i ++ " |-> " ++ showpp (tx e)) <$> M.toList m)- where- tx e = subst (mkSubst $ [(x, EVar $ tidySymbol x) | x <- syms e]) e- showInfo i = show i---makeSolutions :: (NFData a, Fixpoint a, Show a)- => Config -> SInfo a- -> [(KVar, (GWInfo, [[Expr]]))]- -> Maybe [GSol]--makeSolutions _ _ []- = Nothing-makeSolutions cfg fi kes- = Just $ map (GSol env . M.fromList) (allCombinations (go <$> kes))- where- go (k, (i, es)) = [(k, (pAnd (gexpr i:e'), ginfo i)) | e' <- es]- env = symbolEnv cfg fi------------------------------------------------------------------------------------- | Make each gradual appearence unique ----------------------------------------------------------------------------------------------------------------------uniquify :: (NFData a, Fixpoint a, Loc a) => SInfo a -> SInfo a--uniquify fi = fi{cm = cm', ws = ws', bs = bs'}- where- (cm', km, bs') = uniquifyCS (bs fi) (cm fi)- ws' = expandWF km (ws fi)--uniquifyCS :: (NFData a, Fixpoint a, Loc a)- => BindEnv a- -> M.HashMap SubcId (SimpC a)- -> (M.HashMap SubcId (SimpC a), M.HashMap KVar [(KVar, Maybe SrcSpan)], BindEnv a)-uniquifyCS bs cs- = (x, km, benv st)- where- (x, st) = runState (uniq cs) (initUniqueST bs)- km = kmap st---class Unique ann a where- uniq :: a -> UniqueM ann a--instance Unique ann a => Unique ann (M.HashMap SubcId a) where- uniq m = M.fromList <$> mapM (\(i,x) -> (i,) <$> uniq x) (M.toList m)--instance Loc a => Unique a (SimpC a) where- uniq cs = do- updateLoc $ srcSpan $ _cinfo cs- rhs <- uniq (_crhs cs)- env <- uniq (_cenv cs)- return cs{_crhs = rhs, _cenv = env}--instance Unique ann IBindEnv where- uniq env = withCache (fromListIBindEnv <$> mapM uniq (elemsIBindEnv env))--instance Unique ann BindId where- uniq i = do- bs <- benv <$> get- let (x, t, ann) = lookupBindEnv i bs- resetChange- t' <- uniq t- hasChanged <- change <$> get- if hasChanged- then do let (i', bs') = insertBindEnv x t' ann bs- updateBEnv i bs'- return i'- else return i--instance Unique ann SortedReft where- uniq (RR s r) = RR s <$> uniq r--instance Unique ann Reft where- uniq (Reft (x,e)) = Reft . (x,) <$> uniq e--instance Unique ann Expr where- uniq = mapMExpr go- where- go (PGrad k su i e) = do- k' <- freshK k- src <- uloc <$> get- return $ PGrad k' su (i{gused = src}) e- go e = return e------------------------------------------------------------------------------------ | The Unique Monad -------------------------------------------------------------------------------------------------------------------------------------------type UniqueM ann = State (UniqueST ann)-data UniqueST a- = UniqueST { freshId :: Integer- , kmap :: M.HashMap KVar [(KVar, Maybe SrcSpan)]- , change :: Bool- , cache :: M.HashMap KVar KVar- , uloc :: Maybe SrcSpan- , ubs :: [BindId]- , benv :: BindEnv a- }--updateLoc :: SrcSpan -> UniqueM ann ()-updateLoc x = modify $ \s -> s{uloc = Just x}--withCache :: UniqueM ann a -> UniqueM ann a-withCache act = do- emptyCache- a <- act- emptyCache- return a--emptyCache :: UniqueM ann ()-emptyCache = modify $ \s -> s{cache = mempty}--addCache :: KVar -> KVar -> UniqueM ann ()-addCache k k' = modify $ \s -> s{cache = M.insert k k' (cache s)}--updateBEnv :: BindId -> BindEnv a -> UniqueM a ()-updateBEnv i bs = modify $ \s -> s{benv = bs, ubs = i : ubs s}--setChange :: UniqueM ann ()-setChange = modify $ \s -> s{change = True}--resetChange :: UniqueM ann ()-resetChange = modify $ \s -> s{change = False}--initUniqueST :: BindEnv a -> UniqueST a-initUniqueST = UniqueST 0 mempty False mempty Nothing mempty--freshK, freshK' :: KVar -> UniqueM ann KVar-freshK k = do- setChange- cached <- cache <$> get- case M.lookup k cached of- {- OPTIMIZATION: Only create one fresh occurence of ? per constraint environment. -}- Just k' -> return k'- Nothing -> freshK' k--freshK' k = do- i <- freshId <$> get- modify (\s -> s{freshId = i + 1})- let k' = KV $ gradIntSymbol i- addK k k'- addCache k k'- return k'--addK :: KVar -> KVar -> UniqueM ann ()-addK key val =- modify (\s -> s{kmap = M.insertWith (++) key [(val, uloc s)] (kmap s)})------------------------------------------------------------------------------------ | expandWF ---------------------------------------------------------------------------------------------------------------------------------------------------expandWF :: (NFData a, Fixpoint a)- => M.HashMap KVar [(KVar, Maybe SrcSpan)]- -> M.HashMap KVar (WfC a)- -> M.HashMap KVar (WfC a)-expandWF km ws- = M.fromList- ([(k, updateKVar k src w) | (i, w) <- gws, (kw, ks) <- km', kw == i, (k, src) <- ks]- ++ kws)- where- (gws, kws) = L.partition (isGWfc . snd) $ M.toList ws- km' = M.toList km-- updateKVar k src wfc = let wrft' = (\(v,s,_) -> (v,s,k)) $ wrft wfc in- case wfc of- GWfC{} -> wfc { wrft = wrft', wloc = (wloc wfc){gused = src} }- WfC{} -> wfc { wrft = wrft' }------------------------------------------------------------------------------------ | Substitute Gradual Solution -------------------------------------------------------------------------------------------------------------------------------class Gradual a where- gsubst :: ElabFlags -> GSol -> a -> a--instance Gradual Expr where- gsubst ef (GSol env m) e = mapGVars' (\(k, _) -> Just (fromMaybe (err k) (mknew k))) e- where- mknew k = So.elaborate (So.ElabParam ef "initBGind.mkPred" env) $ fst <$> M.lookup k m- err k = errorstar ("gradual substitution: Cannot find " ++ showpp k)--instance Gradual Reft where- gsubst ef su (Reft (x, e)) = Reft (x, gsubst ef su e)--instance Gradual SortedReft where- gsubst ef su r = r {sr_reft = gsubst ef su (sr_reft r)}--instance Gradual (SimpC a) where- gsubst ef su c = c {_crhs = gsubst ef su (_crhs c)}--instance Gradual (BindEnv a) where- gsubst ef su = mapBindEnv (\_ (x, r, l) -> (x, gsubst ef su r, l))--instance Gradual v => Gradual (M.HashMap k v) where- gsubst ef su = M.map (gsubst ef su)--instance Gradual (SInfo a) where- gsubst ef su fi = fi { bs = gsubst ef su (bs fi)- , cm = gsubst ef su (cm fi)- }
src/Language/Fixpoint/Types/Names.hs view
@@ -72,7 +72,6 @@ , dummySymbol , intSymbol , tempSymbol- , gradIntSymbol , appendSymbolText , hvarArgSymbol @@ -81,6 +80,7 @@ , bindSymbol , testSymbol , renameSymbol+ , renameSubstSymbol , kArgSymbol , existSymbol , suffixSymbol@@ -101,6 +101,7 @@ , mapConName , bagConName , arrayConName+ , ffldConName , strConName , charConName , nilName@@ -108,8 +109,8 @@ , vvName , sizeName , bitVecName- -- , bvAndName, bvOrName, bvSubName, bvAddName , intbv32Name, intbv64Name, bv32intName, bv64intName+ , intbv8Name, intbv16Name, bv8intName, bv16intName , propConName -- HKT , tyAppName@@ -407,9 +408,6 @@ unconsSym :: Symbol -> Maybe (Char, Symbol) unconsSym (symbolText -> s) = second symbol <$> T.uncons s --- singletonSym :: Char -> Symbol -- Yuck--- singletonSym = (`consSym` "")- lengthSym :: Symbol -> Int lengthSym (symbolText -> t) = T.length t @@ -443,7 +441,6 @@ suffixSymbolText x y = x <> symSepName <> y vv :: Maybe Integer -> Symbol--- vv (Just i) = symbol $ symbolSafeText vvName `T.snoc` symSepName `mappend` T.pack (show i) vv (Just i) = intSymbol vvName i vv Nothing = vvName @@ -454,12 +451,6 @@ vvCon = vvName `suffixSymbol` "F" dummySymbol = dummyName --- ctorSymbol :: Symbol -> Symbol--- ctorSymbol s = ctorPrefix `mappendSym` s---- isCtorSymbol :: Symbol -> Bool--- isCtorSymbol = isPrefixOfSym ctorPrefix- -- | 'testSymbol c' creates the `is-c` symbol for the adt-constructor named 'c'. testSymbol :: Symbol -> Symbol testSymbol s = testPrefix `mappendSym` s@@ -485,6 +476,9 @@ tempSymbol :: Symbol -> Integer -> Symbol tempSymbol prefix = intSymbol (tempPrefix `mappendSym` prefix) +renameSubstSymbol :: Symbol -> Int -> Symbol+renameSubstSymbol prefix = intSymbol (substPrefix `mappendSym` prefix)+ renameSymbol :: Symbol -> Int -> Symbol renameSymbol prefix = intSymbol (renamePrefix `mappendSym` prefix) @@ -494,9 +488,6 @@ existSymbol :: Symbol -> Integer -> Symbol existSymbol prefix = intSymbol (existPrefix `mappendSym` prefix) -gradIntSymbol :: Integer -> Symbol-gradIntSymbol = intSymbol gradPrefix- hvarArgSymbol :: Symbol -> Int -> Symbol hvarArgSymbol s i = intSymbol (suffixSymbol hvarPrefix s) i @@ -507,20 +498,17 @@ bindSymbol :: Integer -> Symbol bindSymbol = intSymbol bindPrefix -tempPrefix, anfPrefix, renamePrefix, litPrefix, gradPrefix, bindPrefix :: Symbol+tempPrefix, anfPrefix, renamePrefix, substPrefix, litPrefix, bindPrefix :: Symbol tempPrefix = "lq_tmp$" anfPrefix = "lq_anf$" renamePrefix = "lq_rnm$"+substPrefix = "subst$" litPrefix = "lit$"-gradPrefix = "grad$" bindPrefix = "b$" testPrefix :: Symbol testPrefix = "is$" --- ctorPrefix :: Symbol--- ctorPrefix = "mk$"- kArgPrefix, existPrefix, hvarPrefix :: Symbol kArgPrefix = "lq_karg$" existPrefix = "lq_ext$"@@ -534,26 +522,42 @@ unKArgSymbol :: Symbol -> Symbol unKArgSymbol = unSuffixSymbol . unSuffixSymbol . unPrefixSymbol kArgPrefix --- | 'tidySymbol' is used to prettify the names of parameters of kvars appearing in solutions.(*)--- For example, if you have a kvar $k0 with two parameters, you may have a solution that looks like--- 0 < lq_karg$nnf_arg$##k0##0##k0+-- | @tidySymbol@ is used to prettify the names of parameters of kvars appearing+-- in solutions. For example, if you have a kvar $k0 with two parameters, you+-- may have a solution that looks like+--+-- > 0 < lq_karg$nnf_arg$##k0##0##k0+-- -- where we know it is a kvar-arg because of the--- - `kArgPrefix` (`lq_arg`)--- - `hvarArgPrefix` (`nnf_arg`)--- - `k0` the name of the kvar--- - `0` the parameter index--- - `k0` again (IDK why?!)--- all of which are separated by `##`--- So `tidySymbol` tests if indeed it is a `kArgPrefix`-ed symbol and if so converts--- `lq_karg$nnf_arg$##k0##0##k0` ----> `$k0##0`+-- - @kArgPrefix@ (@lq_arg@)+-- - @hvarArgPrefix@ (@nnf_arg@)+-- - @k0@ the name of the kvar+-- - @0@ the parameter index+-- - @k0@ again (IDK why?!)+-- all of which are separated by @##@+--+-- So @tidySymbol@ tests if indeed it is a @kArgPrefix@-ed symbol and if so+-- converts+--+-- > lq_karg$nnf_arg$##k0##0##k0 ----> $k0##0+--+-- KArgs from Liquid Haskell come in the form @k_##0@ instead, and parameters+-- are like @lq_karg$param_name##0##k_##0@. In this case, tidySymbol will+-- convert+--+-- > lq_karg$param_name##0##k_##0 ----> $param_name##0##k_ tidySymbol :: Symbol -> Symbol tidySymbol s | s == s' = s | otherwise = s'' where- s' = unPrefixSymbol kArgPrefix s- s'' = consSym '$' . unPrefixSymbol symSepName . unSuffixSymbol . unPrefixSymbol hvarPrefix $ s'+ s' = unPrefixSymbol kArgPrefix s+ s'' =+ consSym '$' $+ unPrefixSymbol symSepName $+ unSuffixSymbol $+ unPrefixSymbol hvarPrefix s' unPrefixSymbol :: Symbol -> Symbol -> Symbol unPrefixSymbol p s = fromMaybe s (stripPrefix p s)@@ -562,10 +566,6 @@ unSuffixSymbol s@(symbolText -> t) = maybe s symbol $ T.stripSuffix symSepName $ fst $ T.breakOnEnd symSepName t --- takeWhileSym :: (Char -> Bool) -> Symbol -> Symbol--- takeWhileSym p (symbolText -> t) = symbol $ T.takeWhile p t-- nonSymbol :: Symbol nonSymbol = "" @@ -652,48 +652,41 @@ preludeName = "Prelude" dummyName = "LIQUID$dummy" boolConName = "Bool"-boolLConName = "bool"+boolLConName = "bool" funConName = "->" -listConName, listLConName, propConName, _hpropConName, vvName, setConName, mapConName, bagConName, arrayConName:: Symbol-listConName = "[]"-listLConName = "List"-setConName = "Set_Set"-mapConName = "Map_t"-bagConName = "Bag_t"-arrayConName = "Array_t"-vvName = "VV"-propConName = "Prop"+listConName, listLConName, propConName, _hpropConName, vvName, setConName, mapConName, bagConName, arrayConName, ffldConName :: Symbol+listConName = "[]"+listLConName = "List"+setConName = "Set_Set"+mapConName = "Map_t"+bagConName = "Bag_t"+arrayConName = "Array_t"+ffldConName = "FFld_t"+vvName = "VV"+propConName = "Prop" _hpropConName = "HProp" strConName, charConName :: (IsString a) => a strConName = "Str" charConName = "Char"--- symSepName :: Char--- symSepName = '#' -- DO NOT EVER CHANGE THIS symSepName :: (IsString a) => a symSepName = "##" --- nilName, consName, size32Name, size64Name, bitVecName :: Symbol--- nilName = "nil"--- consName = "cons"--- size32Name = "Size32"--- size64Name = "Size64"--- bitVecName = "BitVec"---- bvOrName, bvAndName, bvSubName, bvAddName, intbv32Name, intbv64Name, bv32intName, bv64intName :: Symbol--- bvOrName = "bvor"--- bvAndName = "bvand"--- bvSubName = "bvsub"--- bvAddName = "bvadd" intbv32Name = "int_to_bv32" intbv64Name = "int_to_bv64" bv32intName = "bv32_to_int" bv64intName = "bv64_to_int" +intbv8Name, intbv16Name, bv8intName, bv16intName :: Symbol+intbv8Name = "int_to_bv8"+intbv16Name = "int_to_bv16"+bv8intName = "bv8_to_int"+bv16intName = "bv16_to_int"+ nilName, consName, sizeName, bitVecName :: Symbol nilName = "nil" consName = "cons"@@ -717,8 +710,6 @@ , "List" , "[]" , "bool"- -- , "int"- -- , "real" , setConName , charConName , "Set_sng"
src/Language/Fixpoint/Types/Refinements.hs view
@@ -28,7 +28,6 @@ , Brel (..) , ExprV (..), Pred , Expr- , GradInfo (..) , pattern PTrue, pattern PTop, pattern PFalse, pattern EBot , pattern ETimes, pattern ERTimes, pattern EDiv, pattern ERDiv , pattern EEq@@ -104,11 +103,6 @@ , debruijnIndex - -- * Gradual Type Manipulation- , pGAnds, pGAnd- , HasGradual (..)- , srcGradInfo- ) where import Prelude hiding ((<>))@@ -122,6 +116,7 @@ import Data.HashSet (HashSet) import qualified Data.HashSet as HashSet import GHC.Generics (Generic)+import GHC.Stack (HasCallStack) #if MIN_VERSION_base(4,20,0) import Data.List (partition) #else@@ -148,7 +143,6 @@ instance NFData KVar instance NFData v => NFData (SubstV v)-instance NFData GradInfo instance NFData Constant instance NFData SymConst instance NFData Brel@@ -163,7 +157,6 @@ instance S.Store KVar instance S.Store Subst-instance S.Store GradInfo instance S.Store Constant instance S.Store SymConst instance S.Store Brel@@ -175,7 +168,6 @@ instance B.Binary SymConst instance B.Binary Constant instance B.Binary Bop-instance B.Binary GradInfo instance B.Binary Brel instance B.Binary KVar instance (Hashable a, Eq a, B.Binary a) => B.Binary (HashSet a) where@@ -194,54 +186,18 @@ reftConjuncts (Reft (v, ra)) = [Reft (v, ra') | ra' <- ras'] where ras' = if null ps then ks else conj ps : ks -- see [NOTE:pAnd-SLOW]- (ps, ks) = partition isConc (refaConjuncts ra)+ (ps, ks) = partition isConc (conjuncts ra) isConc :: Expr -> Bool-isConc p = not (isKvar p || isGradual p)+isConc p = not (isKvar p) concConjuncts :: Expr -> [Expr]-concConjuncts e = filter isConc (refaConjuncts e)+concConjuncts e = filter isConc (conjuncts e) isKvar :: Expr -> Bool isKvar (PKVar _ _) = True isKvar _ = False -class HasGradual a where- isGradual :: a -> Bool- gVars :: a -> [KVar]- gVars _ = []- ungrad :: a -> a- ungrad x = x--instance HasGradual Expr where- isGradual PGrad{} = True- isGradual (PAnd xs) = any isGradual xs- isGradual _ = False-- gVars (PGrad k _ _ _) = [k]- gVars (PAnd xs) = concatMap gVars xs- gVars _ = []-- ungrad PGrad{} = PTrue- ungrad (PAnd xs) = PAnd (ungrad <$> xs )- ungrad e = e---instance HasGradual Reft where- isGradual (Reft (_,r)) = isGradual r- gVars (Reft (_,r)) = gVars r- ungrad (Reft (x,r)) = Reft(x, ungrad r)--instance HasGradual SortedReft where- isGradual = isGradual . sr_reft- gVars = gVars . sr_reft- ungrad r = r {sr_reft = ungrad (sr_reft r)}--refaConjuncts :: Expr -> [Expr]-refaConjuncts p = [p' | p' <- conjuncts p, not $ isTautoPred p']--- -------------------------------------------------------------------------------- -- | Kvars --------------------------------------------------------------------- --------------------------------------------------------------------------------@@ -249,6 +205,8 @@ newtype KVar = KV { kv :: Symbol } deriving (Eq, Ord, Data, Typeable, Generic, IsString, ToJSON, FromJSON) +instance ToJSONKey KVar+ intKvar :: Integer -> KVar intKvar = KV . intSymbol "k_" @@ -260,7 +218,6 @@ instance Hashable Bop instance Hashable SymConst instance Hashable Constant-instance Hashable GradInfo instance Hashable v => Hashable (SubstV v) instance Hashable v => Hashable (ExprV v) instance Hashable v => Hashable (ReftV v)@@ -337,6 +294,7 @@ | EApp !(ExprV v) !(ExprV v) | ENeg !(ExprV v) | EBin !Bop !(ExprV v) !(ExprV v)+ | ELet !Symbol !(ExprV v) !(ExprV v) | EIte !(ExprV v) !(ExprV v) !(ExprV v) | ECst !(ExprV v) !Sort | ELam !(Symbol, Sort) !(ExprV v)@@ -351,7 +309,6 @@ | PKVar !KVar !(SubstV v) | PAll ![(Symbol, Sort)] !(ExprV v) | PExist ![(Symbol, Sort)] !(ExprV v)- | PGrad !KVar !(SubstV v) !GradInfo !(ExprV v) | ECoerc !Sort !Sort !(ExprV v) deriving (Eq, Show, Ord, Data, Typeable, Generic, Functor, Foldable, Traversable) @@ -405,6 +362,7 @@ go (ECoerc _ _ e) = go e go (ENeg e) = go e go (EBin _ e1 e2) = gos [e1, e2]+ go (ELet x e1 e2) = HashSet.union (go e1) (HashSet.delete x $ go e2) go (EIte p e1 e2) = gos [p, e1, e2] go (ECst e _) = go e go (PAnd ps) = gos ps@@ -451,6 +409,7 @@ go (ECoerc _ _ e) = go e go (ENeg e) = go e go (EBin _ e1 e2) = gos [e1, e2]+ go (ELet _ e1 e2) = gos [e1, e2] go (EIte p e1 e2) = gos [p, e1, e2] go (ECst e _) = go e go (PAnd ps) = gos ps@@ -465,15 +424,6 @@ go (PExist _xts p) = go p go _ = HashMap.empty -data GradInfo = GradInfo {gsrc :: SrcSpan, gused :: Maybe SrcSpan}- deriving (Eq, Ord, Show, Data, Typeable, Generic)--instance ToJSON GradInfo-instance FromJSON GradInfo--srcGradInfo :: SourcePos -> GradInfo-srcGradInfo src = GradInfo (SS src src) Nothing- mkEApp :: LocSymbol -> [Expr] -> Expr mkEApp = eApps . EVar . val @@ -520,6 +470,7 @@ go (EVar _) = 1 go (ENeg e) = go e go (EBin _ e1 e2) = go e1 + go e2+ go (ELet _ e1 e2) = 1 + go e1 + go e2 go (EIte e e1 e2) = go e + go e1 + go e2 go (ETAbs e _) = go e go (ETApp e _) = go e@@ -532,7 +483,6 @@ go (PAll _ e) = go e go (PExist _ e) = go e go (PKVar _ _) = 1- go (PGrad _ _ _ e) = go e go (ECoerc _ _ e) = go e type Reft = ReftV Symbol@@ -574,9 +524,6 @@ encodeSymConst :: SymConst -> Symbol encodeSymConst (SL s) = litSymbol $ symbol s --- _decodeSymConst :: Symbol -> Maybe SymConst--- _decodeSymConst = fmap (SL . symbolText) . unLitSymbol- instance Fixpoint SymConst where toFix (SL t) = text (show t) @@ -609,6 +556,7 @@ toFix e@(EApp _ _) = parens $ hcat $ punctuate " " $ toFix <$> (f:es) where (f, es) = splitEApp e toFix (ENeg e) = parens $ text "-" <+> parens (toFix e) toFix (EBin o e1 e2) = parens $ sep [toFix e1 <+> toFix o, nest 2 (toFix e2)]+ toFix (ELet x e1 e2) = parens $ sep [text "let" <+> toFix x <+> text "=" <+> toFix e1 <+> text "in", nest 2 (toFix e2)] toFix (EIte p e1 e2) = parens $ sep [text "if" <+> toFix p <+> text "then", nest 2 (toFix e1), text "else", nest 2 (toFix e2)] -- toFix (ECst e _so) = toFix e toFix (ECst e so) = parens $ toFix e <+> text " : " <+> toFix so@@ -623,15 +571,14 @@ toFix (POr ps) = text "||" <+> toFix ps toFix (PAtom r e1 e2) = parens $ sep [ toFix e1 <+> toFix r, nest 2 (toFix e2)] toFix (PKVar k su) = toFix k <-> toFix su- toFix (PAll xts p) = "forall" <+> (toFix xts+ toFix (PAll xts p) = parens $ "forall" <+> (toFix xts $+$ ("." <+> toFix p))- toFix (PExist xts p) = "exists" <+> (toFix xts+ toFix (PExist xts p) = parens $ "exists" <+> (toFix xts $+$ ("." <+> toFix p)) toFix (ETApp e s) = text "tapp" <+> toFix e <+> toFix s toFix (ETAbs e s) = text "tabs" <+> toFix e <+> toFix s- toFix (PGrad k _ _ e) = toFix e <+> text "&&" <+> toFix k -- text "??" -- <+> toFix k <+> toFix su toFix (ECoerc a t e) = parens (text "coerce" <+> toFix a <+> text "~" <+> toFix t <+> text "in" <+> toFix e)- toFix (ELam (x,s) e) = text "lam" <+> toFix x <+> ":" <+> toFix s <+> "." <+> toFix e+ toFix (ELam (x,s) e) = parens (char '\\' <+> toFix x <+> ":" <+> toFix s <+> "->" <+> toFix e) simplify = simplifyExpr dedup where@@ -664,10 +611,6 @@ else if sq == PFalse then PNot sp else PIff sp sq - go (PGrad k su i e)- | isContraPred e = PFalse- | otherwise = PGrad k su i (go e)- go (PAnd ps) | any isContraPred ps = PFalse -- Note: Performance of some tests is very sensitive to this code. See #480@@ -789,6 +732,10 @@ pprintTidy k o <+> pprintPrec (zo+1) k e2 where zo = opPrec o+ pprintPrec _ k (ELet x e1 e2) = parens+ "let" <+> toFix x <+> "=" <+> pprintTidy k e1 <+>+ "in" <+> pprintTidy k e2+ pprintPrec z k (EIte p e1 e2) = parensIf (z > zi) $ "if" <+> pprintPrec (zi+1) k p <+> "then" <+> pprintPrec (zi+1) k e1 <+>@@ -824,19 +771,18 @@ pprintTidy k r <+> pprintPrec (za+1) k e2 where za = 4- pprintPrec _ k (PAll xts p) = pprintQuant k "forall" xts p- pprintPrec _ k (PExist xts p) = pprintQuant k "exists" xts p+ pprintPrec z k (PAll xts p) = parensIf (z > 0) $ pprintQuant k "forall" xts p+ pprintPrec z k (PExist xts p) = parensIf (z > 0) $ pprintQuant k "exists" xts p pprintPrec _ k (ELam (x,t) e) = "lam" <+> toFix x <+> ":" <+> toFix t <+> text "." <+> pprintTidy k e pprintPrec _ k (ECoerc a t e) = parens $ "coerce" <+> toFix a <+> "~" <+> toFix t <+> text "in" <+> pprintTidy k e pprintPrec _ _ p@PKVar{} = toFix p pprintPrec _ _ (ETApp e s) = "ETApp" <+> toFix e <+> toFix s pprintPrec _ _ (ETAbs e s) = "ETAbs" <+> toFix e <+> toFix s- pprintPrec z k (PGrad x _ _ e) = pprintPrec z k e <+> "&&" <+> toFix x -- "??" pprintQuant :: (Ord v, Fixpoint v, PPrint v) => Tidy -> Doc -> [(Symbol, Sort)] -> ExprV v -> Doc-pprintQuant k d xts p = (d <+> toFix xts)+pprintQuant k d xts p = (d <+> pprintTidy k xts) $+$ (" ." <+> pprintTidy k p) @@ -930,7 +876,7 @@ -- | 'conj' is a fast version of 'pAnd' needed for the ebind tests conj :: [Pred] -> Pred-conj [] = PFalse+conj [] = PTrue conj [p] = p conj ps = PAnd ps @@ -1011,17 +957,6 @@ reftBind (Reft (x, _)) = x --------------------------------------------------------------- | Gradual Type Manipulation ------------------------------------------------------------------------------------------pGAnds :: (Fixpoint v, Ord v) => [ExprV v] -> ExprV v-pGAnds = foldl' pGAnd PTrue--pGAnd :: (Fixpoint v, Ord v) => ExprV v -> ExprV v -> ExprV v-pGAnd (PGrad k su i p) q = PGrad k su i (pAnd [p, q])-pGAnd p (PGrad k su i q) = PGrad k su i (pAnd [p, q])-pGAnd p q = pAnd [p,q]-------------------------------------------------------------- -- | Generally Useful Refinements -------------------------- ------------------------------------------------------------ @@ -1079,7 +1014,7 @@ -- substa f = substf (EVar . f) substf :: (Symbol -> Expr) -> a -> a- subst :: Subst -> a -> a+ subst :: HasCallStack => Subst -> a -> a subst1 :: a -> (Symbol, Expr) -> a subst1 y (x, e) = subst (Su $ M.fromList [(x,e)]) y
+ src/Language/Fixpoint/Types/SMTPrint.hs view
@@ -0,0 +1,130 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}++module Language.Fixpoint.Types.SMTPrint where+++import qualified Language.Fixpoint.Misc as Misc+import qualified Text.PrettyPrint.HughesPJ.Compat as P+import qualified Language.Fixpoint.Types.PrettyPrint as F+import qualified Language.Fixpoint.Types.Names as F+import qualified Language.Fixpoint.Types.Sorts as F+import qualified Language.Fixpoint.Types.Spans as F+import qualified Language.Fixpoint.Types.Refinements as F+-- import qualified Language.Fixpoint.Types.Constraints as F++-----------------------------------------------------------------------------------------------------------------+-- Human readable but robustly parseable SMT-LIB format pretty printer+-----------------------------------------------------------------------------------------------------------------+class ToHornSMT a where+ toHornSMT :: a -> P.Doc+++instance ToHornSMT F.Symbol where+ toHornSMT s = F.pprint s++++toHornWithBinders :: (ToHornSMT a, ToHornSMT t) => P.Doc -> [(F.Symbol, t)] -> a -> P.Doc+toHornWithBinders name xts p = P.parens (name P.<+> toHornSMT xts P.<+> toHornSMT p)++instance ToHornSMT a => ToHornSMT (F.Symbol, a) where+ toHornSMT (x, t) = P.parens $ F.pprint x P.<+> toHornSMT t++instance ToHornSMT a => ToHornSMT [a] where+ toHornSMT = toHornMany . fmap toHornSMT++toHornMany :: [P.Doc] -> P.Doc+toHornMany = P.parens . P.sep++toHornAnd :: (a -> P.Doc) -> [a] -> P.Doc+toHornAnd f xs = P.parens (P.vcat ("and" : (P.nest 1 . f <$> xs)))+++instance ToHornSMT F.DataDecl where+ toHornSMT (F.DDecl tc n ctors) =+ P.parens $ P.vcat [+ P.text "datatype" P.<+> P.parens (toHornSMT tc P.<+> P.int n)+ , P.parens (P.vcat (toHornSMT <$> ctors))+ ]++instance ToHornSMT F.FTycon where+ toHornSMT c+ | c == F.listFTyCon = "list"+ | otherwise = toHornSMT (F.symbol c)++instance ToHornSMT a => ToHornSMT (F.Located a) where+ toHornSMT = toHornSMT . F.val++instance ToHornSMT F.DataCtor where+ toHornSMT (F.DCtor x flds) = P.parens (toHornSMT x P.<+> toHornSMT flds)++instance ToHornSMT F.DataField where+ toHornSMT (F.DField x t) = toHornSMT (F.val x, t)++instance ToHornSMT F.Sort where+ toHornSMT = toHornSort++toHornSort :: F.Sort -> P.Doc+toHornSort (F.FVar i) = "@" P.<-> P.parens (P.int i)+toHornSort F.FInt = "Int"+toHornSort F.FReal = "Real"+toHornSort F.FFrac = "Frac"+toHornSort (F.FObj x) = toHornSMT x -- P.parens ("obj" P.<+> toHornSMT x)+toHornSort F.FNum = "num"+toHornSort t@(F.FAbs _ _) = toHornAbsApp t+toHornSort t@(F.FFunc _ _)= toHornAbsApp t+toHornSort (F.FTC c) = toHornSMT c+toHornSort t@(F.FApp _ _) = toHornFApp (F.unFApp t)+toHornSort (F.FNatNum x) = P.integer x++toHornAbsApp :: F.Sort -> P.Doc+toHornAbsApp (F.functionSort -> Just (vs, ss, s)) = P.parens ("func" P.<+> P.int (length vs) P.<+> toHornSMT ss P.<+> toHornSMT s )+toHornAbsApp _ = error "Unexpected nothing function sort"++toHornFApp :: [F.Sort] -> P.Doc+toHornFApp [t] = toHornSMT t+toHornFApp ts = toHornSMT ts++instance ToHornSMT F.Subst where+ toHornSMT (F.Su m) = toHornSMT (Misc.hashMapToAscList m)++++instance ToHornSMT F.KVar where+ toHornSMT (F.KV k) = "$" P.<-> toHornSMT k++instance ToHornSMT F.Expr where+ toHornSMT = toHornExpr++toHornExpr :: F.Expr -> P.Doc+toHornExpr (F.ESym c) = F.pprint c+toHornExpr (F.ECon c) = F.pprint c+toHornExpr (F.EVar s) = toHornSMT s+toHornExpr (F.ENeg e) = P.parens ("-" P.<+> toHornExpr e)+toHornExpr (F.EApp e1 e2) = toHornSMT [e1, e2]+toHornExpr (F.EBin o e1 e2) = toHornOp (F.toFix o) [e1, e2]+toHornExpr (F.ELet x e1 e2) = toHornMany ["let", toHornSMT [(x, e1)], toHornSMT e2]+toHornExpr (F.EIte e1 e2 e3) = toHornOp "if" [e1, e2, e3]+toHornExpr (F.ECst e t) = toHornMany ["cast", toHornSMT e, toHornSMT t]+toHornExpr (F.PNot p) = toHornOp "not" [p]+toHornExpr (F.PImp e1 e2) = toHornOp "=>" [e1, e2]+toHornExpr (F.PIff e1 e2) = toHornOp "<=>" [e1, e2]+toHornExpr e@F.PTrue = F.pprint e+toHornExpr e@F.PFalse = F.pprint e+toHornExpr (F.PAnd es) = toHornOp "and" es+toHornExpr (F.POr es) = toHornOp "or" es+toHornExpr (F.PAtom r e1 e2) = toHornOp (F.toFix r) [e1, e2]+toHornExpr (F.PAll xts p) = toHornMany ["forall", toHornSMT xts, toHornSMT p]+toHornExpr (F.PExist xts p) = toHornMany ["exists", toHornSMT xts, toHornSMT p]+toHornExpr (F.ELam b e) = toHornMany ["lam", toHornSMT b, toHornSMT e]+toHornExpr (F.ECoerc a t e) = toHornMany ["coerce", toHornSMT a, toHornSMT t, toHornSMT e]+toHornExpr (F.PKVar k su) = toHornMany [toHornSMT k, toHornSMT su]+toHornExpr (F.ETApp e s) = toHornMany ["ETApp" , toHornSMT e, toHornSMT s]+toHornExpr (F.ETAbs e s) = toHornMany ["ETAbs" , toHornSMT e, toHornSMT s]++toHornOp :: ToHornSMT a => P.Doc -> [a] -> P.Doc+toHornOp op es = toHornMany (op : (toHornSMT <$> es))
src/Language/Fixpoint/Types/Solutions.hs view
@@ -7,13 +7,11 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE TupleSections #-} {-# OPTIONS_GHC -Wno-name-shadowing #-} @@ -23,49 +21,39 @@ module Language.Fixpoint.Types.Solutions ( -- * Solution tables- Solution, GSolution- , Sol (gMap, sEnv, sEbd, sxEnv)- , updateGMap, updateGMapWithKey- , sHyp- , sScp+ Solution+ , Sol (..) , CMap -- * Solution elements- , Hyp, Cube (..), QBind, GBind+ , Hyp, Cube (..), QBind (..) , EQual (..)- , EbindSol (..) -- * Equal elements , eQual , trueEqual - -- * Gradual Solution elements- , qbToGb, gbToQbs, gbEquals, equalsGb, emptyGMap, qbExprs+ , qbExprs -- * Solution Candidates (move to SolverMonad?) , Cand - -- * Constructor- , fromList- -- * Update , update- , updateEbind -- * Lookup , lookupQBind- , lookup, glookup+ , lookup -- * Manipulating QBind , qb , qbPreds , qbFilter , qbFilterM- , gbFilterM -- * Conversion for client- , result, resultGradual+ , result -- * "Fast" Solver (DEPRECATED as unsound) , Index (..)@@ -77,7 +65,6 @@ import Prelude hiding (lookup) import GHC.Generics import Control.DeepSeq-import Control.Monad.Reader import Data.Hashable import qualified Data.Maybe as Mb import qualified Data.HashMap.Strict as M@@ -87,62 +74,41 @@ import Control.Monad (filterM) import Language.Fixpoint.Misc import Language.Fixpoint.Types.PrettyPrint--- import Language.Fixpoint.Types.Config as Cfg import Language.Fixpoint.Types.Spans import Language.Fixpoint.Types.Names import Language.Fixpoint.Types.Sorts-import Language.Fixpoint.Types.Theories import Language.Fixpoint.Types.Refinements import Language.Fixpoint.Types.Environments import Language.Fixpoint.Types.Constraints import Language.Fixpoint.Types.Substitutions-import Language.Fixpoint.SortCheck (ElabM, ElabParam(..), elaborate) import Text.PrettyPrint.HughesPJ.Compat ----------------------------------------------------------------------------------- | Update Solution ---------------------------------------------------------------------------------------------------------------------------------------------update :: Sol a QBind -> [KVar] -> [(KVar, EQual)] -> (Bool, Sol a QBind)+-- | Update Solution+--+-- @update s kqs@ sets in @s@ each KVar in @kqs@ to the corresponding QBind.+--+-- Yields a pair @(b, s')@ where @b@ is true if the mapping of any KVar was+-- changed.+--+-- Precondition: @kqs@ contains no duplicate KVars.+--+update :: Sol QBind -> [(KVar, QBind)] -> (Bool, Sol QBind) ---------------------------------------------------------------------------------update s ks kqs = {- tracepp msg -} (or bs, s')- where- kqss = groupKs ks kqs- (bs, s') = folds update1 s kqss- -- msg = printf "ks = %s, s = %s" (showpp ks) (showpp s)--folds :: (a -> b -> (c, a)) -> a -> [b] -> ([c], a)-folds f b = L.foldl' step ([], b)- where- step (cs, acc) x = (c:cs, x')- where- (c, x') = f acc x--groupKs :: [KVar] -> [(KVar, EQual)] -> [(KVar, QBind)]-groupKs ks kqs = [ (k, QB eqs) | (k, eqs) <- M.toList $ groupBase m0 kqs ]- where- m0 = M.fromList $ (,[]) <$> ks--update1 :: Sol a QBind -> (KVar, QBind) -> (Bool, Sol a QBind)-update1 s (k, qs) = (change, updateK k qs s)+update s kqs = L.foldl' step (False, s) kqs where- oldQs = lookupQBind s k- change = qbSize oldQs /= qbSize qs-+ step :: (Bool, Sol QBind) -> (KVar, QBind) -> (Bool, Sol QBind)+ step (changed, s) (k, qs) = (changed || distinctSizes, updateK k qs s)+ where+ oldQs = lookupQBind s k+ distinctSizes = qbSize oldQs /= qbSize qs -------------------------------------------------------------------------------- -- | The `Solution` data type -------------------------------------------------- ---------------------------------------------------------------------------------type Solution = Sol () QBind-type GSolution = Sol (((Symbol, Sort), Expr), GBind) QBind+type Solution = Sol QBind newtype QBind = QB [EQual] deriving (Show, Data, Typeable, Generic, Eq)-newtype GBind = GB [[EQual]] deriving (Show, Data, Typeable, Generic) -emptyGMap :: GSolution -> GSolution-emptyGMap sol = mapGMap sol (\(x,_) -> (x, GB []))--updateGMapWithKey :: [(KVar, QBind)] -> GSolution -> GSolution-updateGMapWithKey kqs sol = sol {gMap = L.foldl' (\m (k, QB eq) -> M.adjust (\(x, GB eqs) -> (x, GB (if eq `elem` eqs then eqs else eq:eqs))) k m) (gMap sol) kqs }- qb :: [EQual] -> QBind qb = QB @@ -152,22 +118,6 @@ qbExprs :: QBind -> [Expr] qbExprs (QB xs) = eqPred <$> xs -qbToGb :: QBind -> GBind-qbToGb (QB xs) = GB $ map (:[]) xs--gbToQbs :: GBind -> [QBind]-gbToQbs (GB []) = [QB [trueEqual]]-gbToQbs (GB ess) = QB <$> ess--gbEquals :: GBind -> [[EQual]]-gbEquals (GB eqs) = eqs--equalsGb :: [[EQual]] -> GBind-equalsGb = GB--gbFilterM :: Monad m => ([EQual] -> m Bool) -> GBind -> m GBind-gbFilterM f (GB eqs) = GB <$> filterM f eqs- qbSize :: QBind -> Int qbSize = length . qbEQuals @@ -178,87 +128,41 @@ qbFilterM f (QB eqs) = QB <$> filterM f eqs instance NFData QBind-instance NFData GBind instance PPrint QBind where pprintTidy k = pprintTidy k . qbEQuals ----------------------------------------------------------------------------------- | An `EbindSol` contains the relevant information for an existential-binder;--- (See tests/pos/ebind-*.fq for examples.) This is either--- 1. the constraint whose HEAD is a singleton that defines the binder, OR--- 2. the solved out TERM that we should use in place of the ebind at USES.----------------------------------------------------------------------------------data EbindSol- = EbDef [SimpC ()] Symbol -- ^ The constraint whose HEAD "defines" the Ebind- -- and the @Symbol@ for that EBind- | EbSol Expr -- ^ The solved out term that should be used at USES.- | EbIncr -- ^ EBinds not to be solved for (because they're currently being solved for)- deriving (Show, Generic, NFData)--instance PPrint EbindSol where- pprintTidy k (EbDef i x) = "EbDef:" <+> pprintTidy k i <+> pprintTidy k x- pprintTidy k (EbSol e) = "EbSol:" <+> pprintTidy k e- pprintTidy _ EbIncr = "EbIncr"-----------------------------------------------------------------------------------updateEbind :: Sol a b -> BindId -> Pred -> Sol a b----------------------------------------------------------------------------------updateEbind s i !e = case M.lookup i (sEbd s) of- Nothing -> errorstar $ "updateEBind: Unknown ebind " ++ show i- Just (EbSol e0) -> errorstar $ "updateEBind: Re-assigning ebind " ++ show i ++ " with solution: " ++ show e0- Just _ -> s { sEbd = M.insert i (EbSol e) (sEbd s) }---------------------------------------------------------------------------------- -- | A `Sol` contains the various indices needed to compute a solution, -- in particular, to compute `lhsPred` for any given constraint. ---------------------------------------------------------------------------------data Sol b a = Sol- { sEnv :: !SymEnv -- ^ Environment used to elaborate solutions- , sMap :: !(M.HashMap KVar a) -- ^ Actual solution (for cut kvar)- , gMap :: !(M.HashMap KVar b) -- ^ Solution for gradual variables+data Sol a = Sol+ { sMap :: !(M.HashMap KVar a) -- ^ Actual solution (for cut kvar) , sHyp :: !(M.HashMap KVar Hyp) -- ^ Defining cubes (for non-cut kvar)- , sScp :: !(M.HashMap KVar IBindEnv) -- ^ Set of allowed binders for kvar- , sEbd :: !(M.HashMap BindId EbindSol) -- ^ EbindSol for each existential binder- , sxEnv :: !(SEnv (BindId, Sort)) -- TODO: merge with sEnv? used for sorts of ebinds to solve ebinds in lhsPred+ , sScp :: !(M.HashMap KVar IBindEnv) -- ^ Set of binders which are in scope for every+ -- occurrence of the kvar } deriving (Generic) -deriving instance (NFData b, NFData a) => NFData (Sol b a)--updateGMap :: Sol b a -> M.HashMap KVar b -> Sol b a-updateGMap sol gmap = sol {gMap = gmap}--mapGMap :: Sol b a -> (b -> b) -> Sol b a-mapGMap sol f = sol {gMap = M.map f (gMap sol)}+deriving instance NFData a => NFData (Sol a) -instance Semigroup (Sol a b) where- s1 <> s2 = Sol { sEnv = sEnv s1 <> sEnv s2- , sMap = sMap s1 <> sMap s2- , gMap = gMap s1 <> gMap s2+instance Semigroup (Sol a) where+ s1 <> s2 = Sol { sMap = sMap s1 <> sMap s2 , sHyp = sHyp s1 <> sHyp s2 , sScp = sScp s1 <> sScp s2- , sEbd = sEbd s1 <> sEbd s2- , sxEnv = sxEnv s1 <> sxEnv s2 } -instance Monoid (Sol a b) where- mempty = Sol { sEnv = mempty- , sMap = mempty- , gMap = mempty+instance Monoid (Sol a) where+ mempty = Sol { sMap = mempty , sHyp = mempty , sScp = mempty- , sEbd = mempty- , sxEnv = mempty } mappend = (<>) -instance Functor (Sol a) where- fmap f (Sol e s m1 m2 m3 m4 m5) = Sol e (f <$> s) m1 m2 m3 m4 m5+instance Functor Sol where+ fmap f (Sol s m1 m2) = Sol (f <$> s) m1 m2 -instance (PPrint a, PPrint b) => PPrint (Sol a b) where- pprintTidy k s = vcat [ "sMap :=" <+> pprintTidy k (sMap s)- , "sEbd :=" <+> pprintTidy k (sEbd s)- ]+instance PPrint a => PPrint (Sol a) where+ pprintTidy k s = vcat [ "sMap :=" <+> pprintTidy k (sMap s) ] -------------------------------------------------------------------------------- -- | A `Cube` is a single constraint defining a KVar ---------------------------@@ -278,78 +182,27 @@ instance Show Cube where show = showpp ---------------------------------------------------------------------------------result :: Sol a QBind -> M.HashMap KVar Expr----------------------------------------------------------------------------------result s = sMap $ pAnd . fmap eqPred . qbEQuals <$> s------------------------------------------------------------------------------------resultGradual :: GSolution -> M.HashMap KVar (Expr, [Expr])+result :: Sol QBind -> M.HashMap KVar Expr ---------------------------------------------------------------------------------resultGradual s = fmap go' (gMap s)- where- go' ((_,e), GB eqss)- = (e, [PAnd $ fmap eqPred eqs | eqs <- eqss])+result s = pAnd . fmap eqPred . qbEQuals <$> sMap s ----------------------------------------------------------------------------------- | Create a Solution -------------------------------------------------------------------------------------------------------------------------------------------fromList :: SymEnv- -> [(KVar, a)]- -> [(KVar, b)]- -> [(KVar, Hyp)]- -> M.HashMap KVar IBindEnv- -> [(BindId, EbindSol)]- -> SEnv (BindId, Sort)- -> Sol a b-fromList env kGs kXs kYs z ebs xbs- = Sol env kXm kGm kYm z ebm xbs- where- kXm = M.fromList kXs- kYm = M.fromList kYs- kGm = M.fromList kGs- ebm = M.fromList ebs-----------------------------------------------------------------------------------qbPreds :: String -> Sol a QBind -> Subst -> QBind -> ElabM [(Pred, EQual)]+qbPreds :: Subst -> QBind -> [(Pred, EQual)] ---------------------------------------------------------------------------------qbPreds msg s su (QB eqs) =- do ef <- ask- pure [ (elabPred ef eq, eq) | eq <- eqs ]- where- elabPred ef eq = elaborate (ElabParam ef (atLoc eq $ "qbPreds:" ++ msg) env)- . subst su- . eqPred- $ eq- env = sEnv s+qbPreds su (QB eqs) = [ (subst su $ eqPred eq, eq) | eq <- eqs ] -------------------------------------------------------------------------------- -- | Read / Write Solution at KVar --------------------------------------------- ---------------------------------------------------------------------------------lookupQBind :: Sol a QBind -> KVar -> QBind+lookupQBind :: Sol QBind -> KVar -> QBind -------------------------------------------------------------------------------- lookupQBind s k = {- tracepp _msg $ -} Mb.fromMaybe (QB []) (lookupElab s k) where _msg = "lookupQB: k = " ++ show k ---------------------------------------------------------------------------------glookup :: GSolution -> KVar -> Either Hyp (Either QBind (((Symbol, Sort), Expr), GBind))----------------------------------------------------------------------------------glookup s k- | Just gbs <- M.lookup k (gMap s)- = Right (Right gbs)- | Just cs <- M.lookup k (sHyp s) -- non-cut variable, return its cubes- = Left cs- | Just eqs <- lookupElab s k- = Right (Left eqs) -- TODO: don't initialize kvars that have a hyp solution- | otherwise- = errorstar $ "solLookup: Unknown kvar " ++ show k-------------------------------------------------------------------------------------lookup :: Sol a QBind -> KVar -> Either Hyp QBind+lookup :: Sol QBind -> KVar -> Either Hyp QBind -------------------------------------------------------------------------------- lookup s k | Just cs <- M.lookup k (sHyp s) -- non-cut variable, return its cubes@@ -359,11 +212,11 @@ | otherwise = errorstar $ "solLookup: Unknown kvar " ++ show k -lookupElab :: Sol b QBind -> KVar -> Maybe QBind+lookupElab :: Sol QBind -> KVar -> Maybe QBind lookupElab s k = M.lookup k (sMap s) ---------------------------------------------------------------------------------updateK :: KVar -> a -> Sol b a -> Sol b a+updateK :: KVar -> a -> Sol a -> Sol a -------------------------------------------------------------------------------- updateK k qs s = s { sMap = M.insert k qs (sMap s) -- , sBot = M.delete k (sBot s)@@ -381,8 +234,8 @@ -------------------------------------------------------------------------------- data EQual = EQL { eqQual :: !Qualifier- , eqPred :: !Expr- , _eqArgs :: ![Expr]+ , eqPred :: !Expr -- ^ predicate obtained by instantiating the qualifier+ , _eqArgs :: ![Expr] -- ^ actual arguments used to instantiate the qualifier } deriving (Eq, Show, Data, Typeable, Generic) instance Loc EQual where@@ -396,7 +249,7 @@ instance NFData EQual -{- EQL :: q:_ -> p:_ -> ListX F.Expr {q_params q} -> _ @-}+-- | @eQual q xs@ instantiates @q@ with the arguments in @xs@ eQual :: Qualifier -> [Symbol] -> EQual eQual q xs = {- tracepp "eQual" $ -} EQL q p es where
src/Language/Fixpoint/Types/Sorts.hs view
@@ -34,11 +34,13 @@ , strFTyCon , setFTyCon , mapFTyCon -- TODO: hide these+ , ffldFTyCon , mapFVar , basicSorts, intSort, realSort, boolSort, strSort, funcSort -- , bitVec32Sort, bitVec64Sort , setSort, bitVecSort, bagSort , arraySort+ , finfieldSort , sizedBitVecSort , mapSort, charSort , listFTyCon@@ -66,7 +68,7 @@ , sortSymbols , substSort - , isBool, isNumeric, isReal, isString, isSet, isMap, isBag, isArray, isPolyInst+ , isBool, isNumeric, isReal, isString, isSet, isMap, isBag, isArray, isFinfield, isPolyInst -- * User-defined ADTs , DataField (..)@@ -152,7 +154,7 @@ defStrInfo = False charFTyCon, intFTyCon, boolFTyCon, realFTyCon, funcFTyCon, numFTyCon :: FTycon-strFTyCon, listFTyCon, mapFTyCon, bagFTyCon, setFTyCon :: FTycon+strFTyCon, listFTyCon, mapFTyCon, bagFTyCon, setFTyCon, ffldFTyCon :: FTycon intFTyCon = TC (dummyLoc "int" ) numTcInfo boolFTyCon = TC (dummyLoc boolLConName) defTcInfo realFTyCon = TC (dummyLoc "real" ) realTcInfo@@ -164,6 +166,7 @@ setFTyCon = TC (dummyLoc setConName ) defTcInfo mapFTyCon = TC (dummyLoc mapConName ) defTcInfo bagFTyCon = TC (dummyLoc bagConName ) defTcInfo+ffldFTyCon = TC (dummyLoc ffldConName ) defTcInfo isListConName :: LocSymbol -> Bool isListConName x = c == listConName || c == listLConName --"List"@@ -205,6 +208,14 @@ isArrayTC :: FTycon -> Bool isArrayTC (TC z _) = isArrayConName z +isFinfieldConName :: LocSymbol -> Bool+isFinfieldConName x = c == ffldConName+ where+ c = val x++isFinfieldTC :: FTycon -> Bool+isFinfieldTC (TC z _) = isFinfieldConName z+ sizeBv :: FTycon -> Maybe Int sizeBv tc = do let s = val $ fTyconSymbol tc@@ -293,6 +304,7 @@ go t@FReal = t go t@FNum = t go t@FFrac = t+ go t@(FNatNum _) = t -------------------------------------------------------------------------------- -- | Sorts ---------------------------------------------------------------------@@ -301,12 +313,13 @@ | FReal | FNum -- ^ numeric kind for Num tyvars | FFrac -- ^ numeric kind for Fractional tyvars- | FObj !Symbol -- ^ uninterpreted type- | FVar !Int -- ^ fixpoint type variable- | FFunc !Sort !Sort -- ^ function- | FAbs !Int !Sort -- ^ type-abstraction- | FTC !FTycon- | FApp !Sort !Sort -- ^ constructed type+ | FObj !Symbol -- ^ uninterpreted type+ | FVar !Int -- ^ fixpoint type variable+ | FFunc !Sort !Sort -- ^ function+ | FAbs !Int !Sort -- ^ type-abstraction+ | FTC !FTycon+ | FApp !Sort !Sort -- ^ constructed type+ | FNatNum !Integer -- ^ typelevel natural numeral deriving (Eq, Ord, Show, Data, Typeable, Generic, ToJSON, FromJSON) instance PPrint Sort where@@ -423,6 +436,10 @@ isArray (FTC c) = isArrayTC c isArray _ = False +isFinfield :: Sort -> Bool+isFinfield (FTC c) = isFinfieldTC c+isFinfield _ = False+ isChar :: Sort -> Bool isChar (FTC c) = c == charFTyCon isChar _ = False@@ -490,6 +507,7 @@ toFixSort t@(FFunc _ _)= toFixAbsApp t toFixSort (FTC c) = toFix c toFixSort t@(FApp _ _) = toFixFApp (unFApp t)+toFixSort (FNatNum x) = toFix x toFixAbsApp :: Sort -> Doc toFixAbsApp (functionSort -> Just (vs, ss, s)) =@@ -571,6 +589,9 @@ arraySort :: Sort -> Sort -> Sort arraySort = FApp . FApp (FTC (symbolFTycon' arrayConName))++finfieldSort :: Sort -> Sort+finfieldSort = FApp (FTC ffldFTyCon) symbolFTycon' :: Symbol -> FTycon symbolFTycon' = symbolFTycon . dummyLoc
src/Language/Fixpoint/Types/Substitutions.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE FlexibleInstances #-} {-# OPTIONS_GHC -Wno-orphans #-}+{-# LANGUAGE InstanceSigs #-} -- | This module contains the various instances for Subable, -- which (should) depend on the visitors, and hence cannot@@ -12,14 +13,18 @@ , substExcept , substfExcept , subst1Except+ , substSymbolsSet+ , rapierSubstExpr , targetSubstSyms , filterSubst , catSubst , exprSymbolsSet+ , extendSubst , meetReft , pprReft ) where +import Data.List as List import Data.Maybe import qualified Data.HashMap.Strict as M import qualified Data.HashSet as S@@ -61,7 +66,8 @@ targetSubstSyms :: Subst -> [Symbol] targetSubstSyms (Su ms) = syms $ M.elems ms -+substSymbolsSet :: Subst -> S.HashSet Symbol+substSymbolsSet (Su m) = S.unions $ map exprSymbolsSet (M.elems m) instance Subable () where syms _ = []@@ -120,17 +126,19 @@ subSymbol Nothing x = x subSymbol a b = errorstar (printf "Cannot substitute symbol %s with expression %s" (showFix b) (showFix a)) -substfLam :: (Symbol -> Expr) -> (Symbol, Sort) -> Expr -> Expr-substfLam f s@(x, _) e = ELam s (substf (\y -> if y == x then EVar x else f y) e)+captureAvoiding :: Symbol -> (Symbol -> Expr) -> Symbol -> Expr+captureAvoiding x f y = if y == x then EVar x else f y instance Subable Expr where syms = exprSymbols substa f = substf (EVar . f)+ substf :: (Symbol -> Expr) -> Expr -> Expr substf f (EApp s e) = EApp (substf f s) (substf f e)- substf f (ELam x e) = substfLam f x e+ substf f (ELam (x,t) e) = ELam (x, t) (substf (captureAvoiding x f) e) substf f (ECoerc a t e) = ECoerc a t (substf f e) substf f (ENeg e) = ENeg (substf f e) substf f (EBin op e1 e2) = EBin op (substf f e1) (substf f e2)+ substf f (ELet x e1 e2) = ELet x (substf f e1) (substf (captureAvoiding x f) e2) substf f (EIte p e1 e2) = EIte (substf f p) (substf f e1) (substf f e2) substf f (ECst e so) = ECst (substf f e) so substf f (EVar x) = f x@@ -141,43 +149,154 @@ substf f (PIff p1 p2) = PIff (substf f p1) (substf f p2) substf f (PAtom r e1 e2) = PAtom r (substf f e1) (substf f e2) substf f (PKVar k (Su su)) = PKVar k (Su $ M.map (substf f) su)- substf _ (PAll _ _) = errorstar "substf: FORALL"- substf f (PGrad k su i e)= PGrad k su i (substf f e)+ substf _ (PAll _ _) = errorstar "substf: FORALL"+ substf f (PExist xts e) = PExist xts (substf f e) substf _ p = p - subst su (EApp f e) = EApp (subst su f) (subst su e)- subst su (ELam x e) = ELam x (subst (removeSubst su (fst x)) e)- subst su (ECoerc a t e) = ECoerc a t (subst su e)- subst su (ENeg e) = ENeg (subst su e)- subst su (EBin op e1 e2) = EBin op (subst su e1) (subst su e2)- subst su (EIte p e1 e2) = EIte (subst su p) (subst su e1) (subst su e2)- subst su (ECst e so) = ECst (subst su e) so- subst su (EVar x) = appSubst su x- subst su (PAnd ps) = PAnd $ map (subst su) ps- subst su (POr ps) = POr $ map (subst su) ps- subst su (PNot p) = PNot $ subst su p- subst su (PImp p1 p2) = PImp (subst su p1) (subst su p2)- subst su (PIff p1 p2) = PIff (subst su p1) (subst su p2)- subst su (PAtom r e1 e2) = PAtom r (subst su e1) (subst su e2)- subst su (PKVar k su') = PKVar k $ su' `catSubst` su- subst su (PGrad k su' i e) = PGrad k (su' `catSubst` su) i (subst su e)- subst su (PAll bs p)- | disjoint su bs = PAll bs $ subst su p --(substExcept su (fst <$> bs)) p- | otherwise = errorstar "subst: PAll (without disjoint binds)"- subst su (PExist bs p)- | disjoint su bs = PExist bs $ subst su p --(substExcept su (fst <$> bs)) p- | otherwise = errorstar ("subst: EXISTS (without disjoint binds)" ++ show (bs, su, p))- subst _ p = p+ subst = go+ where+ -- The auxiliary go function skips the HasCallStack constraint on every+ -- recursive call. In case of error, the call stack only contains the+ -- point at which subst was first called.+ go su e0 = case e0 of+ EApp f e ->+ EApp (go su f) (go su e)+ ELam x e ->+ let su' = removeSubst su (fst x)+ in ELam x (go su' e)+ ELet x e1 e2 ->+ let su' = removeSubst su x+ in ELet x (go su e1) (go su' e2)+ ECoerc a t e ->+ ECoerc a t (go su e)+ ENeg e ->+ ENeg (go su e)+ EBin op e1 e2 ->+ EBin op (go su e1) (go su e2)+ EIte p e1 e2 ->+ EIte (go su p) (go su e1) (go su e2)+ ECst e so ->+ ECst (go su e) so+ EVar x ->+ appSubst su x+ PAnd ps ->+ PAnd $ map (go su) ps+ POr ps ->+ POr $ map (go su) ps+ PNot p ->+ PNot $ go su p+ PImp p1 p2 ->+ PImp (go su p1) (go su p2)+ PIff p1 p2 ->+ PIff (go su p1) (go su p2)+ PAtom r e1 e2 ->+ PAtom r (go su e1) (go su e2)+ PKVar k su' ->+ PKVar k $ su' `catSubst` su+ PAll bs p+ | disjoint su bs ->+ PAll bs $ go su p --(substExcept su (fst <$> bs)) p+ | otherwise ->+ errorstar $ unlines+ [ "subst: FORALL without disjoint binds"+ , "su: " ++ showpp su+ , "expr: " ++ showpp e0+ ]+ PExist bs p+ | disjoint su bs ->+ PExist bs $ go su p --(substExcept su (fst <$> bs)) p+ | otherwise ->+ errorstar $ unlines+ [ "subst: EXISTS without disjoint binds"+ , "su: " ++ showpp su+ , "expr: " ++ showpp e0+ ]+ p ->+ p removeSubst :: Subst -> Symbol -> Subst removeSubst (Su su) x = Su $ M.delete x su +-- | Rapier style capture-avoiding substitution+--+-- The scope set parameter must contain any symbols that are expected+-- to appear free in the result expression. Typically, this is the set of+-- symbols that are free in the range of the substitution, plus any symbols+-- that are already free in the input expression.+rapierSubstExpr :: S.HashSet Symbol -> Subst -> Expr -> Expr+rapierSubstExpr s su e0 =+ let go = rapierSubstExpr+ in case e0 of+ EApp f e -> EApp (go s su f) (go s su e)+ ELam (x, t) e ->+ if x `S.member` s then+ let x' = fresh x+ su' = extendSubst su x (EVar x')+ in ELam (x', t) (go (S.insert x' s) su' e)+ else+ ELam (x, t) (go (S.insert x s) (removeSubst su x) e)+ ELet x e1 e2 ->+ if x `S.member` s then+ let x' = fresh x+ su' = extendSubst su x (EVar x')+ in ELet x' (go s su e1) (go (S.insert x' s) su' e2)+ else+ let su' = removeSubst su x+ in ELet x (go s su e1) (go (S.insert x s) su' e2)++ ECoerc a t e -> ECoerc a t (go s su e)+ ENeg e -> ENeg (go s su e)+ EBin op e1 e2 -> EBin op (go s su e1) (go s su e2)+ EIte p e1 e2 -> EIte (go s su p) (go s su e1) (go s su e2)+ ECst e so -> ECst (go s su e) so+ EVar x -> appSubst su x+ PAnd ps -> PAnd $ map (go s su) ps+ POr ps -> POr $ map (go s su) ps+ PNot p -> PNot $ go s su p+ PImp p1 p2 -> PImp (go s su p1) (go s su p2)+ PIff p1 p2 -> PIff (go s su p1) (go s su p2)+ PAtom r e1 e2 -> PAtom r (go s su e1) (go s su e2)+ PKVar k su' -> PKVar k $ catSubstGo su' su+ PAll bs p ->+ let mfs = map (maybeFresh . fst) bs+ fs = map (either (\x -> (x, x)) id) mfs+ su' = List.foldl' (\su1 (x, x') -> extendSubst su1 x (EVar x')) su fs+ bs' = zip (map (either id snd) mfs) (map snd bs)+ s' = foldr (S.insert . fst) s bs'+ in+ PAll bs' $ go s' su' p+ PExist bs p ->+ let mfs = map (maybeFresh . fst) bs+ fs = map (either (\x -> (x, x)) id) mfs+ su' = List.foldl' (\su1 (x, x') -> extendSubst su1 x (EVar x')) su fs+ bs' = zip (map (either id snd) mfs) (map snd bs)+ s' = foldr (S.insert . fst) s bs'+ in+ PExist bs' $ go s' su' p+ p -> p+ where+ fresh :: Symbol -> Symbol+ fresh x = head $ dropWhile (`S.member` s) candidates+ where+ candidates = [ renameSubstSymbol x i | i <- [0..] ]++ maybeFresh x =+ if x `S.member` s then Right (x, fresh x) else Left x++ catSubstGo :: Subst -> Subst -> Subst+ catSubstGo (Su s1) su2@(Su s2) = Su $ M.union s1' s2+ where+ s1' = rapierSubstExpr s su2 <$> s1++extendSubst :: Subst -> Symbol -> Expr -> Subst+extendSubst (Su m) x e = Su $ M.insert x e m+ disjoint :: Subst -> [(Symbol, Sort)] -> Bool disjoint (Su su) bs = S.null $ suSyms `S.intersection` bsSyms where- suSyms = S.fromList $ syms (M.elems su) ++ syms (M.keys su)- bsSyms = S.fromList $ syms $ fst <$> bs+ suSyms = S.fromList $ syms (M.elems su) ++ M.keys su+ bsSyms = S.fromList $ fst <$> bs meetReft :: Reft -> Reft -> Reft meetReft (Reft (v, ra)) (Reft (v', ra'))
src/Language/Fixpoint/Types/Templates.hs view
@@ -46,6 +46,8 @@ = matchesTemplate (xs, t) e matchesTemplate (xs, EBin b t1 t2) (EBin b' e1 e2) = b == b' && matchesTemplate (xs, t1) e1 && matchesTemplate (xs, t2) e2+matchesTemplate (xs, ELet x t1 t2) (ELet x' e1 e2)+ = x == x' && matchesTemplate (xs, t1) e1 && matchesTemplate (xs, t2) e2 matchesTemplate (xs, EIte t1 t2 t3) (EIte e1 e2 e3) = matchesTemplate (xs, t1) e1 && matchesTemplate (xs, t2) e2 && matchesTemplate (xs, t3) e3 matchesTemplate (xs, ECst t s) (ECst e s')@@ -72,8 +74,6 @@ = s == s' && matchesTemplate (xs, t) e matchesTemplate (xs, PExist s t) (PExist s' e) = s == s' && matchesTemplate (xs, t) e-matchesTemplate (xs, PGrad s1 s2 s3 t) (PGrad s1' s2' s3' e)- = s1 == s1' && s2 == s2' && s3 == s3' && matchesTemplate (xs, t) e matchesTemplate (xs, ECoerc s1 s2 t) (ECoerc s1' s2' e) = s1 == s1' && s2 == s2' && matchesTemplate (xs, t) e matchesTemplate (_, t) e
src/Language/Fixpoint/Types/Theories.hs view
@@ -20,11 +20,18 @@ -- * Theory Sorts , SmtSort (..)+ , FuncSort , sortSmtSort , isIntSmtSort + , mergeTopAppls+ , pushAppls+ , popAppls+ , peekAppls+ -- * Symbol Environments , SymEnv (..)+ , SymM , symEnv , symEnvSort , symEnvTheory@@ -32,9 +39,10 @@ , deleteSymEnv , insertsSymEnv , symbolAtName- , symbolAtSmtName+ , symbolAtSortIndex -- * Coercing sorts in environments+ , coerceSort , coerceEnv , coerceSortEnv , TheorySymbols(..)@@ -45,12 +53,13 @@ import Data.Typeable (Typeable) import Data.Hashable import GHC.Generics (Generic)+import Control.Applicative+import Control.Monad.State import Control.DeepSeq import Language.Fixpoint.Types.Config import Language.Fixpoint.Types.PrettyPrint import Language.Fixpoint.Types.Names import Language.Fixpoint.Types.Sorts-import Language.Fixpoint.Types.Errors import Language.Fixpoint.Types.Environments import Text.PrettyPrint.HughesPJ.Compat@@ -69,41 +78,96 @@ -------------------------------------------------------------------------------- -- | 'SymEnv' is used to resolve the 'Sort' and 'Sem' of each 'Symbol' --------------------------------------------------------------------------------++-- | Apply tags already used to declare @apply@ symbols in the SMT solver.+--+-- The tags are organized in a stack because every time we pop the SMT solver+-- state, it forgets the tags declared since the last push.+--+-- Each entry in the stack describes the integer tag corresponding to a+-- particular function sort. Every time we issue a `push` a new level+-- is added to the stack, and correspondingly, a `pop` removes a level.+--+-- See 'seApplsCur' in 'SymEnv' for details about actually declaring the+-- tags to the SMT solver.+type Appls = [M.HashMap FuncSort Int]++lookupAppls :: FuncSort -> Appls -> Maybe Int+lookupAppls fs = foldr (\hm acc -> acc <|> M.lookup fs hm) Nothing++mergeTopAppls :: M.HashMap FuncSort Int -> Appls -> Appls+mergeTopAppls m (top : rest) = (top <> m) : rest+mergeTopAppls m [] = [m]++pushAppls :: Appls -> Appls+pushAppls aps = M.empty : aps++popAppls :: Appls -> Appls+popAppls [] = []+popAppls (_:xs) = xs++peekAppls :: Appls -> Maybe (M.HashMap FuncSort Int)+peekAppls [] = Nothing+peekAppls (x:_) = Just x+ data SymEnv = SymEnv- { seSort :: !(SEnv Sort) -- ^ Sorts of *all* defined symbols- , seTheory :: !(SEnv TheorySymbol) -- ^ Information about theory-specific Symbols- , seData :: !(SEnv DataDecl) -- ^ User-defined data-declarations- , seLits :: !(SEnv Sort) -- ^ Distinct Constant symbols- , seAppls :: !(M.HashMap FuncSort Int) -- ^ Types at which `apply` was used;- -- see [NOTE:apply-monomorphization]+ { seSort :: !(SEnv Sort) -- ^ Sorts of *all* defined symbols+ , seTheory :: !(SEnv TheorySymbol) -- ^ Information about theory-specific Symbols+ , seData :: !(SEnv DataDecl) -- ^ User-defined data-declarations+ , seLits :: !(SEnv Sort) -- ^ Distinct Constant symbols++ -- | Apply tags already declared in the SMT solver.+ --+ -- This is inspected when serializing applications of functions to determine+ -- if a new tag needs to be created for a given function sort+ -- (@funcSortIndex@).+ , seAppls :: !Appls++ -- | Apply tags that have been created while serializing expressions for the+ -- SMT solver, but which have not been used to declare apply symbols yet in+ -- the SMT solver.+ --+ -- The apply symbols using the tags are declared whenever we need to send+ -- the serialized expressions to the SMT solver (using @funcSortVars@). At+ -- this point, the contents of this map are merged into the top of the+ -- 'seAppls' stack, and @seApplsCur@ is cleared.+ , seApplsCur :: !(M.HashMap FuncSort Int)+ , seIx :: !Int -- ^ Largest unused index for sorts } deriving (Eq, Show, Data, Typeable, Generic) {- type FuncSort = {v:Sort | isFFunc v} @-} type FuncSort = (SmtSort, SmtSort) +-- | Generating SMT expressions is a stateful process because new symbols ('apply', 'coerce',+-- 'smt_lambda' and 'lam_arg') need to be emitted with unique ids for each newly encountered+-- function sort. The 'SymM' monad carries the 'SymEnv' state required to track the ids.+-- The state updates are performed in `L.F.Smt.Serialize` (functions `smt2App`, `smt2Coerc`,+-- `smt2Lam` and `smtLamArg`, correspondingly).+type SymM a = State SymEnv a+ instance NFData SymEnv instance S.Store SymEnv instance Semigroup SymEnv where- e1 <> e2 = SymEnv { seSort = seSort e1 <> seSort e2- , seTheory = seTheory e1 <> seTheory e2- , seData = seData e1 <> seData e2- , seLits = seLits e1 <> seLits e2- , seAppls = seAppls e1 <> seAppls e2+ e1 <> e2 = SymEnv { seSort = seSort e1 <> seSort e2+ , seTheory = seTheory e1 <> seTheory e2+ , seData = seData e1 <> seData e2+ , seLits = seLits e1 <> seLits e2+ , seAppls = zipWith (<>) (seAppls e1) (seAppls e2)+ , seApplsCur = seApplsCur e1 <> seApplsCur e2+ , seIx = seIx e1 `max` seIx e2 } instance Monoid SymEnv where- mempty = SymEnv emptySEnv emptySEnv emptySEnv emptySEnv mempty+ mempty = SymEnv emptySEnv emptySEnv emptySEnv emptySEnv [] mempty 0 mappend = (<>) symEnv :: SEnv Sort -> SEnv TheorySymbol -> [DataDecl] -> SEnv Sort -> [Sort] -> SymEnv-symEnv xEnv fEnv ds ls ts = SymEnv xEnv' fEnv dEnv ls sortMap+symEnv xEnv fEnv ds ls _ = SymEnv xEnv' fEnv dEnv ls [] mempty 0 where xEnv' = unionSEnv xEnv wiredInEnv dEnv = fromListSEnv [(symbol d, d) | d <- ds]- sortMap = M.fromList (zip smts [0..])- smts = funcSorts dEnv ts -- | These are "BUILT-in" polymorphic functions which are -- UNINTERPRETED but POLYMORPHIC, hence need to go through@@ -114,88 +178,6 @@ , (tyCastName, FAbs 0 $ FAbs 1 $ FFunc (FVar 0) (FVar 1)) ] ---- | 'funcSorts' attempts to compute a list of all the input-output sorts--- at which applications occur. This is a gross hack; as during unfolding--- we may create _new_ terms with weird new sorts. Ideally, we MUST allow--- for EXTENDING the apply-sorts with those newly created terms.--- the solution is perhaps to *preface* each VC query of the form------ push--- assert p--- check-sat--- pop------ with the declarations needed to make 'p' well-sorted under SMT, i.e.--- change the above to------ declare apply-sorts--- push--- assert p--- check-sat--- pop------ such a strategy would NUKE the entire apply-sort machinery from the CODE base.--- [TODO]: dynamic-apply-declaration--funcSorts :: SEnv DataDecl -> [Sort] -> [FuncSort]-funcSorts dEnv ts = [ (t1, t2) | t1 <- smts, t2 <- smts]- where- smts = Misc.sortNub $ concat $ [ tx t1 ++ tx t2 | FFunc t1 t2 <- ts ]- tx = inlineArrSetBag False dEnv---- Related to the above, after merging #688, we now allow types other than--- Int to which Arrays/Sets/Bags can be applied.--- However, the `sortSmtSort` function below, previously used in `funcSorts`,--- only instantiates type variables at Ints. This causes the solver to crash--- when PLE generates apply queries for polymorphic sets (see--- https://github.com/ucsd-progsys/liquidhaskell/issues/2438). The following--- pair of functions is a temporary fix for this - it generates additional--- array/set/bag sorts instantiated at all user types for a "polymorphic depth 1"--- (i.e., `Array (Foo Int) Int` but not `Array (Foo (Foo Int)) Int`, to keep--- the applys table from blowing up exponentially). Ultimately, a general--- solution should be implemented for generating ad-hoc sets of applys on the--- fly, as described above.--inlineArrSetBag :: Bool -> SEnv DataDecl -> Sort -> [SmtSort]-inlineArrSetBag isASB env t = go . unAbs $ t- where- m = sortAbs t- go (FFunc _ _) = [SInt]- go FInt = [SInt]- go FReal = [SReal]- go t- | t == boolSort = [SBool]- | isString t = [SString]- go (FVar _)- | isASB = SInt : map (\q -> let dd = snd q in- SData (ddTyCon dd) (replicate (ddVars dd) SInt))- (M.toList $ seBinds env)- | otherwise = [SInt]- go t- | (ct:ts) <- unFApp t = inlineArrSetBagFApp m env ct ts- | otherwise = error "Unexpected empty 'unFApp t'"--inlineArrSetBagFApp :: Int -> SEnv DataDecl -> Sort -> [Sort] -> [SmtSort]-inlineArrSetBagFApp m env = go- where- go (FTC c) [a]- | setConName == symbol c = SSet <$> inlineArrSetBag True env a- go (FTC c) [a]- | bagConName == symbol c = SBag <$> inlineArrSetBag True env a- go (FTC c) [a, b]- | arrayConName == symbol c = SArray <$> inlineArrSetBag True env a <*> inlineArrSetBag True env b- go (FTC bv) [FTC s]- | bitVecName == symbol bv- , Just n <- sizeBv s = [SBitVec n]- go s []- | isString s = [SString]- go (FTC c) ts- | Just n <- tyArgs c env- , let i = n - length ts = [SData c ((inlineArrSetBag False env . FAbs m =<< ts) ++ replicate i SInt)]- go _ _ = [SInt]-- symEnvTheory :: Symbol -> SymEnv -> Maybe TheorySymbol symEnvTheory x env = lookupSEnv x (seTheory env) @@ -211,20 +193,31 @@ insertsSymEnv :: SymEnv -> [(Symbol, Sort)] -> SymEnv insertsSymEnv = L.foldl' (\env (x, s) -> insertSymEnv x s env) -symbolAtName :: (PPrint a) => Symbol -> SymEnv -> a -> Sort -> Text-symbolAtName mkSym env e = symbolAtSmtName mkSym env e . ffuncSort env-{-# SCC symbolAtName #-}+symbolAtSortIndex :: Symbol -> Int -> Text+symbolAtSortIndex mkSym si = appendSymbolText mkSym . Text.pack . show $ si -symbolAtSmtName :: (PPrint a) => Symbol -> SymEnv -> a -> FuncSort -> Text-symbolAtSmtName mkSym env e =- -- formerly: intSymbol mkSym . funcSortIndex env e- appendSymbolText mkSym . Text.pack . show . funcSortIndex env e-{-# SCC symbolAtSmtName #-}+symbolAtName :: Symbol -> Sort -> SymM Text+symbolAtName mkSym s =+ do env <- get+ fsi <- funcSortIndex (ffuncSort env s)+ pure $ symbolAtSortIndex mkSym fsi+{-# SCC symbolAtName #-} -funcSortIndex :: (PPrint a) => SymEnv -> a -> FuncSort -> Int-funcSortIndex env e fs = M.lookupDefault err fs (seAppls env)- where- err = panic ("Unknown func-sort: " ++ show fs ++ " for " ++ showpp e)+-- See 'seAppls' and 'seApplsCur' in 'SymEnv' for explanation.+funcSortIndex :: FuncSort -> SymM Int+funcSortIndex fs =+ do env <- get+ let aps = seAppls env+ let apsc = seApplsCur env+ case lookupAppls fs aps of+ Just i -> pure i+ Nothing ->+ case M.lookup fs apsc of+ Just i -> pure i+ Nothing ->+ do let i = seIx env+ modify (\env -> env { seApplsCur = M.insert fs i apsc , seIx = 1 + i })+ pure i ffuncSort :: SymEnv -> Sort -> FuncSort ffuncSort env t = {- tracepp ("ffuncSort " ++ showpp (t1,t2)) -} (tx t1, tx t2)@@ -292,8 +285,11 @@ | SBool | SReal | SString+ --- CVC(5) only | SSet !SmtSort | SBag !SmtSort+ | SFFld !Integer+ --- | SArray !SmtSort !SmtSort | SBitVec !Int | SVar !Int@@ -334,9 +330,11 @@ -- HKT go t@(FVar _) ts = SApp (sortSmtSort poly env <$> (t:ts)) go (FTC c) [a]- | setConName == symbol c = SSet (sortSmtSort poly env a)+ | setConName == symbol c = SSet (sortSmtSort poly env a) go (FTC c) [a]- | bagConName == symbol c = SBag (sortSmtSort poly env a)+ | bagConName == symbol c = SBag (sortSmtSort poly env a)+ go (FTC c) [FNatNum n]+ | ffldConName == symbol c = SFFld n go (FTC c) [a, b] | arrayConName == symbol c = SArray (sortSmtSort poly env a) (sortSmtSort poly env b) go (FTC bv) [FTC s]@@ -362,6 +360,7 @@ pprintTidy _ SString = text "Str" pprintTidy k (SSet a) = ppParens k (text "Set") [a] pprintTidy k (SBag a) = ppParens k (text "Bag") [a]+ pprintTidy _ (SFFld n) = text "FiniteField" <+> integer n pprintTidy k (SArray a b) = ppParens k (text "Array") [a, b] pprintTidy _ (SBitVec n) = text "BitVec" <+> int n pprintTidy _ (SVar i) = text "@" <-> int i@@ -376,13 +375,18 @@ -------------------------------------------------------------------------------- coerceSortEnv :: ElabFlags -> SEnv Sort -> SEnv Sort-coerceSortEnv ef ss = (if elabSetBag ef then coerceSetBagToArray else id) . coerceMapToArray <$> ss+coerceSortEnv ef ss = coerceSort ef <$> ss +coerceSort :: ElabFlags -> Sort -> Sort+coerceSort ef = (if elabSetBag ef then coerceSetBagToArray else id) . coerceMapToArray+ coerceEnv :: ElabFlags -> SymEnv -> SymEnv coerceEnv slv env =- SymEnv { seSort = coerceSortEnv slv (seSort env)- , seTheory = seTheory env- , seData = seData env- , seLits = seLits env- , seAppls = seAppls env+ SymEnv { seSort = coerceSortEnv slv (seSort env)+ , seTheory = seTheory env+ , seData = seData env+ , seLits = seLits env+ , seAppls = seAppls env+ , seApplsCur = seApplsCur env+ , seIx = seIx env }
src/Language/Fixpoint/Types/Utils.hs view
@@ -31,14 +31,14 @@ -------------------------------------------------------------------------------- -- | Compute the domain of a kvar ---------------------------------------------------------------------------------kvarDomain :: SInfo a -> KVar -> [Symbol]+kvarDomain :: GInfo c a -> KVar -> [Symbol] -------------------------------------------------------------------------------- kvarDomain si k = domain (bs si) (getWfC si k) domain :: BindEnv a -> WfC a -> [Symbol] domain be wfc = fst3 (wrft wfc) : map fst (envCs be $ wenv wfc) -getWfC :: SInfo a -> KVar -> WfC a+getWfC :: GInfo c a -> KVar -> WfC a getWfC si k = ws si M.! k --------------------------------------------------------------------------------@@ -49,19 +49,20 @@ reftFreeVars r@(Reft (v, _)) = S.delete v $ S.fromList $ syms r ----------------------------------------------------------------------------------- | Split a SortedReft into its concrete and KVar components+-- | Split a SortedReft into its concrete and KVar conjuncts+--+-- Produces @(concrete conjunts, normal kvars)@ ---------------------------------------------------------------------------------sortedReftConcKVars :: Symbol -> SortedReft -> ([Pred], [KVSub], [KVSub])-sortedReftConcKVars x sr = go [] [] [] ves+sortedReftConcKVars :: Symbol -> SortedReft -> ([Pred], [KVSub])+sortedReftConcKVars x sr = go [] [] ves where ves = [(v, p `subst1` (v, eVar x)) | Reft (v, p) <- rs ] rs = reftConjuncts (sr_reft sr) t = sr_sort sr - go ps ks gs ((v, PKVar k su ):xs) = go ps (KVS v t k su:ks) gs xs- go ps ks gs ((v, PGrad k su _ _):xs) = go ps ks (KVS v t k su:gs) xs- go ps ks gs ((_, p):xs) = go (p:ps) ks gs xs- go ps ks gs [] = (ps, ks, gs)+ go ps ks ((v, PKVar k su ):xs) = go ps (KVS v t k su:ks) xs+ go ps ks ((_, p):xs) = go (p:ps) ks xs+ go ps ks [] = (ps, ks) -------------------------------------------------------------------------------
src/Language/Fixpoint/Types/Visitor.hs view
@@ -33,7 +33,7 @@ , envKVars , envKVarsN , rhsKVars- , mapKVars, mapKVars', mapGVars', mapKVarSubsts+ , mapKVars, mapKVars', mapKVarSubsts , mapExpr, mapExprOnExpr, mapMExpr -- * Coercion Substitutions@@ -112,6 +112,7 @@ step (EApp e1 e2) = EApp (vE e1) (vE e2) step (ENeg e) = ENeg (vE e) step (EBin o e1 e2) = EBin o (vE e1) (vE e2)+ step (ELet x e1 e2) = ELet x (vE e1) (vE e2) step (EIte p e1 e2) = EIte (vE p) (vE e1) (vE e2) step (ECst e t) = ECst (vE e) t step (PAnd ps) = PAnd (map vE ps)@@ -127,7 +128,6 @@ step (ETApp e s) = ETApp (vE e) s step (ETAbs e s) = ETAbs (vE e) s step p@(PKVar _ _) = p- step (PGrad k su i e) = PGrad k su i (vE e) instance Visitable Reft where transE v (Reft (x, ra)) = Reft (x, transE v ra)@@ -164,7 +164,7 @@ aenvEqs = transE v <$> aenvEqs x, aenvSimpl = transE v <$> aenvSimpl x }- + instance Visitable Equation where transE v eq = eq { eqBody = transE v (eqBody eq)@@ -180,12 +180,12 @@ rn <- newIORef a result <- runReaderT (f v c x) rn finalAcc <- readIORef rn- return (result, finalAcc) + return (result, finalAcc) type FoldM acc = ReaderT (IORef acc) IO accum :: (Monoid a) => a -> FoldM a ()-accum !z = do +accum !z = do ref <- ask liftIO $ modifyIORef' ref (mappend z) @@ -259,6 +259,7 @@ step !c (EApp f e) = EApp <$> vE c f <*> vE c e step !c (ENeg e) = ENeg <$> vE c e step !c (EBin o e1 e2) = EBin o <$> vE c e1 <*> vE c e2+ step !c (ELet x e1 e2) = ELet x <$> vE c e1 <*> vE c e2 step !c (EIte p e1 e2) = EIte <$> vE c p <*> vE c e1 <*> vE c e2 step !c (ECst e t) = (`ECst` t) <$> vE c e step !c (PAnd ps) = PAnd <$> (vE c `traverse` ps)@@ -274,7 +275,6 @@ step !c (ETApp e s) = (`ETApp` s) <$> vE c e step !c (ETAbs e s) = (`ETAbs` s) <$> vE c e step _ p@(PKVar _ _) = return p- step !c (PGrad k su i e) = PGrad k su i <$> vE c e mapKVars :: Visitable t => (KVar -> Maybe Expr) -> t -> t mapKVars f = mapKVars' f'@@ -286,19 +286,9 @@ where txK (PKVar k su) | Just p' <- f (k, su) = subst su p'- txK (PGrad k su _ _)- | Just p' <- f (k, su) = subst su p' txK p = p --mapGVars' :: Visitable t => ((KVar, Subst) -> Maybe Expr) -> t -> t-mapGVars' f = trans txK- where- txK (PGrad k su _ _)- | Just p' <- f (k, su) = subst su p'- txK p = p- mapExpr :: Visitable t => (Expr -> Expr) -> t -> t mapExpr f = trans f @@ -318,6 +308,10 @@ let !e1' = go e1 !e2' = go e2 in EBin o e1' e2'+ ELet x e1 e2 ->+ let !e1' = go e1+ !e2' = go e2+ in ELet x e1' e2' EIte p e1 e2 -> let !p' = go p !e1' = go e1@@ -365,10 +359,7 @@ ETAbs e s -> let !e' = go e in ETAbs e' s- PGrad k su i e ->- let !e' = go e- in PGrad k su i e'- e@PKVar{} -> e+ PKVar k (Su m) -> PKVar k (Su (go <$>m)) e@EVar{} -> e e@ESym{} -> e e@ECon{} -> e@@ -408,7 +399,6 @@ go e@(ECon _) = f e go e@(EVar _) = f e go e@(PKVar _ _) = f e- go (PGrad k s i e) = f . PGrad k s i =<< go e go (ENeg e) = f . ENeg =<< go e go (PNot p) = f . PNot =<< go p go (ECst e t) = f . (`ECst` t) =<< go e@@ -423,6 +413,7 @@ go (PImp p1 p2) = f =<< (PImp <$> go p1 <*> go p2 ) go (PIff p1 p2) = f =<< (PIff <$> go p1 <*> go p2 ) go (PAtom r e1 e2) = f =<< (PAtom r <$> go e1 <*> go e2 )+ go (ELet x e1 e2) = f =<< (ELet x <$> go e1 <*> go e2 ) go (EIte p e1 e2) = f =<< (EIte <$> go p <*> go e1 <*> go e2) go (PAnd ps) = f . PAnd =<< (go `traverse` ps) go (POr ps) = f . POr =<< (go `traverse` ps)@@ -431,7 +422,6 @@ mapKVarSubsts f = trans txK where txK (PKVar k su) = PKVar k (f k su)- txK (PGrad k su i e) = PGrad k (f k su) i e txK p = p newtype MInt = MInt Integer -- deriving (Eq, NFData)@@ -475,7 +465,6 @@ ECon _ -> acc EVar _ -> acc PKVar k _ -> k : acc- PGrad k _ _ _ -> k : acc ENeg e -> go acc e PNot p -> go acc p ECst e _t -> go acc e@@ -490,6 +479,7 @@ 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+ ELet _ 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@@ -517,7 +507,6 @@ isKvar :: Expr -> Bool isKvar PKVar{} = True-isKvar PGrad{} = True isKvar _ = False isConc :: Expr -> Bool
src/Language/Fixpoint/Utils/Builder.hs view
@@ -6,6 +6,7 @@ ( fromText , fromString , parens+ , quotes , (<+>) , parenSeqs , seqs@@ -31,6 +32,9 @@ parens :: Builder -> Builder parens b = "(" <> b <> ")"++quotes :: Builder -> Builder+quotes b = "\"" <> b <> "\"" infixl 9 <+> (<+>) :: Builder -> Builder -> Builder
src/Language/Fixpoint/Utils/Files.hs view
@@ -14,6 +14,7 @@ , extFileName , extFileNameR , tempDirectory+ , tempFileName , extModuleName , withExt , isExtFile@@ -139,11 +140,10 @@ withExt f ext = replaceExtension f (extMap ext) extFileName :: Ext -> FilePath -> FilePath-extFileName e f = path </> addExtension file ext- where- path = tempDirectory f- file = takeFileName f- ext = extMap e+extFileName e f = tempFileName (addExtension f (extMap e))++tempFileName :: FilePath -> FilePath+tempFileName f = tempDirectory f </> takeFileName f tempDirectory :: FilePath -> FilePath tempDirectory f
− tests/neg/ebind-00.fq
@@ -1,16 +0,0 @@-fixpoint "--eliminate=all"--// bind 0 x1 : {v: int | v = 10 }-ebind 0 x1 : { int }--constraint:- env [0]- lhs {v1 : int | v1 = 10}- rhs {v1 : int | v1 = x1}- id 1 tag []--constraint:- env [0]- lhs {v2 : int | v2 = x1 + 1 }- rhs {v2 : int | v2 = 110 }- id 2 tag []
− tests/neg/ebind-01.fq
@@ -1,17 +0,0 @@-fixpoint "--eliminate=all"--bind 1 m : {v: int | true }-ebind 2 x1 : { int }-// bind 2 x1 : {v: int | v = m + 1 }--constraint:- env [1; 2]- lhs {v : int | v = m + 1 }- rhs {v : int | v = x1 }- id 1 tag []--constraint:- env [1; 2]- lhs {v : int | v = x1 + 1}- rhs {v : int | v = 20 + m }- id 2 tag []
− tests/neg/ebind-02.fq
@@ -1,28 +0,0 @@-fixpoint "--eliminate=all"--bind 0 m : {v: int | true }-bind 1 z : {v: int | v = m - 1 }-ebind 2 x1 : { int }-// bind 2 x1 : {v: int | v = m + 1 }--constraint:- env [0; 1]- lhs {v : int | v = z + 2 }- rhs {v : int | $k }- id 1 tag []--constraint:- env [0; 2]- lhs {v : int | $k }- rhs {v : int | v = x1 }- id 2 tag []--constraint:- env [0; 2]- lhs {v : int | v = x1 + 1 }- rhs {v : int | v = m + 20 }- id 3 tag []--wf: - env [0]- reft {v:int | [$k] }
− tests/neg/ebind-03.fq
@@ -1,45 +0,0 @@-fixpoint "--eliminate=all"--ebind 1 x1 : { int }-ebind 2 x2 : { int }---constraint:- env [1]- lhs {v : int | v = 1 }- rhs {v : int | v = x1 }- id 1 tag []--constraint:- env [1]- lhs {v : int | v = x1 + 1 }- rhs {v : int | $ka }- id 2 tag []--constraint:- env [2]- lhs {v : int | $ka }- rhs {v : int | v = x2 }- id 3 tag []--constraint:- env [2]- lhs {v : int | v = x2 + 1}- rhs {v : int | $kb }- id 4 tag []--constraint:- env []- lhs {v : int | $kb }- rhs {v : int | v = 30 } - id 5 tag []---wf: - env []- reft {v:int | [$ka] }--wf: - env []- reft {v:int | [$kb] }-
− tests/neg/ebind-04.fq
@@ -1,35 +0,0 @@-fixpoint "--eliminate=all"--ebind 1 x : { int }--constraint:- env [1]- lhs {v : int | $k1 }- rhs {v : int | v = x }- id 1 tag []--constraint:- env [1]- lhs {v : int | v = x + 1 }- rhs {v : int | $k2 }- id 2 tag []--constraint:- env []- lhs {v : int | v = 3 }- rhs {v : int | $k1 }- id 3 tag []--constraint:- env []- lhs {v : int | $k2 }- rhs {v : int | v = 40 }- id 4 tag []--wf: - env []- reft {v:int | [$k1] }--wf: - env []- reft {v:int | [$k2] }
− tests/neg/ebind-elim2.fq
@@ -1,26 +0,0 @@-bind 1 a : { a : int | true }-ebind 2 c : { int }--wf:- env [1]- reft {VV##1 : Tuple | [$k_##1]}--constraint:- env [1;2]- lhs {VV##F##4 : int | VV##F##4 = c }- rhs {VV##F##4 : int | $k_##1[VV##1 := VV##F##4] }- id 1 tag []--constraint:- env [1;2]- lhs {VV##F##5 : int | $k_##1[VV##1:=VV##F##5] }- rhs {VV##F##5 : int | VV##F##5 = c }- id 2 tag []--// The following constraint is needed only to prevent eliminate's **sharing** optimization.--constraint:- env []- lhs {VV##F##6 : int | $k_##1[VV##1:=VV##F##6] }- rhs {VV##F##6 : int | VV##F##6 = 0 }- id 3 tag []
tests/neg/elim-dep-00.fq view
@@ -1,7 +1,7 @@ -qualif False(v:int) : (0 = 1)-qualif Zero(v:int) : (0 = v)-qualif One(v:int) : (1 = v)+qualif False(v:int) { 0 = 1 }+qualif Zero(v:int) { 0 = v }+qualif One(v:int) { 1 = v } bind 1 x : {v:int | $k2 }
tests/neg/qualif-template-00.fq view
@@ -1,4 +1,4 @@-qualif Prefix(v:a, z as (moon . $1) : b) : (v = z)+qualif Prefix(v:a, z as (moon . $1) : b) { v = z } bind 0 monday : {v : int | true} bind 10 tuesday : {v : int | true}
tests/neg/qualif-template-01.fq view
@@ -1,6 +1,6 @@ // qualif Goob(v:a, z: b) : (v = z) // qualif Prefix2(v:a, x as (mon . $1) : b, y as (sun . $1)) : (v = x + y)-qualif Prefix(v:a, z as ($1 . sday) : b) : (v = z)+qualif Prefix(v:a, z as ($1 . sday) : b) { v = z } bind 0 monday : {v : int | true} bind 10 tuesday : {v : int | true}
tests/neg/qualif-template-02.fq view
@@ -1,6 +1,6 @@ fixpoint "--eliminate=none" -qualif Prefix2(v:a, x as (sun . $1) : b, y as (tues . $1) : b) : (v = x + y)+qualif Prefix2(v:a, x as (sun . $1) : b, y as (tues . $1) : b) { v = x + y } bind 0 sunday : {v : int | v = 6 } bind 1 monday : {v : int | v = 4 }
tests/neg/test00.fq view
@@ -1,6 +1,6 @@ -qualif Zog(v:a) : (10 <= v)-qualif Bog(v:a, x:a) : (x <= v)+qualif Zog(v:a) { 10 <= v }+qualif Bog(v:a, x:a) { x <= v } bind 0 a : {v: int | $k0}
tests/neg/test00.hs.fq view
@@ -1,51 +1,51 @@-qualif Fst(v : @(1), y : @(0)): (v = fst([y])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.spec" (line 29, column 8)-qualif Snd(v : @(1), y : @(0)): (v = snd([y])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.spec" (line 30, column 8)-qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]): ((? Prop([v])) <=> (len([xs]) > 0)) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 13, column 8)-qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]): ((? Prop([v])) <=> (len([xs]) = 0)) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 14, column 8)-qualif ListZ(v : [@(0)]): (len([v]) = 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 16, column 8)-qualif ListZ(v : [@(0)]): (len([v]) >= 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 17, column 8)-qualif ListZ(v : [@(0)]): (len([v]) > 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 18, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) = len([xs])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 20, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) >= len([xs])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 21, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) > len([xs])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 22, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) <= len([xs])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 23, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) < len([xs])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 24, column 8)-qualif EqLen(v : int, xs : [@(0)]): (v = len([xs])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 26, column 8)-qualif LenEq(v : [@(0)], x : int): (x = len([v])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 27, column 8)-qualif LenDiff(v : [@(0)], x : int): (len([v]) = (x + 1)) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 28, column 8)-qualif LenDiff(v : [@(0)], x : int): (len([v]) = (x - 1)) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 29, column 8)-qualif LenAcc(v : int, xs : [@(0)], n : int): (v = (len([xs]) + n)) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 30, column 8)-qualif Bot(v : @(0)): (0 = 1) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 3, column 8)-qualif Bot(v : @(0)): (0 = 1) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 4, column 8)-qualif Bot(v : @(0)): (0 = 1) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 5, column 8)-qualif Bot(v : bool): (0 = 1) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 6, column 8)-qualif Bot(v : int): (0 = 1) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 7, column 8)-qualif CmpZ(v : @(0)): (v < 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 9, column 8)-qualif CmpZ(v : @(0)): (v <= 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 10, column 8)-qualif CmpZ(v : @(0)): (v > 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 11, column 8)-qualif CmpZ(v : @(0)): (v >= 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 12, column 8)-qualif CmpZ(v : @(0)): (v = 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 13, column 8)-qualif CmpZ(v : @(0)): (v != 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 14, column 8)-qualif Cmp(v : @(0), x : @(0)): (v < x) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 16, column 8)-qualif Cmp(v : @(0), x : @(0)): (v <= x) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 17, column 8)-qualif Cmp(v : @(0), x : @(0)): (v > x) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 18, column 8)-qualif Cmp(v : @(0), x : @(0)): (v >= x) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 19, column 8)-qualif Cmp(v : @(0), x : @(0)): (v = x) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 20, column 8)-qualif Cmp(v : @(0), x : @(0)): (v != x) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 21, column 8)-qualif One(v : int): (v = 1) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 28, column 8)-qualif True(v : bool): (? v) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 29, column 8)-qualif False(v : bool): (~ ((? v))) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 30, column 8)-qualif True1(v : GHC.Types.Bool): (? Prop([v])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 31, column 8)-qualif False1(v : GHC.Types.Bool): (~ ((? Prop([v])))) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 32, column 8)-qualif Papp(v : @(0), p : (Pred @(0))): (? papp1([p;- v])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 35, column 8)-qualif Papp2(v : @(1), x : @(0), p : (Pred @(1) @(0))): (? papp2([p;+qualif Fst(v : @(1), y : @(0)) { v = fst([y]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.spec" (line 29, column 8)+qualif Snd(v : @(1), y : @(0)) { v = snd([y]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.spec" (line 30, column 8)+qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]) { (Prop([v])) <=> (len([xs]) > 0) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 13, column 8)+qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]) { (Prop([v])) <=> (len([xs]) = 0) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 14, column 8)+qualif ListZ(v : [@(0)]) { len([v]) = 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 16, column 8)+qualif ListZ(v : [@(0)]) { len([v]) >= 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 17, column 8)+qualif ListZ(v : [@(0)]) { len([v]) > 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 18, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) = len([xs]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 20, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) >= len([xs]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 21, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) > len([xs]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 22, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) <= len([xs]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 23, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) < len([xs]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 24, column 8)+qualif EqLen(v : int, xs : [@(0)]) { v = len([xs]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 26, column 8)+qualif LenEq(v : [@(0)], x : int) { x = len([v]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 27, column 8)+qualif LenDiff(v : [@(0)], x : int) { len([v]) = (x + 1) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 28, column 8)+qualif LenDiff(v : [@(0)], x : int) { len([v]) = (x - 1) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 29, column 8)+qualif LenAcc(v : int, xs : [@(0)], n : int) { v = (len([xs]) + n) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 30, column 8)+qualif Bot(v : @(0)) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 3, column 8)+qualif Bot(v : @(0)) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 4, column 8)+qualif Bot(v : @(0)) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 5, column 8)+qualif Bot(v : bool) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 6, column 8)+qualif Bot(v : int) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 7, column 8)+qualif CmpZ(v : @(0)) { v < 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 9, column 8)+qualif CmpZ(v : @(0)) { v <= 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 10, column 8)+qualif CmpZ(v : @(0)) { v > 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 11, column 8)+qualif CmpZ(v : @(0)) { v >= 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 12, column 8)+qualif CmpZ(v : @(0)) { v = 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 13, column 8)+qualif CmpZ(v : @(0)) { v != 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 14, column 8)+qualif Cmp(v : @(0), x : @(0)) { v < x } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 16, column 8)+qualif Cmp(v : @(0), x : @(0)) { v <= x } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 17, column 8)+qualif Cmp(v : @(0), x : @(0)) { v > x } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 18, column 8)+qualif Cmp(v : @(0), x : @(0)) { v >= x } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 19, column 8)+qualif Cmp(v : @(0), x : @(0)) { v = x } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 20, column 8)+qualif Cmp(v : @(0), x : @(0)) { v != x } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 21, column 8)+qualif One(v : int) { v = 1 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 28, column 8)+qualif True(v : bool) { v } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 29, column 8)+qualif False(v : bool) { ~ ((v)) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 30, column 8)+qualif True1(v : GHC.Types.Bool) { Prop([v]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 31, column 8)+qualif False1(v : GHC.Types.Bool) { ~ ((Prop([v]))) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 32, column 8)+qualif Papp(v : @(0), p : (Pred @(0))) { (papp1([p;+ v])) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 35, column 8)+qualif Papp2(v : @(1), x : @(0), p : (Pred @(1) @(0))) { (papp2([p; v;- x])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 38, column 8)-qualif Papp3(v : @(2), x : @(0), y : @(1), p : (Pred @(2) @(0) @(1))): (? papp3([p;+ x])) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 38, column 8)+qualif Papp3(v : @(2), x : @(0), y : @(1), p : (Pred @(2) @(0) @(1))) { (papp3([p; v; x;- y])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 41, column 8)+ y])) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 41, column 8) @@ -137,33 +137,33 @@ bind 3 GHC.Types.EQ$35$6U : {VV$35$167 : GHC.Types.Ordering | [(VV$35$167 = GHC.Types.EQ$35$6U)]} bind 4 GHC.Types.LT$35$6S : {VV$35$168 : GHC.Types.Ordering | [(VV$35$168 = GHC.Types.LT$35$6S)]} bind 5 GHC.Types.GT$35$6W : {VV$35$169 : GHC.Types.Ordering | [(VV$35$169 = GHC.Types.GT$35$6W)]}-bind 6 GHC.Types.True$35$6u : {v$35$4 : GHC.Types.Bool | [(? Prop([v$35$4]))]}-bind 7 GHC.Types.False$35$68 : {v$35$5 : GHC.Types.Bool | [(~ ((? Prop([v$35$5]))))]}-bind 8 GHC.Types.False$35$68 : {v$35$5 : GHC.Types.Bool | [(~ ((? Prop([v$35$5]))))]}+bind 6 GHC.Types.True$35$6u : {v$35$4 : GHC.Types.Bool | [(Prop([v$35$4]))]}+bind 7 GHC.Types.False$35$68 : {v$35$5 : GHC.Types.Bool | [(~ ((Prop([v$35$5]))))]}+bind 8 GHC.Types.False$35$68 : {v$35$5 : GHC.Types.Bool | [(~ ((Prop([v$35$5]))))]} bind 9 GHC.Types.$91$$93$$35$6m : {VV : func(1, [[@(0)]]) | []}-bind 10 GHC.Types.True$35$6u : {v$35$4 : GHC.Types.Bool | [(? Prop([v$35$4]))]}+bind 10 GHC.Types.True$35$6u : {v$35$4 : GHC.Types.Bool | [(Prop([v$35$4]))]} bind 11 GHC.Types.GT$35$6W : {VV$35$214 : GHC.Types.Ordering | [(cmp([VV$35$214]) = GHC.Types.GT$35$6W)]} bind 12 GHC.Types.LT$35$6S : {VV$35$215 : GHC.Types.Ordering | [(cmp([VV$35$215]) = GHC.Types.LT$35$6S)]} bind 13 GHC.Types.EQ$35$6U : {VV$35$216 : GHC.Types.Ordering | [(cmp([VV$35$216]) = GHC.Types.EQ$35$6U)]} bind 14 GHC.Base.Nothing$35$r1d : {VV : func(1, [(GHC.Base.Maybe @(0))]) | []} bind 15 z$35$a10N : {VV$35$221 : int | [$k_$35$222]} bind 16 lq_anf$36$_d116 : {lq_tmp$36$x$35$229 : int | [(lq_tmp$36$x$35$229 = (100 : int))]}-bind 17 lq_anf$36$_d117 : {lq_tmp$36$x$35$236 : GHC.Types.Bool | [((? Prop([lq_tmp$36$x$35$236])) <=> (z$35$a10N >= lq_anf$36$_d116))]}+bind 17 lq_anf$36$_d117 : {lq_tmp$36$x$35$236 : GHC.Types.Bool | [((Prop([lq_tmp$36$x$35$236])) <=> (z$35$a10N >= lq_anf$36$_d116))]} bind 18 lq_anf$36$_d118 : {lq_tmp$36$x$35$254 : int | [(lq_tmp$36$x$35$254 = (0 : int))]} bind 19 Test0.x$35$rYP : {VV$35$250 : int | [$k_$35$251]} bind 20 lq_anf$36$_d119 : {lq_tmp$36$x$35$269 : int | [(lq_tmp$36$x$35$269 = (0 : int))]}-bind 21 lq_anf$36$_d11a : {lq_tmp$36$x$35$275 : GHC.Types.Bool | [((? Prop([lq_tmp$36$x$35$275])) <=> (Test0.x$35$rYP > lq_anf$36$_d119))]}+bind 21 lq_anf$36$_d11a : {lq_tmp$36$x$35$275 : GHC.Types.Bool | [((Prop([lq_tmp$36$x$35$275])) <=> (Test0.x$35$rYP > lq_anf$36$_d119))]} bind 22 lq_anf$36$_d11b : {lq_tmp$36$x$35$291 : GHC.Types.Bool | [(lq_tmp$36$x$35$291 = lq_anf$36$_d11a)]} bind 23 lq_anf$36$_d11b : {lq_tmp$36$x$35$293 : GHC.Types.Bool | [(lq_tmp$36$x$35$293 = lq_anf$36$_d11a)]} bind 24 lq_anf$36$_d11b : {lq_tmp$36$x$35$293 : GHC.Types.Bool | [(lq_tmp$36$x$35$293 = lq_anf$36$_d11a);- (~ ((? Prop([lq_tmp$36$x$35$293]))));- (~ ((? Prop([lq_tmp$36$x$35$293]))));- (~ ((? Prop([lq_tmp$36$x$35$293]))))]}+ (~ ((Prop([lq_tmp$36$x$35$293]))));+ (~ ((Prop([lq_tmp$36$x$35$293]))));+ (~ ((Prop([lq_tmp$36$x$35$293]))))]} bind 25 lq_anf$36$_d11b : {lq_tmp$36$x$35$299 : GHC.Types.Bool | [(lq_tmp$36$x$35$299 = lq_anf$36$_d11a)]} bind 26 lq_anf$36$_d11b : {lq_tmp$36$x$35$299 : GHC.Types.Bool | [(lq_tmp$36$x$35$299 = lq_anf$36$_d11a);- (? Prop([lq_tmp$36$x$35$299]));- (? Prop([lq_tmp$36$x$35$299]));- (? Prop([lq_tmp$36$x$35$299]))]}+ (Prop([lq_tmp$36$x$35$299]));+ (Prop([lq_tmp$36$x$35$299]));+ (Prop([lq_tmp$36$x$35$299]))]} bind 27 Test0.prop_abs$35$r10h : {VV$35$265 : GHC.Types.Bool | [$k_$35$266]} bind 28 VV$35$310 : {VV$35$310 : GHC.Types.Bool | [$k_$35$226[lq_tmp$36$x$35$307:=Test0.x$35$rYP][lq_tmp$36$x$35$305:=VV$35$310][VV$35$225:=VV$35$310][z$35$a10N:=Test0.x$35$rYP]]} bind 29 VV$35$310 : {VV$35$310 : GHC.Types.Bool | [$k_$35$226[lq_tmp$36$x$35$307:=Test0.x$35$rYP][lq_tmp$36$x$35$305:=VV$35$310][VV$35$225:=VV$35$310][z$35$a10N:=Test0.x$35$rYP]]}@@ -183,8 +183,8 @@ bind 43 VV$35$331 : {VV$35$331 : int | [(VV$35$331 = lq_anf$36$_d118)]} bind 44 VV$35$334 : {VV$35$334 : int | [(VV$35$334 = 0)]} bind 45 VV$35$334 : {VV$35$334 : int | [(VV$35$334 = 0)]}-bind 46 VV$35$337 : {VV$35$337 : GHC.Types.Bool | [(? Prop([VV$35$337]))]}-bind 47 VV$35$337 : {VV$35$337 : GHC.Types.Bool | [(? Prop([VV$35$337]))]}+bind 46 VV$35$337 : {VV$35$337 : GHC.Types.Bool | [(Prop([VV$35$337]))]}+bind 47 VV$35$337 : {VV$35$337 : GHC.Types.Bool | [(Prop([VV$35$337]))]} bind 48 VV$35$340 : {VV$35$340 : GHC.Types.Bool | [(VV$35$340 = lq_anf$36$_d117)]} bind 49 VV$35$340 : {VV$35$340 : GHC.Types.Bool | [(VV$35$340 = lq_anf$36$_d117)]} bind 50 VV$35$343 : {VV$35$343 : int | [(VV$35$343 = lq_anf$36$_d116)]}@@ -260,7 +260,7 @@ 14; 15] lhs {VV$35$F8 : GHC.Types.Bool | [(VV$35$F8 = lq_anf$36$_d117)]}- rhs {VV$35$F8 : GHC.Types.Bool | [(? Prop([VV$35$F8]))]}+ rhs {VV$35$F8 : GHC.Types.Bool | [(Prop([VV$35$F8]))]} id 8 tag [1] // META constraint id 8 : tests/neg/test00.hs:11:23-35
tests/neg/test00a.fq view
@@ -1,6 +1,6 @@ // This qualifier saves the day; solve constraints WITHOUT IT -qualif Zog(v:a) : (10 <= v)+qualif Zog(v:a) { 10 <= v } bind 0 x : {v : int | true} bind 1 y : {v : int | true}
tests/neg/test1.fq view
@@ -1,6 +1,6 @@ // This qualifier saves the day; solve constraints WITHOUT IT-qualif Zog(v:a) : (10 <= v)+qualif Zog(v:a) { 10 <= v } bind 0 x : {v : int | v = 9} bind 1 y : {v : int | v = 20}
tests/neg/test2.fq view
@@ -1,9 +1,9 @@ // This qualifier saves the day; solve constraints WITHOUT IT-qualif Zog(v:a): (10 <= v)+qualif Zog(v:a) { 10 <= v } // But you may use this one-qualif Pog(v:a): (0 <= v)+qualif Pog(v:a) { 0 <= v } bind 0 x: {v: int | v = 9 } bind 1 a: {v: int | $k1 }
tests/neg/test3.fq view
@@ -1,5 +1,5 @@ -qualif Zog(v:a, z:b) : (v = z)+qualif Zog(v:a, z:b) { v = z } bind 0 x : {v : int | true} bind 1 q : {v : int | true}
tests/pos/LogicCurry1.hs.fq view
@@ -1,46 +1,46 @@ fixpoint "--allowho" -qualif Fst(v : @(1), y : @(0)): ((v = (fst y))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.spec" (line 28, column 8)-qualif Snd(v : @(1), y : @(0)): ((v = (snd y))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.spec" (line 29, column 8)-qualif Auto(v##1 : int, n : int, x : int): ((v##1 = (ack n x))) // "/Users/rjhala/research/stack/liquidhaskell/tests/pos/LogicCurry1.hs" (line 10, column 1)-qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]): ((v <=> ((len xs) > 0))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 13, column 8)-qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]): ((v <=> ((len xs) = 0))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 14, column 8)-qualif ListZ(v : [@(0)]): (((len v) = 0)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 16, column 8)-qualif ListZ(v : [@(0)]): (((len v) >= 0)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 17, column 8)-qualif ListZ(v : [@(0)]): (((len v) > 0)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 18, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (((len v) = (len xs))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 20, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (((len v) >= (len xs))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 21, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (((len v) > (len xs))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 22, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (((len v) <= (len xs))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 23, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (((len v) < (len xs))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 24, column 8)-qualif EqLen(v : int, xs : [@(0)]): ((v = (len xs))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 26, column 8)-qualif LenEq(v : [@(0)], x : int): ((x = (len v))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 27, column 8)-qualif LenDiff(v : [@(0)], x : int): (((len v) = (x + 1))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 28, column 8)-qualif LenDiff(v : [@(0)], x : int): (((len v) = (x - 1))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 29, column 8)-qualif LenAcc(v : int, xs : [@(0)], n : int): ((v = ((len xs) + n))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 30, column 8)-qualif Bot(v : @(0)): ((0 = 1)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 3, column 8)-qualif Bot(v : @(0)): ((0 = 1)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 4, column 8)-qualif Bot(v : @(0)): ((0 = 1)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 5, column 8)-qualif Bot(v : bool): ((0 = 1)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 6, column 8)-qualif Bot(v : int): ((0 = 1)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 7, column 8)-qualif CmpZ(v : @(0)): ((v < 0)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 9, column 8)-qualif CmpZ(v : @(0)): ((v <= 0)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 10, column 8)-qualif CmpZ(v : @(0)): ((v > 0)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 11, column 8)-qualif CmpZ(v : @(0)): ((v >= 0)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 12, column 8)-qualif CmpZ(v : @(0)): ((v = 0)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 13, column 8)-qualif CmpZ(v : @(0)): ((v != 0)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 14, column 8)-qualif Cmp(v : @(0), x : @(0)): ((v < x)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 16, column 8)-qualif Cmp(v : @(0), x : @(0)): ((v <= x)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 17, column 8)-qualif Cmp(v : @(0), x : @(0)): ((v > x)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 18, column 8)-qualif Cmp(v : @(0), x : @(0)): ((v >= x)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 19, column 8)-qualif Cmp(v : @(0), x : @(0)): ((v = x)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 20, column 8)-qualif Cmp(v : @(0), x : @(0)): ((v != x)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 21, column 8)-qualif One(v : int): ((v = 1)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 28, column 8)-qualif True1(v : GHC.Types.Bool): (v) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 29, column 8)-qualif False1(v : GHC.Types.Bool): ((~ (v))) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 30, column 8)-qualif Papp(v : @(0), p : (Pred @(0))): ((papp1 p v)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 34, column 8)-qualif Papp2(v : @(1), x : @(0), p : (Pred @(1) @(0))): ((papp2 p v x)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 37, column 8)-qualif Papp3(v : @(2), x : @(0), y : @(1), p : (Pred @(2) @(0) @(1))): ((papp3 p v x y)) // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 39, column 8)+qualif Fst(v : @(1), y : @(0)) { (v = (fst y)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.spec" (line 28, column 8)+qualif Snd(v : @(1), y : @(0)) { (v = (snd y)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.spec" (line 29, column 8)+qualif Auto(v##1 : int, n : int, x : int) { (v##1 = (ack n x)) } // "/Users/rjhala/research/stack/liquidhaskell/tests/pos/LogicCurry1.hs" (line 10, column 1)+qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]) { (v <=> ((len xs) > 0)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 13, column 8)+qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]) { (v <=> ((len xs) = 0)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 14, column 8)+qualif ListZ(v : [@(0)]) { ((len v) = 0) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 16, column 8)+qualif ListZ(v : [@(0)]) { ((len v) >= 0) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 17, column 8)+qualif ListZ(v : [@(0)]) { ((len v) > 0) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 18, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { ((len v) = (len xs)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 20, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { ((len v) >= (len xs)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 21, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { ((len v) > (len xs)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 22, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { ((len v) <= (len xs)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 23, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { ((len v) < (len xs)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 24, column 8)+qualif EqLen(v : int, xs : [@(0)]) { (v = (len xs)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 26, column 8)+qualif LenEq(v : [@(0)], x : int) { (x = (len v)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 27, column 8)+qualif LenDiff(v : [@(0)], x : int) { ((len v) = (x + 1)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 28, column 8)+qualif LenDiff(v : [@(0)], x : int) { ((len v) = (x - 1)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 29, column 8)+qualif LenAcc(v : int, xs : [@(0)], n : int) { (v = ((len xs) + n)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/GHC/Base.hquals" (line 30, column 8)+qualif Bot(v : @(0)) { (0 = 1) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 3, column 8)+qualif Bot(v : @(0)) { (0 = 1) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 4, column 8)+qualif Bot(v : @(0)) { (0 = 1) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 5, column 8)+qualif Bot(v : bool) { (0 = 1) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 6, column 8)+qualif Bot(v : int) { (0 = 1) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 7, column 8)+qualif CmpZ(v : @(0)) { (v < 0) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 9, column 8)+qualif CmpZ(v : @(0)) { (v <= 0) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 10, column 8)+qualif CmpZ(v : @(0)) { (v > 0) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 11, column 8)+qualif CmpZ(v : @(0)) { (v >= 0) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 12, column 8)+qualif CmpZ(v : @(0)) { (v = 0) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 13, column 8)+qualif CmpZ(v : @(0)) { (v != 0) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 14, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v < x) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 16, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v <= x) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 17, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v > x) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 18, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v >= x) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 19, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v = x) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 20, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v != x) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 21, column 8)+qualif One(v : int) { (v = 1) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 28, column 8)+qualif True1(v : GHC.Types.Bool) { v } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 29, column 8)+qualif False1(v : GHC.Types.Bool) { (~ (v)) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 30, column 8)+qualif Papp(v : @(0), p : (Pred @(0))) { (papp1 p v) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 34, column 8)+qualif Papp2(v : @(1), x : @(0), p : (Pred @(1) @(0))) { (papp2 p v x) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 37, column 8)+qualif Papp3(v : @(2), x : @(0), y : @(1), p : (Pred @(2) @(0) @(1))) { (papp3 p v x y) } // "/Users/rjhala/research/stack/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2016-05-21/7.10.3/share/x86_64-osx-ghc-7.10.3/liquidhaskell-0.6.0.0/include/Prelude.hquals" (line 39, column 8)
tests/pos/MergeSort.fq view
@@ -1,52 +1,52 @@-qualif Fst(v : @(1), y : @(0)): ((v = (fst y))) // "tests/todo/MergeSort.new.min.fq" (line 1, column 8)-qualif Snd(v : @(1), y : @(0)): ((v = (snd y))) // "tests/todo/MergeSort.new.min.fq" (line 2, column 8)-qualif Auto(VV : @(0), fld##0 : @(0)): ((VV >= fld##0)) // "tests/todo/MergeSort.new.min.fq" (line 3, column 8)-qualif Auto(VV : @(0), fld##0 : @(0)): ((VV >= fld##0)) // "tests/todo/MergeSort.new.min.fq" (line 4, column 8)-qualif Auto(VV : [@(0)], xs : [@(0)], ys : [@(0)]): (((len VV) = ((len xs) + (len ys)))) // "tests/todo/MergeSort.new.min.fq" (line 5, column 8)-qualif Auto(VV : @(0), fld##0 : @(0)): ((VV >= fld##0)) // "tests/todo/MergeSort.new.min.fq" (line 6, column 8)-qualif Auto(VV : [@(0)], xs : [@(0)]): (((len VV) = (len xs))) // "tests/todo/MergeSort.new.min.fq" (line 7, column 8)-qualif Auto(VV : @(0), fld##0 : @(0)): ((VV >= fld##0)) // "tests/todo/MergeSort.new.min.fq" (line 8, column 8)-qualif Auto(v##0 : (Tuple [@(0)] [@(0)]), xs : [@(0)]): ((((len (fst v##0)) + (len (snd v##0))) = (len xs))) // "tests/todo/MergeSort.new.min.fq" (line 9, column 8)-qualif Auto(v##0 : [@(0)], xs : [@(0)]): ((((len v##0) > 1) => ((len v##0) < (len xs)))) // "tests/todo/MergeSort.new.min.fq" (line 10, column 8)-qualif Auto(v##0 : [@(0)], xs : [@(0)]): ((((len v##0) > 1) => ((len v##0) < (len xs)))) // "tests/todo/MergeSort.new.min.fq" (line 11, column 8)-qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]): (((Prop v) <=> ((len xs) > 0))) // "tests/todo/MergeSort.new.min.fq" (line 12, column 8)-qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]): (((Prop v) <=> ((len xs) = 0))) // "tests/todo/MergeSort.new.min.fq" (line 13, column 8)-qualif ListZ(v : [@(0)]): (((len v) = 0)) // "tests/todo/MergeSort.new.min.fq" (line 14, column 8)-qualif ListZ(v : [@(0)]): (((len v) >= 0)) // "tests/todo/MergeSort.new.min.fq" (line 15, column 8)-qualif ListZ(v : [@(0)]): (((len v) > 0)) // "tests/todo/MergeSort.new.min.fq" (line 16, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (((len v) = (len xs))) // "tests/todo/MergeSort.new.min.fq" (line 17, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (((len v) >= (len xs))) // "tests/todo/MergeSort.new.min.fq" (line 18, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (((len v) > (len xs))) // "tests/todo/MergeSort.new.min.fq" (line 19, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (((len v) <= (len xs))) // "tests/todo/MergeSort.new.min.fq" (line 20, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (((len v) < (len xs))) // "tests/todo/MergeSort.new.min.fq" (line 21, column 8)-qualif EqLen(v : int, xs : [@(0)]): ((v = (len xs))) // "tests/todo/MergeSort.new.min.fq" (line 22, column 8)-qualif LenEq(v : [@(0)], x : int): ((x = (len v))) // "tests/todo/MergeSort.new.min.fq" (line 23, column 8)-qualif LenDiff(v : [@(0)], x : int): (((len v) = (x + 1))) // "tests/todo/MergeSort.new.min.fq" (line 24, column 8)-qualif LenDiff(v : [@(0)], x : int): (((len v) = (x - 1))) // "tests/todo/MergeSort.new.min.fq" (line 25, column 8)-qualif LenAcc(v : int, xs : [@(0)], n : int): ((v = ((len xs) + n))) // "tests/todo/MergeSort.new.min.fq" (line 26, column 8)-qualif Bot(v : @(0)): ((0 = 1)) // "tests/todo/MergeSort.new.min.fq" (line 27, column 8)-qualif Bot(v : @(0)): ((0 = 1)) // "tests/todo/MergeSort.new.min.fq" (line 28, column 8)-qualif Bot(v : @(0)): ((0 = 1)) // "tests/todo/MergeSort.new.min.fq" (line 29, column 8)-qualif Bot(v : bool): ((0 = 1)) // "tests/todo/MergeSort.new.min.fq" (line 30, column 8)-qualif Bot(v : int): ((0 = 1)) // "tests/todo/MergeSort.new.min.fq" (line 31, column 8)-qualif CmpZ(v : @(0)): ((v < 0)) // "tests/todo/MergeSort.new.min.fq" (line 32, column 8)-qualif CmpZ(v : @(0)): ((v <= 0)) // "tests/todo/MergeSort.new.min.fq" (line 33, column 8)-qualif CmpZ(v : @(0)): ((v > 0)) // "tests/todo/MergeSort.new.min.fq" (line 34, column 8)-qualif CmpZ(v : @(0)): ((v >= 0)) // "tests/todo/MergeSort.new.min.fq" (line 35, column 8)-qualif CmpZ(v : @(0)): ((v = 0)) // "tests/todo/MergeSort.new.min.fq" (line 36, column 8)-qualif CmpZ(v : @(0)): ((v != 0)) // "tests/todo/MergeSort.new.min.fq" (line 37, column 8)-qualif Cmp(v : @(0), x : @(0)): ((v < x)) // "tests/todo/MergeSort.new.min.fq" (line 38, column 8)-qualif Cmp(v : @(0), x : @(0)): ((v <= x)) // "tests/todo/MergeSort.new.min.fq" (line 39, column 8)-qualif Cmp(v : @(0), x : @(0)): ((v > x)) // "tests/todo/MergeSort.new.min.fq" (line 40, column 8)-qualif Cmp(v : @(0), x : @(0)): ((v >= x)) // "tests/todo/MergeSort.new.min.fq" (line 41, column 8)-qualif Cmp(v : @(0), x : @(0)): ((v = x)) // "tests/todo/MergeSort.new.min.fq" (line 42, column 8)-qualif Cmp(v : @(0), x : @(0)): ((v != x)) // "tests/todo/MergeSort.new.min.fq" (line 43, column 8)-qualif One(v : int): ((v = 1)) // "tests/todo/MergeSort.new.min.fq" (line 44, column 8)-qualif True1(v : GHC.Types.Bool): ((Prop v)) // "tests/todo/MergeSort.new.min.fq" (line 45, column 8)-qualif False1(v : GHC.Types.Bool): ((~ ((Prop v)))) // "tests/todo/MergeSort.new.min.fq" (line 46, column 8)-qualif Papp(v : @(0), p : (Pred @(0))): ((papp1 p v)) // "tests/todo/MergeSort.new.min.fq" (line 47, column 8)-qualif Papp2(v : @(1), x : @(0), p : (Pred @(1) @(0))): ((papp2 p v x)) // "tests/todo/MergeSort.new.min.fq" (line 48, column 8)-qualif Papp3(v : @(2), x : @(0), y : @(1), p : (Pred @(2) @(0) @(1))): ((papp3 p v x y)) // "tests/todo/MergeSort.new.min.fq" (line 49, column 8)+qualif Fst(v : @(1), y : @(0)) { (v = (fst y)) } // "tests/todo/MergeSort.new.min.fq" (line 1, column 8)+qualif Snd(v : @(1), y : @(0)) { (v = (snd y)) } // "tests/todo/MergeSort.new.min.fq" (line 2, column 8)+qualif Auto(VV : @(0), fld##0 : @(0)) { (VV >= fld##0) } // "tests/todo/MergeSort.new.min.fq" (line 3, column 8)+qualif Auto(VV : @(0), fld##0 : @(0)) { (VV >= fld##0) } // "tests/todo/MergeSort.new.min.fq" (line 4, column 8)+qualif Auto(VV : [@(0)], xs : [@(0)], ys : [@(0)]) { ((len VV) = ((len xs) + (len ys))) } // "tests/todo/MergeSort.new.min.fq" (line 5, column 8)+qualif Auto(VV : @(0), fld##0 : @(0)) { (VV >= fld##0) } // "tests/todo/MergeSort.new.min.fq" (line 6, column 8)+qualif Auto(VV : [@(0)], xs : [@(0)]) { ((len VV) = (len xs)) } // "tests/todo/MergeSort.new.min.fq" (line 7, column 8)+qualif Auto(VV : @(0), fld##0 : @(0)) { (VV >= fld##0) } // "tests/todo/MergeSort.new.min.fq" (line 8, column 8)+qualif Auto(v##0 : (Tuple [@(0)] [@(0)]), xs : [@(0)]) { (((len (fst v##0)) + (len (snd v##0))) = (len xs)) } // "tests/todo/MergeSort.new.min.fq" (line 9, column 8)+qualif Auto(v##0 : [@(0)], xs : [@(0)]) { (((len v##0) > 1) => ((len v##0) < (len xs))) } // "tests/todo/MergeSort.new.min.fq" (line 10, column 8)+qualif Auto(v##0 : [@(0)], xs : [@(0)]) { (((len v##0) > 1) => ((len v##0) < (len xs))) } // "tests/todo/MergeSort.new.min.fq" (line 11, column 8)+qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]) { ((Prop v) <=> ((len xs) > 0)) } // "tests/todo/MergeSort.new.min.fq" (line 12, column 8)+qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]) { ((Prop v) <=> ((len xs) = 0)) } // "tests/todo/MergeSort.new.min.fq" (line 13, column 8)+qualif ListZ(v : [@(0)]) { ((len v) = 0) } // "tests/todo/MergeSort.new.min.fq" (line 14, column 8)+qualif ListZ(v : [@(0)]) { ((len v) >= 0) } // "tests/todo/MergeSort.new.min.fq" (line 15, column 8)+qualif ListZ(v : [@(0)]) { ((len v) > 0) } // "tests/todo/MergeSort.new.min.fq" (line 16, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { ((len v) = (len xs)) } // "tests/todo/MergeSort.new.min.fq" (line 17, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { ((len v) >= (len xs)) } // "tests/todo/MergeSort.new.min.fq" (line 18, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { ((len v) > (len xs)) } // "tests/todo/MergeSort.new.min.fq" (line 19, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { ((len v) <= (len xs)) } // "tests/todo/MergeSort.new.min.fq" (line 20, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { ((len v) < (len xs)) } // "tests/todo/MergeSort.new.min.fq" (line 21, column 8)+qualif EqLen(v : int, xs : [@(0)]) { (v = (len xs)) } // "tests/todo/MergeSort.new.min.fq" (line 22, column 8)+qualif LenEq(v : [@(0)], x : int) { (x = (len v)) } // "tests/todo/MergeSort.new.min.fq" (line 23, column 8)+qualif LenDiff(v : [@(0)], x : int) { ((len v) = (x + 1)) } // "tests/todo/MergeSort.new.min.fq" (line 24, column 8)+qualif LenDiff(v : [@(0)], x : int) { ((len v) = (x - 1)) } // "tests/todo/MergeSort.new.min.fq" (line 25, column 8)+qualif LenAcc(v : int, xs : [@(0)], n : int) { (v = ((len xs) + n)) } // "tests/todo/MergeSort.new.min.fq" (line 26, column 8)+qualif Bot(v : @(0)) { (0 = 1) } // "tests/todo/MergeSort.new.min.fq" (line 27, column 8)+qualif Bot(v : @(0)) { (0 = 1) } // "tests/todo/MergeSort.new.min.fq" (line 28, column 8)+qualif Bot(v : @(0)) { (0 = 1) } // "tests/todo/MergeSort.new.min.fq" (line 29, column 8)+qualif Bot(v : bool) { (0 = 1) } // "tests/todo/MergeSort.new.min.fq" (line 30, column 8)+qualif Bot(v : int) { (0 = 1) } // "tests/todo/MergeSort.new.min.fq" (line 31, column 8)+qualif CmpZ(v : @(0)) { (v < 0) } // "tests/todo/MergeSort.new.min.fq" (line 32, column 8)+qualif CmpZ(v : @(0)) { (v <= 0) } // "tests/todo/MergeSort.new.min.fq" (line 33, column 8)+qualif CmpZ(v : @(0)) { (v > 0) } // "tests/todo/MergeSort.new.min.fq" (line 34, column 8)+qualif CmpZ(v : @(0)) { (v >= 0) } // "tests/todo/MergeSort.new.min.fq" (line 35, column 8)+qualif CmpZ(v : @(0)) { (v = 0) } // "tests/todo/MergeSort.new.min.fq" (line 36, column 8)+qualif CmpZ(v : @(0)) { (v != 0) } // "tests/todo/MergeSort.new.min.fq" (line 37, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v < x) } // "tests/todo/MergeSort.new.min.fq" (line 38, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v <= x) } // "tests/todo/MergeSort.new.min.fq" (line 39, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v > x) } // "tests/todo/MergeSort.new.min.fq" (line 40, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v >= x) } // "tests/todo/MergeSort.new.min.fq" (line 41, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v = x) } // "tests/todo/MergeSort.new.min.fq" (line 42, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v != x) } // "tests/todo/MergeSort.new.min.fq" (line 43, column 8)+qualif One(v : int) { (v = 1) } // "tests/todo/MergeSort.new.min.fq" (line 44, column 8)+qualif True1(v : GHC.Types.Bool) { (Prop v) } // "tests/todo/MergeSort.new.min.fq" (line 45, column 8)+qualif False1(v : GHC.Types.Bool) { (~ ((Prop v))) } // "tests/todo/MergeSort.new.min.fq" (line 46, column 8)+qualif Papp(v : @(0), p : (Pred @(0))) { (papp1 p v) } // "tests/todo/MergeSort.new.min.fq" (line 47, column 8)+qualif Papp2(v : @(1), x : @(0), p : (Pred @(1) @(0))) { (papp2 p v x) } // "tests/todo/MergeSort.new.min.fq" (line 48, column 8)+qualif Papp3(v : @(2), x : @(0), y : @(1), p : (Pred @(2) @(0) @(1))) { (papp3 p v x y) } // "tests/todo/MergeSort.new.min.fq" (line 49, column 8) cut $k_##795
tests/pos/T416.fq view
@@ -7,7 +7,7 @@ ] define compose (lq1:func(0,[b;c]), lq2:func(0,[a;b]), lq3:a) : c = { lq1 (lq2 lq3) }-define first (lq1:func(0,[a;c]), lq2:(Pair a b)) : Pair a c = {+define first (lq1:func(0,[a;c]), lq2:(Pair a b)) : Pair c b = { Pair (lq1 (pfst lq2)) (psnd lq2) } define plus1 (x:int) : int = { x + 1 }@@ -22,7 +22,7 @@ @(1)])) constant first : (func(3 , [func(0 , [@(1); @(2)]); (Pair @(1) @(0));- (Pair @(2) @(0))])) + (Pair @(2) @(0))])) bind 0 g : {VV : func(0 , [b; c]) | []} bind 1 f : {VV : func(0 , [a; b]) | []}
+ tests/pos/T753A.fq view
@@ -0,0 +1,45 @@+// Config {srcFile = "tests/pos/T2535.hs", cores = Nothing, minPartSize = 500, maxPartSize = 700, solver = z3, linear = False, stringTheory = False, defunction = False, allowHO = True, allowHOqs = False, eliminate = some, scrape = no, elimBound = Nothing, smtTimeout = Nothing, elimStats = False, solverStats = False, metadata = False, stats = False, parts = False, save = True, minimize = False, minimizeQs = False, minimizeKs = False, minimalSol = False, etaElim = False, gradual = False, ginteractive = False, autoKuts = False, nonLinCuts = False, noslice = False, rewriteAxioms = False, pleWithUndecidedGuards = False, etabeta = False, localRewrites = False, interpreter = False, oldPLE = False, noIncrPle = False, noEnvironmentReduction = True, inlineANFBindings = False, checkCstr = [], extensionality = False, rwTerminationCheck = False, stdin = False, json = False, noLazyPLE = False, fuel = Nothing, restOrdering = "rpo", noSmtHorn = False}++data AB 2 = [+ | B {selectB : int}+ | A {selectA : int}+ ]+data T 1 = [+ | T {selectT1 : @(0)}+ ]++match selectA A lq_tmp$x##423 { lq_tmp$x##423 }+match selectB B lq_tmp$x##502 { lq_tmp$x##502 }+match check A lq_tmp$x##423 { true }+match check B lq_tmp$x##502 { false }+match isA A lq_tmp$x##423 { true }+match isA B lq_tmp$x##502 { false }++constant A : (func(2 , [int; (AB @(0) @(1))]))+constant selectA : (func(2 , [(AB @(0) @(1)); int]))+constant B : (func(2 , [int; (AB @(0) @(1))]))+constant selectB : (func(2 , [(AB @(0) @(1)); int]))+constant T : (func(1 , [@(0); (T @(0))]))+distinct A : (func(2 , [int; (AB @(0) @(1))]))+distinct B : (func(2 , [int; (AB @(0) @(1))]))+++bind 1 A : {VV : func(2 , [int; (AB @(0) @(1))]) | []}+bind 2 B : {VV : func(2 , [int; (AB @(0) @(1))]) | []}+bind 3 T : {VV : func(1 , [@(0); (T @(0))]) | []}+bind 4 check : {VV : func(2 , [(AB @(0) @(1)); bool]) | []}+bind 5 x : {v : (AB int (T aFD)) | [(check v)]}++constraint:+ env [1; 2; 3; 4; 5]+ lhs {VV : (AB int (T aFD)) | [(VV = (if (is$A VV) then (A (selectA VV)) else (B (selectB VV))))]}+ rhs {VV : (AB int (T aFD)) | [( 3 = (1 + 2) )]}+ id 24 tag [4]+ // META constraint id 24 : tests/pos/T2535.hs:11:1-9+++// unless the sort of application is propagated in both the function and the argument +// as fixed in PR: https://github.com/ucsd-progsys/liquid-fixpoint/pull/753+// the above query crashes with +// Crash!: :1:1-1:1: Error+// crash: SMTLIB2 respSat = Error "line 3 column 13267: Sorts (AB Int (T Int)) and (AB Int Int) are incompatible"
tests/pos/adt_qual.fq view
@@ -1,6 +1,6 @@ -qualif Eq(v:@(0), x:@(0)): (v = x)-qualif Leq(v:@(0), x:@(0)): (v <= x)+qualif Eq(v:@(0), x:@(0)) { v = x }+qualif Leq(v:@(0), x:@(0)) { v <= x } data Zob 0 = [ | boo { choo : int }
tests/pos/bad-subst00.fq view
@@ -1,5 +1,5 @@-qualif Zog(v:a) : (10 <= v)-qualif Bog(v:a, x:a) : (x <= v)+qualif Zog(v:a) { 10 <= v }+qualif Bog(v:a, x:a) { x <= v } bind 0 a : {v: int | $k0[zogbert := pikachu] }
tests/pos/bad-subst01.fq view
@@ -1,8 +1,8 @@ // fixpoint "--eliminate=some" -qualif Zog(v:a) : (10 <= v)-qualif Bog(v:a, x:a) : (x <= v)+qualif Zog(v:a) { 10 <= v }+qualif Bog(v:a, x:a) { x <= v } bind 0 a : {v: int | $k0 }
tests/pos/bad-subst02.fq view
@@ -1,6 +1,6 @@ fixpoint "--eliminate=none" -qualif Eq(v:a, x:a): (v = x)+qualif Eq(v:a, x:a) { v = x } bind 0 x0 : {v: a0 | true } bind 1 x1 : {v: a1 | true }
tests/pos/bool00.fq view
@@ -1,5 +1,5 @@-qualif Zog(v:a) : (10 <= v)-qualif Bog(v:a, x:a) : (x <= v)+qualif Zog(v:a) { 10 <= v }+qualif Bog(v:a, x:a) { x <= v } bind 0 a : {v: int | $k0} bind 1 tt : {v: bool | v}
tests/pos/bool03.fq view
@@ -1,7 +1,7 @@ // qualif LE(v:a, x:a): (bool_to_int x <= bool_to_int v) -qualif LE(v:a, x:a): (x <= v)+qualif LE(v:a, x:a) { x <= v } constant lit$36$not$45$the$45$hippopotamus : (Str) constant lit#cat : (Str)
− tests/pos/bool04.fq
@@ -1,20 +0,0 @@-fixpoint "--eliminate=some"--bind 1 bx : {v: int | true }-bind 2 by : {v: bool | true }--constraint:- env [ 2 ]- lhs {v : int | true }- rhs {v : int | $k1[bx := by] }- id 1 tag []--constraint:- env [ 1 ]- lhs {v : int | $k1 }- rhs {v : int | v <= v + 1 }- id 2 tag []--wf:- env [1]- reft {v : int | $k1 }
− tests/pos/ebind-00.fq
@@ -1,16 +0,0 @@-fixpoint "--eliminate=all"--// bind 0 x1 : {v: int | v = 10 }-ebind 0 x1 : { int }--constraint:- env [0]- lhs {v1 : int | v1 = 10}- rhs {v1 : int | v1 = x1}- id 1 tag []--constraint:- env [0]- lhs {v2 : int | v2 = x1 + 1 }- rhs {v2 : int | v2 = 11 }- id 2 tag []
− tests/pos/ebind-01.fq
@@ -1,17 +0,0 @@-fixpoint "--eliminate=all"--bind 1 m : {v: int | true }-ebind 2 x1 : { int }-// bind 2 x1 : {v: int | v = m + 1 }--constraint:- env [1; 2]- lhs {v : int | v = m + 1 }- rhs {v : int | v = x1 }- id 1 tag []--constraint:- env [1; 2]- lhs {v : int | v = x1 + 1}- rhs {v : int | v = 2 + m }- id 2 tag []
− tests/pos/ebind-02.fq
@@ -1,28 +0,0 @@-fixpoint "--eliminate=all"--bind 0 m : {v: int | true }-bind 1 z : {v: int | v = m - 1 }-ebind 2 x1 : { int }-// bind 2 x1 : {v: int | v = m + 1 }--constraint:- env [0; 1]- lhs {v : int | v = z + 2 }- rhs {v : int | $k }- id 1 tag []--constraint:- env [0; 2]- lhs {v : int | $k }- rhs {v : int | v = x1 }- id 2 tag []--constraint:- env [0; 2]- lhs {v : int | v = x1 + 1 }- rhs {v : int | v = m + 2 }- id 3 tag []--wf: - env [0]- reft {v:int | [$k] }
− tests/pos/ebind-03.fq
@@ -1,45 +0,0 @@-fixpoint "--eliminate=all"--ebind 1 x1 : { int }-ebind 2 x2 : { int }---constraint:- env [1]- lhs {v : int | v = 1 }- rhs {v : int | v = x1 }- id 1 tag []--constraint:- env [1]- lhs {v : int | v = x1 + 1 }- rhs {v : int | $ka }- id 2 tag []--constraint:- env [2]- lhs {v : int | $ka }- rhs {v : int | v = x2 }- id 3 tag []--constraint:- env [2]- lhs {v : int | v = x2 + 1}- rhs {v : int | $kb }- id 4 tag []--constraint:- env []- lhs {v : int | $kb }- rhs {v : int | v = 3 } - id 5 tag []---wf: - env []- reft {v:int | [$ka] }--wf: - env []- reft {v:int | [$kb] }-
− tests/pos/ebind-03a.fq
@@ -1,55 +0,0 @@-fixpoint "--eliminate=all"--ebind 1 x1 : { int }-ebind 2 x2 : { int }--constraint:- env []- lhs {v : int | v = 1 }- rhs {v : int | $kone }- id 10 tag []--constraint:- env [1]- lhs {v : int | $kone }- rhs {v : int | v = x1 }- id 1 tag []--constraint:- env [1]- lhs {v : int | v = x1 + 1 }- rhs {v : int | $ka }- id 2 tag []--constraint:- env [2]- lhs {v : int | $ka }- rhs {v : int | v = x2 }- id 3 tag []--constraint:- env [2]- lhs {v : int | v = x2 + 1}- rhs {v : int | $kb }- id 4 tag []--constraint:- env []- lhs {v : int | $kb }- rhs {v : int | v = 3 } - id 5 tag []---wf: - env []- reft {v:int | [$ka] }--wf: - env []- reft {v:int | [$kb] }--wf: - env []- reft {v:int | [$kone] }--
− tests/pos/ebind-04.fq
@@ -1,35 +0,0 @@-fixpoint "--eliminate=all"--ebind 1 x : { int }--constraint:- env [1]- lhs {v : int | $k1 }- rhs {v : int | v = x }- id 1 tag []--constraint:- env [1]- lhs {v : int | v = x + 1 }- rhs {v : int | $k2 }- id 2 tag []--constraint:- env []- lhs {v : int | v = 3 }- rhs {v : int | $k1 }- id 3 tag []--constraint:- env []- lhs {v : int | $k2 }- rhs {v : int | v = 4 }- id 4 tag []--wf: - env []- reft {v:int | [$k1] }--wf: - env []- reft {v:int | [$k2] }
− tests/pos/ebind-05.fq
@@ -1,31 +0,0 @@-fixpoint "--eliminate=some"--// This file is SAFE with --eliminate=none-// but both qualifiers are needed--bind 16 m : {VV##131 : int | true }-ebind 19 n : { int }--constraint:- env [16; 19]- lhs {VV##F##4 : int | $k_##137[VV##136:=VV##F##4] }- rhs {VV##F##4 : int | VV##F##4 = n }- id 4 tag []--constraint:- env [16]- lhs {VV##F##5 : int | VV##F##5 = m + 1 }- rhs {VV##F##5 : int | $k_##137[VV##136:=VV##F##5] }- id 5 tag []--// Constraint 3 is only needed to prevent the *sharing* optimization--constraint:- env [16; 19]- lhs {VV##F##3 : int | false }- rhs {VV##F##3 : int | $k_##137[VV##136:=VV##F##3] }- id 3 tag []--wf:- env [16]- reft {VV##136 : int | [$k_##137]}
− tests/pos/ebind-06.fq
@@ -1,27 +0,0 @@-fixpoint "--eliminate=some"--bind 16 m : {VV##131 : int | true }-ebind 19 n : { int }--constraint:- env [16; 19]- lhs {VV##F##3 : int | VV##F##3 = n }- rhs {VV##F##3 : int | VV##F##3 = m + 1 && VV##F##3 = 3 }- id 3 tag []--constraint:- env [16; 19]- lhs {VV##F##4 : int | VV##F##4 = 3 }- rhs {VV##F##4 : int | VV##F##4 = n }- id 4 tag []--constraint:- env [16; 19]- lhs {VV##F##5 : int | VV##F##5 = m + 1 }- rhs {VV##F##5 : int | VV##F##5 = n }- id 5 tag []---wf:- env [16]- reft {VV##136 : int | [$k_##137]}
tests/pos/elim00.fq view
@@ -1,8 +1,8 @@ fixpoint "--defunct" // trick is to do it without these-qualif Cmp(v : @(0), x : @(0)): ((v > x)) // "tests/todo/elim00.hs.fq" (line 1, column 8)-qualif Cmp(v : @(0), x : @(0)): ((v = x)) // "tests/todo/elim00.hs.fq" (line 2, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v > x) } // "tests/todo/elim00.hs.fq" (line 1, column 8)+qualif Cmp(v : @(0), x : @(0)) { (v = x) } // "tests/todo/elim00.hs.fq" (line 2, column 8) constant Control.Exception.Base.irrefutPatError##09 : (func(1, [int;
tests/pos/func00.fq view
@@ -2,7 +2,7 @@ bind 0 f : {v: func(0, [int; int]) | []} constraint:- env [ ]+ env [ 0 ] lhs {v : int | [f = f]} rhs {v : int | [0 < 7]} id 1 tag []
tests/pos/gfp00.fq view
@@ -1,7 +1,7 @@-qualif Pos(v:int) : (0 <= v)-qualif Neg(v:int) : (v <= 0)-qualif NeqZ(v:int) : (0 != v)-qualif False(v:int) : (66 = 77)+qualif Pos(v:int) { 0 <= v }+qualif Neg(v:int) { v <= 0 }+qualif NeqZ(v:int) { 0 != v }+qualif False(v:int) { 66 = 77 } constraint: env []
tests/pos/hex.ts.fq view
@@ -1,23 +1,23 @@-qualif Bot(v : a): (0 = 1) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif Bot(v : obj): (0 = 1) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif Bot(v : Boolean): (0 = 1) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif Bot(v : int): (0 = 1) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif CmpZ(v : int): (v < 0) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif CmpZ(v : int): (v <= 0) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif CmpZ(v : int): (v > 0) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif CmpZ(v : int): (v >= 0) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif CmpZ(v : int): (v = 0) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif CmpZ(v : int): (v != 0) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif Cmp(v : int, x : int): (v < x) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif Cmp(v : int, x : int): (v <= x) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif Cmp(v : int, x : int): (v > x) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif Cmp(v : int, x : int): (v >= x) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif Cmp(v : a, x : a): (v ~~ x) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif Cmp(v : a, x : a): (v != x) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif True1(v : Boolean): (? Prop([v])) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif False1(v : Boolean): (~ ((? Prop([v])))) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif Tag(v : a, x : Str): (ttag([v]) = x) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)-qualif Len(v : b, w : a): (v < len([w])) // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif Bot(v : a) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif Bot(v : obj) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif Bot(v : Boolean) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif Bot(v : int) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif CmpZ(v : int) { v < 0 } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif CmpZ(v : int) { v <= 0 } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif CmpZ(v : int) { v > 0 } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif CmpZ(v : int) { v >= 0 } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif CmpZ(v : int) { v = 0 } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif CmpZ(v : int) { v != 0 } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif Cmp(v : int, x : int) { v < x } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif Cmp(v : int, x : int) { v <= x } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif Cmp(v : int, x : int) { v > x } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif Cmp(v : int, x : int) { v >= x } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif Cmp(v : a, x : a) { v ~~ x } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif Cmp(v : a, x : a) { v != x } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif True1(v : Boolean) { Prop([v]) } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif False1(v : Boolean) { ~ ((Prop([v]))) } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif Tag(v : a, x : Str) { ttag([v]) = x } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1)+qualif Len(v : b, w : a) { v < len([w]) } // "/Users/rjhala/research/stack/liquid/refscript/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/refscript-0.1.0.0/include/prelude.ts" (line 1, column 1) @@ -74,139 +74,139 @@ bind 0 undefined : {v : Undefined | [(ttag([v]) = lit$36$undefined);- (~ ((? Prop([v]))))]}-bind 1 Object : {VV$35$285 : Object | [(? Prop([VV$35$285]));+ (~ ((Prop([v]))))]}+bind 1 Object : {VV$35$285 : Object | [(Prop([VV$35$285])); (ttag([VV$35$285]) = lit$36$object)]}-bind 2 Object.prototype : {VV : (Object Immutable) | [(? extends_interface([VV;+bind 2 Object.prototype : {VV : (Object Immutable) | [(extends_interface([VV; lit$36$Object]));- (? Prop([VV]));+ (Prop([VV])); (ttag([VV]) = lit$36$object); (VV ~~ offset([Object; lit$36$prototype]))]} bind 3 NaN : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v = numeric_nan)]}-bind 4 Number : {VV$35$325 : Object | [(? Prop([VV$35$325]));+bind 4 Number : {VV$35$325 : Object | [(Prop([VV$35$325])); (ttag([VV$35$325]) = lit$36$object)]} bind 5 Number.POSITIVE_INFINITY : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Number; lit$36$POSITIVE_INFINITY]))]} bind 6 Number.MIN_VALUE : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Number; lit$36$MIN_VALUE]))]}-bind 7 Number.prototype : {VV : (Number Immutable) | [(? extends_interface([VV;+bind 7 Number.prototype : {VV : (Number Immutable) | [(extends_interface([VV; lit$36$Number]));- (? Prop([VV]));+ (Prop([VV])); (ttag([VV]) = lit$36$object); (VV ~~ offset([Number; lit$36$prototype]))]} bind 8 Number.NaN : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Number; lit$36$NaN]))]} bind 9 Number.NEGATIVE_INFINITY : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Number; lit$36$NEGATIVE_INFINITY]))]} bind 10 Number.MAX_VALUE : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Number; lit$36$MAX_VALUE]))]}-bind 11 Math : {VV$35$387 : (Math Immutable) | [(? extends_interface([VV$35$387;+bind 11 Math : {VV$35$387 : (Math Immutable) | [(extends_interface([VV$35$387; lit$36$Math]));- (? Prop([VV$35$387]));+ (Prop([VV$35$387])); (ttag([VV$35$387]) = lit$36$object)]} bind 12 Math.SQRT2 : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Math; lit$36$SQRT2]))]} bind 13 Math.LN2 : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Math; lit$36$LN2]))]} bind 14 Math.PI : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Math; lit$36$PI]))]} bind 15 Math.LOG10E : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Math; lit$36$LOG10E]))]} bind 16 Math.LOG2E : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Math; lit$36$LOG2E]))]} bind 17 Math.E : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Math; lit$36$E]))]} bind 18 Math.SQRT1_2 : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Math; lit$36$SQRT1_2]))]} bind 19 Math.LN10 : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Math; lit$36$LN10]))]}-bind 20 String : {VV$35$469 : (StringConstructor Immutable) | [(? extends_interface([VV$35$469;+bind 20 String : {VV$35$469 : (StringConstructor Immutable) | [(extends_interface([VV$35$469; lit$36$StringConstructor]));- (? Prop([VV$35$469]));+ (Prop([VV$35$469])); (ttag([VV$35$469]) = lit$36$object)]}-bind 21 String.prototype : {VV : (String Immutable) | [(? extends_interface([VV;+bind 21 String.prototype : {VV : (String Immutable) | [(extends_interface([VV; lit$36$String]));- (? Prop([VV]));+ (Prop([VV])); (ttag([VV]) = lit$36$object); (VV ~~ offset([String; lit$36$prototype]))]}-bind 22 Array : {VV$35$727 : Object | [(? Prop([VV$35$727]));+bind 22 Array : {VV$35$727 : Object | [(Prop([VV$35$727])); (ttag([VV$35$727]) = lit$36$object)]}-bind 23 Array.prototype : {VV : (Array Mutable Top) | [(? extends_interface([VV;+bind 23 Array.prototype : {VV : (Array Mutable Top) | [(extends_interface([VV; lit$36$Array]));- (? Prop([VV]));+ (Prop([VV])); (ttag([VV]) = lit$36$object); (VV ~~ offset([Array; lit$36$prototype]))]}-bind 24 Function : {VV$35$762 : Object | [(? Prop([VV$35$762]));+bind 24 Function : {VV$35$762 : Object | [(Prop([VV$35$762])); (ttag([VV$35$762]) = lit$36$object)]}-bind 25 Function.prototype : {VV : (Function Immutable) | [(? extends_interface([VV;+bind 25 Function.prototype : {VV : (Function Immutable) | [(extends_interface([VV; lit$36$Function]));- (? Prop([VV]));+ (Prop([VV])); (ttag([VV]) = lit$36$object); (VV ~~ offset([Function; lit$36$prototype]))]}-bind 26 Console : {VV$35$891 : Object | [(? Prop([VV$35$891]));+bind 26 Console : {VV$35$891 : Object | [(Prop([VV$35$891])); (ttag([VV$35$891]) = lit$36$object)]}-bind 27 Console.prototype : {VV : (Console Immutable) | [(? extends_interface([VV;+bind 27 Console.prototype : {VV : (Console Immutable) | [(extends_interface([VV; lit$36$Console]));- (? Prop([VV]));+ (Prop([VV])); (ttag([VV]) = lit$36$object); (VV ~~ offset([Console; lit$36$prototype]))]}-bind 28 console : {VV$35$893 : (Console Immutable) | [(? extends_interface([VV$35$893;+bind 28 console : {VV$35$893 : (Console Immutable) | [(extends_interface([VV$35$893; lit$36$Console]));- (? Prop([VV$35$893]));+ (Prop([VV$35$893])); (ttag([VV$35$893]) = lit$36$object)]}-bind 29 Error : {VV$35$983 : Object | [(? Prop([VV$35$983]));+bind 29 Error : {VV$35$983 : Object | [(Prop([VV$35$983])); (ttag([VV$35$983]) = lit$36$object)]}-bind 30 Error.prototype : {VV : (Error Immutable) | [(? extends_interface([VV;+bind 30 Error.prototype : {VV : (Error Immutable) | [(extends_interface([VV; lit$36$Error]));- (? Prop([VV]));+ (Prop([VV])); (ttag([VV]) = lit$36$object); (VV ~~ offset([Error; lit$36$prototype]))]}-bind 31 Event : {VV$35$1025 : Object | [(? Prop([VV$35$1025]));+bind 31 Event : {VV$35$1025 : Object | [(Prop([VV$35$1025])); (ttag([VV$35$1025]) = lit$36$object)]} bind 32 Event.CAPTURING_PHASE : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Event; lit$36$CAPTURING_PHASE]))]} bind 33 Event.AT_TARGET : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Event; lit$36$AT_TARGET]))]}-bind 34 Event.prototype : {VV : (Event Immutable) | [(? extends_interface([VV;+bind 34 Event.prototype : {VV : (Event Immutable) | [(extends_interface([VV; lit$36$Event]));- (? Prop([VV]));+ (Prop([VV])); (ttag([VV]) = lit$36$object); (VV ~~ offset([Event; lit$36$prototype]))]} bind 35 Event.BUBBLING_PHASE : {v : int | [(ttag([v]) = lit$36$number);- ((? Prop([v])) <=> (v != 0));+ ((Prop([v])) <=> (v != 0)); (v ~~ offset([Event; lit$36$BUBBLING_PHASE]))]}-bind 36 document : {VV$35$1027 : (Document Immutable) | [(? extends_interface([VV$35$1027;+bind 36 document : {VV$35$1027 : (Document Immutable) | [(extends_interface([VV$35$1027; lit$36$Document]));- (? Prop([VV$35$1027]));+ (Prop([VV$35$1027])); (ttag([VV$35$1027]) = lit$36$object)]}-bind 37 document.documentElement : {VV : (HTMLElement Immutable) | [(? extends_interface([VV;+bind 37 document.documentElement : {VV : (HTMLElement Immutable) | [(extends_interface([VV; lit$36$HTMLElement]));- (? Prop([VV]));+ (Prop([VV])); (ttag([VV]) = lit$36$object); (VV ~~ offset([document; lit$36$documentElement]))]}-bind 38 window : {VV$35$1031 : (Window Immutable) | [(? extends_interface([VV$35$1031;+bind 38 window : {VV$35$1031 : (Window Immutable) | [(extends_interface([VV$35$1031; lit$36$Window]));- (? Prop([VV$35$1031]));+ (Prop([VV$35$1031])); (ttag([VV$35$1031]) = lit$36$object)]} bind 39 lq_tmp_nano_1 : {VV : (BitVec Size32) | [(VV = (lit "#x00000008" (BitVec Size32)))]} bind 40 a_SSA_0 : {VV : (BitVec Size32) | [(VV ~~ lq_tmp_nano_1);@@ -217,7 +217,7 @@ bind 43 lq_tmp_nano_3 : {v : (BitVec Size32) | [(v = bvor([a_SSA_0; a_SSA_0]))]} bind 44 lq_tmp_nano_6 : {v : Boolean | [(ttag([v]) = lit$36$boolean);- ((? Prop([v])) <=> (b_SSA_1 ~~ lq_tmp_nano_3))]}+ ((Prop([v])) <=> (b_SSA_1 ~~ lq_tmp_nano_3))]} bind 45 lq_tmp_nano_9 : {VV$35$4 : Void | []} @@ -272,8 +272,8 @@ lhs {VV$35$F1 : Boolean | [(ttag([VV$35$F1]) = lit$36$boolean); (VV$35$F1 ~~ lq_tmp_nano_6); (ttag([VV$35$F1]) = lit$36$boolean);- ((? Prop([VV$35$F1])) <=> (b_SSA_1 ~~ lq_tmp_nano_3))]}- rhs {VV$35$F1 : Boolean | [(? Prop([VV$35$F1]))]}+ ((Prop([VV$35$F1])) <=> (b_SSA_1 ~~ lq_tmp_nano_3))]}+ rhs {VV$35$F1 : Boolean | [(Prop([VV$35$F1]))]} id 1 tag [1] // META constraint id 1 : /Users/rjhala/research/stack/liquid/refscript/tests/pos/simple/hex.ts:7:1-7:22 @@ -327,8 +327,8 @@ lhs {VV$35$F2 : Boolean | [(ttag([VV$35$F2]) = lit$36$boolean); (VV$35$F2 ~~ lq_tmp_nano_6); (ttag([VV$35$F2]) = lit$36$boolean);- ((? Prop([VV$35$F2])) <=> (b_SSA_1 ~~ lq_tmp_nano_3))]}- rhs {VV$35$F2 : Boolean | [(? Prop([VV$35$F2]))]}+ ((Prop([VV$35$F2])) <=> (b_SSA_1 ~~ lq_tmp_nano_3))]}+ rhs {VV$35$F2 : Boolean | [(Prop([VV$35$F2]))]} id 2 tag [1] // META constraint id 2 : /Users/rjhala/research/stack/liquid/refscript/tests/pos/simple/hex.ts:7:1-7:22
tests/pos/kvar-param-poly-00.fq view
@@ -2,7 +2,7 @@ // a kvar's params can be instantiated / substituted with values of a different // type. Here, K0(v:alpha, x:alpha) but is instantiated with int. -qualif Bog(v:a, x:a) : (x = v)+qualif Bog(v:a, x:a) { x = v } bind 1 x : {v: alpha | true}
tests/pos/len00-rename.fq view
@@ -1,7 +1,7 @@ // This qualifier saves the day; solve constraints WITHOUT IT -qualif ListZ(v : [@(0)]): (len v >= 0)+qualif ListZ(v : [@(0)]) { len v >= 0 } constant len : (func(2, [(@(0) @(1)); int]))
tests/pos/len00.fq view
@@ -1,7 +1,7 @@ // This qualifier saves the day; solve constraints WITHOUT IT -qualif ListZ(v : [@(0)]): (len v >= 0)+qualif ListZ(v : [@(0)]) { len v >= 0 } constant len : (func(2, [(@(0) @(1)); int]))
tests/pos/listqual.hs.fq view
@@ -1,53 +1,53 @@-qualif Append(v : [@(0)], xs : [@(0)], ys : [@(0)]): (len([v]) = (len([xs]) + len([ys]))) // "tests/pos/listqual.hs" (line 3, column 12)-qualif Fst(v : @(1), y : @(0)): (v = fst([y])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.spec" (line 29, column 8)-qualif Snd(v : @(1), y : @(0)): (v = snd([y])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.spec" (line 30, column 8)-qualif Auto(v : [int]): (len([v]) = 2) // "tests/pos/listqual.hs" (line 10, column 1)-qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]): ((? Prop([v])) <=> (len([xs]) > 0)) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 13, column 8)-qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]): ((? Prop([v])) <=> (len([xs]) = 0)) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 14, column 8)-qualif ListZ(v : [@(0)]): (len([v]) = 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 16, column 8)-qualif ListZ(v : [@(0)]): (len([v]) >= 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 17, column 8)-qualif ListZ(v : [@(0)]): (len([v]) > 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 18, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) = len([xs])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 20, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) >= len([xs])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 21, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) > len([xs])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 22, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) <= len([xs])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 23, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) < len([xs])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 24, column 8)-qualif EqLen(v : int, xs : [@(0)]): (v = len([xs])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 26, column 8)-qualif LenEq(v : [@(0)], x : int): (x = len([v])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 27, column 8)-qualif LenDiff(v : [@(0)], x : int): (len([v]) = (x + 1)) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 28, column 8)-qualif LenDiff(v : [@(0)], x : int): (len([v]) = (x - 1)) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 29, column 8)-qualif LenAcc(v : int, xs : [@(0)], n : int): (v = (len([xs]) + n)) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 30, column 8)-qualif Bot(v : @(0)): (0 = 1) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 3, column 8)-qualif Bot(v : @(0)): (0 = 1) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 4, column 8)-qualif Bot(v : @(0)): (0 = 1) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 5, column 8)-qualif Bot(v : bool): (0 = 1) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 6, column 8)-qualif Bot(v : int): (0 = 1) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 7, column 8)-qualif CmpZ(v : @(0)): (v < 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 9, column 8)-qualif CmpZ(v : @(0)): (v <= 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 10, column 8)-qualif CmpZ(v : @(0)): (v > 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 11, column 8)-qualif CmpZ(v : @(0)): (v >= 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 12, column 8)-qualif CmpZ(v : @(0)): (v = 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 13, column 8)-qualif CmpZ(v : @(0)): (v != 0) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 14, column 8)-qualif Cmp(v : @(0), x : @(0)): (v < x) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 16, column 8)-qualif Cmp(v : @(0), x : @(0)): (v <= x) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 17, column 8)-qualif Cmp(v : @(0), x : @(0)): (v > x) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 18, column 8)-qualif Cmp(v : @(0), x : @(0)): (v >= x) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 19, column 8)-qualif Cmp(v : @(0), x : @(0)): (v = x) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 20, column 8)-qualif Cmp(v : @(0), x : @(0)): (v != x) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 21, column 8)-qualif One(v : int): (v = 1) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 28, column 8)-qualif True(v : bool): (? v) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 29, column 8)-qualif False(v : bool): (~ ((? v))) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 30, column 8)-qualif True1(v : GHC.Types.Bool): (? Prop([v])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 31, column 8)-qualif False1(v : GHC.Types.Bool): (~ ((? Prop([v])))) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 32, column 8)-qualif Papp(v : @(0), p : (Pred @(0))): (? papp1([p;- v])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 35, column 8)-qualif Papp2(v : @(1), x : @(0), p : (Pred @(1) @(0))): (? papp2([p;+qualif Append(v : [@(0)], xs : [@(0)], ys : [@(0)]) { len([v]) = (len([xs]) + len([ys])) } // "tests/pos/listqual.hs" (line 3, column 12)+qualif Fst(v : @(1), y : @(0)) { v = fst([y]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.spec" (line 29, column 8)+qualif Snd(v : @(1), y : @(0)) { v = snd([y]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.spec" (line 30, column 8)+qualif Auto(v : [int]) { len([v]) = 2 } // "tests/pos/listqual.hs" (line 10, column 1)+qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]) { Prop([v]) <=> len([xs]) > 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 13, column 8)+qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]) { Prop([v]) <=> len([xs]) = 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 14, column 8)+qualif ListZ(v : [@(0)]) { len([v]) = 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 16, column 8)+qualif ListZ(v : [@(0)]) { len([v]) >= 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 17, column 8)+qualif ListZ(v : [@(0)]) { len([v]) > 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 18, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) = len([xs]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 20, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) >= len([xs]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 21, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) > len([xs]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 22, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) <= len([xs]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 23, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) < len([xs]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 24, column 8)+qualif EqLen(v : int, xs : [@(0)]) { v = len([xs]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 26, column 8)+qualif LenEq(v : [@(0)], x : int) { x = len([v]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 27, column 8)+qualif LenDiff(v : [@(0)], x : int) { len([v]) = (x + 1) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 28, column 8)+qualif LenDiff(v : [@(0)], x : int) { len([v]) = (x - 1) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 29, column 8)+qualif LenAcc(v : int, xs : [@(0)], n : int) { v = (len([xs]) + n) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/GHC/Base.hquals" (line 30, column 8)+qualif Bot(v : @(0)) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 3, column 8)+qualif Bot(v : @(0)) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 4, column 8)+qualif Bot(v : @(0)) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 5, column 8)+qualif Bot(v : bool) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 6, column 8)+qualif Bot(v : int) { 0 = 1 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 7, column 8)+qualif CmpZ(v : @(0)) { v < 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 9, column 8)+qualif CmpZ(v : @(0)) { v <= 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 10, column 8)+qualif CmpZ(v : @(0)) { v > 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 11, column 8)+qualif CmpZ(v : @(0)) { v >= 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 12, column 8)+qualif CmpZ(v : @(0)) { v = 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 13, column 8)+qualif CmpZ(v : @(0)) { v != 0 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 14, column 8)+qualif Cmp(v : @(0), x : @(0)) { v < x } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 16, column 8)+qualif Cmp(v : @(0), x : @(0)) { v <= x } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 17, column 8)+qualif Cmp(v : @(0), x : @(0)) { v > x } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 18, column 8)+qualif Cmp(v : @(0), x : @(0)) { v >= x } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 19, column 8)+qualif Cmp(v : @(0), x : @(0)) { v = x } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 20, column 8)+qualif Cmp(v : @(0), x : @(0)) { v != x } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 21, column 8)+qualif One(v : int) { v = 1 } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 28, column 8)+qualif True(v : bool) { v } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 29, column 8)+qualif False(v : bool) { ~ v } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 30, column 8)+qualif True1(v : GHC.Types.Bool) { Prop([v]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 31, column 8)+qualif False1(v : GHC.Types.Bool) { ~ Prop([v]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 32, column 8)+qualif Papp(v : @(0), p : (Pred @(0))) { papp1([p;+ v]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 35, column 8)+qualif Papp2(v : @(1), x : @(0), p : (Pred @(1) @(0))) { papp2([p; v;- x])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 38, column 8)-qualif Papp3(v : @(2), x : @(0), y : @(1), p : (Pred @(2) @(0) @(1))): (? papp3([p;+ x]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 38, column 8)+qualif Papp3(v : @(2), x : @(0), y : @(1), p : (Pred @(2) @(0) @(1))) { papp3([p; v; x;- y])) // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 41, column 8)+ y]) } // "/Users/rjhala/research/stack/liquid/liquidhaskell/.stack-work/install/x86_64-osx/nightly-2015-09-24/7.10.2/share/x86_64-osx-ghc-7.10.2/liquidhaskell-0.5.0.2/include/Prelude.hquals" (line 41, column 8) cut $k__185@@ -163,10 +163,10 @@ bind 13 lq_anf__dwU : {lq_tmp_x_198 : [a_awA] | [(lq_tmp_x_198 = ds_dwT); (len([lq_tmp_x_198]) >= 0); (len([lq_tmp_x_198]) = 0);- ((? null([lq_tmp_x_198])) <=> true);+ (null([lq_tmp_x_198]) <=> true); (lq_tmp_x_198 = GHC.Types.$91$$93$$35$6m([])); (len([lq_tmp_x_198]) = 0);- ((? null([lq_tmp_x_198])) <=> true);+ (null([lq_tmp_x_198]) <=> true); (len([lq_tmp_x_198]) >= 0)]} bind 14 lq_anf__dwU : {lq_tmp_x_208 : [a_awA] | [(lq_tmp_x_208 = ds_dwT); (len([lq_tmp_x_208]) >= 0);@@ -176,13 +176,13 @@ bind 17 lq_anf__dwU : {lq_tmp_x_208 : [a_awA] | [(lq_tmp_x_208 = ds_dwT); (len([lq_tmp_x_208]) >= 0); (len([lq_tmp_x_208]) = (1 + len([xs$35$awp])));- ((? null([lq_tmp_x_208])) <=> false);+ (null([lq_tmp_x_208]) <=> false); (xsListSelector([lq_tmp_x_208]) = xs$35$awp); (xListSelector([lq_tmp_x_208]) = x$35$awo); (lq_tmp_x_208 = GHC.Types.$58$$35$64([x$35$awo; xs$35$awp])); (len([lq_tmp_x_208]) = (1 + len([xs$35$awp])));- ((? null([lq_tmp_x_208])) <=> false);+ (null([lq_tmp_x_208]) <=> false); (xsListSelector([lq_tmp_x_208]) = xs$35$awp); (xListSelector([lq_tmp_x_208]) = x$35$awo); (len([lq_tmp_x_208]) >= 0)]}@@ -192,22 +192,22 @@ bind 20 lq_anf__dwW : {lq_tmp_x_264 : int | [(lq_tmp_x_264 = (1 : int))]} bind 21 lq_tmp_x_278 : {VV$35$279 : int | []} bind 22 lq_anf__dwX : {lq_tmp_x_270 : [int] | [(len([lq_tmp_x_270]) = 0);- ((? null([lq_tmp_x_270])) <=> true);+ (null([lq_tmp_x_270]) <=> true); (len([lq_tmp_x_270]) >= 0)]} bind 23 lq_tmp_x_296 : {VV$35$297 : int | []} bind 24 lq_anf__dwY : {lq_tmp_x_284 : [int] | [(len([lq_tmp_x_284]) = (1 + len([lq_anf__dwX])));- ((? null([lq_tmp_x_284])) <=> false);+ (null([lq_tmp_x_284]) <=> false); (xsListSelector([lq_tmp_x_284]) = lq_anf__dwX); (xListSelector([lq_tmp_x_284]) = lq_anf__dwW); (len([lq_tmp_x_284]) >= 0)]} bind 25 lq_anf__dwZ : {lq_tmp_x_305 : int | [(lq_tmp_x_305 = (2 : int))]} bind 26 lq_tmp_x_319 : {VV$35$320 : int | []} bind 27 lq_anf__dx0 : {lq_tmp_x_311 : [int] | [(len([lq_tmp_x_311]) = 0);- ((? null([lq_tmp_x_311])) <=> true);+ (null([lq_tmp_x_311]) <=> true); (len([lq_tmp_x_311]) >= 0)]} bind 28 lq_tmp_x_337 : {VV$35$338 : int | []} bind 29 lq_anf__dx1 : {lq_tmp_x_325 : [int] | [(len([lq_tmp_x_325]) = (1 + len([lq_anf__dx0])));- ((? null([lq_tmp_x_325])) <=> false);+ (null([lq_tmp_x_325]) <=> false); (xsListSelector([lq_tmp_x_325]) = lq_anf__dx0); (xListSelector([lq_tmp_x_325]) = lq_anf__dwZ); (len([lq_tmp_x_325]) >= 0)]}@@ -269,12 +269,12 @@ bind 72 VV$35$427 : {VV$35$427 : int | [(VV$35$427 = 1)]} bind 73 VV$35$427 : {VV$35$427 : int | [(VV$35$427 = 1)]} bind 74 VV$35$430 : {VV$35$430 : [a_awA] | [(len([VV$35$430]) = (1 + len([lq_anf__dwV])));- ((? null([VV$35$430])) <=> false);+ (null([VV$35$430]) <=> false); (xsListSelector([VV$35$430]) = lq_anf__dwV); (xListSelector([VV$35$430]) = x$35$awo); (len([VV$35$430]) >= 0)]} bind 75 VV$35$430 : {VV$35$430 : [a_awA] | [(len([VV$35$430]) = (1 + len([lq_anf__dwV])));- ((? null([VV$35$430])) <=> false);+ (null([VV$35$430]) <=> false); (xsListSelector([VV$35$430]) = lq_anf__dwV); (xListSelector([VV$35$430]) = x$35$awo); (len([VV$35$430]) >= 0)]}@@ -384,7 +384,7 @@ constraint: env [0; 16; 1; 17; 2; 18; 3; 4; 5; 6; 7; 8; 9; 10; 74; 11; 14; 15] lhs {VV$35$F18 : [a_awA] | [(len([VV$35$F18]) = (1 + len([lq_anf__dwV])));- ((? null([VV$35$F18])) <=> false);+ (null([VV$35$F18]) <=> false); (xsListSelector([VV$35$F18]) = lq_anf__dwV); (xListSelector([VV$35$F18]) = x$35$awo); (len([VV$35$F18]) >= 0)]}
tests/pos/meas02.fq view
@@ -1,7 +1,7 @@ -qualif SumZ(v:[real]): (sumD v = 0.0)+qualif SumZ(v:[real]) { sumD v = 0.0 } -qualif SumZ(v:[real]): (((sumD v) / (sumD v)) = 1.0)+qualif SumZ(v:[real]) { ((sumD v) / (sumD v)) = 1.0 } constant sumD : (func(0, [[real]; real]))
tests/pos/min00.fq view
@@ -1,8 +1,8 @@ -qualif Zog(v:a) : (10 <= v)-qualif Zog(v:a) : (9 <= v)-qualif Zog(v:a) : (8 <= v)-qualif Zog(v:a) : (99 <= v)+qualif Zog(v:a) { 10 <= v }+qualif Zog(v:a) { 9 <= v }+qualif Zog(v:a) { 8 <= v }+qualif Zog(v:a) { 99 <= v } constraint: env []
tests/pos/num00.fq view
@@ -1,6 +1,6 @@ // This qualifier saves the day; solve constraints WITHOUT IT -qualif Zog(v:a) : (0 <= v)+qualif Zog(v:a) { 0 <= v } bind 0 alpha : {v : num | true}
tests/pos/numoverload00.fq view
@@ -1,6 +1,6 @@ -qualif Foo(v:real, xiggety:real): (v = xiggety * xiggety)-qualif Bar(v:real): (v = 0.0)+qualif Foo(v:real, xiggety:real) { v = xiggety * xiggety }+qualif Bar(v:real) { v = 0.0 } bind 0 zero : {VV : real | VV = 0.0 } bind 1 one : {VV : real | VV = (1.0 / 1.0) }
tests/pos/qualif-inst.fq view
@@ -1,6 +1,6 @@ // adapted from LH test eqelems.hs -qualif Cmp(v : @(0), fix##126#X : @(0)): (v >= fix##126#X)+qualif Cmp(v : @(0), fix##126#X : @(0)) { v >= fix##126#X } constant elems : (func(1, [(Goo.T @(0)); (Set_Set @(0))]))
tests/pos/qualif-template-00.fq view
@@ -1,6 +1,6 @@ // qualif Goob(v:a, z: b) : (v = z) // qualif Prefix2(v:a, x as (mon . $1) : b, y as (sun . $1)) : (v = x + y)-qualif Prefix(v:a, z as (mon . $1) : b) : (v = z)+qualif Prefix(v:a, z as (mon . $1) : b) { v = z } bind 0 monday : {v : int | true} bind 10 tuesday : {v : int | true}
tests/pos/qualif-template-01.fq view
@@ -1,6 +1,6 @@ // qualif Goob(v:a, z: b) : (v = z) // qualif Prefix2(v:a, x as (mon . $1) : b, y as (sun . $1)) : (v = x + y)-qualif Prefix(v:a, z as ($1 . nday) : b) : (v = z)+qualif Prefix(v:a, z as ($1 . nday) : b) { v = z } bind 0 monday : {v : int | true} bind 10 tuesday : {v : int | true}
tests/pos/qualif-template-02.fq view
@@ -1,4 +1,4 @@-qualif Prefix2(v:a, x as (sun . $1) : b, y as (mon . $1) : b) : (v = x + y)+qualif Prefix2(v:a, x as (sun . $1) : b, y as (mon . $1) : b) { v = x + y } bind 0 sunday : {v : int | v = 6 } bind 1 monday : {v : int | v = 4 }
tests/pos/sets.fq view
@@ -2,6 +2,6 @@ constraint: env []- lhs {v : Set_Set a_aTp | [(? Set_emp([v]))]}+ lhs {v : Set_Set a_aTp | [(Set_emp([v]))]} rhs {v : Set_Set a_aTp | [(v = Set_empty([0]))]} id 3 tag [2]
tests/pos/test00.fq view
@@ -1,5 +1,5 @@-qualif Zog(v:a) : (10 <= v)-qualif Bog(v:a, x:a) : (x <= v)+qualif Zog(v:a) { 10 <= v }+qualif Bog(v:a, x:a) { x <= v } bind 0 a : {va: int | $k0[v := va][thing := thang] } bind 1 thing : {v: int | true }
tests/pos/test00.hs.fq view
@@ -1,61 +1,61 @@ -qualif IsEmp(v:GHC.Types.Bool, xs: [a]) : (Prop(v) <=> len([xs]) > 0)-qualif IsEmp(v:GHC.Types.Bool, xs: [a]) : (Prop(v) <=> len([xs]) = 0)-qualif ListZ(v: [a]) : len([v]) = 0 -qualif ListZ(v: [a]) : len([v]) >= 0 -qualif ListZ(v: [a]) : len([v]) > 0 -qualif CmpLen(v:[a], xs:[b]) : len([v]) = len([xs]) -qualif CmpLen(v:[a], xs:[b]) : len([v]) >= len([xs]) -qualif CmpLen(v:[a], xs:[b]) : len([v]) > len([xs]) -qualif CmpLen(v:[a], xs:[b]) : len([v]) <= len([xs]) -qualif CmpLen(v:[a], xs:[b]) : len([v]) < len([xs]) -qualif EqLen(v:int, xs: [a]): v = len([xs]) -qualif LenEq(v:[a], x: int) : x = len([v]) -qualif LenDiff(v:[a], x:int): len([v]) = x + 1-qualif LenDiff(v:[a], x:int): len([v]) = x - 1-qualif LenAcc(v:int, xs:[a], n: int): (v = len([xs]) + n)+qualif IsEmp(v:GHC.Types.Bool, xs: [a]) { Prop(v) <=> len([xs]) > 0 }+qualif IsEmp(v:GHC.Types.Bool, xs: [a]) { Prop(v) <=> len([xs]) = 0 }+qualif ListZ(v: [a]) { len([v]) = 0 }+qualif ListZ(v: [a]) { len([v]) >= 0 }+qualif ListZ(v: [a]) { len([v]) > 0 }+qualif CmpLen(v:[a], xs:[b]) { len([v]) = len([xs]) }+qualif CmpLen(v:[a], xs:[b]) { len([v]) >= len([xs]) }+qualif CmpLen(v:[a], xs:[b]) { len([v]) > len([xs]) }+qualif CmpLen(v:[a], xs:[b]) { len([v]) <= len([xs]) }+qualif CmpLen(v:[a], xs:[b]) { len([v]) < len([xs]) }+qualif EqLen(v:int, xs: [a]) { v = len([xs]) }+qualif LenEq(v:[a], x: int) { x = len([v]) }+qualif LenDiff(v:[a], x:int) { len([v]) = x + 1 }+qualif LenDiff(v:[a], x:int) { len([v]) = x - 1 }+qualif LenAcc(v:int, xs:[a], n: int) { v = len([xs]) + n } -qualif Bot(v:obj): 0 = 1 -qualif Bot(v:a): 0 = 1 -qualif Bot(v:bool): 0 = 1 -qualif Bot(v:int): 0 = 1 -qualif CmpZ(v:a): (v < 0)-qualif CmpZ(v:a): (v <= 0)-qualif CmpZ(v:a): (v > 0)-qualif CmpZ(v:a): (v >= 0)-qualif CmpZ(v:a): (v = 0)-qualif CmpZ(v:a): (v != 0)+qualif Bot(v:obj) { 0 = 1 }+qualif Bot(v:a) { 0 = 1 }+qualif Bot(v:bool) { 0 = 1 }+qualif Bot(v:int) { 0 = 1 }+qualif CmpZ(v:a) { v < 0 }+qualif CmpZ(v:a) { v <= 0 }+qualif CmpZ(v:a) { v > 0 }+qualif CmpZ(v:a) { v >= 0 }+qualif CmpZ(v:a) { v = 0 }+qualif CmpZ(v:a) { v != 0 } -qualif Cmp(v:a, x:a): (v < x)-qualif Cmp(v:a, x:a): (v <= x)-qualif Cmp(v:a, x:a): (v > x)-qualif Cmp(v:a, x:a): (v >= x)-qualif Cmp(v:a, x:a): (v = x)-qualif Cmp(v:a, x:a): (v != x)+qualif Cmp(v:a, x:a) { v < x }+qualif Cmp(v:a, x:a) { v <= x }+qualif Cmp(v:a, x:a) { v > x }+qualif Cmp(v:a, x:a) { v >= x }+qualif Cmp(v:a, x:a) { v = x }+qualif Cmp(v:a, x:a) { v != x } -qualif One(v:int) : v = 1-qualif True(v:bool) : (? v) -qualif False(v:bool) : ~ (? v) -qualif True1(v:GHC.Types.Bool): (Prop(v))-qualif False1(v:GHC.Types.Bool): (~ Prop(v))-qualif Papp(v:a, p:Pred a) : (papp1 p v)+qualif One(v:int) { v = 1 }+qualif True(v:bool) { v }+qualif False(v:bool) { ~ (v) }+qualif True1(v:GHC.Types.Bool) { Prop(v) }+qualif False1(v:GHC.Types.Bool) { ~ Prop(v) }+qualif Papp(v:a, p:Pred a) { papp1 p v } constant papp1 : func(1, [Pred @(0); @(0); bool]) -qualif Papp2(v:a,x:b,p:Pred a b) : (papp2 p v x)+qualif Papp2(v:a,x:b,p:Pred a b) { papp2 p v x } constant papp2 : func(4, [Pred @(0) @(1); @(2); @(3); bool]) -qualif Papp3(v:a,x:b, y:c, p:Pred a b c) : (papp3 p v x y)+qualif Papp3(v:a,x:b, y:c, p:Pred a b c) { papp3 p v x y } constant papp3 : func(6, [Pred @(0) @(1) @(2); @(3); @(4); @(5); bool]) -qualif Papp4(v:a,x:b, y:c, z:d, p:Pred a b c d) : (papp4 p v x y z)+qualif Papp4(v:a,x:b, y:c, z:d, p:Pred a b c d) { papp4 p v x y z } constant papp4 : func(8, [Pred @(0) @(1) @(2) @(6); @(3); @(4); @(5); @(7); bool]) constant Prop : func(0, [GHC.Types.Bool; bool])-qualif Fst(v : @(1), fix##126#Y : @(0)): (v = fst([fix##126#Y])) // "/Users/rjhala/research/liquid/liquidhaskell/.cabal-sandbox/share/x86_64-osx-ghc-7.8.3/liquidhaskell-0.3.1.0/include/GHC/Base.spec" (line 26, column 8)-qualif Snd(v : @(1), fix##126#Y : @(0)): (v = snd([fix##126#Y])) // "/Users/rjhala/research/liquid/liquidhaskell/.cabal-sandbox/share/x86_64-osx-ghc-7.8.3/liquidhaskell-0.3.1.0/include/GHC/Base.spec" (line 27, column 8)+qualif Fst(v : @(1), fix##126#Y : @(0)) { v = fst([fix##126#Y]) } // "/Users/rjhala/research/liquid/liquidhaskell/.cabal-sandbox/share/x86_64-osx-ghc-7.8.3/liquidhaskell-0.3.1.0/include/GHC/Base.spec" (line 26, column 8)+qualif Snd(v : @(1), fix##126#Y : @(0)) { v = snd([fix##126#Y]) } // "/Users/rjhala/research/liquid/liquidhaskell/.cabal-sandbox/share/x86_64-osx-ghc-7.8.3/liquidhaskell-0.3.1.0/include/GHC/Base.spec" (line 27, column 8) constant Prop : func(0, [GHC.Types.Bool; bool]) constant x_Tuple54 : func(5, [FAppTy (FAppTy (FAppTy (FAppTy (FAppTy fix##40##41# @(0)) @(1)) @(2)) @(3)) @(4);@@ -138,8 +138,8 @@ bind 7 GHC.Types.EQ#6U : {VV#179 : GHC.Types.Ordering | []} bind 8 GHC.Types.LT#6S : {VV#180 : GHC.Types.Ordering | []} bind 9 GHC.Types.GT#6W : {VV#181 : GHC.Types.Ordering | []}-bind 10 GHC.Types.True#6u : {v : GHC.Types.Bool | [(? Prop([v]))]}-bind 11 GHC.Types.False#68 : {v : GHC.Types.Bool | [(~ ((? Prop([v]))))]}+bind 10 GHC.Types.True#6u : {v : GHC.Types.Bool | [(Prop([v]))]}+bind 11 GHC.Types.False#68 : {v : GHC.Types.Bool | [(~ ((Prop([v]))))]} bind 12 Language.Haskell.Liquid.Prelude.plus#rou : {VV : func(0, [int; int; int]) | []}@@ -206,25 +206,25 @@ bind 39 gooberding#a15N : {VV#234 : a_a164 | [$k_235]} bind 40 lq_anf__d16w : {lq_tmp_x241 : int | [(lq_tmp_x241 = 0)]} bind 41 lq_anf__d16x : {VV : a_a164 | [(VV = lq_anf__d16w)]}-bind 42 lq_anf__d16y : {lq_tmp_x254 : GHC.Types.Bool | [((? Prop([lq_tmp_x254])) <=> (gooberding#a15N >= lq_anf__d16x))]}+bind 42 lq_anf__d16y : {lq_tmp_x254 : GHC.Types.Bool | [((Prop([lq_tmp_x254])) <=> (gooberding#a15N >= lq_anf__d16x))]} bind 43 lq_anf__d16z : {lq_tmp_x276 : int | [(lq_tmp_x276 = (0 : int))]} bind 44 Test0.x#r12i : {VV#272 : int | [$k_273]} bind 45 lq_anf__d16A : {lq_tmp_x291 : int | [(lq_tmp_x291 = (0 : int))]}-bind 46 lq_anf__d16B : {lq_tmp_x297 : GHC.Types.Bool | [((? Prop([lq_tmp_x297])) <=> (Test0.x#r12i > lq_anf__d16A))]}-bind 47 lq_anf__d16C : {lq_tmp_x313 : GHC.Types.Bool | [((? Prop([lq_tmp_x313])) <=> (Test0.x#r12i > lq_anf__d16A));+bind 46 lq_anf__d16B : {lq_tmp_x297 : GHC.Types.Bool | [((Prop([lq_tmp_x297])) <=> (Test0.x#r12i > lq_anf__d16A))]}+bind 47 lq_anf__d16C : {lq_tmp_x313 : GHC.Types.Bool | [((Prop([lq_tmp_x313])) <=> (Test0.x#r12i > lq_anf__d16A)); (lq_tmp_x313 = lq_anf__d16B)]}-bind 48 lq_anf__d16C : {lq_tmp_x315 : GHC.Types.Bool | [((? Prop([lq_tmp_x315])) <=> (Test0.x#r12i > lq_anf__d16A));+bind 48 lq_anf__d16C : {lq_tmp_x315 : GHC.Types.Bool | [((Prop([lq_tmp_x315])) <=> (Test0.x#r12i > lq_anf__d16A)); (lq_tmp_x315 = lq_anf__d16B)]}-bind 49 lq_anf__d16C : {lq_tmp_x315 : GHC.Types.Bool | [((? Prop([lq_tmp_x315])) <=> (Test0.x#r12i > lq_anf__d16A));+bind 49 lq_anf__d16C : {lq_tmp_x315 : GHC.Types.Bool | [((Prop([lq_tmp_x315])) <=> (Test0.x#r12i > lq_anf__d16A)); (lq_tmp_x315 = lq_anf__d16B);- (~ ((? Prop([lq_tmp_x315]))));- (~ ((? Prop([lq_tmp_x315]))))]}-bind 50 lq_anf__d16C : {lq_tmp_x321 : GHC.Types.Bool | [((? Prop([lq_tmp_x321])) <=> (Test0.x#r12i > lq_anf__d16A));+ (~ ((Prop([lq_tmp_x315]))));+ (~ ((Prop([lq_tmp_x315]))))]}+bind 50 lq_anf__d16C : {lq_tmp_x321 : GHC.Types.Bool | [((Prop([lq_tmp_x321])) <=> (Test0.x#r12i > lq_anf__d16A)); (lq_tmp_x321 = lq_anf__d16B)]}-bind 51 lq_anf__d16C : {lq_tmp_x321 : GHC.Types.Bool | [((? Prop([lq_tmp_x321])) <=> (Test0.x#r12i > lq_anf__d16A));+bind 51 lq_anf__d16C : {lq_tmp_x321 : GHC.Types.Bool | [((Prop([lq_tmp_x321])) <=> (Test0.x#r12i > lq_anf__d16A)); (lq_tmp_x321 = lq_anf__d16B);- (? Prop([lq_tmp_x321]));- (? Prop([lq_tmp_x321]))]}+ (Prop([lq_tmp_x321]));+ (Prop([lq_tmp_x321]))]} bind 52 Test0.prop_abs#r12j : {VV#287 : GHC.Types.Bool | [$k_288]} bind 53 VV#343 : {VV#343 : GHC.Types.Bool | [$k_239[VV#238:=VV#343][fix##36#dOrd_a165:=fix#GHC.Classes.#36#fOrdInt#35#rhx][fix##36#dNum_a166:=fix#GHC.Num.#36#fNumInt#35#rhy][gooberding#a15N:=Test0.x#r12i][lq_tmp_x332:=fix#GHC.Classes.#36#fOrdInt#35#rhx][lq_tmp_x333:=fix#GHC.Num.#36#fNumInt#35#rhy][lq_tmp_x334:=Test0.x#r12i][lq_tmp_x328:=VV#343]]} bind 54 VV#343 : {VV#343 : GHC.Types.Bool | [$k_239[VV#238:=VV#343][fix##36#dOrd_a165:=fix#GHC.Classes.#36#fOrdInt#35#rhx][fix##36#dNum_a166:=fix#GHC.Num.#36#fNumInt#35#rhy][gooberding#a15N:=Test0.x#r12i][lq_tmp_x332:=fix#GHC.Classes.#36#fOrdInt#35#rhx][lq_tmp_x333:=fix#GHC.Num.#36#fNumInt#35#rhy][lq_tmp_x334:=Test0.x#r12i][lq_tmp_x328:=VV#343]]}@@ -232,9 +232,9 @@ (VV#346 = Test0.x#r12i)]} bind 56 VV#346 : {VV#346 : int | [$k_273[VV#272:=VV#346][lq_tmp_x341:=VV#346]; (VV#346 = Test0.x#r12i)]}-bind 57 VV#349 : {VV#349 : GHC.Types.Bool | [(~ ((? Prop([VV#349]))));+bind 57 VV#349 : {VV#349 : GHC.Types.Bool | [(~ ((Prop([VV#349])))); (VV#349 = GHC.Types.False#68)]}-bind 58 VV#349 : {VV#349 : GHC.Types.Bool | [(~ ((? Prop([VV#349]))));+bind 58 VV#349 : {VV#349 : GHC.Types.Bool | [(~ ((Prop([VV#349])))); (VV#349 = GHC.Types.False#68)]} bind 59 VV#352 : {VV#352 : int | [(VV#352 = (0 : int)); (VV#352 = lq_anf__d16A)]}@@ -254,11 +254,11 @@ (VV#364 = lq_anf__d16z)]} bind 69 VV#367 : {VV#367 : int | [(VV#367 = 0)]} bind 70 VV#367 : {VV#367 : int | [(VV#367 = 0)]}-bind 71 VV#370 : {VV#370 : GHC.Types.Bool | [(? Prop([VV#370]))]}-bind 72 VV#370 : {VV#370 : GHC.Types.Bool | [(? Prop([VV#370]))]}-bind 73 VV#373 : {VV#373 : GHC.Types.Bool | [((? Prop([VV#373])) <=> (gooberding#a15N >= lq_anf__d16x));+bind 71 VV#370 : {VV#370 : GHC.Types.Bool | [(Prop([VV#370]))]}+bind 72 VV#370 : {VV#370 : GHC.Types.Bool | [(Prop([VV#370]))]}+bind 73 VV#373 : {VV#373 : GHC.Types.Bool | [((Prop([VV#373])) <=> (gooberding#a15N >= lq_anf__d16x)); (VV#373 = lq_anf__d16y)]}-bind 74 VV#373 : {VV#373 : GHC.Types.Bool | [((? Prop([VV#373])) <=> (gooberding#a15N >= lq_anf__d16x));+bind 74 VV#373 : {VV#373 : GHC.Types.Bool | [((Prop([VV#373])) <=> (gooberding#a15N >= lq_anf__d16x)); (VV#373 = lq_anf__d16y)]} bind 75 VV : {VV : a_a164 | [(VV = lq_anf__d16w); (VV = lq_anf__d16x)]}@@ -417,7 +417,7 @@ 15; 31; 47]- lhs {VV#F3 : GHC.Types.Bool | [(~ ((? Prop([VV#F3]))));+ lhs {VV#F3 : GHC.Types.Bool | [(~ ((Prop([VV#F3])))); (VV#F3 = GHC.Types.False#68)]} rhs {VV#F3 : GHC.Types.Bool | [$k_288[VV#287:=VV#F3][VV#349:=VV#F3][VV#F:=VV#F3]]} id 3 tag [3]@@ -603,7 +603,7 @@ 30; 15; 31]- lhs {VV#F7 : GHC.Types.Bool | [(? Prop([VV#F7]))]}+ lhs {VV#F7 : GHC.Types.Bool | [(Prop([VV#F7]))]} rhs {VV#F7 : GHC.Types.Bool | [$k_239[VV#238:=VV#F7][VV#370:=VV#F7][VV#F:=VV#F7]]} id 7 tag [1] @@ -653,9 +653,9 @@ 30; 15; 31]- lhs {VV#F8 : GHC.Types.Bool | [((? Prop([VV#F8])) <=> (gooberding#a15N >= lq_anf__d16x));+ lhs {VV#F8 : GHC.Types.Bool | [((Prop([VV#F8])) <=> (gooberding#a15N >= lq_anf__d16x)); (VV#F8 = lq_anf__d16y)]}- rhs {VV#F8 : GHC.Types.Bool | [(? Prop([VV#F8]))]}+ rhs {VV#F8 : GHC.Types.Bool | [(Prop([VV#F8]))]} id 8 tag [1]
tests/pos/test000.hs.fq view
@@ -1,51 +1,51 @@-qualif Fst(v : @(1), y : @(0)): (v = fst([y])) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.spec" (line 29, column 8)-qualif Snd(v : @(1), y : @(0)): (v = snd([y])) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.spec" (line 30, column 8)-qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]): ((? Prop([v])) <=> (len([xs]) > 0)) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 13, column 8)-qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]): ((? Prop([v])) <=> (len([xs]) = 0)) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 14, column 8)-qualif ListZ(v : [@(0)]): (len([v]) = 0) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 16, column 8)-qualif ListZ(v : [@(0)]): (len([v]) >= 0) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 17, column 8)-qualif ListZ(v : [@(0)]): (len([v]) > 0) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 18, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) = len([xs])) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 20, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) >= len([xs])) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 21, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) > len([xs])) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 22, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) <= len([xs])) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 23, column 8)-qualif CmpLen(v : [@(1)], xs : [@(0)]): (len([v]) < len([xs])) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 24, column 8)-qualif EqLen(v : int, xs : [@(0)]): (v = len([xs])) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 26, column 8)-qualif LenEq(v : [@(0)], x : int): (x = len([v])) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 27, column 8)-qualif LenDiff(v : [@(0)], x : int): (len([v]) = (x + 1)) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 28, column 8)-qualif LenDiff(v : [@(0)], x : int): (len([v]) = (x - 1)) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 29, column 8)-qualif LenAcc(v : int, xs : [@(0)], n : int): (v = (len([xs]) + n)) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 30, column 8)-qualif Bot(v : @(0)): (0 = 1) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 3, column 8)-qualif Bot(v : @(0)): (0 = 1) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 4, column 8)-qualif Bot(v : @(0)): (0 = 1) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 5, column 8)-qualif Bot(v : bool): (0 = 1) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 6, column 8)-qualif Bot(v : int): (0 = 1) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 7, column 8)-qualif CmpZ(v : @(0)): (v < 0) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 9, column 8)-qualif CmpZ(v : @(0)): (v <= 0) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 10, column 8)-qualif CmpZ(v : @(0)): (v > 0) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 11, column 8)-qualif CmpZ(v : @(0)): (v >= 0) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 12, column 8)-qualif CmpZ(v : @(0)): (v = 0) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 13, column 8)-qualif CmpZ(v : @(0)): (v != 0) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 14, column 8)-qualif Cmp(v : @(0), x : @(0)): (v < x) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 16, column 8)-qualif Cmp(v : @(0), x : @(0)): (v <= x) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 17, column 8)-qualif Cmp(v : @(0), x : @(0)): (v > x) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 18, column 8)-qualif Cmp(v : @(0), x : @(0)): (v >= x) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 19, column 8)-qualif Cmp(v : @(0), x : @(0)): (v = x) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 20, column 8)-qualif Cmp(v : @(0), x : @(0)): (v != x) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 21, column 8)-qualif One(v : int): (v = 1) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 28, column 8)-qualif True(v : bool): (? v) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 29, column 8)-qualif False(v : bool): (~ ((? v))) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 30, column 8)-qualif True1(v : GHC.Types.Bool): (? Prop([v])) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 31, column 8)-qualif False1(v : GHC.Types.Bool): (~ ((? Prop([v])))) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 32, column 8)-qualif Papp(v : @(0), p : (Pred @(0))): (? papp1([p;- v])) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 35, column 8)-qualif Papp2(v : @(1), x : @(0), p : (Pred @(1) @(0))): (? papp2([p;+qualif Fst(v : @(1), y : @(0)) { v = fst([y]) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.spec" (line 29, column 8)+qualif Snd(v : @(1), y : @(0)) { v = snd([y]) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.spec" (line 30, column 8)+qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]) { (Prop([v])) <=> (len([xs]) > 0) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 13, column 8)+qualif IsEmp(v : GHC.Types.Bool, xs : [@(0)]) { (Prop([v])) <=> (len([xs]) = 0) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 14, column 8)+qualif ListZ(v : [@(0)]) { len([v]) = 0 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 16, column 8)+qualif ListZ(v : [@(0)]) { len([v]) >= 0 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 17, column 8)+qualif ListZ(v : [@(0)]) { len([v]) > 0 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 18, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) = len([xs]) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 20, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) >= len([xs]) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 21, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) > len([xs]) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 22, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) <= len([xs]) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 23, column 8)+qualif CmpLen(v : [@(1)], xs : [@(0)]) { len([v]) < len([xs]) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 24, column 8)+qualif EqLen(v : int, xs : [@(0)]) { v = len([xs]) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 26, column 8)+qualif LenEq(v : [@(0)], x : int) { x = len([v]) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 27, column 8)+qualif LenDiff(v : [@(0)], x : int) { len([v]) = (x + 1) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 28, column 8)+qualif LenDiff(v : [@(0)], x : int) { len([v]) = (x - 1) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 29, column 8)+qualif LenAcc(v : int, xs : [@(0)], n : int) { v = (len([xs]) + n) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/GHC/Base.hquals" (line 30, column 8)+qualif Bot(v : @(0)) { 0 = 1 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 3, column 8)+qualif Bot(v : @(0)) { 0 = 1 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 4, column 8)+qualif Bot(v : @(0)) { 0 = 1 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 5, column 8)+qualif Bot(v : bool) { 0 = 1 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 6, column 8)+qualif Bot(v : int) { 0 = 1 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 7, column 8)+qualif CmpZ(v : @(0)) { v < 0 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 9, column 8)+qualif CmpZ(v : @(0)) { v <= 0 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 10, column 8)+qualif CmpZ(v : @(0)) { v > 0 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 11, column 8)+qualif CmpZ(v : @(0)) { v >= 0 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 12, column 8)+qualif CmpZ(v : @(0)) { v = 0 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 13, column 8)+qualif CmpZ(v : @(0)) { v != 0 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 14, column 8)+qualif Cmp(v : @(0), x : @(0)) { v < x } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 16, column 8)+qualif Cmp(v : @(0), x : @(0)) { v <= x } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 17, column 8)+qualif Cmp(v : @(0), x : @(0)) { v > x } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 18, column 8)+qualif Cmp(v : @(0), x : @(0)) { v >= x } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 19, column 8)+qualif Cmp(v : @(0), x : @(0)) { v = x } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 20, column 8)+qualif Cmp(v : @(0), x : @(0)) { v != x } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 21, column 8)+qualif One(v : int) { v = 1 } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 28, column 8)+qualif True(v : bool) { v } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 29, column 8)+qualif False(v : bool) { ~ ((v)) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 30, column 8)+qualif True1(v : GHC.Types.Bool) { Prop([v]) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 31, column 8)+qualif False1(v : GHC.Types.Bool) { ~ ((Prop([v]))) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 32, column 8)+qualif Papp(v : @(0), p : (Pred @(0))) { (papp1([p;+ v])) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 35, column 8)+qualif Papp2(v : @(1), x : @(0), p : (Pred @(1) @(0))) { (papp2([p; v;- x])) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 38, column 8)-qualif Papp3(v : @(2), x : @(0), y : @(1), p : (Pred @(2) @(0) @(1))): (? papp3([p;+ x])) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 38, column 8)+qualif Papp3(v : @(2), x : @(0), y : @(1), p : (Pred @(2) @(0) @(1))) { (papp3([p; v; x;- y])) // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 41, column 8)+ y])) } // "/Users/benjamin/UCSDrepos/liquidhaskell/include/Prelude.hquals" (line 41, column 8) @@ -138,11 +138,11 @@ bind 4 GHC.Types.EQ$35$6U : {VV$35$180 : GHC.Types.Ordering | [(VV$35$180 = GHC.Types.EQ$35$6U)]} bind 5 GHC.Types.LT$35$6S : {VV$35$181 : GHC.Types.Ordering | [(VV$35$181 = GHC.Types.LT$35$6S)]} bind 6 GHC.Types.GT$35$6W : {VV$35$182 : GHC.Types.Ordering | [(VV$35$182 = GHC.Types.GT$35$6W)]}-bind 7 GHC.Types.True$35$6u : {v_4 : GHC.Types.Bool | [(? Prop([v_4]))]}-bind 8 GHC.Types.False$35$68 : {v_5 : GHC.Types.Bool | [(~ ((? Prop([v_5]))))]}-bind 9 GHC.Types.False$35$68 : {v_5 : GHC.Types.Bool | [(~ ((? Prop([v_5]))))]}+bind 7 GHC.Types.True$35$6u : {v_4 : GHC.Types.Bool | [(Prop([v_4]))]}+bind 8 GHC.Types.False$35$68 : {v_5 : GHC.Types.Bool | [(~ ((Prop([v_5]))))]}+bind 9 GHC.Types.False$35$68 : {v_5 : GHC.Types.Bool | [(~ ((Prop([v_5]))))]} bind 10 GHC.Types.$91$$93$$35$6m : {VV : func(1, [[@(0)]]) | []}-bind 11 GHC.Types.True$35$6u : {v_4 : GHC.Types.Bool | [(? Prop([v_4]))]}+bind 11 GHC.Types.True$35$6u : {v_4 : GHC.Types.Bool | [(Prop([v_4]))]} bind 12 GHC.Types.GT$35$6W : {VV$35$227 : GHC.Types.Ordering | [(cmp([VV$35$227]) = GHC.Types.GT$35$6W)]} bind 13 GHC.Types.LT$35$6S : {VV$35$228 : GHC.Types.Ordering | [(cmp([VV$35$228]) = GHC.Types.LT$35$6S)]} bind 14 GHC.Types.EQ$35$6U : {VV$35$229 : GHC.Types.Ordering | [(cmp([VV$35$229]) = GHC.Types.EQ$35$6U)]}@@ -154,29 +154,29 @@ bind 20 lq_anf__d12s : {lq_tmp_x_275 : GHC.Types.Bool | [(lq_tmp_x_275 = Test0.toss$35$rYP)]} bind 21 lq_anf__d12s : {lq_tmp_x_277 : GHC.Types.Bool | [(lq_tmp_x_277 = Test0.toss$35$rYP)]} bind 22 lq_anf__d12s : {lq_tmp_x_277 : GHC.Types.Bool | [(lq_tmp_x_277 = Test0.toss$35$rYP);- (~ ((? Prop([lq_tmp_x_277]))));- (~ ((? Prop([lq_tmp_x_277]))));- (~ ((? Prop([lq_tmp_x_277]))))]}+ (~ ((Prop([lq_tmp_x_277]))));+ (~ ((Prop([lq_tmp_x_277]))));+ (~ ((Prop([lq_tmp_x_277]))))]} bind 23 lq_anf__d12s : {lq_tmp_x_283 : GHC.Types.Bool | [(lq_tmp_x_283 = Test0.toss$35$rYP)]} bind 24 lq_anf__d12s : {lq_tmp_x_283 : GHC.Types.Bool | [(lq_tmp_x_283 = Test0.toss$35$rYP);- (? Prop([lq_tmp_x_283]));- (? Prop([lq_tmp_x_283]));- (? Prop([lq_tmp_x_283]))]}+ (Prop([lq_tmp_x_283]));+ (Prop([lq_tmp_x_283]));+ (Prop([lq_tmp_x_283]))]} bind 25 lq_anf__d12t : {lq_tmp_x_288 : GHC.Types.Bool | [(lq_tmp_x_288 = lq_anf__d12s)]} bind 26 lq_anf__d12t : {lq_tmp_x_290 : GHC.Types.Bool | [(lq_tmp_x_290 = lq_anf__d12s)]} bind 27 lq_anf__d12t : {lq_tmp_x_290 : GHC.Types.Bool | [(lq_tmp_x_290 = lq_anf__d12s);- (~ ((? Prop([lq_tmp_x_290]))));- (~ ((? Prop([lq_tmp_x_290]))));- (~ ((? Prop([lq_tmp_x_290]))))]}+ (~ ((Prop([lq_tmp_x_290]))));+ (~ ((Prop([lq_tmp_x_290]))));+ (~ ((Prop([lq_tmp_x_290]))))]} bind 28 lq_anf__d12t : {lq_tmp_x_296 : GHC.Types.Bool | [(lq_tmp_x_296 = lq_anf__d12s)]} bind 29 lq_anf__d12t : {lq_tmp_x_296 : GHC.Types.Bool | [(lq_tmp_x_296 = lq_anf__d12s);- (? Prop([lq_tmp_x_296]));- (? Prop([lq_tmp_x_296]));- (? Prop([lq_tmp_x_296]))]}+ (Prop([lq_tmp_x_296]));+ (Prop([lq_tmp_x_296]));+ (Prop([lq_tmp_x_296]))]} bind 30 Test0.prop_abs$35$r10h : {VV$35$272 : GHC.Types.Bool | [$k__273]} bind 31 x$35$a11A : {VV$35$307 : int | [$k__308]} bind 32 lq_anf__d12u : {lq_tmp_x_315 : int | [(lq_tmp_x_315 = (0 : int))]}-bind 33 lq_anf__d12v : {lq_tmp_x_321 : GHC.Types.Bool | [((? Prop([lq_tmp_x_321])) <=> (x$35$a11A > lq_anf__d12u))]}+bind 33 lq_anf__d12v : {lq_tmp_x_321 : GHC.Types.Bool | [((Prop([lq_tmp_x_321])) <=> (x$35$a11A > lq_anf__d12u))]} bind 34 lq_anf__d12w : {lq_tmp_x_345 : int | [$k__343[lq_tmp_x_340:=lq_anf__d12v][VV$35$342:=lq_tmp_x_345][lq_tmp_x_341:=x$35$a11A]]} bind 35 lq_anf__d12x : {lq_tmp_x_350 : int | [(lq_tmp_x_350 = (1 : int))]} bind 36 lq_anf__d12y : {lq_tmp_x_373 : int | [(lq_tmp_x_373 = (12 : int))]}@@ -223,16 +223,16 @@ bind 77 VV$35$477 : {VV$35$477 : int | [(VV$35$477 = x$35$a11A)]} bind 78 VV$35$480 : {VV$35$480 : int | [(VV$35$480 = 0)]} bind 79 VV$35$480 : {VV$35$480 : int | [(VV$35$480 = 0)]}-bind 80 VV$35$483 : {VV$35$483 : GHC.Types.Bool | [(? Prop([VV$35$483]))]}-bind 81 VV$35$483 : {VV$35$483 : GHC.Types.Bool | [(? Prop([VV$35$483]))]}+bind 80 VV$35$483 : {VV$35$483 : GHC.Types.Bool | [(Prop([VV$35$483]))]}+bind 81 VV$35$483 : {VV$35$483 : GHC.Types.Bool | [(Prop([VV$35$483]))]} bind 82 VV$35$486 : {VV$35$486 : GHC.Types.Bool | [(VV$35$486 = lq_anf__d12t)]} bind 83 VV$35$486 : {VV$35$486 : GHC.Types.Bool | [(VV$35$486 = lq_anf__d12t)]} bind 84 VV$35$489 : {VV$35$489 : GHC.Types.Bool | [(VV$35$489 = GHC.Types.False$35$68)]} bind 85 VV$35$489 : {VV$35$489 : GHC.Types.Bool | [(VV$35$489 = GHC.Types.False$35$68)]} bind 86 VV$35$492 : {VV$35$492 : GHC.Types.Bool | [(VV$35$492 = GHC.Types.False$35$68)]} bind 87 VV$35$492 : {VV$35$492 : GHC.Types.Bool | [(VV$35$492 = GHC.Types.False$35$68)]}-bind 88 VV$35$495 : {VV$35$495 : GHC.Types.Bool | [((? Prop([VV$35$495])) <=> (lq_anf__d12q > lq_anf__d12r))]}-bind 89 VV$35$495 : {VV$35$495 : GHC.Types.Bool | [((? Prop([VV$35$495])) <=> (lq_anf__d12q > lq_anf__d12r))]}+bind 88 VV$35$495 : {VV$35$495 : GHC.Types.Bool | [((Prop([VV$35$495])) <=> (lq_anf__d12q > lq_anf__d12r))]}+bind 89 VV$35$495 : {VV$35$495 : GHC.Types.Bool | [((Prop([VV$35$495])) <=> (lq_anf__d12q > lq_anf__d12r))]} bind 90 VV$35$498 : {VV$35$498 : int | [(VV$35$498 = lq_anf__d12r)]} bind 91 VV$35$498 : {VV$35$498 : int | [(VV$35$498 = lq_anf__d12r)]} bind 92 VV$35$501 : {VV$35$501 : int | [(VV$35$501 = lq_anf__d12q)]}@@ -309,7 +309,7 @@ 15; 31] lhs {VV$35$F8 : GHC.Types.Bool | [(VV$35$F8 = lq_anf__d12v)]}- rhs {VV$35$F8 : GHC.Types.Bool | [(? Prop([VV$35$F8]))]}+ rhs {VV$35$F8 : GHC.Types.Bool | [(Prop([VV$35$F8]))]} id 8 tag [3] // META constraint id 8 : tests/pos/test000.hs:14:23-29 @@ -339,7 +339,7 @@ 29; 14; 15]- lhs {VV$35$F11 : GHC.Types.Bool | [(? Prop([VV$35$F11]))]}+ lhs {VV$35$F11 : GHC.Types.Bool | [(Prop([VV$35$F11]))]} rhs {VV$35$F11 : GHC.Types.Bool | [$k__273[VV$35$272:=VV$35$F11][VV$35$F:=VV$35$F11][VV$35$483:=VV$35$F11]]} id 11 tag [6] // META constraint id 11 : tests/pos/test000.hs:10:33-50@@ -371,7 +371,7 @@ 14; 15] lhs {VV$35$F12 : GHC.Types.Bool | [(VV$35$F12 = lq_anf__d12t)]}- rhs {VV$35$F12 : GHC.Types.Bool | [(? Prop([VV$35$F12]))]}+ rhs {VV$35$F12 : GHC.Types.Bool | [(Prop([VV$35$F12]))]} id 12 tag [6] // META constraint id 12 : tests/pos/test000.hs:10:47-50 @@ -456,7 +456,7 @@ 13; 14; 15]- lhs {VV$35$F15 : GHC.Types.Bool | [((? Prop([VV$35$F15])) <=> (lq_anf__d12q > lq_anf__d12r))]}+ lhs {VV$35$F15 : GHC.Types.Bool | [((Prop([VV$35$F15])) <=> (lq_anf__d12q > lq_anf__d12r))]} rhs {VV$35$F15 : GHC.Types.Bool | [$k__235[VV$35$F:=VV$35$F15][VV$35$495:=VV$35$F15][VV$35$234:=VV$35$F15]]} id 15 tag [5] // META constraint id 15 : tests/pos/test000.hs:6:1-22
tests/pos/test00a.fq view
@@ -1,5 +1,5 @@ // This qualifier saves the day; solve constraints WITHOUT IT-qualif Zog(v:a) : (10 <= v)+qualif Zog(v:a) { 10 <= v } bind 0 x : {v : int | true} bind 1 y : {v : int | true}
tests/pos/test1.fq view
@@ -1,6 +1,6 @@ // This qualifier saves the day; solve constraints WITHOUT IT-qualif Zog(v:a) : (10 <= v)+qualif Zog(v:a) { 10 <= v } bind 0 x : {v : int | v = 10} bind 1 y : {v : int | v = 20}
tests/pos/test2.fq view
@@ -1,9 +1,9 @@ // This qualifier saves the day; solve constraints WITHOUT IT-qualif Zog(v:a): (10 <= v)+qualif Zog(v:a) { 10 <= v } // But you may use this one-qualif Pog(v:a): (0 <= v)+qualif Pog(v:a) { 0 <= v } bind 0 x: {v: int | v = 10} bind 1 a: {v: int | $k1 }
tests/pos/test3.fq view
@@ -1,5 +1,5 @@ -qualif Zog(v:a, z:b) : (v = z)+qualif Zog(v:a, z:b) { v = z } bind 0 x : {v : int | true} bind 1 q : {v : int | true}
tests/pos/test4.fq view
@@ -1,4 +1,4 @@-qualif Auto(v_2 : a_ax6, A0 : a_ax6): (v_2 = A0)+qualif Auto(v_2 : a_ax6, A0 : a_ax6) { v_2 = A0 } bind 20 ds_dxx : {VV263 : a_ax6 | []}
tests/pos/unexpected-ge.fq view
@@ -1,2 +1,2 @@ -qualif Auto(v : int, x : int): (v = (if (x > 0) then 0 else 0))+qualif Auto(v : int, x : int) { v = (if (x > 0) then 0 else 0) }
tests/pos/wl00.fq view
@@ -1,6 +1,6 @@-qualif Nat(v:int) : (0 <= v)-qualif N10(v:int) : (10 = v)-qualif N20(v:int) : (20 = v)+qualif Nat(v:int) { 0 <= v }+qualif N10(v:int) { 10 = v }+qualif N20(v:int) { 20 = v } bind 0 x0 : {v: int | [$k0]}
tests/pos/wl01.fq view
@@ -1,4 +1,4 @@-qualif Nat(v:int) : (0 <= v)+qualif Nat(v:int) { 0 <= v } bind 0 x : {v: int | [$k0]} bind 1 y : {v: int | [$k0]}
tests/pos/wl02.fq view
@@ -1,4 +1,4 @@-qualif Nat(v:int) : (0 <= v)+qualif Nat(v:int) { 0 <= v } bind 0 x0 : {v: int | [$k0]} bind 1 x1 : {v: int | [$k1]}
tests/tasty/Arbitrary.hs view
@@ -22,7 +22,6 @@ import Language.Fixpoint.Types.Refinements as R import Language.Fixpoint.Parse (isNotReserved) import Language.Fixpoint.Types as T hiding (Result)-import Language.Fixpoint.Types.Spans as Spans import Data.Traversable (for) {-@@ -76,8 +75,8 @@ subexprs (PKVar _ _) = [] subexprs (PAll _ e) = [e] subexprs (PExist _ e) = [e]-subexprs (PGrad _ _ _ e) = [e] subexprs (ECoerc _ _ e) = [e]+subexprs (ELet _ e1 e2) = [e1, e2] -- TODO: Adjust frequencies -- | To ensure this reliably terminates we require that `zeroExprGen` generates@@ -105,8 +104,8 @@ , (1, PKVar <$> arbitrary <*> arbitrary) , (1, PAll <$> arbitraryList arbitrary <*> arbitraryExpr') , (1, PExist <$> arbitraryList arbitrary <*> arbitraryExpr')- , (1, PGrad <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitraryExpr') , (1, ECoerc <$> arbitrary <*> arbitrary <*> arbitraryExpr')+ , (1, ELet <$> arbitrary <*> arbitraryExpr' <*> arbitraryExpr') ] where arbitraryExpr' = arbitraryFiniteExpr zeroExprGen (n `div` 2)@@ -132,12 +131,6 @@ instance Arbitrary KVar where arbitrary = KV <$> arbitrary---- NOTE: This dummy Arbitrary instance returns a constant GradInfo.-instance Arbitrary GradInfo where- arbitrary = pure $ GradInfo (SS pos pos) Nothing- where pos = Spans.dummyPos "<unknown>"- shrink _ = mempty instance Arbitrary Subst where arbitrary = do
tests/tasty/Main.hs view
@@ -5,6 +5,7 @@ import qualified ParserTests import qualified ShareMapTests import qualified SimplifyTests+import qualified SimplifyKVarTests import qualified InterpretTests import qualified UndoANFTests import Test.Tasty@@ -14,6 +15,7 @@ [ ParserTests.tests , ShareMapTests.tests , SimplifyTests.tests+ , SimplifyKVarTests.tests , InterpretTests.tests , UndoANFTests.tests ]
tests/tasty/ParserTests.hs view
@@ -131,11 +131,7 @@ testFunAppP :: TestTree testFunAppP = testGroup "FunAppP"- [ testCase "ECon (litP)" $- show (doParse' funAppP "test" "lit \"#x00000008\" (BitVec Size32)") @?=- "ECon (L \"#x00000008\" (FApp (FTC (TC \"BitVec\" defined at: test:1:19-1:25 (TCInfo {tc_isNum = False, tc_isReal = False, tc_isString = False}))) (FTC (TC \"Size32\" defined at: test:1:27-1:33 (TCInfo {tc_isNum = False, tc_isReal = False, tc_isString = False})))))"-- , testCase "ECon (exprFunSpacesP)" $+ [ testCase "ECon (exprFunSpacesP)" $ show (doParse' funAppP "test" "fooBar baz qux") @?= "EApp (EApp (EVar \"fooBar\") (EVar \"baz\")) (EVar \"qux\")" , testCase "ECon (exprFunCommasP)" $@@ -200,54 +196,14 @@ show (doParse' expr0P "test" "1") @?= "ECon (I 1)" ] --- ----------------------------------------------------------------------{---pred = expressionParse (prefixOp++infixOp) pred0--prefixOp = '~' | 'not'--infixOp = '&&' | '||' | '=>' | '==>' | '<=>'---- terms are pred0-pred0 = 'true' | 'false'- | '??'- | kvarPred- | fastIfP- | predr- | '(' pred ')'- | '?' expr- | funApp- | symbol- | '&&' preds- | '||' preds--kvarPred = kvar substs--kvar = '$' symbol--substs = {- empty -}- | subst substs--subst = '[' symbol ':=' expr ']'--preds = '[' predslist ']'--predslist = pred- | pred `;` predslist--fastIf = 'if' pred 'then' pred 'else' pred--predr = expr brel expr--brelP = '==' | '=' | '~~' | '!=' | '/=' | '!~' | '<' | '<=' | '>' | '>='---}- testPredP :: TestTree testPredP =- testGroup "predP"- [ testCase "PTrue" $+ testGroup "exprP"+ [ testCase "ECon (litP)" $+ show (doParse' exprP "test" "lit \"#x00000008\" (BitVec Size32)") @?=+ "ECon (L \"#x00000008\" (FApp (FTC (TC \"BitVec\" defined at: test:1:19-1:25 (TCInfo {tc_isNum = False, tc_isReal = False, tc_isString = False}))) (FTC (TC \"Size32\" defined at: test:1:27-1:33 (TCInfo {tc_isNum = False, tc_isReal = False, tc_isString = False})))))"++ , testCase "PTrue" $ show (doParse' predP "test" "true") @?= "PAnd []" -- pattern for PTrue , testCase "PFalse" $@@ -268,8 +224,7 @@ , testCase "fastIf" $ show (doParse' predP "test" "if true then true else false" ) @?=- -- note conversion- "PAnd [PImp (PAnd []) (PAnd []),PImp (PNot (PAnd [])) (POr [])]"+ "EIte (PAnd []) (PAnd []) (POr [])" , testCase "brel" $ show (doParse' predP "test" "1 == 2") @?= "PAtom Eq (ECon (I 1)) (ECon (I 2))"@@ -277,9 +232,6 @@ , testCase "parens pred" $ show (doParse' predP "test" "((1 == 2))") @?= "PAtom Eq (ECon (I 1)) (ECon (I 2))" - , testCase "? expr" $- show (doParse' predP "test" "? (1+2)") @?= "EBin Plus (ECon (I 1)) (ECon (I 2))"- , testCase "funApp 1" $ show (doParse' predP "test" "f a b") @?= "EApp (EApp (EVar \"f\") (EVar \"a\")) (EVar \"b\")" @@ -290,10 +242,10 @@ show (doParse' predP "test" "f ([a; b])") @?= "EApp (EApp (EVar \"f\") (EVar \"a\")) (EVar \"b\")" , testCase "funApp 4" $- show (doParse' funAppP "" "f ?(x > 1)") @?= "EApp (EVar \"f\") (PAtom Gt (EVar \"x\") (ECon (I 1)))"+ show (doParse' funAppP "" "f (x > 1)") @?= "EApp (EVar \"f\") (PAtom Gt (EVar \"x\") (ECon (I 1)))" , testCase "funApp 5" $- show (doParse' predP "" "f ?(x > 1)") @?= "EApp (EVar \"f\") (PAtom Gt (EVar \"x\") (ECon (I 1)))"+ show (doParse' predP "" "f (x > 1)") @?= "EApp (EVar \"f\") (PAtom Gt (EVar \"x\") (ECon (I 1)))" , testCase "symbol" $ show (doParse' predP "test" "f") @?= "EVar \"f\""@@ -302,7 +254,7 @@ show (doParse' predP "test" "&& []") @?= "PAnd []" , testCase "&& 1" $- show (doParse' predP "test" "&& [x]") @?= "EVar \"x\""+ show (doParse' predP "test" "&& [x]") @?= "PAnd [EVar \"x\"]" , testCase "&& 2" $ show (doParse' predP "test" "&& [x;y]") @?= "PAnd [EVar \"x\",EVar \"y\"]"
tests/tasty/SimplifyPLE.hs view
@@ -17,7 +17,6 @@ KN { knSims = M.empty, -- :: Map Symbol [(Rewrite, IsUserDataSMeasure)] knAms = M.empty, -- :: Map Symbol Equation- knContext = undefined, -- :: SMT.Context knPreds = undefined, -- :: SMT.Context -> [(Symbol, Sort)] -> Expr -> IO Bool knLams = [], -- :: ![(Symbol, Sort)] knSummary = [], -- :: ![(Symbol, Int)]@@ -33,13 +32,16 @@ emptyICtx = ICtx { icAssms = S.empty, -- S.HashSet Pred- icCands = S.empty, -- :: S.HashSet Expr- icEquals = S.empty, -- :: EvAccum+ icCands = mempty, -- :: S.HashSet Expr+ icEquals = mempty, -- :: EvAccum icSimpl = SM.empty, -- :: !ConstMap icSubcId = Nothing, -- :: Maybe SubcId icANFs = [], -- :: [[(Symbol, SortedReft)]] icLRWs = mempty, icEtaBetaFlag = False, icExtensionalityFlag = False,- icLocalRewritesFlag = False+ icLocalRewritesFlag = False,+ icBindIds = mempty,+ icFreshExistentialCounter = 0,+ icInitialLHSs = mempty }
+ tests/tasty/ghc-9.12.1/SimplifyKVarTests.hs view
@@ -0,0 +1,400 @@+{-# LANGUAGE MultilineStrings #-}++module SimplifyKVarTests (tests) where++import Control.Monad (when)+import qualified Data.HashSet as HashSet+import Language.Fixpoint.Parse+import qualified Language.Fixpoint.Types as F+import qualified Language.Fixpoint.Solver.Solution as F+import Test.Tasty+import Test.Tasty.HUnit+++tests :: TestTree+tests =+ testGroup "simplifyKVar" $ map simplificationTest+ [ SimplificationTest+ { name = "single elimination"+ , expected = """+ exists [y : int] . P C y+ """+ , input = """+ exists [x : int, y : int] . x == C && P x y+ """+ }++ , SimplificationTest+ { name = "full elimination"+ , expected = """+ P C D+ """+ , input = """+ exists [x : int, y : int] . x == C && P x y && y == D+ """+ }++ , SimplificationTest+ { name = "alpha equivalence"+ , expected = """+ (exists [w : int, z : int] . Q w z) &&+ (exists [w : int, z : int] . P w z)+ """+ , input = """+ (exists [w : int, z : int] . Q w z) &&+ (exists [w : int, z : int] . P w z) &&+ (exists [x : int, y : int] . P x y)+ """+ }++ , SimplificationTest+ { name = "floating"+ , expected = """+ (exists [x : int, y : int] . P x y) && A == C+ """+ , input = """+ exists [x : int, y : int] . A == C && P x y+ """+ }++ , SimplificationTest+ { name = "inner floating"+ , expected = """+ (exists [x : int] . P x && Q x) && (exists [y : int] . P y)+ """+ , input = """+ exists [x : int] . P x && (exists [ y : int] . P y && Q x)+ """+ }++ , largeSimplificationTest+ ]++data SimplificationTest = SimplificationTest+ { input :: String+ , expected :: String+ , name :: String+ }++simplificationTest :: SimplificationTest -> TestTree+simplificationTest test =+ testCase (name test) $ do+ let actual =+ F.simplifyKVar+ HashSet.empty+ (doParse'' True predP (name test) (input test))+ expectedE = doParse'' True predP (name test) (expected test)+ when (not (F.alphaEq HashSet.empty actual expectedE)) $ do+ assertFailure $ unlines+ [ "output is not as expected"+ , "Expected:"+ , expected test+ , ""+ , "Actual:"+ , F.showpp actual+ ]++largeSimplificationTest :: SimplificationTest+largeSimplificationTest =+ SimplificationTest+ { name = "large simplification"+ , expected = """+ exists [w : int] . Test.gt0xy w i##aS7+ """+ , input = """+ exists [VV##1821##k_ : int,+ i##aS7##k_ : int,+ lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ lq_anf##7205759403792798200##d1cc##k_ : (Test.State int int),+ lq_tmpx##1823##k_ : int,+ lq_tmpx##1824##k_ : int]+ . (exists [w : int,+ w2 : int,+ x : int,+ y : Tuple0,+ VV##F##13 : int]+ . VV##1821##k_ == VV##F##13+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && lq_tmpx##1823##k_ == w+ && lq_tmpx##1824##k_ == x+ && (exists [VV##1829 : int,+ lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_anf##7205759403792798200##d1cc##k_ : (Test.State int int),+ VV##1805##k_ : int,+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ i##aS7##k_ : int]+ . VV##1829 == w+ && VV##1805##k_ == w+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && (exists [VV##F##3 : int]+ . Test.gt0xy VV##F##3 i##aS7+ && VV##1805##k_ == VV##F##3+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc))+ && (exists [VV##1830 : int,+ lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ i##aS7##k_ : int,+ lq_anf##7205759403792798200##d1cc##k_ : (Test.State int int),+ VV##1807##k_ : int]+ . VV##1830 == w2+ && VV##1807##k_ == w2+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && (exists [w : int,+ VV##F##14 : int,+ lq_rnmx##255 : Tuple0]+ . (exists [VV##1828 : int,+ lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_anf##7205759403792798200##d1cc##k_ : (Test.State int int),+ VV##1805##k_ : int,+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ i##aS7##k_ : int]+ . VV##1828 == w+ && VV##1805##k_ == w+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && (exists [VV##F##3 : int]+ . Test.gt0xy VV##F##3 i##aS7+ && VV##1805##k_ == VV##F##3+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc))+ && (exists [lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ i##aS7##k_ : int,+ lq_tmpx##1812##k_ : Tuple0,+ VV##1809##k_ : int,+ lq_tmpx##1811##k_ : int,+ lq_anf##7205759403792798200##d1cc##k_ : (Test.State int int)]+ . VV##1809##k_ == VV##F##14+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && lq_tmpx##1811##k_ == w+ && lq_tmpx##1812##k_ == lq_rnmx##255+ && (exists [VV##F##12 : int,+ lq_tmpx##1811 : int,+ lq_tmpx##1812 : Tuple0,+ lq_tmpdb##43 : int,+ lq_tmpdb##44 : Tuple0]+ . VV##F##12 == i##aS7+ && VV##1809##k_ == VV##F##12+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && lq_tmpx##1811##k_ == lq_tmpx##1811+ && lq_tmpx##1812##k_ == lq_tmpx##1812))+ && (exists [i##aS7##k_ : int,+ lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_anf##7205759403792798200##d1cc##k_ : (Test.State int int),+ lq_tmpx##1801 : Tuple0,+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ VV##1799##k_ : Tuple0]+ . VV##1799##k_ == lq_rnmx##255+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && lq_tmpx##1801 == lq_rnmx##255+ && (exists [VV##F##10 : Tuple0]+ . VV##1799##k_ == VV##F##10+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc))+ && VV##1807##k_ == VV##F##14+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc))+ && (exists [i##aS7##k_ : int,+ lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_anf##7205759403792798200##d1cc##k_ : (Test.State int int),+ lq_tmpx##1801 : Tuple0,+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ VV##1799##k_ : Tuple0]+ . VV##1799##k_ == y+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && lq_tmpx##1801 == y+ && (exists [VV##F##10 : Tuple0]+ . VV##1799##k_ == VV##F##10+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc))+ && (exists [i##aS7##k_ : int,+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ lq_tmpx##1804 : int,+ lq_anf##7205759403792798200##d1cc##k_ : (Test.State int int),+ lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ VV##1802##k_ : int]+ . VV##1802##k_ == x+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && lq_tmpx##1804 == x+ && (exists [VV##F##6 : int]+ . (exists [i##aS7##k_ : int,+ lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ VV##1796##k_ : int]+ . VV##1796##k_ == VV##F##6+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && (exists [VV##F##7 : int]+ . (exists [lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ i##aS7##k_ : int,+ lq_anf##7205759403792798200##d1cc##k_ : (Test.State int int),+ VV##1807##k_ : int]+ . VV##1807##k_ == VV##F##7+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && (exists [w : int,+ VV##F##14 : int,+ lq_rnmx##255 : Tuple0]+ . (exists [VV##1828 : int,+ lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_anf##7205759403792798200##d1cc##k_ : (Test.State int int),+ VV##1805##k_ : int,+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ i##aS7##k_ : int]+ . VV##1828 == w+ && VV##1805##k_ == w+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && (exists [VV##F##3 : int]+ . Test.gt0xy VV##F##3 i##aS7+ && VV##1805##k_ == VV##F##3+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc))+ && (exists [lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ i##aS7##k_ : int,+ lq_tmpx##1812##k_ : Tuple0,+ VV##1809##k_ : int,+ lq_tmpx##1811##k_ : int,+ lq_anf##7205759403792798200##d1cc##k_ : (Test.State int int)]+ . VV##1809##k_ == VV##F##14+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && lq_tmpx##1811##k_ == w+ && lq_tmpx##1812##k_ == lq_rnmx##255+ && (exists [VV##F##12 : int,+ lq_tmpx##1811 : int,+ lq_tmpx##1812 : Tuple0,+ lq_tmpdb##43 : int,+ lq_tmpdb##44 : Tuple0]+ . VV##F##12 == i##aS7+ && VV##1809##k_ == VV##F##12+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && lq_tmpx##1811##k_ == lq_tmpx##1811+ && lq_tmpx##1812##k_ == lq_tmpx##1812))+ && (exists [i##aS7##k_ : int,+ lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_anf##7205759403792798200##d1cc##k_ : (Test.State int int),+ lq_tmpx##1801 : Tuple0,+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ VV##1799##k_ : Tuple0]+ . VV##1799##k_ == lq_rnmx##255+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && lq_tmpx##1801 == lq_rnmx##255+ && (exists [VV##F##10 : Tuple0]+ . VV##1799##k_ == VV##F##10+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc))+ && VV##1807##k_ == VV##F##14+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc))+ && VV##1796##k_ == VV##F##7+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb))+ && (exists [i##aS7##k_ : int,+ lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ VV##1793##k_ : int]+ . VV##1793##k_ == VV##F##6+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && (exists [VV##F##5 : int]+ . VV##1793##k_ == VV##F##5+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb))+ && VV##1802##k_ == VV##F##6+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc))+ && (exists [lq_anf##7205759403792798200##d1cc##k_ : (Test.State int int),+ lq_tmpx##1818##k_ : int,+ lq_anf##7205759403792798198##d1ca##k_ : (GHC.Internal.Base.Monad (Test.State int)),+ lq_tmpx##1817##k_ : int,+ VV##1815##k_ : int,+ lq_anf##7205759403792798199##d1cb##k_ : (Test.State int Tuple0),+ i##aS7##k_ : int]+ . VV##1815##k_ == VV##F##13+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && lq_tmpx##1817##k_ == w2+ && lq_tmpx##1818##k_ == x+ && (exists [VV##F##8 : int,+ lq_tmpx##1817 : int,+ lq_tmpx##1818 : int,+ lq_tmpdb##47 : int,+ lq_tmpdb##48 : int]+ . lq_tmpx##1818 == VV##F##8+ && VV##F##8 == lq_tmpx##1817+ && VV##1815##k_ == VV##F##8+ && i##aS7##k_ == i##aS7+ && lq_anf##7205759403792798198##d1ca##k_ == lq_anf##7205759403792798198##d1ca+ && lq_anf##7205759403792798199##d1cb##k_ == lq_anf##7205759403792798199##d1cb+ && lq_anf##7205759403792798200##d1cc##k_ == lq_anf##7205759403792798200##d1cc+ && lq_tmpx##1817##k_ == lq_tmpx##1817+ && lq_tmpx##1818##k_ == lq_tmpx##1818)))+ """+ }
+ tests/tasty/ghc-before-9.12.1/SimplifyKVarTests.hs view
@@ -0,0 +1,12 @@++module SimplifyKVarTests (tests) where++import Test.Tasty+import Test.Tasty.HUnit++tests :: TestTree+tests =+ testGroup "simplifyKVar"+ [ testCase "Disabled because it needs MultilineStrings (ghc >= 9.12.1)" $+ return ()+ ]
tests/test.hs view
@@ -87,26 +87,27 @@ unitTests :: FilePath -> IO TestTree unitTests lfDir = group "Unit" [- testGroup "native-pos" <$> dirTests nativeCmd "tests/pos" skipNativePos ExitSuccess- , testGroup "native-neg" <$> dirTests nativeCmd "tests/neg" ["float.fq"] (ExitFailure 1)- , testGroup "elim-crash" <$> dirTests nativeCmd "tests/crash" [] (ExitFailure 1)- , testGroup "elim-pos1" <$> dirTests elimCmd "tests/pos" [] ExitSuccess- , testGroup "elim-pos2" <$> dirTests elimCmd "tests/elim" [] ExitSuccess- , testGroup "elim-neg" <$> dirTests elimCmd "tests/neg" ["float.fq"] (ExitFailure 1)- , testGroup "elim-crash" <$> dirTests elimCmd "tests/crash" [] (ExitFailure 1)- , testGroup "cvc5-pos" <$> dirTests cvc5Cmd "tests/pos" skipNativePos ExitSuccess- , testGroup "proof" <$> dirTests elimCmd "tests/proof" [] ExitSuccess- , testGroup "rankN" <$> dirTests elimCmd "tests/rankNTypes" [] ExitSuccess- , testGroup "horn-pos-el" <$> dirTests elimSaveCmd "tests/horn/pos" [] ExitSuccess- , testGroup "horn-pos-cvc5" <$> dirTests cvc5Cmd "tests/horn/pos" [] ExitSuccess- , testGroup "horn-neg-el" <$> dirTests elimSaveCmd "tests/horn/neg" [] (ExitFailure 1)- , testGroup "horn-neg-cvc5" <$> dirTests cvc5Cmd "tests/horn/neg" [] (ExitFailure 1)- , testGroup "horn-json-pos-el" <$> dirJsonTests elimCmd "tests/horn/pos/.liquid" [] ExitSuccess- , testGroup "horn-json-neg-el" <$> dirJsonTests elimCmd "tests/horn/neg/.liquid" [] (ExitFailure 1)- , testGroup "horn-smt2-pos-el" <$> dirHornTests elimCmd "tests/horn/pos/.liquid" [] ExitSuccess- , testGroup "horn-smt2-neg-el" <$> dirHornTests elimCmd "tests/horn/neg/.liquid" [] (ExitFailure 1)- , testGroup "horn-pos-na" <$> dirTests nativeCmd "tests/horn/pos" [] ExitSuccess- , testGroup "horn-neg-na" <$> dirTests nativeCmd "tests/horn/neg" [] (ExitFailure 1)+ testGroup "native-pos" <$> dirTests nativeCmd "tests/pos" skipNativePos ExitSuccess+ , testGroup "native-neg" <$> dirTests nativeCmd "tests/neg" ["float.fq"] (ExitFailure 1)+ , testGroup "elim-crash" <$> dirTests nativeCmd "tests/crash" [] (ExitFailure 1)+ , testGroup "elim-pos1" <$> dirTests elimCmd "tests/pos" [] ExitSuccess+ , testGroup "elim-pos2" <$> dirTests elimCmd "tests/elim" [] ExitSuccess+ , testGroup "elim-neg" <$> dirTests elimCmd "tests/neg" ["float.fq"] (ExitFailure 1)+ , testGroup "elim-crash" <$> dirTests elimCmd "tests/crash" [] (ExitFailure 1)+ , testGroup "cvc5-pos" <$> dirTests cvc5Cmd "tests/pos" skipNativePos ExitSuccess+ , testGroup "cvc5-spec" <$> dirTests cvc5Cmd "tests/cvc5" skipNativePos ExitSuccess+ , testGroup "proof" <$> dirTests elimCmd "tests/proof" [] ExitSuccess+ , testGroup "rankN" <$> dirTests elimCmd "tests/rankNTypes" [] ExitSuccess+ , testGroup "horn-pos-el" <$> dirTests elimSaveCmd "tests/horn/pos" [] ExitSuccess+ , testGroup "horn-pos-cvc5" <$> dirTests cvc5Cmd "tests/horn/pos" [] ExitSuccess+ , testGroup "horn-neg-el" <$> dirTests elimSaveCmd "tests/horn/neg" [] (ExitFailure 1)+ , testGroup "horn-neg-cvc5" <$> dirTests cvc5Cmd "tests/horn/neg" [] (ExitFailure 1)+ , testGroup "horn-json-pos-el" <$> dirJsonTests elimCmd "tests/horn/pos/.liquid" [] ExitSuccess+ , testGroup "horn-json-neg-el" <$> dirJsonTests elimCmd "tests/horn/neg/.liquid" [] (ExitFailure 1)+ , testGroup "horn-smt2-pos-el" <$> dirHornTests elimCmd "tests/horn/pos/.liquid" [] ExitSuccess+ , testGroup "horn-smt2-neg-el" <$> dirHornTests elimCmd "tests/horn/neg/.liquid" [] (ExitFailure 1)+ , testGroup "horn-pos-na" <$> dirTests nativeCmd "tests/horn/pos" [] ExitSuccess+ , testGroup "horn-neg-na" <$> dirTests nativeCmd "tests/horn/neg" [] (ExitFailure 1) ] where dirTests = dirTests' isTest
unix/Language/Fixpoint/Utils/Progress.hs view
@@ -1,6 +1,8 @@+{-# LANGUAGE ForeignFunctionInterface #-} -- | Progress Bar API module Language.Fixpoint.Utils.Progress ( withProgress+ , withProgressM , progressInit , progressTick , progressClose@@ -13,21 +15,32 @@ import System.Console.AsciiProgress -- import Language.Fixpoint.Misc (traceShow) +foreign import ccall unsafe "unistd.h isatty"+ c_isatty :: Int -> IO Int+ {-# NOINLINE pbRef #-} pbRef :: IORef (Maybe ProgressBar) pbRef = unsafePerformIO (newIORef Nothing) withProgress :: Int -> IO a -> IO a-withProgress n act = do+withProgress = withProgressM id++withProgressM :: (m a -> IO b) -> Int -> m a -> IO b+withProgressM mToIO n act = do showBar <- (Quiet /=) <$> getVerbosity- if showBar+ -- We don't show the progress bar if the output is not a terminal.+ -- Besides improving the output, this also avoids a concurrency+ -- issue:+ -- https://github.com/ucsd-progsys/liquid-fixpoint/issues/782+ isTTY <- (== 1) <$> c_isatty 1+ if showBar && isTTY then displayConsoleRegions $ do -- putStrLn $ "withProgress: " ++ show n progressInit n- r <- act+ r <- mToIO act progressClose return r- else act+ else mToIO act progressInit :: Int -> IO () progressInit n = do
win/Language/Fixpoint/Utils/Progress.hs view
@@ -1,6 +1,7 @@ -- | Progress Bar API module Language.Fixpoint.Utils.Progress ( withProgress+ , withProgressM , progressInit , progressTick , progressClose@@ -8,6 +9,9 @@ withProgress :: Int -> IO a -> IO a withProgress _ x = x++withProgressM :: (m a -> IO b) -> Int -> m a -> IO b+withProgressM f _ = f progressInit :: Int -> IO () progressInit _ = return ()