module CSPM.Interpreter.Hash
(
mix
,mix3
,MD5Digest (..)
,Hash (..)
,hs
,closureDigest
,mixInt
)
where
import CSPM.CoreLanguage hiding (PrefixState, Event)
import qualified Language.CSPM.AST as AST
import CSPM.Interpreter.Types as Types
import Data.Digest.Pure.HashMD5
import Data.Digest.Pure.MD5
import qualified Data.Set as Set
import qualified Data.IntMap as IntMap
import qualified Data.Map as Map
hs :: String -> Digest
hs = hash
instance Hash Value where
hash = hashValue
hashValue :: Value -> Digest
hashValue v = case v of
VInt i -> if i == fromIntegral int
then mixInt (hs "VInt") int
else error $ "Hash.hs : integer out of bounds" ++ show i
where int = fromIntegral i
VBool True -> hs "VBool True"
VBool False -> hs "VBool False"
VList l -> foldHash (hs "VList") l
VTuple l -> foldHash (hs "VTuple") l
VDotTuple l -> foldHash (hs "VDotTuple") l
VSet s -> foldHash (hs "VSet") $ Set.toAscList s
VClosure c -> mix (hs "VClosure") $ hash c
VFun f -> mix (hs "VFun") $ hash f
VProcess p -> hashProcess p
VChannel c -> mixInt (hs "VChannel") $ chanId c
VUnit -> hs "VUnit"
VAllInts -> hs "VAllInts"
VAllSequences s -> foldHash (hs "VAllSequences" ) $ Set.toAscList s
VConstructor c -> mix (hs "VConstructor") $ hash c
VDataType d -> foldHash (hs "VDataType") d
VNameType _d -> error "Hash : hash nametype "
VPartialApplied f l -> mix3 (hs "VPartialApplied") (hash f) (hash l)
instance Hash AST.LExp where
hash expr = mixInt (hs "AST.LExp") $ AST.unNodeId $ AST.nodeId expr
closureDigest :: AST.LExp -> Env -> AST.FreeNames -> Digest
closureDigest expr env free = foldHash (hs "closureDigest") ( (hash expr) : binds)
where
binds = map lookupAndHash $ IntMap.elems free
lookupAndHash :: AST.UniqueIdent -> Digest
lookupAndHash ident
= mixInt h i
where
!i = AST.uniqueIdentId ident
!h = case AST.bindType ident of
AST.NotLetBound -> case IntMap.lookup i (argBindings env) of
Just val -> hash val
Nothing -> err
AST.LetBound -> case IntMap.lookup i (letDigests env) of
Just d -> d
Nothing -> err
err = error ( "Hash.hs Bindings lookup failure :"
++ "\n\n" ++ show expr
++ "\n\n" ++ show free
++ "\n\n" ++ show ident
++ "\n\n" ++ (show $ argBindings env)
)
hashProcess :: Types.Process -> Digest
hashProcess proc = case proc of
Prefix e -> mix (hs "Prefix") $ hash e
ExternalChoice a b -> mix3 (hs "ExtChoice") (hash a) (hash b)
InternalChoice a b -> mix3 (hs "InternalChoice") (hash a) (hash b)
Interleave a b -> mix3 (hs "Interleave") (hash a) (hash b)
Interrupt a b -> mix3 (hs "Interrupt") (hash a) (hash b)
Timeout a b -> mix3 (hs "Timeout") (hash a) (hash b)
Sharing a e b -> mix (hs "Sharing") $ mix3 (hash a) (hash e) (hash b)
AParallel c1 c2 p q -> mix3 (hs "AParalle") (hash c1) $ mix3 (hash c2) (hash p) (hash q)
Seq a b -> mix3 (hs "Seq") (hash a) (hash b)
Hide s e -> mix3 (hs "Hide") (hash s) $ hash e
Stop -> hs "Stop"
Skip -> hs "Skip"
Omega -> hs "Omega"
AProcess i -> mixInt (hs "AProcess") i
SwitchedOff p -> mix (hs "SwitchedOff") $ hash p
RepAParallel l -> foldHash (hs "RepAParallel") l
Renaming r p -> mix3 (hs "Renaming") (hash r) (hash p)
Chaos c -> mix (hs "Chaos") $ hash c
LinkParallel c p q -> mix (hs "LinkParallel") $ mix3 (hash c) (hash p) (hash q)
Exception c p q -> mix (hs "Exception") $ mix3 (hash c) (hash p) (hash q)
instance Hash Types.Process where hash = hashProcess
instance Hash PrefixState where hash = prefixDigest
instance Hash SwitchedOffProc where hash = switchedOffDigest
instance Hash Types.ClosureSet where hash = closureSetDigest
instance Hash Types.RenamingRelation where hash = renamingDigest
instance Hash Constructor where hash c = mixInt (hs "Constructor") $ constrId c
instance Hash FunClosure where hash = getFunId
instance Hash PrefixTrie where
hash p = case p of
PTNil -> hs "PTNil"
PTAny l -> mix (hs "PTAny") $ hash l
PTMap l -> foldHash (hs "PTMap") $ Map.assocs l
PTRec s t -> mix (hs "PRRec") $ foldHash (hash t) $ Set.toList s
PTClosure t -> mix (hs "PTClosure") $ hash t
PTSingle v t -> mix3 (hs "PTSingle") (hash v) (hash t)