CurryInfo: coosy-3.1.0 / Coosy.ShowObserve

classes:

              
documentation:

              
name:
Coosy.ShowObserve
operations:
catTerms categoriseBy constructTermD constructTermV eventLabels findFn findMaps insertToCategory main makeevent paren prettierTerm prettyShowTerm printCatEvents readAndPrintEvents repairOrder separate separate' separate3 separate4 sp startSeparation startSeparation2 startSeparation3 startSeparation4 term
sourcecode:
module Coosy.ShowObserve where

import Data.List ( intersperse, isPrefixOf )

import System.Directory

import Coosy.Prettier as Prettier
import Coosy.Trace

main = readAndPrintEvents putStr ShowLogVarBinds

-- Read trace file and print it with parameter function:
readAndPrintEvents :: (String -> IO ()) -> ViewConf -> IO ()
readAndPrintEvents outstr viewConf =
  getDirectoryContents logDir >>= \files ->
  mapM_ (\label -> readFile (logFile label) >>= \eventStr ->
                   printCatEvents outstr viewConf (label,readTrace eventStr))
        (eventLabels files)

eventLabels files =
    let eventFiles = filter (isPrefixOf logFilePrefix) files
        initialLength = length logFilePrefix in
      map (drop initialLength) eventFiles


printCatEvents :: (String -> IO ()) -> ViewConf -> (String,Trace)
                  -> IO ()
printCatEvents outstr viewConf (label,events) = 
    outstr label >> outstr "\n" >>
    outstr (take (length label) (repeat '-')) >>
    mapM_ (\t -> outstr "\n" >>
                  mapM_ (\s -> outstr s >> outstr "\n")
                        ((reverse . (map (prettyShowTerm viewConf))) t))
          (catTerms events) >>
    outstr "\n"

catTerms :: Trace -> [[Term]]
catTerms events = 
    let traces =  map reverse $ (startSeparation2 $ makeevent events)
        termTraces = categoriseBy (getRef . head) traces
    in
      map ((map term) . repairOrder . snd)  termTraces

makeevent event = zip (reverse event) (repeat False)

data Term = Cons String [Term]
          | FunTerm [(Term,Term)]
          | LogVarTerm Term
          | UnEval
          | Bottom
          | Black Term
 deriving Eq

startSeparation :: [(Event,Bool)] -> [Trace]
startSeparation [] = []
startSeparation ((_,True):ts) = startSeparation ts
startSeparation ((t,False):ts) 
  = let 
      (newts,termEvent) = separate [getParent t, getPred t] ts
    in (t:termEvent):startSeparation newts
  
separate :: [EventID] -> [(Event,Bool)] -> ([(Event,Bool)],Trace)
separate _ [] = ([],[])
separate toFind ((dv,flag):ts)
  | elem (getRef dv) toFind
  = let 
      newToFind = getParent dv : getPred dv : filter (/=(getRef dv)) toFind
      (newts,termEvent) = separate newToFind ts 
    in ((dv,True):newts,dv:termEvent)
  | otherwise 
  = let 
      (newts,termEvent) = separate toFind ts 
    in ((dv,flag):newts,termEvent) 

startSeparation2 [] = []
startSeparation2 ((_,True):trace) = startSeparation2 trace
startSeparation2 ((event,False):trace) 
  = let 
      (termTrace,restTrace) = separate' False [getParent event, getPred event] 
                                              trace
    in (event:termTrace):startSeparation2 restTrace
  
separate' tokenSet toFind ((event,flag):trace)
  | found && getParent event == (-1)
  = let 
      tokenTrace = if not tokenSet  
                      then [Separator,event]
                      else [event]
    in (tokenTrace,(event,True):trace)
  | found
  = let 
      newToFind = getParent event:getPred event:filter (/=(getRef event)) toFind
      (termTrace,restTrace) = separate' flag newToFind trace
      tokenTrace = if not tokenSet && flag 
                      then (Separator:event:termTrace) 
                      else (event:termTrace)
    in (tokenTrace,(event,True):restTrace)
  | otherwise 
  = let 
      (termTrace,restTrace) = separate' tokenSet toFind trace
    in (termTrace,(event,flag):restTrace) 
  where
    found = elem (getRef event) toFind 

