module Compiler.Hoopl.Graph
( O, C, Block(..), Body, Body'(..), Graph, Graph'(..)
, MaybeO(..), MaybeC(..), Shape(..), IndexedCO
, NonLocal(entryLabel, successors)
, emptyBody, addBlock, bodyList
, mapGraph, mapMaybeO, mapMaybeC, mapBlock
)
where
import Compiler.Hoopl.Collections
import Compiler.Hoopl.Label
data O
data C
data Block n e x where
BFirst :: n C O -> Block n C O
BMiddle :: n O O -> Block n O O
BLast :: n O C -> Block n O C
BCat :: Block n O O -> Block n O O -> Block n O O
BHead :: Block n C O -> n O O -> Block n C O
BTail :: n O O -> Block n O C -> Block n O C
BClosed :: Block n C O -> Block n O C -> Block n C C
type Body n = LabelMap (Block n C C)
newtype Body' block n = Body (LabelMap (block n C C))
type Graph = Graph' Block
data Graph' block n e x where
GNil :: Graph' block n O O
GUnit :: block n O O -> Graph' block n O O
GMany :: MaybeO e (block n O C)
-> LabelMap (block n C C)
-> MaybeO x (block n C O)
-> Graph' block n e x
data MaybeO ex t where
JustO :: t -> MaybeO O t
NothingO :: MaybeO C t
data MaybeC ex t where
JustC :: t -> MaybeC C t
NothingC :: MaybeC O t
data Shape ex where
Closed :: Shape C
Open :: Shape O
type family IndexedCO ex a b :: *
type instance IndexedCO C a b = a
type instance IndexedCO O a b = b
instance Functor (MaybeO ex) where
fmap _ NothingO = NothingO
fmap f (JustO a) = JustO (f a)
instance Functor (MaybeC ex) where
fmap _ NothingC = NothingC
fmap f (JustC a) = JustC (f a)
class NonLocal thing where
entryLabel :: thing C x -> Label
successors :: thing e C -> [Label]
instance NonLocal n => NonLocal (Block n) where
entryLabel (BFirst n) = entryLabel n
entryLabel (BHead h _) = entryLabel h
entryLabel (BClosed h _) = entryLabel h
successors (BLast n) = successors n
successors (BTail _ t) = successors t
successors (BClosed _ t) = successors t
emptyBody :: LabelMap (thing C C)
emptyBody = mapEmpty
addBlock :: NonLocal thing => thing C C -> LabelMap (thing C C) -> LabelMap (thing C C)
addBlock b body = nodupsInsert (entryLabel b) b body
where nodupsInsert l b body = if mapMember l body then
error $ "duplicate label " ++ show l ++ " in graph"
else
mapInsert l b body
bodyList :: NonLocal (block n) => Body' block n -> [(Label,block n C C)]
bodyList (Body body) = mapToList body
mapGraph :: (forall e x. n e x -> n' e x) -> Graph n e x -> Graph n' e x
mapGraph _ GNil = GNil
mapGraph f (GUnit b) = GUnit (mapBlock f b)
mapGraph f (GMany x y z)
= GMany (mapMaybeO f x)
(mapMap (mapBlock f) y)
(mapMaybeO f z)
mapMaybeO :: (forall e x. n e x -> n' e x) -> MaybeO ex (Block n e x) -> MaybeO ex (Block n' e x)
mapMaybeO _ NothingO = NothingO
mapMaybeO f (JustO b) = JustO (mapBlock f b)
mapMaybeC :: (forall e x. n e x -> n' e x) -> MaybeC ex (Block n e x) -> MaybeC ex (Block n' e x)
mapMaybeC _ NothingC = NothingC
mapMaybeC f (JustC b) = JustC (mapBlock f b)
mapBlock :: (forall e x. n e x -> n' e x) -> Block n e x -> Block n' e x
mapBlock f (BFirst n) = BFirst (f n)
mapBlock f (BMiddle n) = BMiddle (f n)
mapBlock f (BLast n) = BLast (f n)
mapBlock f (BCat b1 b2) = BCat (mapBlock f b1) (mapBlock f b2)
mapBlock f (BHead b n) = BHead (mapBlock f b) (f n)
mapBlock f (BTail n b) = BTail (f n) (mapBlock f b)
mapBlock f (BClosed b1 b2) = BClosed (mapBlock f b1) (mapBlock f b2)