module Language.Haskell.Liquid.Tidy (tidySpecType) where
import Outputable (showPpr)
import Control.Applicative
import qualified Data.HashMap.Strict as M
import qualified Data.HashSet as S
import qualified Data.List as L
import Language.Haskell.Liquid.Misc
import Language.Haskell.Liquid.GhcMisc (stringTyVar)
import Language.Haskell.Liquid.FileNames (symSepName)
import Language.Haskell.Liquid.Fixpoint
import Language.Haskell.Liquid.RefType
tidySpecType :: SpecType -> SpecType
tidySpecType = tidyDSymbols
. tidySymbols
. tidyLocalRefas
. tidyTyVars
tidySymbols :: SpecType -> SpecType
tidySymbols t = substa dropSuffix $ mapBind dropBind t
where
xs = S.fromList (syms t)
dropBind x = if x `S.member` xs then dropSuffix x else nonSymbol
dropSuffix = S . takeWhile (/= symSepName) . symbolString
tidyLocalRefas :: SpecType -> SpecType
tidyLocalRefas = mapReft (txReft)
where
txReft (U (FReft (Reft (v,ras))) p) = U (FReft (Reft (v, dropLocals ras))) p
txReft (U (FSReft s (Reft (v,ras))) p) = U (FSReft s (Reft (v, dropLocals ras))) p
dropLocals = filter (not . any isTmp . syms) . flattenRefas
isTmp x = let str = symbolString x in
(anfPrefix `L.isPrefixOf` str)
tidyDSymbols :: SpecType -> SpecType
tidyDSymbols t = mapBind tx $ substa tx t
where
tx y = M.lookupDefault y y (M.fromList dxs)
dxs = zip ds (var <$> [1..])
ds = [ x | x <- syms t, isTmp x ]
isTmp = (tempPrefix `L.isPrefixOf`) . symbolString
var = stringSymbol . ('x' :) . show
isTmpSymbol x = (anfPrefix `L.isPrefixOf` str) ||
(tempPrefix `L.isPrefixOf` str) ||
("ds_" `L.isPrefixOf` str)
where str = symbolString x
tidyTyVars :: SpecType -> SpecType
tidyTyVars t = subsTyVarsAll αβs t
where
αβs = zipWith (\α β -> (α, toRSort β, β)) αs βs
αs = L.nub (tyVars t)
βs = map (rVar . stringTyVar) pool
pool = [[c] | c <- ['a'..'z']] ++ [ "t" ++ show i | i <- [1..]]
tyVars (RAllP _ t) = tyVars t
tyVars (RAllT α t) = α : tyVars t
tyVars (RFun _ t t' _) = tyVars t ++ tyVars t'
tyVars (RApp _ ts _ _) = concatMap tyVars ts
tyVars (RCls _ ts) = concatMap tyVars ts
tyVars (RVar α _) = [α]
tyVars (REx _ _ t) = tyVars t
tyVars (RExprArg _) = []
tyVars (ROth _) = []
subsTyVarsAll ats = go
where
abm = M.fromList [(a, b) | (a, _, (RVar b _)) <- ats]
go (RAllT a t) = RAllT (M.lookupDefault a a abm) (go t)
go t = subsTyVars_meet ats t