| 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 | PROCESS(..), CommAlpha(..), CommType(..), TypedChanName(..)) |
|---|
| 21 | |
|---|
| 22 | import CspCASL.AS_CspCASL () |
|---|
| 23 | import CspCASL.Print_CspCASL |
|---|
| 24 | |
|---|
| 25 | import CASL.AS_Basic_CASL (FORMULA, SORT) |
|---|
| 26 | import CASL.Sign (emptySign, Sign, extendedInfo, sortRel) |
|---|
| 27 | import CASL.Morphism (Morphism) |
|---|
| 28 | |
|---|
| 29 | import Common.AS_Annotation (Named) |
|---|
| 30 | |
|---|
| 31 | import Common.Doc |
|---|
| 32 | import Common.DocUtils |
|---|
| 33 | |
|---|
| 34 | import Common.Id (Id, SIMPLE_ID, mkSimpleId, nullRange) |
|---|
| 35 | import Common.Lib.Rel (predecessors) |
|---|
| 36 | import Common.Result |
|---|
| 37 | |
|---|
| 38 | import Control.Monad (unless) |
|---|
| 39 | import qualified Data.Map as Map |
|---|
| 40 | import qualified Data.Set as Set |
|---|
| 41 | |
|---|
| 42 | -- | A process has zero or more parameter sorts, and a communication |
|---|
| 43 | -- alphabet. |
|---|
| 44 | data ProcProfile = ProcProfile [SORT] CommAlpha |
|---|
| 45 | deriving (Eq, Show) |
|---|
| 46 | |
|---|
| 47 | type ChanNameMap = Map.Map CHANNEL_NAME SORT |
|---|
| 48 | type ProcNameMap = Map.Map PROCESS_NAME ProcProfile |
|---|
| 49 | type ProcVarMap = Map.Map SIMPLE_ID SORT |
|---|
| 50 | type ProcVarList = [(SIMPLE_ID, SORT)] |
|---|
| 51 | |
|---|
| 52 | -- Close a communication alphabet under CASL subsort |
|---|
| 53 | closeCspCommAlpha :: CspCASLSign -> CommAlpha -> CommAlpha |
|---|
| 54 | closeCspCommAlpha sig = Set.unions . Set.toList . Set.map (closeOneCspComm sig) |
|---|
| 55 | |
|---|
| 56 | -- Close one CommType under CASL subsort |
|---|
| 57 | closeOneCspComm :: CspCASLSign -> CommType -> CommAlpha |
|---|
| 58 | closeOneCspComm sig x = let |
|---|
| 59 | mkTypedChan c s = CommTypeChan $ TypedChanName c s |
|---|
| 60 | subsorts s' = Set.singleton s' `Set.union` predecessors (sortRel sig) s' |
|---|
| 61 | in case x of |
|---|
| 62 | CommTypeSort s -> Set.map CommTypeSort (subsorts s) |
|---|
| 63 | CommTypeChan (TypedChanName c s) -> Set.map CommTypeSort (subsorts s) |
|---|
| 64 | `Set.union` Set.map (mkTypedChan c) (subsorts s) |
|---|
| 65 | |
|---|
| 66 | {- Will probably be useful, but doesn't appear to be right now. |
|---|
| 67 | |
|---|
| 68 | -- Extract the sorts from a process alphabet |
|---|
| 69 | procAlphaSorts :: CommAlpha -> Set.Set SORT |
|---|
| 70 | procAlphaSorts a = stripMaybe $ Set.map justSort a |
|---|
| 71 | where justSort n = case n of |
|---|
| 72 | (CommTypeSort s) -> Just s |
|---|
| 73 | _ -> Nothing |
|---|
| 74 | -- Extract the typed channel names from a process alphabet |
|---|
| 75 | procAlphaChans :: CommAlpha -> Set.Set TypedChanName |
|---|
| 76 | procAlphaChans a = stripMaybe $ Set.map justChan a |
|---|
| 77 | where justChan n = case n of |
|---|
| 78 | (CommTypeChan c) -> Just c |
|---|
| 79 | _ -> Nothing |
|---|
| 80 | -- Given a set of Maybes, filter to keep only the Justs |
|---|
| 81 | stripMaybe :: Ord a => Set.Set (Maybe a) -> Set.Set a |
|---|
| 82 | stripMaybe x = Set.fromList $ Maybe.catMaybes $ Set.toList x |
|---|
| 83 | |
|---|
| 84 | -- Close a set of sorts under a subsort relation |
|---|
| 85 | cspSubsortCloseSorts :: CspCASLSign -> Set.Set SORT -> Set.Set SORT |
|---|
| 86 | cspSubsortCloseSorts sig sorts = |
|---|
| 87 | Set.unions subsort_sets |
|---|
| 88 | where subsort_sets = Set.toList $ Set.map (cspSubsortPreds sig) sorts |
|---|
| 89 | |
|---|
| 90 | -} |
|---|
| 91 | |
|---|
| 92 | -- | CSP process signature. |
|---|
| 93 | data CspSign = CspSign |
|---|
| 94 | { chans :: ChanNameMap |
|---|
| 95 | , procSet :: ProcNameMap |
|---|
| 96 | -- | Added for uniformity to the CASL static analysis. After |
|---|
| 97 | -- static analysis this is the empty list. |
|---|
| 98 | , ccSentences :: [Named CspCASLSen] |
|---|
| 99 | } deriving (Eq, Show) |
|---|
| 100 | |
|---|
| 101 | -- | A CspCASL signature is a CASL signature with a CSP process |
|---|
| 102 | -- signature in the extendedInfo part. |
|---|
| 103 | type CspCASLSign = Sign () CspSign |
|---|
| 104 | |
|---|
| 105 | ccSig2CASLSign :: CspCASLSign -> Sign () () |
|---|
| 106 | ccSig2CASLSign sigma = sigma { extendedInfo = () } |
|---|
| 107 | |
|---|
| 108 | ccSig2CspSign :: CspCASLSign -> CspSign |
|---|
| 109 | ccSig2CspSign sigma = extendedInfo sigma |
|---|
| 110 | |
|---|
| 111 | -- | Empty CspCASL signature. |
|---|
| 112 | emptyCspCASLSign :: CspCASLSign |
|---|
| 113 | emptyCspCASLSign = emptySign emptyCspSign |
|---|
| 114 | |
|---|
| 115 | -- | Empty CSP process signature. |
|---|
| 116 | emptyCspSign :: CspSign |
|---|
| 117 | emptyCspSign = CspSign |
|---|
| 118 | { chans = Map.empty |
|---|
| 119 | , procSet = Map.empty |
|---|
| 120 | , ccSentences =[] |
|---|
| 121 | } |
|---|
| 122 | |
|---|
| 123 | -- | Compute union of two CSP process signatures. |
|---|
| 124 | addCspProcSig :: CspSign -> CspSign -> CspSign |
|---|
| 125 | addCspProcSig a b = |
|---|
| 126 | a { chans = chans a `Map.union` chans b |
|---|
| 127 | , procSet = procSet a `Map.union` procSet b |
|---|
| 128 | } |
|---|
| 129 | |
|---|
| 130 | -- XXX looks incomplete! |
|---|
| 131 | isInclusion :: CspSign -> CspSign -> Bool |
|---|
| 132 | isInclusion _ _ = True |
|---|
| 133 | |
|---|
| 134 | |
|---|
| 135 | -- XXX morphisms between CSP process signatures? |
|---|
| 136 | |
|---|
| 137 | data CspAddMorphism = CspAddMorphism |
|---|
| 138 | { channelMap :: Map.Map Id Id |
|---|
| 139 | , processMap :: Map.Map Id Id |
|---|
| 140 | } deriving (Eq, Show) |
|---|
| 141 | |
|---|
| 142 | composeIdMaps :: Map.Map Id Id -> Map.Map Id Id -> Map.Map Id Id |
|---|
| 143 | composeIdMaps m1 m2 = Map.foldWithKey (\ i j -> case Map.lookup j m2 of |
|---|
| 144 | Nothing -> error "SignCsp.composeIdMaps" |
|---|
| 145 | Just k -> Map.insert i k) Map.empty m1 |
|---|
| 146 | |
|---|
| 147 | composeCspAddMorphism :: CspAddMorphism -> CspAddMorphism |
|---|
| 148 | -> Result CspAddMorphism |
|---|
| 149 | composeCspAddMorphism m1 m2 = return emptyCspAddMorphism |
|---|
| 150 | { channelMap = composeIdMaps (channelMap m1) $ channelMap m2 |
|---|
| 151 | , processMap = composeIdMaps (processMap m1) $ processMap m2 } |
|---|
| 152 | |
|---|
| 153 | inverseCspAddMorphism :: CspAddMorphism -> Result CspAddMorphism |
|---|
| 154 | inverseCspAddMorphism cm = do |
|---|
| 155 | let chL = Map.toList $ channelMap cm |
|---|
| 156 | prL = Map.toList $ processMap cm |
|---|
| 157 | swap = map $ \ (a, b) -> (b, a) |
|---|
| 158 | isInj l = length l == Set.size (Set.fromList $ map snd l) |
|---|
| 159 | unless (isInj chL) $ fail "invertCspAddMorphism.channelMap" |
|---|
| 160 | unless (isInj prL) $ fail "invertCspAddMorphism.processMap" |
|---|
| 161 | return emptyCspAddMorphism |
|---|
| 162 | { channelMap = Map.fromList $ swap chL |
|---|
| 163 | , processMap = Map.fromList $ swap prL } |
|---|
| 164 | |
|---|
| 165 | type CspMorphism = Morphism () CspSign CspAddMorphism |
|---|
| 166 | |
|---|
| 167 | emptyCspAddMorphism :: CspAddMorphism |
|---|
| 168 | emptyCspAddMorphism = CspAddMorphism |
|---|
| 169 | { channelMap = Map.empty -- ??? |
|---|
| 170 | , processMap = Map.empty |
|---|
| 171 | } |
|---|
| 172 | |
|---|
| 173 | -- dummy instances, need to be elaborated! |
|---|
| 174 | instance Pretty CspSign where |
|---|
| 175 | pretty = text . show |
|---|
| 176 | instance Pretty CspAddMorphism where |
|---|
| 177 | pretty = text . show |
|---|
| 178 | |
|---|
| 179 | -- Sentences |
|---|
| 180 | |
|---|
| 181 | -- A CspCASl senetence is either a CASL formula or a Procsses |
|---|
| 182 | -- equation. A process equation has on the LHS a process name, a list |
|---|
| 183 | -- of parameters which are qualified variables (which are terms), a |
|---|
| 184 | -- constituent communication alphabet and finally on the RHS a fully |
|---|
| 185 | -- qualified process. |
|---|
| 186 | data CspCASLSen = CASLSen (FORMULA ()) |
|---|
| 187 | | ProcessEq PROCESS_NAME ProcVarList CommAlpha PROCESS |
|---|
| 188 | deriving (Show, Eq, Ord) |
|---|
| 189 | |
|---|
| 190 | instance Pretty CspCASLSen where |
|---|
| 191 | -- Not implemented yet - the pretty printing of the casl sentences |
|---|
| 192 | pretty(CASLSen _) = text "Pretty printing for CASLSen not implemented yet" |
|---|
| 193 | pretty(ProcessEq pn varList alpha proc) = |
|---|
| 194 | let varDoc = if (null varList) |
|---|
| 195 | then empty |
|---|
| 196 | else parens $ sepByCommas $ map pretty (map fst varList) |
|---|
| 197 | in pretty pn <+> varDoc <+> equals <+> pretty proc |
|---|
| 198 | |
|---|
| 199 | emptyCCSen :: CspCASLSen |
|---|
| 200 | emptyCCSen = |
|---|
| 201 | let emptyProcName = mkSimpleId "empty" |
|---|
| 202 | emptyVarList = [] |
|---|
| 203 | emptyAlphabet = Set.empty |
|---|
| 204 | emptyProc = Skip nullRange |
|---|
| 205 | in ProcessEq emptyProcName emptyVarList emptyAlphabet emptyProc |
|---|
| 206 | |
|---|
| 207 | isCASLSen :: CspCASLSen -> Bool |
|---|
| 208 | isCASLSen (CASLSen _) = True |
|---|
| 209 | isCASLSen _ = False |
|---|
| 210 | |
|---|
| 211 | isProcessEq :: CspCASLSen -> Bool |
|---|
| 212 | isProcessEq (ProcessEq _ _ _ _) = True |
|---|
| 213 | isProcessEq _ = False |
|---|
| 214 | |
|---|