{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TemplateHaskell #-} -- | This module should contain all the global type definitions and basic instances. module Language.Haskell.Liquid.Types ( -- * Options Config (..) , HasConfig (..) , hasOpt -- * Ghc Information , GhcInfo (..) , GhcSpec (..) , TargetVars (..) -- * Located Things , Located (..) , dummyLoc -- * Symbols , LocSymbol , LocText -- * Default unknown name , dummyName, isDummy -- * Refined Type Constructors , RTyCon (RTyCon, rtc_tc, rtc_info) , TyConInfo(..), defaultTyConInfo , rTyConPVs , rTyConPropVs , isClassRTyCon, isClassType, isEqType -- * Refinement Types , RType (..), Ref(..), RTProp, rPropP , RTyVar (..) , RTAlias (..) -- * Worlds , HSeg (..) , World (..) -- * Classes describing operations on `RTypes` , TyConable (..) , RefTypable (..) , SubsTy (..) -- * Predicate Variables , PVar (PV, pname, parg, ptype, pargs), isPropPV, pvType , PVKind (..) , Predicate (..) -- * Refinements , UReft(..) -- * Parse-time entities describing refined data types , DataDecl (..) , DataConP (..) , TyConP (..) -- * Pre-instantiated RType , RRType, BRType, RRProp , BSort, BPVar -- * Instantiated RType , BareType, PrType , SpecType, SpecProp , RSort , UsedPVar, RPVar, RReft , REnv (..) -- * Constructing & Destructing RTypes , RTypeRep(..), fromRTypeRep, toRTypeRep , mkArrow, bkArrowDeep, bkArrow, safeBkArrow , mkUnivs, bkUniv, bkClass , rFun, rCls, rRCls -- * Manipulating `Predicates` , pvars, pappSym, pApp -- * Some tests on RTypes , isBase , isFunTy , isTrivial -- * Traversing `RType` , efoldReft, foldReft, foldReft' , mapReft, mapReftM , mapBot, mapBind -- * ??? , Oblig(..) , ignoreOblig , addInvCond -- * Inferred Annotations , AnnInfo (..) , Annot (..) -- * Overall Output , Output (..) -- * Refinement Hole , hole, isHole, hasHole -- * Converting To and From Sort , ofRSort, toRSort , rTypeValueVar , rTypeReft , stripRTypeBase -- * Class for values that can be pretty printed , PPrint (..), pprint , showpp -- * Printer Configuration , PPEnv (..) , ppEnv , ppEnvShort -- * Modules and Imports , ModName (..), ModType (..) , isSrcImport, isSpecImport , getModName, getModString -- * Refinement Type Aliases , RTEnv (..) , mapRT, mapRE -- * Errors and Error Messages , module Language.Haskell.Liquid.Types.Errors , Error , ErrorResult -- * Source information (associated with constraints) , Cinfo (..) -- * Measures , Measure (..) , CMeasure (..) , Def (..) , Body (..) , MSpec (..) -- * Type Classes , RClass (..) -- * KV Profiling , KVKind (..) -- types of kvars , KVProf -- profile table , emptyKVProf -- empty profile , updKVProf -- extend profile -- * Misc , mapRTAVars , insertsSEnv -- * Strata , Stratum(..), Strata , isSVar , getStrata , makeDivType, makeFinType -- * CoreToLogic , LogicMap(..), toLogicMap, eAppWithMap, LMap(..) -- * Refined Instances , RDEnv, DEnv(..), RInstance(..) -- * Ureftable Instances , UReftable(..) -- * String Literals , liquidBegin, liquidEnd , Axiom(..), HAxiom, LAxiom ) where import Prelude hiding (error) import SrcLoc (SrcSpan) import TyCon import DataCon import NameSet import Module (moduleNameFS) import TypeRep hiding (maybeParen, pprArrowChain) import Var import GHC (HscEnv, ModuleName, moduleNameString) import GHC.Generics import Class import CoreSyn (CoreBind, CoreExpr) import PrelInfo (isNumericClass) import Type (getClassPredTys_maybe) import TysPrim (eqPrimTyCon) import TysWiredIn (listTyCon) import Control.Monad (liftM, liftM2, liftM3, liftM4) import Control.DeepSeq import Data.Bifunctor import Data.Bifunctor.TH import Data.Typeable (Typeable) import Data.Generics (Data) import qualified Data.Foldable as F import Data.Hashable import qualified Data.HashMap.Strict as M import qualified Data.HashSet as S import Data.Maybe (fromMaybe, mapMaybe) import Data.List (nub) import Data.Text (Text) import qualified Data.Text as T import Text.PrettyPrint.HughesPJ hiding (first) import Text.Printf import Language.Fixpoint.Misc import Language.Fixpoint.Types hiding (Error, SrcSpan, Result, Predicate, R) import Language.Haskell.Liquid.GHC.Misc import Language.Haskell.Liquid.Types.Variance import Language.Haskell.Liquid.Types.Errors import Language.Haskell.Liquid.Misc import Language.Haskell.Liquid.UX.Config import Data.Default ----------------------------------------------------------------------------- -- | Printer ---------------------------------------------------------------- ----------------------------------------------------------------------------- data PPEnv = PP { ppPs :: Bool , ppTyVar :: Bool -- TODO if set to True all Bare fails , ppSs :: Bool , ppShort :: Bool } ppEnv = ppEnvCurrent ppEnvCurrent = PP False False False False _ppEnvPrintPreds = PP False False False False ppEnvShort pp = pp { ppShort = True } ------------------------------------------------------------------ -- | GHC Information : Code & Spec ------------------------------ ------------------------------------------------------------------ data GhcInfo = GI { target :: !FilePath , env :: !HscEnv , cbs :: ![CoreBind] , derVars :: ![Var] , impVars :: ![Var] , defVars :: ![Var] , useVars :: ![Var] , hqFiles :: ![FilePath] , imports :: ![String] , includes :: ![FilePath] , spec :: !GhcSpec } instance HasConfig GhcInfo where getConfig = getConfig . spec -- | The following is the overall type for /specifications/ obtained from -- parsing the target source and dependent libraries data GhcSpec = SP { tySigs :: ![(Var, Located SpecType)] -- ^ Asserted Reftypes -- eg. see include/Prelude.spec , asmSigs :: ![(Var, Located SpecType)] -- ^ Assumed Reftypes , inSigs :: ![(Var, Located SpecType)] -- ^ Auto generated Signatures , ctors :: ![(Var, Located SpecType)] -- ^ Data Constructor Measure Sigs -- eg. (:) :: a -> xs:[a] -> {v: Int | v = 1 + len(xs) } , meas :: ![(Symbol, Located SpecType)] -- ^ Measure Types -- eg. len :: [a] -> Int , invariants :: ![Located SpecType] -- ^ Data Type Invariants -- eg. forall a. {v: [a] | len(v) >= 0} , ialiases :: ![(Located SpecType, Located SpecType)] -- ^ Data Type Invariant Aliases , dconsP :: ![(DataCon, DataConP)] -- ^ Predicated Data-Constructors -- e.g. see tests/pos/Map.hs , tconsP :: ![(TyCon, TyConP)] -- ^ Predicated Type-Constructors -- eg. see tests/pos/Map.hs , freeSyms :: ![(Symbol, Var)] -- ^ List of `Symbol` free in spec and corresponding GHC var -- eg. (Cons, Cons#7uz) from tests/pos/ex1.hs , tcEmbeds :: TCEmb TyCon -- ^ How to embed GHC Tycons into fixpoint sorts -- e.g. "embed Set as Set_set" from include/Data/Set.spec , qualifiers :: ![Qualifier] -- ^ Qualifiers in Source/Spec files -- e.g tests/pos/qualTest.hs , tgtVars :: ![Var] -- ^ Top-level Binders To Verify (empty means ALL binders) , decr :: ![(Var, [Int])] -- ^ Lexicographically ordered size witnesses for termination , texprs :: ![(Var, [Expr])] -- ^ Lexicographically ordered expressions for termination , lvars :: !(S.HashSet Var) -- ^ Variables that should be checked in the environment they are used , lazy :: !(S.HashSet Var) -- ^ Binders to IGNORE during termination checking , autosize :: !(S.HashSet TyCon) -- ^ Binders to IGNORE during termination checking , config :: !Config -- ^ Configuration Options , exports :: !NameSet -- ^ `Name`s exported by the module being verified , measures :: [Measure SpecType DataCon] , tyconEnv :: M.HashMap TyCon RTyCon , dicts :: DEnv Var SpecType -- ^ Dictionary Environment , axioms :: [HAxiom] -- Axioms from axiomatized functions , logicMap :: LogicMap , proofType :: Maybe Type } instance HasConfig GhcSpec where getConfig = config data LogicMap = LM { logic_map :: M.HashMap Symbol LMap , axiom_map :: M.HashMap Var Symbol } deriving (Show) instance Monoid LogicMap where mempty = LM M.empty M.empty mappend (LM x1 x2) (LM y1 y2) = LM (M.union x1 y1) (M.union x2 y2) data LMap = LMap { lvar :: Symbol , largs :: [Symbol] , lexpr :: Expr } instance Show LMap where show (LMap x xs e) = show x ++ " " ++ show xs ++ "\t|->\t" ++ show e toLogicMap ls = mempty {logic_map = M.fromList $ map toLMap ls} where toLMap (x, xs, e) = (x, LMap {lvar = x, largs = xs, lexpr = e}) eAppWithMap lmap f es def | Just (LMap _ xs e) <- M.lookup (val f) (logic_map lmap), length xs == length es = subst (mkSubst $ zip xs es) e | Just (LMap _ xs e) <- M.lookup (val f) (logic_map lmap), isApp e = subst (mkSubst $ zip xs es) $ dropApp e (length xs - length es) | otherwise = def dropApp e i | i <= 0 = e dropApp (EApp e _) i = dropApp e (i-1) dropApp _ _ = errorstar "impossible" isApp (EApp (EVar _) (EVar _)) = True isApp (EApp e (EVar _)) = isApp e isApp _ = False data TyConP = TyConP { freeTyVarsTy :: ![RTyVar] , freePredTy :: ![PVar RSort] , freeLabelTy :: ![Symbol] , varianceTs :: !VarianceInfo , variancePs :: !VarianceInfo , sizeFun :: !(Maybe (Symbol -> Expr)) } deriving (Generic, Data, Typeable) data DataConP = DataConP { dc_loc :: !SourcePos , freeTyVars :: ![RTyVar] , freePred :: ![PVar RSort] , freeLabels :: ![Symbol] , tyConsts :: ![SpecType] -- FIXME: WHAT IS THIS?? , tyArgs :: ![(Symbol, SpecType)] -- FIXME: These are backwards, why?? , tyRes :: !SpecType , dc_locE :: !SourcePos } deriving (Generic, Data, Typeable) -- | Which Top-Level Binders Should be Verified data TargetVars = AllVars | Only ![Var] -------------------------------------------------------------------- -- | Abstract Predicate Variables ---------------------------------- -------------------------------------------------------------------- data PVar t = PV { pname :: !Symbol , ptype :: !(PVKind t) , parg :: !Symbol , pargs :: ![(t, Symbol, Expr)] } deriving (Generic, Data, Typeable, Show, Functor) instance Eq (PVar t) where pv == pv' = pname pv == pname pv' {- UNIFY: What about: && eqArgs pv pv' -} instance Ord (PVar t) where compare (PV n _ _ _) (PV n' _ _ _) = compare n n' instance NFData t => NFData (PVar t) instance Hashable (PVar a) where hashWithSalt i (PV n _ _ _) = hashWithSalt i n pvType :: PVar t -> t pvType p = case ptype p of PVProp t -> t PVHProp -> panic Nothing "pvType on HProp-PVar" data PVKind t = PVProp t | PVHProp deriving (Generic, Data, Typeable, Functor, F.Foldable, Traversable, Show) instance NFData a => NFData (PVKind a) -------------------------------------------------------------------- ------------------ Predicates -------------------------------------- -------------------------------------------------------------------- type UsedPVar = PVar () newtype Predicate = Pr [UsedPVar] deriving (Generic, Data, Typeable) instance NFData Predicate where rnf _ = () instance Monoid Predicate where mempty = pdTrue mappend p p' = pdAnd [p, p'] instance (Monoid a) => Monoid (UReft a) where mempty = MkUReft mempty mempty mempty mappend (MkUReft x y z) (MkUReft x' y' z') = MkUReft (mappend x x') (mappend y y') (mappend z z') pdTrue = Pr [] pdAnd ps = Pr (nub $ concatMap pvars ps) pvars (Pr pvs) = pvs instance Subable UsedPVar where syms pv = [ y | (_, x, EVar y) <- pargs pv, x /= y ] subst s pv = pv { pargs = mapThd3 (subst s) <$> pargs pv } substf f pv = pv { pargs = mapThd3 (substf f) <$> pargs pv } substa f pv = pv { pargs = mapThd3 (substa f) <$> pargs pv } instance Subable Predicate where syms (Pr pvs) = concatMap syms pvs subst s (Pr pvs) = Pr (subst s <$> pvs) substf f (Pr pvs) = Pr (substf f <$> pvs) substa f (Pr pvs) = Pr (substa f <$> pvs) instance Subable Qualifier where syms = syms . q_body subst = mapQualBody . subst substf = mapQualBody . substf substa = mapQualBody . substa mapQualBody f q = q { q_body = f (q_body q) } instance NFData r => NFData (UReft r) instance NFData RTyVar -- MOVE TO TYPES newtype RTyVar = RTV TyVar deriving (Generic, Data, Typeable) instance Symbolic RTyVar where symbol (RTV tv) = symbol . T.pack . showPpr $ tv data RTyCon = RTyCon { rtc_tc :: TyCon -- ^ GHC Type Constructor , rtc_pvars :: ![RPVar] -- ^ Predicate Parameters , rtc_info :: !TyConInfo -- ^ TyConInfo } deriving (Generic, Data, Typeable) instance NFData RTyCon -- | Accessors for @RTyCon@ isClassRTyCon = isClassTyCon . rtc_tc rTyConPVs = rtc_pvars rTyConPropVs = filter isPropPV . rtc_pvars isPropPV = isProp . ptype isEqType (RApp c _ _ _) = isEqual c isEqType _ = False isClassType (RApp c _ _ _) = isClass c isClassType _ = False -- rTyConPVHPs = filter isHPropPV . rtc_pvars -- isHPropPV = not . isPropPV isProp (PVProp _) = True isProp _ = False defaultTyConInfo = TyConInfo [] [] Nothing instance Default TyConInfo where def = defaultTyConInfo ----------------------------------------------------------------------- -- | Co- and Contra-variance for TyCon -------------------------------- ----------------------------------------------------------------------- -- | Indexes start from 0 and type or predicate arguments can be both -- covariant and contravaariant e.g., for the below Foo dataType -- -- data Foo a b c d
Prop, q :: Int -> Prop, r :: a -> Prop>
-- = F (a ) | Q (c -> a) | G (Int -> a