module Lvm.Core.Saturate (coreSaturate) where
import Data.List
import Data.Maybe
import Lvm.Common.Id
import Lvm.Common.IdMap
import Lvm.Core.Expr
import Lvm.Core.Utils
data Env = Env NameSupply (IdMap Int)
uniqueId :: Env -> (Id, Env)
uniqueId (Env supply arities)
= let (x,supply') = freshId supply
in (x,Env supply' arities)
findArity :: Id -> Env -> Int
findArity x (Env _ arities)
= fromMaybe 0 (lookupMap x arities)
splitEnv :: Env -> (Env, Env)
splitEnv (Env supply arities)
= let (s0,s1) = splitNameSupply supply
in (Env s0 arities, Env s1 arities)
splitEnvs :: Env -> [Env]
splitEnvs (Env supply arities)
= map (`Env` arities) (splitNameSupplies supply)
coreSaturate :: NameSupply -> CoreModule -> CoreModule
coreSaturate supply m
= mapExprWithSupply (satDeclExpr arities) supply m
where
arities = mapFromList [(declName d,declArity d) | d <- moduleDecls m, isDeclCon d || isDeclExtern d]
satDeclExpr :: IdMap Int -> NameSupply -> Expr -> Expr
satDeclExpr arities supply = satExpr (Env supply arities)
satExpr :: Env -> Expr -> Expr
satExpr env expr
= case expr of
Let binds e
-> let (env0,env1) = splitEnv env
in Let (satBinds env0 binds) (satExpr env1 e)
Match x alts
-> Match x (satAlts env alts)
Lam x e
-> Lam x (satExpr env e)
_
-> let expr' = satExprSimple env expr
in addLam env (requiredArgs env expr') expr'
satBinds :: Env -> Binds -> Binds
satBinds = zipBindsWith (\env x expr -> Bind x (satExpr env expr)) . splitEnvs
satAlts :: Env -> Alts -> Alts
satAlts = zipAltsWith (\env pat expr -> Alt pat (satExpr env expr)) . splitEnvs
satExprSimple :: Env -> Expr -> Expr
satExprSimple env expr
= case expr of
Let _ _ -> satExpr env expr
Match _ _ -> satExpr env expr
Lam _ _ -> satExpr env expr
Ap e1 e2 -> let (env1,env2) = splitEnv env
in Ap (satExprSimple env1 e1) (satExpr env2 e2)
_ -> expr
addLam :: (Num a, Enum a) => Env -> a -> Expr -> Expr
addLam env n expr
= let (_,ids) = mapAccumR (\env2 _ -> let (x,env') = uniqueId env2 in (env',x)) env [1..n]
in foldr Lam (foldl Ap expr (map Var ids)) ids
requiredArgs :: Env -> Expr -> Int
requiredArgs env expr
= case expr of
Let _ _ -> 0
Match _ _ -> 0
Lam _ _ -> 0
Ap e1 _ -> requiredArgs env e1 1
Var x -> findArity x env
Con (ConId x) -> findArity x env
Con (ConTag _ arity) -> arity
_ -> 0