module Env.Class
( ClassEnv, initClassEnv
, ClassInfo, bindClassInfo, mergeClassInfo, lookupClassInfo
, superClasses, allSuperClasses, classMethods, hasDefaultImpl
) where
import Data.List (nub, sort)
import qualified Data.Map as Map (Map, empty, insertWith, lookup)
import Curry.Base.Ident
import Base.Messages (internalError)
type ClassInfo = ([QualIdent], [(Ident, Bool)])
type ClassEnv = Map.Map QualIdent ClassInfo
initClassEnv :: ClassEnv
initClassEnv = Map.empty
bindClassInfo :: QualIdent -> ClassInfo -> ClassEnv -> ClassEnv
bindClassInfo cls (sclss, ms) =
Map.insertWith mergeClassInfo cls (sort sclss, ms)
mergeClassInfo :: ClassInfo -> ClassInfo -> ClassInfo
mergeClassInfo (sclss1, ms1) (_, ms2) = (sclss1, if null ms1 then ms2 else ms1)
lookupClassInfo :: QualIdent -> ClassEnv -> Maybe ClassInfo
lookupClassInfo = Map.lookup
superClasses :: QualIdent -> ClassEnv -> [QualIdent]
superClasses cls clsEnv = case lookupClassInfo cls clsEnv of
Just (sclss, _) -> sclss
_ -> internalError $ "Env.Classes.superClasses: " ++ show cls
allSuperClasses :: QualIdent -> ClassEnv -> [QualIdent]
allSuperClasses cls clsEnv = nub $ classes cls
where
classes cls' = cls' : concatMap classes (superClasses cls' clsEnv)
classMethods :: QualIdent -> ClassEnv -> [Ident]
classMethods cls clsEnv = case lookupClassInfo cls clsEnv of
Just (_, ms) -> map fst ms
_ -> internalError $ "Env.Classes.classMethods: " ++ show cls
hasDefaultImpl :: QualIdent -> Ident -> ClassEnv -> Bool
hasDefaultImpl cls f clsEnv = case lookupClassInfo cls clsEnv of
Just (_, ms) -> case lookup f ms of
Just dflt -> dflt
Nothing -> internalError $ "Env.Classes.hasDefaultImpl: " ++ show f
_ -> internalError $ "Env.Classes.hasDefaultImpl: " ++ show cls