module Language.Nano.Liquid.Types (
RefType
, REnv
, NanoRefType
, CGEnv (..)
, emptyCGEnv
, Cinfo (..)
, ci
, SubC (..) , WfC (..)
, FixSubC , FixWfC
, RefTypable (..)
, eSingleton
, pSingleton
, rTypeReft
, rTypeSort
, rTypeSortedReft
, rTypeValueVar
, isBaseRType
, isTrivialRefType
, mapReftM
, prefixOpRTy
, infixOpRTy
) where
import Data.Maybe (fromMaybe)
import qualified Data.List as L
import qualified Data.HashMap.Strict as M
import Language.ECMAScript3.Syntax
import Language.ECMAScript3.PrettyPrint
import Language.Nano.Types
import Language.Nano.Env
import Language.Nano.Typecheck.Types
import qualified Language.Fixpoint.Types as F
import Language.Fixpoint.PrettyPrint
import Text.PrettyPrint.HughesPJ
import Control.Applicative
type RefType = RType F.Reft
type REnv = Env RefType
type NanoRefType = Nano AnnType RefType
data CGEnv
= CGE { renv :: !(Env RefType)
, fenv :: F.IBindEnv
, guards :: ![F.Pred]
}
emptyCGEnv = CGE envEmpty F.emptyIBindEnv []
instance PP CGEnv where
pp (CGE re _ gs) = vcat [pp re, pp gs]
newtype Cinfo = Ci SourcePos deriving (Eq, Ord, Show)
ci :: (IsLocated a) => a -> Cinfo
ci = Ci . srcPos
instance PP Cinfo where
pp (Ci l) = text "CInfo:" <+> pp l
instance IsLocated Cinfo where
srcPos (Ci x) = x
instance F.Fixpoint Cinfo where
toFix = pp
data SubC
= Sub { senv :: !CGEnv
, sinfo :: !Cinfo
, slhs :: !RefType
, srhs :: !RefType
}
data WfC
= W { wenv :: !CGEnv
, winfo :: !Cinfo
, wtyp :: !RefType
}
instance PP F.Reft where
pp = pprint
instance PP SubC where
pp (Sub γ i t t') = pp (renv γ) $+$ pp (guards γ)
$+$ ((text "|-") <+> (pp t $+$ text "<:" $+$ pp t'))
$+$ ((text "from:") <+> pp i)
instance PP WfC where
pp (W γ t i) = pp (renv γ)
$+$ (text "|-" <+> pp t)
$+$ ((text "from:") <+> pp i)
instance IsLocated SubC where
srcPos = srcPos . sinfo
instance IsLocated WfC where
srcPos = srcPos . winfo
type FixSubC = F.SubC Cinfo
type FixWfC = F.WfC Cinfo
class RefTypable a where
rType :: a -> RefType
instance RefTypable Type where
rType = ofType
instance RefTypable RefType where
rType = ofType . toType
eSingleton :: (F.Expression e) => RefType -> e -> RefType
eSingleton t e = t `strengthen` (F.exprReft e)
pSingleton :: (F.Predicate p) => RefType -> p -> RefType
pSingleton t p = t `strengthen` (F.propReft p)
rTypeSortedReft :: (F.Reftable r) => RType r -> F.SortedReft
rTypeSortedReft t = F.RR (rTypeSort t) (rTypeReft t)
rTypeReft :: (F.Reftable r) => RType r -> F.Reft
rTypeReft = fromMaybe F.top . fmap F.toReft . stripRTypeBase
rTypeValueVar :: (F.Reftable r) => RType r -> F.Symbol
rTypeValueVar t = vv where F.Reft (vv,_) = rTypeReft t
rTypeSort :: (F.Reftable r) => RType r -> F.Sort
rTypeSort (TApp TInt [] _) = F.FInt
rTypeSort (TVar α _) = F.FObj $ F.symbol α
rTypeSort t@(TAll _ _) = rTypeSortForAll t
rTypeSort (TFun xts t _) = F.FFunc 0 $ rTypeSort <$> (b_type <$> xts) ++ [t]
rTypeSort (TApp c ts _) = rTypeSortApp c ts
rTypeSortApp TInt [] = F.FInt
rTypeSortApp c ts = F.FApp (tconFTycon c) (rTypeSort <$> ts)
tconFTycon TInt = F.intFTyCon
tconFTycon TBool = F.stringFTycon "boolean"
tconFTycon TVoid = F.stringFTycon "void"
tconFTycon (TDef s) = F.stringFTycon $ F.symbolString s
rTypeSortForAll t = genSort n θ $ rTypeSort tbody
where
(αs, tbody) = bkAll t
n = length αs
θ = M.fromList $ zip (F.symbol <$> αs) (F.FVar <$> [0..])
genSort n θ (F.FFunc _ t) = F.FFunc n (F.sortSubst θ <$> t)
genSort n θ t = F.FFunc n [F.sortSubst θ t]
stripRTypeBase :: RType r -> Maybe r
stripRTypeBase (TApp _ _ r) = Just r
stripRTypeBase (TVar _ r) = Just r
stripRTypeBase (TFun _ _ r) = Just r
stripRTypeBase _ = Nothing
instance (F.Reftable r, F.Subable r) => F.Subable (RType r) where
syms = foldReft (\r acc -> F.syms r ++ acc) []
substa = fmap . F.substa
substf f = emapReft (F.substf . F.substfExcept f) []
subst su = emapReft (F.subst . F.substExcept su) []
subst1 t su = emapReft (\xs r -> F.subst1Except xs r su) [] t
emapReft :: (F.Reftable a) => ([F.Symbol] -> a -> b) -> [F.Symbol] -> RType a -> RType b
emapReft f γ (TVar α r) = TVar α (f γ r)
emapReft f γ (TApp c ts r) = TApp c (emapReft f γ <$> ts) (f γ r)
emapReft f γ (TAll α t) = TAll α (emapReft f γ t)
emapReft f γ (TFun xts t r) = TFun (emapReftBind f γ' <$> xts) (emapReft f γ' t) (f γ r)
where
γ' = (b_sym <$> xts) ++ γ
emapReftBind f γ (B x t) = B x $ emapReft f γ t
mapReftM :: (F.Reftable b, Monad m, Applicative m) => (a -> m b) -> RType a -> m (RType b)
mapReftM f (TVar α r) = TVar α <$> f r
mapReftM f (TApp c ts r) = TApp c <$> mapM (mapReftM f) ts <*> f r
mapReftM f (TFun xts t _) = TFun <$> mapM (mapReftBindM f) xts <*> mapReftM f t <*> (return F.top)
mapReftM f (TAll α t) = TAll α <$> mapReftM f t
mapReftBindM f (B x t) = B x <$> mapReftM f t
foldReft :: (F.Reftable r) => (r -> a -> a) -> a -> RType r -> a
foldReft f = efoldReft (\_ -> ()) (\_ -> f) F.emptySEnv
efoldReft :: (F.Reftable r) => (RType r -> b) -> (F.SEnv b -> r -> a -> a) -> F.SEnv b -> a -> RType r -> a
efoldReft _ f γ z (TVar _ r) = f γ r z
efoldReft g f γ z t@(TApp _ ts r) = f γ r $ efoldRefts g f (efoldExt g (B (rTypeValueVar t) t) γ) z ts
efoldReft g f γ z (TAll _ t) = efoldReft g f γ z t
efoldReft g f γ z (TFun xts t r) = f γ r $ efoldReft g f γ' (efoldRefts g f γ' z (b_type <$> xts)) t
where
γ' = foldr (efoldExt g) γ xts
efoldRefts g f γ z ts = L.foldl' (efoldReft g f γ) z ts
efoldExt g xt γ = F.insertSEnv (b_sym xt) (g $ b_type xt) γ
isBaseRType :: RType r -> Bool
isBaseRType (TApp _ [] _) = True
isBaseRType (TVar _ _) = True
isBaseRType _ = False
isTrivialRefType :: RefType -> Bool
isTrivialRefType t = foldReft (\r -> (f r &&)) True t
where
f (F.Reft (_,ras)) = null ras
prefixOpRTy :: PrefixOp -> CGEnv -> RefType
prefixOpRTy o g = prefixOpTy o $ renv g
infixOpRTy :: InfixOp -> CGEnv -> RefType
infixOpRTy o g = infixOpTy o $ renv g