module DDC.Core.Flow.Transform.Melt
( Info (..)
, meltModule )
where
import DDC.Core.Flow.Prim
import DDC.Core.Flow.Exp
import DDC.Core.Flow.Compounds
import DDC.Core.Module
import DDC.Core.Transform.Annotate
import DDC.Core.Transform.Deannotate
import Control.Monad.Writer.Strict
import qualified Data.Set as Set
import Data.Set (Set)
data Info
= Info (Set Name)
instance Monoid Info where
mempty = Info (Set.empty)
mappend (Info s1) (Info s2) = Info (Set.union s1 s2)
meltModule :: Module () Name -> (Module () Name, Info)
meltModule mm
= let (xBody', info)
= runWriter
$ melt
$ deannotate (const Nothing) $ moduleBody mm
in (mm { moduleBody = annotate () xBody' }, info)
class Melt c where
melt :: c -> Writer Info c
instance Melt (Exp () Name) where
melt (XLet (LLet b x1) x2)
| BName nBind _t <- b
, Just ( NameOpStore OpStoreNew
, [XType tElem, xInit]) <- takeXPrimApps x1
, Just ( NameTyConFlow (TyConFlowTuple n)
, tAs) <- takePrimTyConApps tElem
, length tAs == n
= do
let ltsNew
= [ LLet (BName (NameVarMod nBind (show i)) (tRef tA))
$ xNew tA (xProj tAs i xInit)
| i <- [1..n]
| tA <- tAs ]
x2' <- melt x2
return $ xLets ltsNew x2'
melt (XLet (LLet b x1) x2)
| BName nBind _t <- b
, Just ( NameOpStore OpStoreRead
, [XType tElem, XVar (UName nRef)]) <- takeXPrimApps x1
, Just ( NameTyConFlow (TyConFlowTuple n)
, tsA) <- takePrimTyConApps tElem
, length tsA == n
= do
let ltsRead
= [LLet (BName (NameVarMod nBind (show i)) tA)
$ xRead tA
(XVar (UName (NameVarMod nRef (show i))))
| i <- [1..n]
| tA <- tsA ]
let ltOrig
= LLet b
$ xApps (XCon (dcTupleN n))
( [XType t | t <- tsA]
++ [XVar (UName (NameVarMod nBind (show i)))
| i <- [1..n]])
x2' <- melt x2
return $ xLets (ltsRead ++ [ltOrig]) x2'
melt (XLet (LLet b x1) x2)
| BNone tB <- b
, Just ( NameOpStore OpStoreWrite
, [XType tElem, XVar (UName nRef), xV]) <- takeXPrimApps x1
, Just ( NameTyConFlow (TyConFlowTuple n)
, tsA) <- takePrimTyConApps tElem
, length tsA == n
= do
let ltsWrite
= [ LLet (BNone tB)
$ xWrite tA
(XVar (UName (NameVarMod nRef (show i))))
(xProj tsA i xV)
| i <- [1..n]
| tA <- tsA ]
x2' <- melt x2
return $ xLets ltsWrite x2'
melt xx
= case xx of
XAnnot a x -> liftM (XAnnot a) (melt x)
XLet lts x -> liftM2 XLet (melt lts) (melt x)
XApp x1 x2 -> liftM2 XApp (melt x1) (melt x2)
XVar u -> return $ XVar u
XCon dc -> return $ XCon dc
XLAM b x -> liftM (XLAM b) (melt x)
XLam b x -> liftM (XLam b) (melt x)
XCase x alts -> liftM2 XCase (melt x) (mapM melt alts)
XCast c x -> liftM (XCast c) (melt x)
XType t -> return $ XType t
XWitness w -> return $ XWitness w
instance Melt (Lets () Name) where
melt lts
= case lts of
LLet b x -> liftM (LLet b) (melt x)
LRec bxs
-> do let (bs, xs) = unzip bxs
xs' <- mapM melt xs
return $ LRec $ zip bs xs'
LPrivate{} -> return lts
LWithRegion{} -> return lts
instance Melt (Alt () Name) where
melt (AAlt w x) = liftM (AAlt w) (melt x)