lhc-0.6.20081216: src/Grin/Devolve.hs
module Grin.Devolve(twiddleGrin,devolveTransform,devolveGrin) where
import Control.Monad.Identity
import Control.Monad.RWS
import Data.IORef
import qualified Data.Map as Map
import qualified Data.Set as Set
import Util.Gen
import Support.Transform
import Grin.Grin
import Grin.Noodle
import Support.FreeVars
import Options (verbose)
devolveTransform = transformParms {
transformDumpProgress = verbose,
transformCategory = "Devolve",
transformPass = "Grin",
transformOperation = devolveGrin
}
-- devolve grin into a form in which it can be readily converted into C code
-- This lifts any local functions which are ever called in a non-tail-calllike form
-- to the top level.
devolveGrin :: Grin -> IO Grin
devolveGrin grin = do
col <- newIORef []
let g (n,l :-> r) = f r >>= \r -> return (n,l :-> r)
{-f lt@Let { expDefs = defs, expBody = body } = do
let nonTail = expNonNormal lt
(nmaps,rmaps) = splitEither (map z defs)
z fd@FuncDef { funcDefName = name, funcDefBody = as :-> r }
| name `Set.member` nonTail = Left ((name,(as ++ xs) :-> proc r),xs)
| otherwise = Right fd { funcDefBody = as :-> proc r }
where xs = [ Var v t | (v,t) <- Set.toList $ freeVars (as :-> r), v > v0]
pmap = Map.fromList [ (n,xs) | ((n,_),xs) <- nmaps]
proc b = runIdentity (proc' b)
proc' (App a as t) | Just xs <- Map.lookup a pmap = return (App a (as ++ xs) t)
proc' e = mapExpExp proc' e
mapM_ print (Map.toList pmap)
nmaps <- mapM (g . fst) nmaps
modifyIORef col (++ nmaps)
mapExpExp f $ updateLetProps lt { expDefs = rmaps, expBody = proc body }-}
f e = mapExpExp f e
nf <- mapM g (grinFuncs grin)
lf <- readIORef col
let ntenv = extendTyEnv [ createFuncDef False x y | (x,y) <- lf ] (grinTypeEnv grin)
return $ setGrinFunctions (lf ++ nf) grin { grinPhase = PostDevolve, grinTypeEnv = ntenv }
data Env = Env {
envMap :: Map.Map Var Var,
envVar :: Var
}
newtype R a = R (RWS Env (Set.Set Var) () a)
deriving(Monad,Functor,MonadReader Env,MonadWriter (Set.Set Var))
runR (R x) = fst $ evalRWS x Env { envMap = mempty, envVar = v1 } ()
class Twiddle a where
twiddle :: a -> R a
twiddle a = return a
instance Twiddle Exp where
twiddle = twiddleExp
instance Twiddle Val where
twiddle = twiddleVal
instance Twiddle a => Twiddle [a] where
twiddle xs = mapM twiddle xs
twiddleExp e = f e where
f (x :>>= lam) = return (:>>=) `ap` twiddle x `ap` twiddle lam
{-f l@Let {} = do
ds <- twiddle (expDefs l)
b <- twiddle (expBody l)
return . updateLetProps $ l { expDefs = ds, expBody = b }-}
f (Case v as) = return Case `ap` twiddle v `ap` twiddle as
f n = do e <- mapExpVal twiddleVal n ; mapExpExp twiddle e
instance Twiddle Lam where
twiddle (vs :-> y) = do
let fvs = freeVars vs
(y,uv) <- censor (Set.filter (`notElem` fvs)) $ listen (twiddle y)
let fvp' = Map.fromList $ concatMap (\v -> if v `Set.member` uv then [] else [(v,v0)]) fvs
vs <- censor (const mempty) . local (\e -> e { envMap = fvp' }) $ twiddle vs
return (vs :-> y)
-- twiddle (vs :-> y) = do
-- cv <- asks envVar
-- let fvp = Map.fromList $ zip fvs [cv ..]
-- fvs = freeVars vs
-- local (\e -> e { envVar = head $ drop (length fvs) [cv .. ], envMap = fvp `Map.union` envMap e }) $ do
-- (y,uv) <- censor (Set.filter (`notElem` take (length fvs) [cv .. ])) $ listen (twiddle y)
-- let fvp' = fmap (\v -> if v `Set.member` uv then v else v0) fvp
-- vs <- censor (const mempty) . local (\e -> e { envMap = fvp' }) $ twiddle vs
-- return (vs :-> y)
twiddleGrin grin = grinFunctions_s fs' grin where
fs' = runR . twiddle $ grinFunctions grin
instance Twiddle FuncDef where
twiddle = funcDefBody_uM twiddle
twiddleVal x = f x where
f var@(Var v ty) = do
em <- asks envMap
case Map.lookup v em of
Just n -> tell (Set.singleton n) >> return (Var n ty)
Nothing -> tell (Set.singleton v) >> return var
f x = mapValVal f x