module FreeC.IR.TypeScheme
(
instantiateTypeScheme
, instantiateTypeScheme'
, abstractTypeScheme
, abstractTypeScheme'
) where
import Data.Composition ( (.:) )
import Data.List ( (\\), partition )
import Data.Maybe ( fromJust )
import FreeC.Environment.Fresh
import FreeC.IR.SrcSpan
import FreeC.IR.Subst
import qualified FreeC.IR.Syntax as IR
import FreeC.Monad.Converter
instantiateTypeScheme :: IR.TypeScheme -> Converter IR.Type
instantiateTypeScheme = fmap fst . instantiateTypeScheme'
instantiateTypeScheme' :: IR.TypeScheme -> Converter (IR.Type, [IR.Type])
instantiateTypeScheme' (IR.TypeScheme _ typeArgs typeExpr) = do
(typeArgs', subst) <- renameTypeArgsSubst typeArgs
let typeExpr' = applySubst subst typeExpr
typeVars' = map IR.typeVarDeclToType typeArgs'
return (typeExpr', typeVars')
abstractTypeScheme :: [IR.QName] -> IR.Type -> IR.TypeScheme
abstractTypeScheme = fst .: abstractTypeScheme'
abstractTypeScheme' :: [IR.QName] -> IR.Type -> (IR.TypeScheme, Subst IR.Type)
abstractTypeScheme' ns t
= let vs = map (fromJust . IR.identFromQName) ns
(ivs, uvs) = partition IR.isInternalIdent vs
vs' = uvs ++ take (length ivs) (map makeTypeArg [0 ..] \\ uvs)
ns' = map (IR.UnQual . IR.Ident) (uvs ++ ivs)
ts = map (IR.TypeVar NoSrcSpan) vs'
subst = composeSubsts (zipWith singleSubst ns' ts)
t' = applySubst subst t
in (IR.TypeScheme NoSrcSpan (map (IR.TypeVarDecl NoSrcSpan) vs') t', subst)
where
makeTypeArg :: Int -> IR.TypeVarIdent
makeTypeArg = (freshTypeArgPrefix ++) . show