startSeparation3 [] = []
startSeparation3 ((_,True):trace) = startSeparation3 trace
startSeparation3 ((event,False):trace) 
  = let 
      (termTrace,restTrace) = separate3 False [getRef event] ((event,False):trace)
    in termTrace ++ startSeparation3 restTrace

separate3 tokenSet toFind ((event,flag):trace)
  | found && getParent event == (-1)
  = let 
      tokenTrace = if not tokenSet  
                      then [[Separator,event]]
                      else [[event]]
    in (tokenTrace,(event,True):trace)
  | found
  = let 
      newToFind = getParent event:getPred event:filter (/=(getRef event)) toFind
      (termTrace:termTraces,restTrace) = separate3 flag newToFind trace
      tokenTrace = if not tokenSet && flag 
                      then (Separator:event:termTrace)
                      else (event:termTrace)
    in (tokenTrace:termTraces,(event,True):restTrace)
  | flag
  = let 
      (termTraces,restTrace) = separate3 tokenSet toFind trace
    in (termTraces,(event,flag):restTrace) 
  | otherwise
  = let 
      (termTrace1:termTraces1,restTrace1) = separate3 False [getParent event,getPred event] 
                                          trace
      (termTraces2,restTrace2) = separate3 tokenSet toFind restTrace1
    in (termTraces2++(event:termTrace1):termTraces1,(event,True):restTrace2) 
  where
    found = elem (getRef event) toFind 

startSeparation4 [] = []
startSeparation4 (event:trace) 
  = let 
      (termTrace,restTrace) = separate4 [getParent event, getPred event] trace
    in (event:termTrace):startSeparation4 restTrace

separate4 _ [] = ([],[])
separate4 toFind (event:trace)
  | elem (getRef event) toFind 
  = let 
      newToFind = getParent event:getPred event:filter (/=(getRef event)) toFind
      (termTrace,restTrace) = separate4 newToFind trace
    in (event:termTrace,restTrace)
  | otherwise 
  = let 
      (termTrace,restTrace) = separate4 toFind trace
    in (termTrace,event:restTrace) 
  

repairOrder []  = []
repairOrder [x] = [x]
repairOrder (t1:t2:traces) 
  = (newGrey1++Separator:newBlack1) :
      repairOrder ((newGrey2++Separator:newBlack2):traces)
  where
    (grey1,_:black1) = span (/= Separator) t1
    (grey2,_:black2) = span (/= Separator) t2
    (newGrey1,newBlack1) = splitAt (length grey2) (grey1++black1)
    (newGrey2,newBlack2) = splitAt (length grey1) (grey2++black2)

term :: Trace -> Term
term events = constructTermD (-1) 0 events

constructTermD :: EventID -> EventID -> Trace -> Term
constructTermD _ _ [] = UnEval
constructTermD parentRef seekArgNr (Demand argNr ref parent _:events) 
   | argNr == seekArgNr && parent == parentRef
   =  constructTermV ref events
   | otherwise = constructTermD parentRef seekArgNr events
constructTermD parentRef seekArgNr (Value _ _ _ _ _:events) 
   = constructTermD parentRef seekArgNr events
constructTermD parentRef seekArgNr (Fun _ _ _:events) 
   = constructTermD parentRef seekArgNr events
constructTermD parentRef seekArgNr (LogVar _ _ _:events) 
   = constructTermD parentRef seekArgNr events
constructTermD parentRef seekArgNr (Separator:events) 
   = Black $ constructTermD parentRef seekArgNr events

constructTermV :: EventID -> [Event] -> Term
constructTermV _ [] = Bottom
constructTermV parentRef (Value arity cname ref parent _ :events)
   | parent == parentRef =
         Cons cname [constructTermD ref arg events | arg<-[1..arity]]
   | otherwise = constructTermV parentRef events

constructTermV parentRef (Fun ref parent _:events)
   | parent == parentRef
   = let [a1,a2]=[constructTermD ref arg events | arg<-[1..2]] in
       case constructTermV parentRef events of
         FunTerm mappings -> FunTerm ((a1,a2):mappings)
         Black (FunTerm mappings) -> Black (FunTerm ((a1,a2):mappings))
         Bottom           -> FunTerm [(a1,a2)]
         Black Bottom     -> FunTerm [(a1,a2)]
   | otherwise = constructTermV parentRef events

