module UHC.Light.Compiler.Pred.Evidence
( Evidence (..)
, evidUnresolved
, evidUpdateUnresolved
, InfoToEvidenceMap, evidMpInsert, evidMpUnion, evidMpSubst )
where
import UHC.Light.Compiler.CHR
import UHC.Light.Compiler.Pred.CHR
import UHC.Light.Compiler.Substitutable
import UHC.Light.Compiler.Base.Common
import Data.List
import qualified Data.Set as Set
import qualified Data.Map as Map
import Data.Maybe
import UHC.Util.Pretty
import UHC.Util.Utils
data Evidence p info
= Evid_Unresolved { evidPred :: !p , evidTrace :: ![UnresolvedTrace p info] }
| Evid_Proof { evidPred :: !p , evidInfo :: !info , evidProofSubs :: ![Evidence p info] }
| Evid_Recurse { evidPred :: !p }
| Evid_Ambig { evidPred :: !p , evidAmbigSubs :: ![(info,[Evidence p info])] }
instance (Show info, Show p) => Show (Evidence p info) where
show _ = "Evidence"
instance (Eq p, Eq info) => Eq (Evidence p info) where
(Evid_Proof _ i1 evs1) == (Evid_Proof _ i2 evs2) = i1 == i2 && evs1 == evs2
(Evid_Recurse p1 ) == (Evid_Recurse p2 ) = p1 == p2
_ == _ = False
instance (Ord p, Ord info) => Ord (Evidence p info) where
Evid_Unresolved _ _ `compare` _ = LT
_ `compare` Evid_Unresolved _ _ = GT
Evid_Proof _ i1 evs1 `compare` Evid_Proof _ i2 evs2 = orderingLexic (i1 `compare` i2 : zipWith compare evs1 evs2)
Evid_Proof _ _ _ `compare` _ = LT
_ `compare` Evid_Proof _ _ _ = GT
Evid_Recurse p1 `compare` Evid_Recurse p2 = p1 `compare` p2
Evid_Recurse _ `compare` _ = LT
_ `compare` Evid_Recurse _ = GT
instance (PP info, PP p) => PP (Evidence p info) where
pp (Evid_Proof _ info []) = "Ev:" >#< info
pp (Evid_Proof _ info es) = "Ev:" >#< info >#< ppBracketsCommas' es
pp (Evid_Recurse p ) = "Ev: recurse:" >#< p
pp (Evid_Ambig _ ess) = "Ev: ambiguous:" >#< ppBracketsCommas' (map (ppBracketsCommas . snd) ess)
pp (Evid_Unresolved p _) = "Ev: unresolved:" >#< p
instance VarExtractable p v => VarExtractable (Evidence p info) v where
varFreeSet (Evid_Unresolved p _ ) = varFreeSet p
varFreeSet (Evid_Proof p _ es) = Set.unions $ varFreeSet p : map varFreeSet es
varFreeSet (Evid_Recurse p ) = varFreeSet p
varFreeSet (Evid_Ambig p ess) = Set.unions $ varFreeSet p : map (Set.unions . map varFreeSet . snd) ess
instance VarUpdatable p s => VarUpdatable (Evidence p info) s where
varUpd s (Evid_Unresolved p u ) = Evid_Unresolved (varUpd s p) u
varUpd s (Evid_Proof p i es) = Evid_Proof (varUpd s p) i (map (varUpd s) es)
varUpd s (Evid_Recurse p ) = Evid_Recurse (varUpd s p)
varUpd s (Evid_Ambig p ess) = Evid_Ambig (varUpd s p) (assocLMapElt (map (varUpd s)) ess)
evidUnresolved :: Eq p => Evidence p info -> [UnresolvedTrace p info]
evidUnresolved (Evid_Unresolved p us) =
us
evidUnresolved (Evid_Proof p i ps)
| null us = []
| otherwise = [UnresolvedTrace_Red p i us]
where us = concatMap evidUnresolved ps
evidUnresolved (Evid_Ambig p pss)
| null us = []
| otherwise = [UnresolvedTrace_Overlap p us]
where us = map (\(i,ps) -> (i,concatMap evidUnresolved ps)) pss
evidUnresolved _ = []
evidUpdateUnresolved :: Eq p => Evidence p info -> Evidence p info -> Evidence p info
evidUpdateUnresolved e (Evid_Unresolved _ _)= e
evidUpdateUnresolved (Evid_Proof p i qs) e = Evid_Proof p i [evidUpdateUnresolved q e | q <- qs]
evidUpdateUnresolved (Evid_Recurse p ) e = Evid_Recurse p
evidUpdateUnresolved u@(Evid_Unresolved q _) e | q == evidPred e = e
| otherwise = u
evidSubstUnresolved :: (p -> Maybe (Evidence p info)) -> Evidence p info -> Evidence p info
evidSubstUnresolved lkup ev
= s ev
where s ev = case ev of
Evid_Unresolved p _
| isJust mbev -> fromJust mbev
where mbev = lkup p
Evid_Proof p i es -> Evid_Proof p i $ map s es
Evid_Ambig p ess -> Evid_Ambig p $ assocLMapElt (map s) ess
_ -> ev
type InfoToEvidenceMap p info = Map.Map info (Evidence p info)
evidMpInsert :: (Eq p, Ord info) => info -> Evidence p info -> InfoToEvidenceMap p info -> InfoToEvidenceMap p info
evidMpInsert = Map.insertWith evidUpdateUnresolved
evidMpUnion :: (Eq p, Ord info) => InfoToEvidenceMap p info -> InfoToEvidenceMap p info -> InfoToEvidenceMap p info
evidMpUnion = Map.unionWith evidUpdateUnresolved
evidMpSubst :: (p -> Maybe (Evidence p info)) -> InfoToEvidenceMap p info -> InfoToEvidenceMap p info
evidMpSubst lkup = Map.map (evidSubstUnresolved lkup)