module Debug.Hoed.EventForest
( EventForest(..)
, mkEventForest
, parentUIDLookup
, parentPosLookup
, InfixOrPrefix(..)
, Location(..)
, Visit
, dfsFold
, idVisit
, treeUIDs
, topLevelApps
, eventsInTree
, dfsChildren
, elems
) where
import Debug.Hoed.Observe
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
type EventForest = IntMap [(ParentPosition, Event)]
isRoot :: Event -> Bool
isRoot e = case change e of Observe{} -> True; _ -> False
elems :: EventForest -> [[(ParentPosition, Event)]]
elems = IntMap.elems
addEvent :: EventForest -> Event -> EventForest
addEvent frt e
| isRoot e = frt
| otherwise = IntMap.insert i s frt
where i = parentUID . eventParent $ e
p = parentPosition . eventParent $ e
ms = IntMap.lookup i frt
s = case ms of Nothing -> [(p,e)]
(Just s') -> (p,e) : s'
mkEventForest :: Trace -> EventForest
mkEventForest trc = foldl addEvent IntMap.empty trc
parentUIDLookup :: UID -> EventForest -> [(ParentPosition,Event)]
parentUIDLookup i frt = case IntMap.lookup i frt of
Nothing -> []
(Just es) -> es
parentPosLookup :: ParentPosition -> [(ParentPosition,Event)] -> [Event]
parentPosLookup p = map snd . filter ((==p) . fst)
data InfixOrPrefix = Infix | Prefix
data Location = Trunk | ArgumentOf Location | ResultOf Location | FieldOf Int Location
deriving Eq
instance Show Location where
show Trunk = ""
show (ArgumentOf loc) = 'a' : show loc
show (ResultOf loc) = 'r' : show loc
show (FieldOf n loc) = 'f' : show n ++ show loc
type Visit a = Maybe Event -> Location -> a -> a
idVisit :: Visit a
idVisit _ _ z = z
dfsChildren :: EventForest -> Event -> [Maybe Event]
dfsChildren frt e = case change e of
Enter{} -> manyByPosition 0
(Cons l _) -> foldl (\acc x -> acc ++ manyByPosition x) [] [0..(l1)]
Observe{} -> manyByPosition 0
Fun -> manyByPosition 0 ++ manyByPosition 1
where manyByPosition :: ParentPosition -> [Maybe Event]
manyByPosition pos = case filter (\(pos',_) -> pos == pos') cs of
[] -> [Nothing]
ts -> map (Just . snd) ts
cs :: [(ParentPosition,Event)]
cs = parentUIDLookup (eventUID e) frt
dfsFold :: InfixOrPrefix -> Visit a -> Visit a -> a
-> Location -> (Maybe Event) -> EventForest -> a
dfsFold ip pre post z loc me frt
= post me loc $ case me of
Nothing -> z'
(Just e) -> case change e of
Fun -> let [arg,res] = cs
in case ip of
Prefix -> csFold $ zip cs [ArgumentOf loc,ArgumentOf loc,ResultOf loc,ResultOf loc]
Infix -> let z1 = dfsFold ip pre post z (ArgumentOf loc) arg frt
z2 = pre me loc z1
in dfsFold ip pre post z2 (ResultOf loc) res frt
Cons{} -> csFold $ zip cs $ map (\i -> FieldOf i loc) [1..]
_ -> csFold $ zip cs (repeat loc)
where z' = pre me loc z
cs :: [Maybe Event]
cs = case me of (Just e) -> dfsChildren frt e; Nothing -> error "dfsFold filter failed"
csFold = foldl (\z'' (c,loc') -> dfsFold ip pre post z'' loc' c frt) z'
treeUIDs :: EventForest -> Event -> [UID]
treeUIDs frt = (map eventUID) . eventsInTree frt
eventsInTree :: EventForest -> Event -> [Event]
eventsInTree frt r = reverse $ dfsFold Prefix add idVisit [] Trunk (Just r) frt
where add (Just e) _ es = e : es
add Nothing _ es = es
topLevelApps :: EventForest -> Event -> [Event]
topLevelApps frt r = foldl appendApp [] $ dfsChildren frt r
appendApp :: [Event] -> Maybe Event -> [Event]
appendApp z me = case me of
Nothing -> z
(Just e) -> case change e of Fun -> e : z
_ -> z