free-theorems-seq-1.0: src/Language/Haskell/FreeTheorems/Variations/PolySeq/AlgCommon.hs
{-# OPTIONS_GHC -XTypeOperators -XRank2Types #-}
{-# LANGUAGE FlexibleContexts, ScopedTypeVariables, DeriveDataTypeable #-}
module Language.Haskell.FreeTheorems.Variations.PolySeq.AlgCommon
(Cont(..)
, emptyCont
, addTermVar
, addTypVar
, getLabTVar
, getTypVarInCont
, makeLabel
, getElemType
, getArrowComps
, isInt
, isBool
, getAllComps
, instantiateWithEpsilon
, annotate
, removeTrue
, getEquals
, substTyp
-- , parseTerm
-- , collectAll
, collectOne
, substLabel
, getUsedLabels
, getUsedExtraLabels
) where
import Data.Generics(Data, everywhere, everywhereM, mkT, mkQ, mkM, gmapT, gmapQ)
import Data.List(nub)
import Control.Monad(mplus)
import Language.Haskell.FreeTheorems.Variations.PolySeq.M
import Language.Haskell.FreeTheorems.Variations.PolySeq.Parser.ParseTerm
import Language.Haskell.FreeTheorems.Variations.PolySeq.Syntax
-- |representation of \Gamma
data Cont = Cont { tVars :: [(TypVar,Label)], vars :: [TypedVar] } deriving (Show,Eq)
emptyCont :: Cont
emptyCont = Cont [] []
-- * auxiliar functions
addTermVar :: Cont -> TypedVar -> Cont
addTermVar (Cont tVars vars) v = Cont tVars (v:vars)
addTypVar :: Cont -> (TypVar,Label) -> Cont
addTypVar (Cont tVars vars) tv = Cont (tv:tVars) vars
getTypVarInCont :: Cont -> TermVar -> M Typ
getTypVarInCont gamma v =
case filter (\x->(fst x == v)) (vars gamma) of
[(_,tau)] -> return tau
_ -> abort
getLabTVar :: Cont -> TypVar -> M Label
getLabTVar gamma tv =
case filter (\x->(fst x == tv)) (tVars gamma) of
[(_,lab)] -> return lab
_ -> abort
makeLabel :: M Label
makeLabel = do{ i <- newLab;
return (LVar (LabVar i))
}
getElemType :: Typ -> M Typ
getElemType tau =
case tau of
TList tau' -> return tau'
_ -> abort
getArrowComps :: Typ -> M (Typ,Typ)
getArrowComps tau =
case tau of
TArrow _ tau1 tau2 -> return (tau1,tau2)
_ -> abort
getAllComps :: Typ -> M (Label,TypVar,Typ)
getAllComps tau =
case tau of
TAll lab tv tau' -> return (lab,tv,tau')
_ -> abort
isInt :: Typ -> M ()
isInt tau = if tau == TInt then return () else abort
isBool :: Typ -> M ()
isBool tau = if tau == TBool then return () else abort
annotate dat = everywhereM (mkM nonToVar) dat
nonToVar :: Label -> M Label
nonToVar l = if l == Non then makeLabel else return l
substLabel :: (Data a) => Label -> Label -> a -> a
substLabel new old dat = everywhere (mkT (substLab new old)) dat
substLab :: Label -> Label -> Label -> Label
substLab new old recent =
if old == recent then new else recent
substTyp :: Typ -> Typ -> TypVar -> Typ
substTyp tau new old = (justUnboundTypVars old) (mkT (substTV new old)) tau
justUnboundTypVars :: TypVar -> (Typ -> Typ) -> Typ -> Typ
justUnboundTypVars tv sub tau =
case tau of
TAll _ tv' _ -> if tv == tv' then tau else gmapT (mkT (justUnboundTypVars tv sub)) (sub tau)
_ -> gmapT (mkT (justUnboundTypVars tv sub)) (sub tau)
substTV :: Typ -> TypVar -> Typ -> Typ
substTV new old tau = case tau of
TVar tv -> if tv == old then new else tau
_ -> tau
getEquals :: Constraint -> [(Label,Label)]
getEquals c = getEquals' (mkQ [] rmEq) c
getEquals' f c =
case c of
Impl c1 c2 -> concat ((f c1) : (gmapQ (mkQ [](getEquals' f)) c1))
_ -> concat ((f c) : (gmapQ (mkQ [] (getEquals' f)) c))
rmEq c =
case c of
Eq l1 l2 -> case l1 of
LVar (LabVar i) -> case l2 of
LVar (LabVar j) -> if i<j then [(l1,l2)] else [(l2,l1)]
_ -> [(l1,l2)]
_ -> [(l2,l1)]
_ -> []
collectAll :: (Data a) => (forall a1. (Data a1) => a1 -> [u]) -> a -> [u]
collectAll f c = concat ((f c) : (gmapQ (collectAll f) c))
collectOne :: (Data a) => (forall a1. (Data a1) => a1 -> Maybe u) -> a -> Maybe u
collectOne f c = foldl mplus (f c) (gmapQ (collectOne f) c)
removeTrue :: Constraint -> Constraint
removeTrue = everywhere (mkT remTru)
remTru :: Constraint -> Constraint
remTru c =
case c of
Conj Tru c2 -> c2
Conj c1 Tru -> c1
Impl Tru c2 -> c2
_ -> c
instantiateWithEpsilon :: Typ -> Typ
instantiateWithEpsilon tau = everywhere (mkT instWithEpsilon) tau
instWithEpsilon :: Label -> Label
instWithEpsilon l = LVal Epsilon
getUsedLabels :: (Data a) => a -> [Int]
getUsedLabels = getUsedExtraLabels []
getUsedExtraLabels ::(Data a) => [Int] -> a -> [Int]
getUsedExtraLabels notIn x = nub (collectAll (mkQ [] (getLabVar notIn)) x)
getLabVar :: [Int] -> LabVar -> [Int]
getLabVar ls (LabVar i) = if i `elem` ls then [] else [i]