| 1 | {- | |
|---|
| 2 | Module : $Id$ |
|---|
| 3 | Description : CspCASL signatures |
|---|
| 4 | Copyright : (c) Markus Roggenbach and Till Mossakowski and Uni Bremen 2004 |
|---|
| 5 | License : similar to LGPL, see HetCATS/LICENSE.txt or LIZENZ.txt |
|---|
| 6 | |
|---|
| 7 | Maintainer : M.Roggenbach@swansea.ac.uk |
|---|
| 8 | Stability : provisional |
|---|
| 9 | Portability : portable |
|---|
| 10 | |
|---|
| 11 | signatures for CSP-CASL |
|---|
| 12 | |
|---|
| 13 | -} |
|---|
| 14 | |
|---|
| 15 | -- todo: implement isInclusion, computeExt |
|---|
| 16 | |
|---|
| 17 | module CspCASL.SignCSP where |
|---|
| 18 | |
|---|
| 19 | import CspCASL.AS_CspCASL_Process (CHANNEL_NAME, PROCESS_NAME) |
|---|
| 20 | |
|---|
| 21 | import CASL.AS_Basic_CASL (SORT) |
|---|
| 22 | import CASL.Sign (emptySign, Sign, extendedInfo, sortRel) |
|---|
| 23 | import CASL.Morphism (Morphism) |
|---|
| 24 | |
|---|
| 25 | import qualified Common.Doc as Doc |
|---|
| 26 | import qualified Common.DocUtils as DocUtils |
|---|
| 27 | import Common.Id (Id, SIMPLE_ID) |
|---|
| 28 | import Common.Lib.Rel (predecessors) |
|---|
| 29 | import Common.Result |
|---|
| 30 | |
|---|
| 31 | import Control.Monad (unless) |
|---|
| 32 | import qualified Data.Map as Map |
|---|
| 33 | import qualified Data.Set as Set |
|---|
| 34 | |
|---|
| 35 | -- | A process has zero or more parameter sorts, and a communication |
|---|
| 36 | -- alphabet. |
|---|
| 37 | data ProcProfile = ProcProfile [SORT] CommAlpha |
|---|
| 38 | deriving (Eq, Show) |
|---|
| 39 | |
|---|
| 40 | -- | A process communication alphabet consists of a set of sort names |
|---|
| 41 | -- and typed channel names. |
|---|
| 42 | data TypedChanName = TypedChanName CHANNEL_NAME SORT |
|---|
| 43 | deriving (Eq, Ord, Show) |
|---|
| 44 | data CommType = CommTypeSort SORT |
|---|
| 45 | | CommTypeChan TypedChanName |
|---|
| 46 | deriving (Eq, Ord) |
|---|
| 47 | instance Show CommType where |
|---|
| 48 | show (CommTypeSort s) = show s |
|---|
| 49 | show (CommTypeChan (TypedChanName c s)) = show (c, s) |
|---|
| 50 | |
|---|
| 51 | type CommAlpha = Set.Set CommType |
|---|
| 52 | |
|---|
| 53 | type ChanNameMap = Map.Map CHANNEL_NAME SORT |
|---|
| 54 | type ProcNameMap = Map.Map PROCESS_NAME ProcProfile |
|---|
| 55 | type ProcVarMap = Map.Map SIMPLE_ID SORT |
|---|
| 56 | |
|---|
| 57 | -- Close a communication alphabet under CASL subsort |
|---|
| 58 | closeCspCommAlpha :: CspCASLSign -> CommAlpha -> CommAlpha |
|---|
| 59 | closeCspCommAlpha sig = Set.unions . Set.toList . Set.map (closeOneCspComm sig) |
|---|
| 60 | |
|---|
| 61 | -- Close one CommType under CASL subsort |
|---|
| 62 | closeOneCspComm :: CspCASLSign -> CommType -> CommAlpha |
|---|
| 63 | closeOneCspComm sig x = let |
|---|
| 64 | mkTypedChan c s = CommTypeChan $ TypedChanName c s |
|---|
| 65 | subsorts s' = Set.singleton s' `Set.union` predecessors (sortRel sig) s' |
|---|
| 66 | in case x of |
|---|
| 67 | CommTypeSort s -> Set.map CommTypeSort (subsorts s) |
|---|
| 68 | CommTypeChan (TypedChanName c s) -> Set.map CommTypeSort (subsorts s) |
|---|
| 69 | `Set.union` Set.map (mkTypedChan c) (subsorts s) |
|---|
| 70 | |
|---|
| 71 | {- Will probably be useful, but doesn't appear to be right now. |
|---|
| 72 | |
|---|
| 73 | -- Extract the sorts from a process alphabet |
|---|
| 74 | procAlphaSorts :: CommAlpha -> Set.Set SORT |
|---|
| 75 | procAlphaSorts a = stripMaybe $ Set.map justSort a |
|---|
| 76 | where justSort n = case n of |
|---|
| 77 | (CommTypeSort s) -> Just s |
|---|
| 78 | _ -> Nothing |
|---|
| 79 | -- Extract the typed channel names from a process alphabet |
|---|
| 80 | procAlphaChans :: CommAlpha -> Set.Set TypedChanName |
|---|
| 81 | procAlphaChans a = stripMaybe $ Set.map justChan a |
|---|
| 82 | where justChan n = case n of |
|---|
| 83 | (CommTypeChan c) -> Just c |
|---|
| 84 | _ -> Nothing |
|---|
| 85 | -- Given a set of Maybes, filter to keep only the Justs |
|---|
| 86 | stripMaybe :: Ord a => Set.Set (Maybe a) -> Set.Set a |
|---|
| 87 | stripMaybe x = Set.fromList $ Maybe.catMaybes $ Set.toList x |
|---|
| 88 | |
|---|
| 89 | -- Close a set of sorts under a subsort relation |
|---|
| 90 | cspSubsortCloseSorts :: CspCASLSign -> Set.Set SORT -> Set.Set SORT |
|---|
| 91 | cspSubsortCloseSorts sig sorts = |
|---|
| 92 | Set.unions subsort_sets |
|---|
| 93 | where subsort_sets = Set.toList $ Set.map (cspSubsortPreds sig) sorts |
|---|
| 94 | |
|---|
| 95 | -} |
|---|
| 96 | |
|---|
| 97 | -- | CSP process signature. |
|---|
| 98 | data CspSign = CspSign |
|---|
| 99 | { chans :: ChanNameMap |
|---|
| 100 | , procSet :: ProcNameMap |
|---|
| 101 | } deriving (Eq, Show) |
|---|
| 102 | |
|---|
| 103 | -- | A CspCASL signature is a CASL signature with a CSP process |
|---|
| 104 | -- signature in the extendedInfo part. |
|---|
| 105 | type CspCASLSign = Sign () CspSign |
|---|
| 106 | |
|---|
| 107 | ccSig2CASLSign :: CspCASLSign -> Sign () () |
|---|
| 108 | ccSig2CASLSign sigma = sigma { extendedInfo = () } |
|---|
| 109 | |
|---|
| 110 | -- | Empty CspCASL signature. |
|---|
| 111 | emptyCspCASLSign :: CspCASLSign |
|---|
| 112 | emptyCspCASLSign = emptySign emptyCspSign |
|---|
| 113 | |
|---|
| 114 | -- | Empty CSP process signature. |
|---|
| 115 | emptyCspSign :: CspSign |
|---|
| 116 | emptyCspSign = CspSign |
|---|
| 117 | { chans = Map.empty |
|---|
| 118 | , procSet = Map.empty |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | -- | Compute union of two CSP process signatures. |
|---|
| 122 | addCspProcSig :: CspSign -> CspSign -> CspSign |
|---|
| 123 | addCspProcSig a b = |
|---|
| 124 | a { chans = chans a `Map.union` chans b |
|---|
| 125 | , procSet = procSet a `Map.union` procSet b |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | -- XXX looks incomplete! |
|---|
| 129 | isInclusion :: CspSign -> CspSign -> Bool |
|---|
| 130 | isInclusion _ _ = True |
|---|
| 131 | |
|---|
| 132 | |
|---|
| 133 | -- XXX morphisms between CSP process signatures? |
|---|
| 134 | |
|---|
| 135 | data CspAddMorphism = CspAddMorphism |
|---|
| 136 | { channelMap :: Map.Map Id Id |
|---|
| 137 | , processMap :: Map.Map Id Id |
|---|
| 138 | } deriving (Eq, Show) |
|---|
| 139 | |
|---|
| 140 | composeIdMaps :: Map.Map Id Id -> Map.Map Id Id -> Map.Map Id Id |
|---|
| 141 | composeIdMaps m1 m2 = Map.foldWithKey (\ i j -> case Map.lookup j m2 of |
|---|
| 142 | Nothing -> error "SignCsp.composeIdMaps" |
|---|
| 143 | Just k -> Map.insert i k) Map.empty m1 |
|---|
| 144 | |
|---|
| 145 | composeCspAddMorphism :: CspAddMorphism -> CspAddMorphism |
|---|
| 146 | -> Result CspAddMorphism |
|---|
| 147 | composeCspAddMorphism m1 m2 = return emptyCspAddMorphism |
|---|
| 148 | { channelMap = composeIdMaps (channelMap m1) $ channelMap m2 |
|---|
| 149 | , processMap = composeIdMaps (processMap m1) $ processMap m2 } |
|---|
| 150 | |
|---|
| 151 | inverseCspAddMorphism :: CspAddMorphism -> Result CspAddMorphism |
|---|
| 152 | inverseCspAddMorphism cm = do |
|---|
| 153 | let chL = Map.toList $ channelMap cm |
|---|
| 154 | prL = Map.toList $ processMap cm |
|---|
| 155 | swap = map $ \ (a, b) -> (b, a) |
|---|
| 156 | isInj l = length l == Set.size (Set.fromList $ map snd l) |
|---|
| 157 | unless (isInj chL) $ fail "invertCspAddMorphism.channelMap" |
|---|
| 158 | unless (isInj prL) $ fail "invertCspAddMorphism.processMap" |
|---|
| 159 | return emptyCspAddMorphism |
|---|
| 160 | { channelMap = Map.fromList $ swap chL |
|---|
| 161 | , processMap = Map.fromList $ swap prL } |
|---|
| 162 | |
|---|
| 163 | type CspMorphism = Morphism () CspSign CspAddMorphism |
|---|
| 164 | |
|---|
| 165 | emptyCspAddMorphism :: CspAddMorphism |
|---|
| 166 | emptyCspAddMorphism = CspAddMorphism |
|---|
| 167 | { channelMap = Map.empty -- ??? |
|---|
| 168 | , processMap = Map.empty |
|---|
| 169 | } |
|---|
| 170 | |
|---|
| 171 | -- dummy instances, need to be elaborated! |
|---|
| 172 | instance DocUtils.Pretty CspSign where |
|---|
| 173 | pretty = Doc.text . show |
|---|
| 174 | instance DocUtils.Pretty CspAddMorphism where |
|---|
| 175 | pretty = Doc.text . show |
|---|