{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverlappingInstances #-} -- | This module (should) contain all the global type definitions and basic -- instances. Need to gradually pull things into here, especially from @RefType@ module Language.Haskell.Liquid.Types ( -- * Options Config (..) -- * Ghc Information , GhcInfo (..) , GhcSpec (..) , TargetVars (..) -- * Located Things , Located (..) -- * Symbols , LocSymbol , LocString -- * Data Constructors , BDataCon (..) -- * Constructors and Destructors , mkArrow, bkArrowDeep, bkArrow, safeBkArrow , mkUnivs, bkUniv, bkClass , rFun, rAppTy -- * Manipulating Predicate , pvars -- * All these should be MOVE TO TYPES , RTyVar (..), RType (..), RRType, BRType, RTyCon(..) , TyConable (..), RefTypable (..), SubsTy (..), Ref(..) , RTAlias (..), mapRTAVars , BSort, BPVar, BareType, RSort, UsedPVar, RPVar, RReft, RefType , PrType, SpecType , PVar (..) , Predicate (..), UReft(..), DataDecl (..), TyConInfo(..) , TyConP (..), DataConP (..) -- * Default unknown name , dummyName, isDummy -- * Traversing `RType` , efoldReft, foldReft , mapReft, mapReftM , mapBot, mapBind , isTrivial -- * Converting To and From Sort , ofRSort, toRSort , rTypeValueVar , rTypeReft , stripRTypeBase -- * Class for values that can be pretty printed , PPrint (..) , showpp -- * Printer Configuration , PPEnv (..), ppEnv -- * Import handling , ModName (..), ModType (..), isSrcImport, isSpecImport , getModName, getModString -- * Refinement Type Aliases , RTEnv (..), mapRT, mapRP, RTBareOrSpec -- * Final Result , Result (..) -- * Different kinds of errors , Error (..) , ErrorResult -- * Source information associated with each constraint , Cinfo (..) ) where import FastString (fsLit) import SrcLoc (mkGeneralSrcSpan, SrcSpan) import TyCon import DataCon import TypeRep hiding (maybeParen, pprArrowChain) import Var import Unique import Literal import Text.Printf import GHC (Class, HscEnv, ModuleName, Name, moduleNameString) import GHC (Class, HscEnv) import Language.Haskell.Liquid.GhcMisc import Control.Monad (liftM, liftM2, liftM3) import Control.DeepSeq import Control.Applicative ((<$>)) import Data.Typeable (Typeable) import Data.Generics (Data) import Data.Monoid hiding ((<>)) import qualified Data.Foldable as F import Data.Hashable import qualified Data.HashMap.Strict as M import qualified Data.HashSet as S import Data.Function (on) import Data.Maybe (maybeToList, fromMaybe) import Data.Traversable hiding (mapM) import Data.List (nub, union, unionBy) import Text.Parsec.Pos (SourcePos, newPos) import Text.Parsec.Error (ParseError) import Text.PrettyPrint.HughesPJ import Language.Fixpoint.Config hiding (Config) import Language.Fixpoint.Misc import Language.Fixpoint.Types hiding (Predicate) -- import qualified Language.Fixpoint.Types as F import CoreSyn (CoreBind) import Var ----------------------------------------------------------------------------- -- | Command Line Config Options -------------------------------------------- ----------------------------------------------------------------------------- -- NOTE: adding strictness annotations breaks the help message data Config = Config { files :: [FilePath] -- ^ source files to check , idirs :: [FilePath] -- ^ path to directory for including specs , diffcheck :: Bool -- ^ check subset of binders modified (+ dependencies) since last check , binders :: [String] -- ^ set of binders to check , noCheckUnknown :: Bool -- ^ whether to complain about specifications for unexported and unused values , nofalse :: Bool -- ^ remove false predicates from the refinements , notermination :: Bool -- ^ disable termination check , totality :: Bool -- ^ check totality in definitions , noPrune :: Bool -- ^ disable prunning unsorted Refinements , maxParams :: Int -- ^ the maximum number of parameters to accept when mining qualifiers , smtsolver :: SMTSolver -- ^ name of smtsolver to use [default: z3-API] } deriving (Data, Typeable, Show, Eq) ----------------------------------------------------------------------------- -- | Printer ---------------------------------------------------------------- ----------------------------------------------------------------------------- class PPrint a where pprint :: a -> Doc showpp :: (PPrint a) => a -> String showpp = render . pprint -- pshow :: PPrint a => a -> String -- pshow = render . pprint instance PPrint a => PPrint (Maybe a) where pprint = maybe (text "Nothing") ((text "Just" <+>) . pprint) instance PPrint a => PPrint [a] where pprint = brackets . intersperse comma . map pprint instance (PPrint a, PPrint b) => PPrint (a,b) where pprint (x, y) = (pprint x) <+> text ":" <+> (pprint y) data PPEnv = PP { ppPs :: Bool , ppTyVar :: Bool } ppEnv = ppEnvPrintPreds ppEnvCurrent = PP False False ppEnvPrintPreds = PP True False ----------------------------------------------------------------------------- -- | Located Values --------------------------------------------------------- ----------------------------------------------------------------------------- data Located a = Loc { loc :: !SourcePos , val :: a } type LocSymbol = Located Symbol type LocString = Located String dummyName = "dummy" isDummy :: (Show a) => a -> Bool isDummy a = show a == dummyName instance Fixpoint SourcePos where toFix = text . show instance Fixpoint a => Fixpoint (Located a) where toFix = toFix . val instance Symbolic a => Symbolic (Located a) where symbol = symbol . val instance Expression a => Expression (Located a) where expr = expr . val instance Functor Located where fmap f (Loc l x) = Loc l (f x) instance F.Foldable Located where foldMap f (Loc _ x) = f x instance Traversable Located where traverse f (Loc l x) = Loc l <$> f x instance Show a => Show (Located a) where show (Loc l x) = show x ++ " defined at " ++ show l instance Eq a => Eq (Located a) where (Loc _ x) == (Loc _ y) = x == y instance Ord a => Ord (Located a) where compare x y = compare (val x) (val y) instance Subable a => Subable (Located a) where syms (Loc _ x) = syms x substa f (Loc l x) = Loc l (substa f x) substf f (Loc l x) = Loc l (substf f x) subst su (Loc l x) = Loc l (subst su x) instance Hashable a => Hashable (Located a) where hashWithSalt i = hashWithSalt i . val ------------------------------------------------------------------ -- | GHC Information : Code & Spec ------------------------------ ------------------------------------------------------------------ data GhcInfo = GI { env :: !HscEnv , cbs :: ![CoreBind] , impVars :: ![Var] , defVars :: ![Var] , useVars :: ![Var] , hqFiles :: ![FilePath] , imports :: ![String] , includes :: ![FilePath] , spec :: !GhcSpec } -- | 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/Assumed Reftypes -- eg. see include/Prelude.spec , ctor :: ![(Var, Located SpecType)] -- ^ Data Constructor Measure Sigs -- eg. (:) :: a -> xs:[a] -> {v: Int | v = 1 + len(xs) } , meas :: ![(Symbol, Located RefType)] -- ^ Measure Types -- eg. len :: [a] -> Int , invariants :: ![Located SpecType] -- ^ Data Type Invariants -- eg. forall a. {v: [a] | len(v) >= 0} , 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 , 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 , config :: !Config -- ^ Configuration Options } data TyConP = TyConP { freeTyVarsTy :: ![RTyVar] , freePredTy :: ![(PVar RSort)] , covPs :: ![Int] -- indexes of covariant predicate arguments , contravPs :: ![Int] -- indexes of contravariant predicate arguments , sizeFun :: !(Maybe (Symbol -> Expr)) } data DataConP = DataConP { freeTyVars :: ![RTyVar] , freePred :: ![(PVar RSort)] , tyArgs :: ![(Symbol, SpecType)] , tyRes :: !SpecType } -- | Which Top-Level Binders Should be Verified data TargetVars = AllVars | Only ![Var] -------------------------------------------------------------------- -- | Predicate Variables ------------------------------------------- -------------------------------------------------------------------- -- MOVE TO TYPES data PVar t = PV { pname :: !Symbol , ptype :: !t , pargs :: ![(t, Symbol, Expr)] } deriving (Show) 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 Functor PVar where fmap f (PV x t txys) = PV x (f t) (mapFst3 f <$> txys) instance (NFData a) => NFData (PVar a) where rnf (PV n t txys) = rnf n `seq` rnf t `seq` rnf txys instance Hashable (PVar a) where hashWithSalt i (PV n _ xys) = hashWithSalt i n -- : (thd3 <$> xys) -------------------------------------------------------------------- ------------------ Predicates -------------------------------------- -------------------------------------------------------------------- type UsedPVar = PVar () newtype Predicate = Pr [UsedPVar] -- deriving (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 = U mempty mempty mappend (U x y) (U x' y') = U (mappend x x') (mappend y y') pdTrue = Pr [] pdAnd ps = Pr (nub $ concatMap pvars ps) pvars (Pr pvs) = pvs -- MOVE TO TYPES 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 } -- MOVE TO TYPES 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 NFData r => NFData (UReft r) where rnf (U r p) = rnf r `seq` rnf p instance NFData PrType where rnf _ = () instance NFData RTyVar where rnf _ = () -- MOVE TO TYPES newtype RTyVar = RTV TyVar data RTyCon = RTyCon { rTyCon :: !TyCon -- GHC Type Constructor , rTyConPs :: ![RPVar] -- Predicate Parameters , rTyConInfo :: !TyConInfo -- TyConInfo } -- deriving (Data, Typeable) ----------------------------------------------------------------------- ----------- TyCon get CoVariance - ContraVariance Info ---------------- ----------------------------------------------------------------------- -- indexes start from 0 and type or predicate arguments can be both -- covariant and contravaariant -- eg, 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