constructTermV parentRef (LogVar ref parent _:events)
   | parent == parentRef
   = LogVarTerm (constructTermV ref events)
   | otherwise = constructTermV parentRef events

constructTermV parentRef (Demand _ _ _ _:events) 
   = constructTermV parentRef events

constructTermV parentRef (Separator:events) 
   = Black $ constructTermV parentRef events

-- Pretty printing of a term

data ViewConf = ShowLogVarBinds
              | HideLogVarBinds

prettyShowTerm :: ViewConf -> Term -> String
prettyShowTerm viewConf t = prettyFlat (prettierTerm viewConf t)

prettierTerm :: ViewConf -> Term -> DOC
prettierTerm viewConf = render 0 False

  where
    render :: Int -> Bool -> Term -> DOC
    render prec _ (Cons name args)
     | name=="(:)" && length args == 2 =
      paren (prec > 5)
        (nest 2
          (render 10 False (head args) <> text ":" <> render 5 False (args!!1)))
     | take 2 name == "(," = -- tuple
      paren (prec /= 0)
        (nest 2
          (foldr (<>) nil . intersperse (text ",") .
           map ((Prettier.break <>) . render 10 False) $ args))
     {-| isChar name  = -- char
        text (showTerm name)
     | name == "'\t'" = -- Char tab
      text "'\\t'"
     | name == "'\r'" = -- Char line feed
      text "'\\r'"
     | name == "'\f'" = -- Char form feed
      text "'\\f'"-}
     | otherwise =
      paren (length args > 0 && prec /= 0)
        (nest 2 (text name <> 
          (foldr (<>) nil . map ((Prettier.sep <>) . render 10 False) $ args)))
       where isChar "" = False
             isChar (c:_) | c== '\''  = True
                          | otherwise = False
             
    render _ _ (FunTerm pairs) = 
     if length maps == 1
     then text "{ " <> renderMap (head maps) <> text " }"
     else text "{ " <> foldl1 (\ a b -> a <> line <> text ", " <> b)
                              (map renderMap maps) <> line <> text "}"
     where
       maps = findMaps pairs
    render prec par (LogVarTerm val) =
      if val == Bottom 
        then text "?" 
        else case viewConf of
               ShowLogVarBinds ->
                 paren (prec < 10 || par) 
                 (text "?" <> text "/" <> Prettier.break <> render 9 False val)
               HideLogVarBinds ->
                 render prec par val
    render _ _ UnEval = text "_"
    render _ _ Bottom = text "!"

    render prec par (Black t) 
      = text [chr 7] <> (render prec par t)  <> text [chr 7]

    renderMap :: ([Term],Term) -> DOC
    renderMap (args,res) =
      group  (nest 3
        (text "\\ " <>
          foldr (\ a b -> nest 0 (render 10 False a) <> sp <> b)
            nil
            args <> sep <> text "-> " <> render 0 False res))
        
-- accumulates all arguments for each mapping
findMaps :: [(Term,Term)] -> [([Term],Term)]
findMaps [] = []
findMaps ((a,r):pairs) = 
  map (\(as',r') -> (a:as',r')) (findFn r) ++ findMaps pairs

findFn :: Term -> [([Term],Term)]
findFn t = case t of
  FunTerm pairs -> findMaps pairs
  _ -> [([],t)]  -- result of mapping

paren :: Bool -> DOC -> DOC
paren False doc = group (nest 0 doc)
paren True  doc = group (nest 0 (text "(" <> nest 0 doc <> Prettier.break <> text ")"))

sp = text " "


-- auxiliaries:

categoriseBy :: Eq b => (a -> b) -> [a] -> [(b,[a])]
categoriseBy catF = foldr (\x -> insertToCategory (catF x) x)
                          []

insertToCategory :: Eq b => b -> a -> [(b,[a])] -> [(b,[a])]
insertToCategory cat x [] = [(cat,[x])]
insertToCategory cat x ((cat',xs):cats)
        | cat == cat' = ((cat',x:xs):cats)
        | otherwise   = (cat',xs):insertToCategory cat x  cats
types:
Term ViewConf
unsafe:
safe