uuagc-0.9.39.0: src/Streaming.hs
module Streaming where
import CommonTypes(Name)
import DepTypes
import List(partition)
import Data.Maybe(fromMaybe,fromJust)
mapp :: (a -> b) -> (a,a) -> (b,b)
mapp f (l,r) = (f l,f r)
-- vervangt nub, bepaald wel de nub maar accumuleert tevens de causes
reduce :: [UsedAttr] -> [UsedAttr]
reduce set = red set [] where
red (res:rest) set' = red rest (r res set')
red [] set' = set'
r res [] = [res]
r (r1@(Loc f1 a1 c1)) ((r2@(Loc f2 a2 c2)):rest) = if f1==f2 && a1==a2
then if length c1 < length c2
then (Loc f2 a2 c1):rest
else r2:rest
else r2:(r r1 rest)
r (r1@(Glo a1 c1)) ((r2@(Glo a2 c2)):rest) = if a1==a2
then if length c1 < length c2
then (Glo a2 c1):rest
else r2:rest
else r2:(r r1 rest)
r (r1@(Loc f1 a1 c1)) ((r2@(Glo a2 c2)):rest) = r2:(r r1 rest)
r (r1@(Glo a1 c1)) ((r2@(Loc f2 a2 c2)):rest) = r2:(r r1 rest)
-- NB: de rechter (update-) zijde van een streamelement is nooit bevat in de linker (set-) zijde!!
-- nieuwe update set (nu) is de concat van linker en rechter (lu & ru), maar met de al gevonden resultaten (ls' & rs') eruit gefilterd (lu' & ru').
-- deze al gevonden resultaten kunnen onbekende causes bevatten, zijn worden daarom meegenomen in de reductie van de al gevonden resltaten (ls & rs).
-- deze resultaten zijn dus 100% zeker dubbel, maar worden meegenomen voor bepaling van de causes in het nieuwe resultaat
stUnion :: Stream -> Stream -> Stream
stUnion [] _ = []
stUnion _ [] = []
stUnion ((ls,lu):lr) ((rs,ru):rr) = (ns,nu):nr where
(lu',ls') = partition (flip notElem rs) lu
(ru',rs') = partition (flip notElem ls) ru
nu = lu' ++ ru'
ns = reduce (ls++ls'++rs++rs')
nr = stUnion lr rr
{-
-- oude versie, met nub ipv reduce
stUnion :: Stream -> Stream -> Stream
stUnion [] _ = []
stUnion _ [] = []
stUnion ((xset,xupd):xrest) ((yset,yupd):yrest) = (nub (xset++yset),new):(stUnion xrest yrest) where
new = (filter (flip notElem yset) xupd) ++ (filter (flip notElem xset) yupd)
-}
{-
-- de x wordt gebruikt om te kijken of de poort open staat, de y wordt doorgegeven als de poort openstaat
-- ouder versie, zonder kortste cause
stPort :: Name -> Stream -> Stream -> Stream
stPort attr ((xset,xupd):xrest) ((yset,yupd):yrest) = case lookup attr (map toPair xupd) of
Just causes -> addTrace causes (([],yset++yupd):yrest)
Nothing -> ([],[]):(stPort attr xrest yrest)
-}
-- de x wordt gebruikt om te kijken of de poort open staat, de y wordt doorgegeven als de poort openstaat
-- de recursieve aanroep van stPortRest wordt gedaan om in het uiteindelijke resultaat de kortste cause te krijgen
-- waarom de cause niet initiëel de kortste is, weet ik niet. Maar er worden wel kortere causes gevonden later in het proces
{-
stPort :: Name -> Stream -> Stream -> Stream
stPort attr ((xset,xupd):xrest) ((yset,yupd):yrest) = case lookup attr (map toPair xupd) of
Just causes -> (addTrace causes ([],yset++yupd)):(stPortRest attr xrest yrest)
Nothing -> ([],[]):(stPort attr xrest yrest)
where
stPortRest attr ((xset,xupd):xrest) (y:yrest) = case lookup attr (map toPair xset) of
Just causes -> (addTrace causes y):(stPortRest attr xrest yrest)
Nothing -> (error "Dit mag nooit gebeuren!" ([],[])):(stPortRest attr xrest yrest)
-}
-- 20 januari: herschrijving van bovenstaande versie in 1 functie (zonder where)...
stPort :: Name -> Stream -> Stream -> Stream
stPort attr ((xset,xupd):xrest) ((yset,yupd):yrest) = case lookup attr (map toPair xupd) of
Just causes -> (addTrace causes ([],yset++yupd)):(zipWith (\(xset,xupd) y -> addTrace (fromJust . lookup attr . map toPair $ xset) y) xrest yrest)
Nothing -> ([],[]):(stPort attr xrest yrest)
-- stStart biedt geen functionaliteit voor een initiële cause, want er zijn geen initiële causes:
-- het begin van een stream is namelijk altijd een attribuut dat zichzelf bepaalt. Dat heeft geen oorzaak nodig.
stStart :: Name -> Name -> Stream
stStart field attr = first:(repeat other) where
first = ([],[Loc field attr []])
other = ([Loc field attr []],[])
stEmpty :: Stream
stEmpty = repeat ([],[])
getStream :: Vertex -> [UseStream] -> Stream
getStream vertex streams = fromMaybe stEmpty (lookup vertex streams)
stLocal2global :: Stream -> Stream
stLocal2global = map (mapp (map (\res -> Glo (getAttr res) (getTrace res))))
-- de nub hoeft niet, want het filter op fieldname van een lokaal resultaat filtert doublures er al uit
--stLocal2global = map (mapp (nub . (map (\res -> Glo (getAttr res)))))
stFilterInclSide :: UseStream -> Stream
stFilterInclSide (vertex,stream) = stFilterOnField ((getField vertex)==) stream
stFilterExclSide :: UseStream -> Stream
stFilterExclSide (vertex,stream) = stFilterOnField ((getField vertex)/=) stream
stFilterOnField :: (Name -> Bool) -> Stream -> Stream
stFilterOnField f = map (mapp (filter (f . getField)))