module Base.TypeExpansion
( module Base.TypeExpansion
) where
import qualified Data.Set.Extra as Set (map)
import Curry.Base.Ident
import Curry.Syntax
import Base.CurryTypes
import Base.Messages
import Base.Types
import Base.TypeSubst
import Env.Class
import Env.TypeConstructor
expandType :: ModuleIdent -> TCEnv -> Type -> Type
expandType m tcEnv ty = expandType' m tcEnv ty []
expandType' :: ModuleIdent -> TCEnv -> Type -> [Type] -> Type
expandType' m tcEnv (TypeConstructor tc) tys =
case qualLookupTypeInfo tc tcEnv of
[DataType tc' _ _ ] -> applyType (TypeConstructor tc') tys
[RenamingType tc' _ _ ] -> applyType (TypeConstructor tc') tys
[AliasType _ _ n ty] -> let (tys', tys'') = splitAt n tys
in applyType (expandAliasType tys' ty) tys''
_ -> case qualLookupTypeInfo (qualQualify m tc) tcEnv of
[DataType tc' _ _ ] -> applyType (TypeConstructor tc') tys
[RenamingType tc' _ _ ] -> applyType (TypeConstructor tc') tys
[AliasType _ _ n ty] -> let (tys', tys'') = splitAt n tys
in applyType (expandAliasType tys' ty) tys''
_ -> internalError $ "Base.TypeExpansion.expandType: " ++ show tc
expandType' m tcEnv (TypeApply ty1 ty2) tys =
expandType' m tcEnv ty1 (expandType m tcEnv ty2 : tys)
expandType' _ _ tv@(TypeVariable _) tys = applyType tv tys
expandType' _ _ tc@(TypeConstrained _ _) tys = applyType tc tys
expandType' m tcEnv (TypeArrow ty1 ty2) tys =
applyType (TypeArrow (expandType m tcEnv ty1) (expandType m tcEnv ty2)) tys
expandType' _ _ ts@(TypeSkolem _) tys = applyType ts tys
expandType' m tcEnv (TypeForall tvs ty) tys =
applyType (TypeForall tvs (expandType m tcEnv ty)) tys
expandPred :: ModuleIdent -> TCEnv -> Pred -> Pred
expandPred m tcEnv (Pred qcls ty) = case qualLookupTypeInfo qcls tcEnv of
[TypeClass ocls _ _] -> Pred ocls (expandType m tcEnv ty)
_ -> case qualLookupTypeInfo (qualQualify m qcls) tcEnv of
[TypeClass ocls _ _] -> Pred ocls (expandType m tcEnv ty)
_ -> internalError $ "Base.TypeExpansion.expandPred: " ++ show qcls
expandPredSet :: ModuleIdent -> TCEnv -> ClassEnv -> PredSet -> PredSet
expandPredSet m tcEnv clsEnv = minPredSet clsEnv . Set.map (expandPred m tcEnv)
expandPredType :: ModuleIdent -> TCEnv -> ClassEnv -> PredType -> PredType
expandPredType m tcEnv clsEnv (PredType ps ty) =
PredType (expandPredSet m tcEnv clsEnv ps) (expandType m tcEnv ty)
expandMonoType :: ModuleIdent -> TCEnv -> [Ident] -> TypeExpr -> Type
expandMonoType m tcEnv tvs = expandType m tcEnv . toType tvs
expandPolyType :: ModuleIdent -> TCEnv -> ClassEnv -> QualTypeExpr -> PredType
expandPolyType m tcEnv clsEnv =
normalize 0 . expandPredType m tcEnv clsEnv . toPredType []
expandConstrType :: ModuleIdent -> TCEnv -> ClassEnv -> QualIdent -> [Ident]
-> Context -> [TypeExpr] -> PredType
expandConstrType m tcEnv clsEnv tc tvs cx tys =
normalize n $ expandPredType m tcEnv clsEnv pty
where n = length tvs
pty = toConstrType tc tvs cx tys
expandMethodType :: ModuleIdent -> TCEnv -> ClassEnv -> QualIdent -> Ident
-> QualTypeExpr -> PredType
expandMethodType m tcEnv clsEnv qcls tv =
normalize 1 . expandPredType m tcEnv clsEnv . toMethodType qcls tv