module Helium.ModuleSystem.DictionaryEnvironment
( DictionaryEnvironment, DictionaryTree(..)
, emptyDictionaryEnvironment, addForDeclaration, addForVariable
, getPredicateForDecl, getDictionaryTrees
, makeDictionaryTree, makeDictionaryTrees
) where
import qualified Data.Map as M
import Helium.Syntax.UHA_Syntax (Name)
import Helium.Syntax.UHA_Utils (NameWithRange(..) )
import Helium.Utils.Utils (internalError)
import Top.Types
data DictionaryEnvironment =
DEnv { declMap :: M.Map NameWithRange Predicates
, varMap :: M.Map NameWithRange [DictionaryTree]
}
data DictionaryTree = ByPredicate Predicate
| ByInstance String String [DictionaryTree]
| BySuperClass String String DictionaryTree
deriving Show
instance Show DictionaryEnvironment where
show denv =
"{ declMap = " ++ show (M.assocs $ declMap denv) ++
", varMap = " ++ show (M.assocs $ varMap denv) ++ "}"
emptyDictionaryEnvironment :: DictionaryEnvironment
emptyDictionaryEnvironment =
DEnv { declMap = M.empty, varMap = M.empty }
addForDeclaration :: Name -> Predicates -> DictionaryEnvironment -> DictionaryEnvironment
addForDeclaration name predicates dEnv
| null predicates = dEnv
| otherwise = dEnv { declMap = M.insert (NameWithRange name) predicates (declMap dEnv) }
addForVariable :: Name -> [DictionaryTree] -> DictionaryEnvironment -> DictionaryEnvironment
addForVariable name trees dEnv
| null trees = dEnv
| otherwise = dEnv { varMap = M.insert (NameWithRange name) trees (varMap dEnv) }
getPredicateForDecl :: Name -> DictionaryEnvironment -> Predicates
getPredicateForDecl name dEnv =
M.findWithDefault [] (NameWithRange name) (declMap dEnv)
getDictionaryTrees :: Name -> DictionaryEnvironment -> [DictionaryTree]
getDictionaryTrees name dEnv =
M.findWithDefault [] (NameWithRange name) (varMap dEnv)
makeDictionaryTrees :: ClassEnvironment -> Predicates -> Predicates -> Maybe [DictionaryTree]
makeDictionaryTrees classEnv ps = mapM (makeDictionaryTree classEnv ps)
makeDictionaryTree :: ClassEnvironment -> Predicates -> Predicate -> Maybe DictionaryTree
makeDictionaryTree classEnv availablePredicates p@(Predicate className tp) =
case tp of
TVar _ | p `elem` availablePredicates -> Just (ByPredicate p)
| otherwise -> case [ (path, availablePredicate)
| availablePredicate@(Predicate c t) <- availablePredicates
, t == tp
, path <- superclassPaths c className classEnv
] of
[] -> Nothing
(path,fromPredicate):_ ->
let list = reverse (zip path (tail path))
tree = foldr (uncurry BySuperClass) (ByPredicate fromPredicate) list
in Just tree
_ -> case byInstance noOrderedTypeSynonyms classEnv p of
Nothing -> internalError "DictionaryEnvironment" "makeDictionaryTree" ("reduction error" ++ show (M.assocs classEnv))
Just predicates ->
do let (TCon instanceName, _) = leftSpine tp
trees <- makeDictionaryTrees classEnv availablePredicates predicates
return (ByInstance className instanceName trees)