yoko-0.3.1.2: Examples/LambdaLift/LambdaLift.hs
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}
module LambdaLift.LambdaLift where
import LambdaLift.Common
import LambdaLift.ULC as A
import LambdaLift.TLF
import qualified Data.IntMap as IM
import qualified Data.IntSet as IS
import Data.Yoko
import Data.Yoko.HCompos
import LambdaLift.LLBasics
import LambdaLift.FreeVars (freeVars)
import LambdaLift.DeepSeq (DeepSeq(..))
lambdaLift :: [Type] -> ULC -> Prog
lambdaLift e x = Prog ds tm where
(tm, ds) = runM (ll x) (e, (length e, IM.empty), 0)
data Cnv = Cnv
type instance Idiom Cnv = M
instance HCompos Cnv ULC TLF where hcompos Cnv = ll
ll :: ULC -> M TLF
ll tm = exact_case (hcompos Cnv) tm $ llLam .|| llVar .|. llLet
llLam lams@(Lam_ tyTop tmTop) = do
-- get the body; count formals; determine captives
let ((tys, ty), ulc) = peel ([], tyTop) tmTop where
peel (acc, ty') (Lam ty tm) = peel (ty' : acc, ty) tm
peel acc tm = (acc, tm)
let nLocals = 1 + length tys -- NB "1 +" is for ty
let captives = freeVars $ rejoin lams
captives' = IS.toAscList captives
captives'' = reverse captives'
(rho, rn) <- ask
-- generate a top-level function from the body
do let m = IM.fromDistinctAscList $ zip captives' [0..]
tlf <- ignoreEmissions $
local (const (ty : tys ++ rho, (nLocals, m))) $ ll ulc
emit (map (rho !!) captives'', reverse tys, ty, tlf)
-- replace lambdas with an invocation of tlf
sh <- intermediates
return $ Top (sh - 1) $ map (lookupRN rn) $ captives''
llVar (Var_ i) = ask >>= \(_, rn) -> return $ Occ $ lookupRN rn i
llLet (Let_ ds tm) = ll $ foldr (\(Decl ty tm) x -> A.App (Lam ty tm) x) tm ds
infixl 1 @@
(@@) = A.App
s_comb a b c = Lam (TyFun a (TyFun b c)) . Lam (TyFun a b) . Lam a $
Var 2 @@ Var 0 @@ (Var 1 @@ Var 0)
ex0 = Lam TyInt (Var 0)
ex0' = lambdaLift [] ex0
ex1 = s_comb TyInt TyInt TyInt @@ (Lam TyInt $ Lam TyInt (Var 0))
@@ Lam TyUnit (Var 2 @@ Var 1)
ex1' = lambdaLift [TyInt, TyFun TyInt TyInt] ex1
ex2 = Lam (TyFun (TyFun TyInt TyInt) TyUnit) $
Lam (TyFun TyInt TyInt)
(Var 1 @@ Lam TyInt (Var 1 @@ Var 0))
ex2' = lambdaLift [] ex2
ex3 = Lam TyUnit . Lam TyUnit . Lam TyUnit .
(Var 1 @@) . Lam TyUnit .
(Var 3 @@) . Lam TyInt $
Var 1
ex3' = lambdaLift [] ex3
ex4 = Lam (TyFun TyInt TyInt) (Var 0) @@ Lam TyInt (Var 0)
ex4' = lambdaLift [] ex4
ex5 = Lam (TyFun (TyFun TyInt TyInt) (TyFun TyInt TyInt)) (Var 0) @@
Lam (TyFun TyInt TyInt)
(Lam TyUnit (Var 1) @@ Var 1)
ex5' = lambdaLift [TyUnit] ex5
-- TODO can I make the Tops use scoped instead of global indices?
{-
ex0' ==
Prog [([],[],TyInt,Var 0)
] (Top 0 [])
ex1' ==
Prog [([],[TyFun TyInt (TyFun TyInt TyInt),TyFun TyInt TyInt],TyInt,
App (App (Var 2) (Var 0)) (App (Var 1) (Var 0))),
([],[TyInt],TyInt,Var 0),
([TyFun TyInt TyInt,TyInt],[],TyUnit,App (Var ^1) (Var ^0))
] (App (App (Top 0 []) (Top 1 [])) (Top 2 [1,0]))
ex2' ==
Prog [([TyFun TyInt TyInt],[],TyInt,App (Var ^0) (Var 0)),
([],[TyFun (TyFun TyInt TyInt) TyUnit],TyFun TyInt TyInt,
App (Var 1) (Top 0 [0]))
] (Top 1 [])
ex3' ==
Prog [([TyUnit],[],TyInt,Var ^0),
([TyUnit],[],TyUnit,App (Var ^0) (Top 0 [0])),
([],[TyUnit,TyUnit],TyUnit,App (Var 1) (Top 1 [2]))
] (Top 2 [])
ex4' ==
Prog [([],[],TyFun TyInt TyInt,Var 0),
([],[],TyInt,Var 0)
] (App (Top 0 []) (Top 1 []))
ex5' ==
Prog [([],[],TyFun (TyFun TyInt TyInt) (TyFun TyInt TyInt),Var 0),
([TyFun TyInt TyInt],[],TyUnit,Var ^0),
([TyUnit],[],TyFun TyInt TyInt,App (Top 1 [0]) (Var ^0))
] (App (Top 0 []) (Top 2 [0]))
-}
instance DeepSeq Type where rnf = (`seq` ())
instance DeepSeq Occ where
rnf (Par x) = rnf x
rnf (Env x) = rnf x
instance DeepSeq Prog where rnf (Prog decs tm) = rnf decs `seq` rnf tm
instance DeepSeq TLF where rnf = rnf . reps . disband
all_exs = rnf [ex0', ex1', ex2', ex3', ex4', ex5']