fregel-1.2.0: compiler/Inlining.hs
{-# Language TypeSynonymInstances,FlexibleInstances,MultiParamTypeClasses,FunctionalDependencies,RankNTypes,FlexibleContexts,KindSignatures,ScopedTypeVariables #-}
{-
Inlining functions on values and moving let-bindings (of variables) to the top of the function. (4th step)
Assumption:
- let-bindings are in the order consistent of their dependencies
-}
module Inlining where
import Spec
import Control.Monad.State
import Data.Maybe
import Data.List
import Numeric (showHex)
import Debug.Trace
import ASTData
import TypeChecker
type DBinding = (DVarName, DSmplDef DASTData)
type DBindings = [DBinding]
type DEnvI = (DBindings, [Int], DUnique, [[DSmplDef DASTData]])
-- entry point
runInlining :: DProgramSpec DASTData -> DUnique -> (DProgramSpec DASTData, DUnique)
runInlining p uid = let (p', (_,_,uid',_)) = runState (inlining p) ([],[],uid,[[]])
in (p', uid')
class Inliable a where
inlining :: a -> State DEnvI a -- inliging functions, and storing let-bindings contained in functions to the env.
inlining a = do return a -- by default, returns the input
getBinds :: State DEnvI DBindings
getBinds = do xx <- get
let (bds,_,_,_) = xx
return bds
addBinds :: DBindings -> State DEnvI ()
addBinds bds =
do xx <- get
let (bds', ks, i, vbds) = xx
put (bds++bds', length bds:ks, i, vbds)
popBinds :: State DEnvI ()
popBinds =
do xx <- get
let (bds, k:ks, i, vbds) = xx
put (drop k bds, ks, i, vbds)
getNewName :: String -> State DEnvI DVarName
getNewName s =
do xx <- get
let (bds, ks, i, vbds) = xx
(n, i') = genNewName i (getBaseName s)
put (bds, ks, i', vbds)
return n
addVarBinds :: [DSmplDef DASTData] -> State DEnvI ()
addVarBinds vbds =
do xx <- get
let (bds, ks, i, vbds':vbdss) = xx
put (bds, ks, i, (reverse vbds ++ vbds'):vbdss)
getVarBinds :: State DEnvI [DSmplDef DASTData]
getVarBinds =
do xx <- get
let (bds, ks, i, vbds:vbdss) = xx
put (bds, ks, i, vbdss)
return (reverse vbds)
saveVarBinds :: State DEnvI ()
saveVarBinds =
do (bds, ks, i, vbdss) <- get
put (bds, ks, i, []:vbdss)
instance Inliable (DProgramSpec DASTData) where
inlining (DProgramSpec rs p a) =
do p' <- inlining p
return (DProgramSpec rs p' a)
instance Inliable (DRecordSpec DASTData)
instance Inliable (DType DASTData)
instance Inliable (DConst DASTData)
isFunDefG (DGDefSmpl def a) = isFunDef def
isFunDefG _ = False
isSmplDef (DGDefSmpl def a) = True
isSmplDef _ = False
isFunDefGV _ = False
isFunDef (DDefFun f vs ds e a) = True
isFunDef _ = False
getSmplDef (DGDefSmpl def a) = def
addFunDefBindG :: (DGroundDef DASTData) -> State DEnvI ()
addFunDefBindG def =
do case def of
(DGDefSmpl def' a) -> addFunDefBind def'
_ -> return ()
addFunDefBind :: (DSmplDef DASTData) -> State DEnvI ()
addFunDefBind def =
do case def of
(DDefFun f vs ds e a) -> addBinds [(getName f, def)]
_ -> return ()
popFunDefBindG :: (DGroundDef DASTData) -> State DEnvI ()
popFunDefBindG def =
do case def of
(DGDefSmpl def a) -> popFunDefBind def
_ -> return ()
popFunDefBindGV :: (DDefGraphVar DASTData) -> State DEnvI ()
popFunDefBindGV def =
do return ()
popFunDefBind :: (DSmplDef DASTData) -> State DEnvI ()
popFunDefBind def =
do case def of
(DDefFun f vs ds e a) -> popBinds
_ -> return ()
inliningLetG defs e =
do defs' <- mapM (\def -> do def' <- inlining def; addFunDefBindG def'; return def') defs
e' <- inlining e
mapM (\x -> do popFunDefBindG x) defs
let defs'' = filter (not . isFunDefG) defs'
defs''' = filter (not . isSmplDef) defs''
vdefs = map getSmplDef $ filter (isSmplDef) defs''
addVarBinds vdefs
return (defs''', e')
-- no room for inlining
inliningLetGV defs e = return (defs, e)
inliningLet defs e =
do defs' <- mapM (\def -> do def' <- inlining def; addFunDefBind def'; return def') defs
let defs'' = filter (not . isFunDef) defs'
addVarBinds defs''
e' <- inlining e
mapM (\x -> do popFunDefBind x) defs
return (e')
instance Inliable (DProg DASTData) where
inlining (DProg f defs e a) =
do (defs', e') <- inliningLetG defs e
vdefs <- getVarBinds -- the inner var defs
let vdefs' = map (\def -> DGDefSmpl def (getData def)) vdefs
return (DProg f (vdefs' ++ defs') e' a)
instance Inliable (DGroundDef DASTData) where
inlining (DGDefVI d a) = do d' <- inlining d
return (DGDefVI d' a)
inlining (DGDefVC d a) = do d' <- inlining d
return (DGDefVC d' a)
inlining (DGDefGV d a) = do d' <- inlining d
return (DGDefGV d' a)
inlining (DGDefGF d a) = do d' <- inlining d
return (DGDefGF d' a)
inlining (DGDefSmpl d a) = do d' <- inlining d
return (DGDefSmpl d' a)
instance Inliable (DDefVertComp DASTData) where
inlining (DDefVertComp f defs e a) =
do saveVarBinds
e' <- inliningLet defs e
vdefs <- getVarBinds -- the inner var definitions
return (DDefVertComp f vdefs e' a)
instance Inliable (DDefVertInit DASTData) where
inlining (DDefVertInit f defs e a) =
do saveVarBinds
e' <- inliningLet defs e
vdefs <- getVarBinds -- the inner var definitions
return (DDefVertInit f vdefs e' a)
instance Inliable (DDefGraphVar DASTData) where
inlining (DDefGraphVar v e a) =
do (_, e') <- inliningLetG [] e
return (DDefGraphVar v e' a)
instance Inliable (DDefGraphFun DASTData) where
inlining (DDefGraphFun f v defs e a) =
do (defs', e') <- inliningLetGV defs e
return (DDefGraphFun f v defs' e' a)
instance Inliable (DSmplDef DASTData) where
inlining (DDefFun f vs defs e a) =
do saveVarBinds -- save the outer var definitions
e' <- inliningLet defs e
vdefs' <- getVarBinds -- get the inner var definitions
return (DDefFun f vs vdefs' e' a)
inlining (DDefVar v defs e a) =
do e' <- inliningLet defs e
return (DDefVar v [] e' a) -- no inner definitions
inlining (DDefTuple vs defs e a) =
do e' <- inliningLet defs e
return (DDefTuple vs [] e' a) -- no inner definitions
instance Inliable (DTermination DASTData) where
inlining (DTermF a) = return (DTermF a)
inlining (DTermI e a) =
do e' <- inlining e
return (DTermI e' a)
inlining (DTermU e a) =
do e' <- inlining e
return (DTermU e' a)
instance Inliable (DGraphExpr DASTData)
refreshNameV :: DVar DASTData -> State DEnvI (DVar DASTData)
refreshNameV (DVar v a) =
do n <- getNewName v
return (DVar n a)
refreshName :: DSmplDef DASTData -> State DEnvI (DSmplDef DASTData)
refreshName (DDefVar v [] e a) =
do v' <- refreshNameV v
return (DDefVar v' [] e a)
refreshName (DDefTuple vs [] e a) =
do vs' <- mapM refreshNameV vs
return (DDefTuple vs' [] e a)
refreshNameV2 :: (DASTData, DVar DASTData) -> State DEnvI (DVar DASTData)
refreshNameV2 (a, DVar v _) =
do n <- getNewName v
return (DVar n a)
replaceNamesD :: [(DVarName, DVarName)] -> [(DVarName, DExpr DASTData)] -> DSmplDef DASTData -> DSmplDef DASTData
replaceNamesD subsv subse (DDefVar v [] e a) = (DDefVar v [] (replaceNames subsv subse e) a)
replaceNamesD subsv subse (DDefTuple vs [] e a) = (DDefTuple vs [] (replaceNames subsv subse e) a)
replaceNames :: [(DVarName, DVarName)] -> [(DVarName, DExpr DASTData)] -> DExpr DASTData -> DExpr DASTData
replaceNames subsv subse 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 -> case lookup v subse of
Just e -> e
Nothing -> x
rec (x@(DCExp c a)) = x
updateType :: forall (t :: * -> *).
(DAdditionalData2 (t DASTData) DASTData DASTData (t DASTData),
DAdditionalData (t DASTData) DASTData
)
=> Substitution -> t DASTData -> t DASTData
updateType s x = mapData (\a -> a { typeOf = apply s (typeOf a)}) x
instantiation :: DFun DASTData -> [DExpr DASTData] -> DASTData -> State DEnvI (DExpr DASTData)
instantiation f es a =
do bds <- getBinds
case lookup (getName f) bds of
Just (DDefFun f vs defs e a') -> -- defs are of DefVar/DDefTuple
do let ets = map (typeOf.getData) es -- types of the arguments
eas = map (getData) es -- types and deps of the arguments
defs' <- mapM refreshName defs -- give them new names
vs' <- mapM refreshNameV2 (zip eas vs) -- new variable names with the argument types
let t = typeOf a -- type of the expression
tf = typeOf (getData f) -- type of the function
subs = unify [(tf, typeFunction (ets++[t]))] -- the type-substitution
defs'' = map (updateType subs) defs'
subsv = zip (concatMap getNames defs) (concatMap getNames defs'') -- [(oldvar,newvar)]
defs2 = zipWith (\v e -> DDefVar v [] e (getData v)) vs' es -- arguments are bound to the new variables
subse = zip (map getName vs) (map (\v -> DVExp v (getData v)) vs') -- [(arg, exp)]
defs''' = map (replaceNamesD subsv subse) defs''
e' = replaceNames subsv subse e
e'' = updateType subs e'
addVarBinds (defs''' ++ defs2) -- these are moved to immediately under the VertComp/VertInit
return e''
Nothing -> return (DFunAp f es a) -- built-in functions
instance Inliable (DExpr DASTData) where
inlining (DIf p t e a) =
do p' <- inlining p
t' <- inlining t
e' <- inlining e
return (DIf p' t' e' a)
inlining (DTuple es a) =
do es' <- mapM inlining es
return (DTuple es' a)
inlining (DFunAp f es a) = -- inlining!
do es' <- mapM inlining es
instantiation f es' a
inlining (DConsAp c es a) =
do c' <- inlining c
es' <- mapM inlining es
return (DConsAp c' es' a)
inlining (DFieldAcc t fs a) =
do return (DFieldAcc t fs a)
inlining (DFieldAccE e fs a) =
do return (DFieldAccE e fs a)
inlining (DAggr a' e g es a) =
do e' <- inlining e
es' <- mapM inlining es
return (DAggr a' e' g es' a)
inlining (DVExp v a) =
do return (DVExp v a)
inlining (DCExp c a) =
do return (DCExp c a)
instance Inliable (DGen DASTData)
instance Inliable (DEdge DASTData)
instance Inliable (DTableExpr DASTData)
instance Inliable (DField DASTData)
instance Inliable (DFun DASTData)
instance Inliable (DVar DASTData)
instance Inliable (DConstructor DASTData)