{-# Language TypeSynonymInstances,FlexibleInstances,MultiParamTypeClasses,FunctionalDependencies,RankNTypes,FlexibleContexts,KindSignatures,ScopedTypeVariables #-} {- Instantiating VertComp/VertInit/GraphFun for each use of them (7th step) Assumption: - no function definition (other than the above) - let-bindings are located at the top level (of the above functions) -} module TypeInstantiation where import Spec import ASTData import TypeChecker import Control.Monad.State import Data.Maybe import Data.List import Numeric (showHex) import Debug.Trace type DTypeInstances = (DGroundDef DASTData, [(DTypeInfo, DGroundDef DASTData)]) type DTypeInstanceBinding = ([DVarName], DTypeInstances) type DTypeInstanceBindings = [DTypeInstanceBinding] -- uniq id, stack, stack head indices type DEnvTI = (DUnique, DTypeInstanceBindings, [Int]) class TypeInstantiable a where typeInstantiation :: a -> State DEnvTI a -- functions are replaced with their instances typeInstantiation x = return x -- default -- entry point runTypeInstantiation :: forall (t :: * -> *) a . TypeInstantiable (t DASTData) => (t DASTData) -> DUnique -> (t DASTData, DUnique) runTypeInstantiation p uid = let (p', (uid', _, _)) = runState (typeInstantiation p) (uid, [], []) in (p', uid') -- TODO: built-in functions? addNewBind :: DVarName -> DGroundDef DASTData -> State DEnvTI () addNewBind n def = do (i, bds, ks) <- get let bds' = rec bds put (i, bds', ks) where rec [] = [] rec ((ns, (org, ins)):xs) = case elemIndex n ns of Just _ -> (ns, (org, (typeOf (getData def), def):ins)):xs Nothing -> (ns, (org, ins)):rec xs getNewName :: String -> State (DEnvTI) DVarName getNewName s = do (i, bds, ks) <- get let (n, i') = genNewName i (getBaseName s) put (i', bds, ks) return n getBinds :: State DEnvTI DTypeInstanceBindings getBinds = do (i, bds, ks) <- get return bds addBindsByDefs :: [DGroundDef DASTData] -> State DEnvTI () addBindsByDefs defs = do addBinds (map (\def -> (getNames def, (def, []))) defs) addBindsByDefsS :: [DSmplDef DASTData] -> State DEnvTI () addBindsByDefsS defs = addBindsByDefs (map (\def -> DGDefSmpl def (getData def)) defs) addBindsByDefsV :: [DDefGraphVar DASTData] -> State DEnvTI () addBindsByDefsV defs = addBindsByDefs (map (\def -> DGDefGV def (getData def)) defs) addBinds :: DTypeInstanceBindings -> State DEnvTI () addBinds bds = do (i, bds', ks) <- get put (i, bds++bds', length bds:ks) lookupBind :: DVarName -> State DEnvTI (Maybe (DTypeInstances, Int)) lookupBind n = do bds <- getBinds return (rec bds) where rec [] = Nothing rec ((ns, ins):xs) = case elemIndex n ns of Just i -> (Just (ins, if length ns == 1 then -1 else i)) Nothing -> rec xs popBinds :: State DEnvTI DTypeInstanceBindings popBinds = do xx <- get let (i, bds, k:ks) = xx put (i, drop k bds, ks) return (take k bds) isSmplDef (DGDefSmpl def a) = True isSmplDef _ = False isVertFunDef (DGDefVI def a) = True isVertFunDef (DGDefVC def a) = True isVertFunDef _ = False isGraphFunVarDef (DGDefGV def a) = True isGraphFunVarDef (DGDefGF def a) = True isGraphFunVarDef _ = False instance TypeInstantiable (DProgramSpec DASTData) where typeInstantiation (DProgramSpec rs p a) = do p' <- typeInstantiation p return (DProgramSpec rs p' a) instance TypeInstantiable (DProg DASTData) where typeInstantiation (DProg f defs e a) = do -- add the defs. to the env addBindsByDefs defs e' <- typeInstantiation e defs' <- popBinds let defs'' = concatMap (\(_, (_, ds)) -> map snd ds) defs' return (DProg f defs'' e' a) instance TypeInstantiable (DGraphExpr DASTData) where typeInstantiation (DPregel f0 ft x g a) = do f0' <- typeInstantiation f0 ft' <- typeInstantiation ft x' <- typeInstantiation x g' <- typeInstantiation g return (DPregel f0' ft' x' g' a) typeInstantiation (DGMap f g a) = do f' <- typeInstantiation f g' <- typeInstantiation g return (DGMap f' g' a) typeInstantiation (DGZip g1 g2 a) = do g1' <- typeInstantiation g1 g2' <- typeInstantiation g2 return (DGZip g1' g2' a) typeInstantiation (DGIter f0 ft x g a) = do f0' <- typeInstantiation f0 ft' <- typeInstantiation ft x' <- typeInstantiation x g' <- typeInstantiation g return (DGIter f0' ft' x' g' a) typeInstantiation (DGVar v a) = do v' <- typeInstantiation v return (DGVar v' a) ------------------ giving new names when instantiating class NameRefreshable a where refreshNames :: a -> State DEnvTI a instance NameRefreshable (DGroundDef DASTData) where refreshNames (DGDefVC d a) = do d' <- refreshNames d return (DGDefVC d' a) refreshNames (DGDefVI d a) = do d' <- refreshNames d return (DGDefVI d' a) refreshNames (DGDefSmpl d a) = do d' <- refreshNames d return (DGDefSmpl d' a) refreshNames (DGDefGV d a) = do d' <- refreshNames d return (DGDefGV d' a) refreshNames (DGDefGF d a) = do d' <- refreshNames d return (DGDefGF d' a) replaceNames :: [(DVarName, DVarName)] -> DExpr DASTData -> DExpr DASTData replaceNames subsv e = rec e where rec (DIf p t e a) = let p' = rec p t' = rec t e' = rec e in (DIf p' t' e' a) rec (DTuple es a) = let es' = map rec es in (DTuple es' a) rec (DFunAp f es a) = let es' = map rec es in (DFunAp f es' a) rec (DConsAp c es a) = let es' = map rec es in (DConsAp c es' a) rec (x@(DFieldAcc t fs a)) = x rec (x@(DFieldAccE e fs a)) = x rec (DAggr a' e g es a) = let e' = rec e es' = map rec es in (DAggr a' e' g es' a) rec (x@(DVExp (DVar v av) a)) = case lookup v subsv of Just v' -> (DVExp (DVar v' av) a) Nothing -> x rec (x@(DCExp c a)) = x instance NameRefreshable (DFun DASTData) where refreshNames (DFun f a) = do f' <- getNewName f return (DFun f' a) refreshNames (DBinOp f a) = do f' <- getNewName f return (DBinOp f' a) instance NameRefreshable (DVar DASTData) where refreshNames (DVar v a) = do v' <- getNewName v return (DVar v' a) instance NameRefreshable (DDefVertComp DASTData) where refreshNames (DDefVertComp f defs e a) = do f' <- refreshNames f return (DDefVertComp f' defs e a) instance NameRefreshable (DDefVertInit DASTData) where refreshNames (DDefVertInit f defs e a) = do f' <- refreshNames f return (DDefVertInit f' defs e a) instance NameRefreshable (DDefGraphVar DASTData) where refreshNames (DDefGraphVar v e a) = do v' <- refreshNames v return (DDefGraphVar v' e a) replaceNamesF subse (DFun f a) = case lookup f subse of Nothing -> (DFun f a) Just f' -> (DFun f' a) replaceNamesV subse (DVar v a) = case lookup v subse of Nothing -> (DVar v a) Just v' -> (DVar v' a) replaceNamesG subse (DPregel f0 ft x g a) = let f0' = replaceNamesF subse f0 ft' = replaceNamesF subse ft x' = x g' = replaceNamesG subse g in (DPregel f0' ft' x' g' a) replaceNamesG subse (DGMap f g a) = let f' = replaceNamesF subse f g' = replaceNamesG subse g in (DGMap f' g' a) replaceNamesG subse (DGZip g1 g2 a) = let g1' = replaceNamesG subse g1 g2' = replaceNamesG subse g2 in (DGZip g1' g2' a) replaceNamesG subse (DGIter f0 ft x g a) = let f0' = replaceNamesF subse f0 ft' = replaceNamesF subse ft x' = x g' = replaceNamesG subse g in (DGIter f0' ft' x' g' a) replaceNamesG subse (DGVar v a) = let v' = replaceNamesV subse v in (DGVar v' a) replaceNamesGV subse (DDefGraphVar v e a) = let e' = (replaceNamesG subse e) in (DDefGraphVar v e' a) instance NameRefreshable (DDefGraphFun DASTData) where refreshNames (DDefGraphFun f v defs e a) = do f' <- refreshNames f v' <- refreshNames v defs' <- mapM refreshNames defs let subse = [(getName f, getName f'), (getName v, getName v')] ++ zipWith (\o n -> (getName o, getName n)) defs defs' e' = replaceNamesG subse e defs'' = map (replaceNamesGV subse) defs' return (DDefGraphFun f' v' defs'' e' a) instance NameRefreshable (DSmplDef DASTData) where refreshNames (DDefVar v [] e a) = do v' <- refreshNames v let subse = [(getName v, getName v')] e' = replaceNames subse e return (DDefVar v [] e' a) refreshNames (DDefTuple vs [] e a) = do vs' <- mapM refreshNames vs let subse = zip (map getName vs) (map getName vs') e' = replaceNames subse e return (DDefTuple vs' [] e' a) refreshNames x = error $ "something wrong in refreshNames : x = " ++ show x ---------------------------------------------------------------- instance TypeInstantiable (DGroundDef DASTData) where typeInstantiation (DGDefVC d a) = do d' <- typeInstantiation d return (DGDefVC d' a) typeInstantiation (DGDefVI d a) = do d' <- typeInstantiation d return (DGDefVI d' a) typeInstantiation (DGDefSmpl d a) = do d' <- typeInstantiation d return (DGDefSmpl d' a) typeInstantiation (DGDefGV d a) = do d' <- typeInstantiation d return (DGDefGV d' a) typeInstantiation (DGDefGF d a) = do d' <- typeInstantiation d return (DGDefGF d' a) makeDefs defs = concatMap (\(_, (_, ds)) -> map (\(DGDefSmpl def _) -> def) (map snd ds)) defs makeDefsGV defs = concatMap (\(_, (_, ds)) -> map (\(DGDefGV def _) -> def) (map snd ds)) defs instance TypeInstantiable (DDefVertComp DASTData) where typeInstantiation (DDefVertComp f defs e a) = do addBindsByDefsS defs e' <- typeInstantiation e defs' <- popBinds let defs'' = makeDefs defs' return (DDefVertComp f defs'' e' a) instance TypeInstantiable (DDefVertInit DASTData) where typeInstantiation (DDefVertInit f defs e a) = do addBindsByDefsS defs e' <- typeInstantiation e defs' <- popBinds let defs'' = makeDefs defs' return (DDefVertInit f defs'' e' a) instance TypeInstantiable (DDefGraphVar DASTData) where typeInstantiation (DDefGraphVar v e a) = do e' <- typeInstantiation e return (DDefGraphVar v e' a) instance TypeInstantiable (DDefGraphFun DASTData) where typeInstantiation (DDefGraphFun f v defs e a) = do addBindsByDefsV defs e' <- typeInstantiation e defs' <- popBinds let defs'' = makeDefsGV defs' return (DDefGraphFun f v defs'' e' a) instance TypeInstantiable (DSmplDef DASTData) where typeInstantiation (DDefFun f vs defs e a) = do addBindsByDefsS defs e' <- typeInstantiation e defs' <- popBinds let defs'' = makeDefs defs' return (DDefFun f vs defs'' e' a) typeInstantiation (DDefVar v defs e a) = do addBindsByDefsS defs e' <- typeInstantiation e defs' <- popBinds let defs'' = makeDefs defs' return (DDefVar v defs'' e' a) typeInstantiation (DDefTuple vs defs e a) = do addBindsByDefsS defs e' <- typeInstantiation e defs' <- popBinds let defs'' = makeDefs defs' return (DDefTuple vs defs'' e' a) instance TypeInstantiable (DTermination DASTData) where typeInstantiation (DTermF a) = return (DTermF a) typeInstantiation (DTermI e a) = do e' <- typeInstantiation e return (DTermI e' a) typeInstantiation (DTermU e a) = do e' <- typeInstantiation e return (DTermU e' a) instance TypeInstantiable (DExpr DASTData) where typeInstantiation (DIf p t e a) = do p' <- typeInstantiation p t' <- typeInstantiation t e' <- typeInstantiation e return (DIf p' t' e' a) typeInstantiation (DTuple es a) = do es' <- mapM typeInstantiation es return (DTuple es' a) typeInstantiation (DFunAp f es a) = do f' <- typeInstantiation f es' <- mapM typeInstantiation es return (DFunAp f' es' a) typeInstantiation (DConsAp c es a) = do c' <- typeInstantiation c es' <- mapM typeInstantiation es return (DConsAp c' es' a) typeInstantiation (DFieldAcc t fs a) = do t' <- typeInstantiation t fs' <- mapM typeInstantiation fs return (DFieldAcc t' fs' a) typeInstantiation (DFieldAccE e fs a) = do e' <- typeInstantiation e fs' <- mapM typeInstantiation fs return (DFieldAccE e' fs' a) typeInstantiation (DAggr a' e g es a) = do a'' <- typeInstantiation a' g' <- typeInstantiation g e' <- typeInstantiation e es' <- mapM typeInstantiation es return (DAggr a'' e' g' es' a) typeInstantiation (DVExp v a) = do v' <- typeInstantiation v return (DVExp v' a) typeInstantiation (DCExp c a) = do c' <- typeInstantiation c return (DCExp c' a) unifyUpdate def t = do s <- unify' [(typeOf (getData def), t)] return (mapData (\a -> a { typeOf = apply s (typeOf a)}) def) instance TypeInstantiable (DFun DASTData) where typeInstantiation (DBinOp f a) = instantiation DBinOp f a typeInstantiation (DFun f a) = instantiation DFun f a instance TypeInstantiable (DVar DASTData) where typeInstantiation (DVar v a) = instantiation DVar v a instantiation :: (DVarName -> DASTData -> b) -> DVarName -> DASTData -> State DEnvTI b instantiation build v a = do r <- lookupBind v case r of Nothing -> return (build v a) -- temporary things? Just ((def, ins), pos) -> case def of (DGDefGF _ _) -> do def' <- refreshNames def -- always duplicate it let defe'' = unifyUpdate def' (typeOf a) case defe'' of Right def'' -> do def''' <- typeInstantiation def'' -- instantiate it addNewBind v def''' -- add it to the env return (build (getNames def''' !! (max pos 0)) a) -- use it Left str -> error (str ++ "\nerror during unifying " ++ show def' ++ " and " ++ show (typeOf a) ++ "\nv="++show v ++ "\na="++show a) otherwise -> case lookupAt pos (typeOf a) ins of Just def' -> return (build (getNames def' !! (max pos 0)) a) -- already instantiated Nothing -> if typeAt pos (typeOf (getData def)) == (typeOf a) then do def'' <- typeInstantiation def addNewBind v def'' -- use the original one return (build (getNames def'' !! (max pos 0)) a) else do def' <- refreshNames def -- gives new names let defe'' = unifyUpdate def' (typeOf a) case defe'' of Right def'' -> do def''' <- typeInstantiation def'' -- instantiate it addNewBind v def''' -- add it to the env return (build (getNames def''' !! (max pos 0)) a) -- use it Left str -> error (str ++ "\nerror during unifying2 " ++ show def' ++ " and " ++ show (typeOf a) ++ "\nv="++show v ++ "\na="++show a ++ "\nins="++show ins ++ "\npos="++show pos ) typeAt (-1) t = t typeAt pos (DTypeTerm "(,)" ts) = (ts!!pos) lookupBy' :: Eq b => (a -> b) -> b -> [(a, x)] -> Maybe x lookupBy' _ _ [] = Nothing lookupBy' f key ((a,x):xs) = if f a == key then Just x else lookupBy' f key xs lookupAt :: Int -> DTypeInfo -> [(DTypeInfo, x)] -> Maybe x lookupAt pos t ins | pos == -1 = lookup t ins | otherwise = lookupBy' (typeAt pos) t ins -- tuple case instance TypeInstantiable (DAgg DASTData) instance TypeInstantiable (DGen DASTData) instance TypeInstantiable (DEdge DASTData) instance TypeInstantiable (DTableExpr DASTData) instance TypeInstantiable (DField DASTData) instance TypeInstantiable (DConstructor DASTData) instance TypeInstantiable (DConst DASTData)