| 1 | {- | |
|---|
| 2 | Module : $Header$ |
|---|
| 3 | Description : Symbols and signature morphisms for the CASL logic |
|---|
| 4 | Copyright : (c) Christian Maeder, Till Mossakowski and Uni Bremen 2002-2004 |
|---|
| 5 | License : similar to LGPL, see HetCATS/LICENSE.txt or LIZENZ.txt |
|---|
| 6 | |
|---|
| 7 | Maintainer : Christian.Maeder@dfki.de |
|---|
| 8 | Stability : provisional |
|---|
| 9 | Portability : portable |
|---|
| 10 | |
|---|
| 11 | Symbols and signature morphisms for the CASL logic |
|---|
| 12 | -} |
|---|
| 13 | |
|---|
| 14 | module CASL.Morphism where |
|---|
| 15 | |
|---|
| 16 | import CASL.Sign |
|---|
| 17 | import CASL.AS_Basic_CASL |
|---|
| 18 | |
|---|
| 19 | import qualified Data.Map as Map |
|---|
| 20 | import qualified Data.Set as Set |
|---|
| 21 | import qualified Common.Lib.Rel as Rel |
|---|
| 22 | import Common.Doc |
|---|
| 23 | import Common.DocUtils |
|---|
| 24 | import Common.Id |
|---|
| 25 | import Common.Result |
|---|
| 26 | |
|---|
| 27 | import Control.Exception (assert) |
|---|
| 28 | import Control.Monad |
|---|
| 29 | |
|---|
| 30 | type SymbolSet = Set.Set Symbol |
|---|
| 31 | type SymbolMap = Map.Map Symbol Symbol |
|---|
| 32 | |
|---|
| 33 | data RawSymbol = ASymbol Symbol | AKindedSymb SYMB_KIND Id |
|---|
| 34 | deriving (Show, Eq, Ord) |
|---|
| 35 | |
|---|
| 36 | instance GetRange RawSymbol where |
|---|
| 37 | getRange rs = case rs of |
|---|
| 38 | ASymbol s -> getRange s |
|---|
| 39 | AKindedSymb _ i -> getRange i |
|---|
| 40 | |
|---|
| 41 | type RawSymbolSet = Set.Set RawSymbol |
|---|
| 42 | type RawSymbolMap = Map.Map RawSymbol RawSymbol |
|---|
| 43 | |
|---|
| 44 | type Sort_map = Map.Map SORT SORT |
|---|
| 45 | -- always use the partial profile as key! |
|---|
| 46 | type Op_map = Map.Map (Id, OpType) (Id, OpKind) |
|---|
| 47 | type Pred_map = Map.Map (Id, PredType) Id |
|---|
| 48 | |
|---|
| 49 | data Morphism f e m = Morphism |
|---|
| 50 | { msource :: Sign f e |
|---|
| 51 | , mtarget :: Sign f e |
|---|
| 52 | , sort_map :: Sort_map |
|---|
| 53 | , op_map :: Op_map |
|---|
| 54 | , pred_map :: Pred_map |
|---|
| 55 | , extended_map :: m |
|---|
| 56 | } deriving (Show, Eq) |
|---|
| 57 | |
|---|
| 58 | data DefMorExt e = DefMorExt deriving (Show, Eq) |
|---|
| 59 | |
|---|
| 60 | emptyMorExt :: DefMorExt e |
|---|
| 61 | emptyMorExt = DefMorExt |
|---|
| 62 | |
|---|
| 63 | instance Pretty (DefMorExt e) where |
|---|
| 64 | pretty _ = empty |
|---|
| 65 | |
|---|
| 66 | type CASLMor = Morphism () () () |
|---|
| 67 | |
|---|
| 68 | isInclusionMorphism :: (m -> Bool) -> Morphism f e m -> Bool |
|---|
| 69 | isInclusionMorphism f m = f (extended_map m) && Map.null (sort_map m) |
|---|
| 70 | && Map.null (pred_map m) && isInclOpMap (op_map m) |
|---|
| 71 | |
|---|
| 72 | mapSort :: Sort_map -> SORT -> SORT |
|---|
| 73 | mapSort sorts s = Map.findWithDefault s s sorts |
|---|
| 74 | |
|---|
| 75 | mapOpType :: Sort_map -> OpType -> OpType |
|---|
| 76 | mapOpType sorts t = if Map.null sorts then t else |
|---|
| 77 | t { opArgs = map (mapSort sorts) $ opArgs t |
|---|
| 78 | , opRes = mapSort sorts $ opRes t } |
|---|
| 79 | |
|---|
| 80 | mapOpTypeK :: Sort_map -> OpKind -> OpType -> OpType |
|---|
| 81 | mapOpTypeK sorts k = makeTotal k . mapOpType sorts |
|---|
| 82 | |
|---|
| 83 | makeTotal :: OpKind -> OpType -> OpType |
|---|
| 84 | makeTotal fk t = case fk of |
|---|
| 85 | Total -> t { opKind = Total } |
|---|
| 86 | _ -> t |
|---|
| 87 | |
|---|
| 88 | mapOpSym :: Sort_map -> Op_map -> (Id, OpType) -> (Id, OpType) |
|---|
| 89 | mapOpSym sMap oMap (i, ot) = let mot = mapOpType sMap ot in |
|---|
| 90 | case Map.lookup (i, ot {opKind = Partial} ) oMap of |
|---|
| 91 | Nothing -> (i, mot) |
|---|
| 92 | Just (j, k) -> (j, makeTotal k mot) |
|---|
| 93 | |
|---|
| 94 | -- | Check if two OpTypes are equal modulo totality or partiality |
|---|
| 95 | compatibleOpTypes :: OpType -> OpType -> Bool |
|---|
| 96 | compatibleOpTypes ot1 ot2 = opArgs ot1 == opArgs ot2 && opRes ot1 == opRes ot2 |
|---|
| 97 | |
|---|
| 98 | mapPredType :: Sort_map -> PredType -> PredType |
|---|
| 99 | mapPredType sorts t = if Map.null sorts then t else |
|---|
| 100 | t { predArgs = map (mapSort sorts) $ predArgs t } |
|---|
| 101 | |
|---|
| 102 | mapPredSym :: Sort_map -> Pred_map -> (Id, PredType) -> (Id, PredType) |
|---|
| 103 | mapPredSym sMap oMap (i, pt) = |
|---|
| 104 | (Map.findWithDefault i (i, pt) oMap, mapPredType sMap pt) |
|---|
| 105 | |
|---|
| 106 | embedMorphism :: m -> Sign f e -> Sign f e -> Morphism f e m |
|---|
| 107 | embedMorphism extEm a b = Morphism |
|---|
| 108 | { msource = a |
|---|
| 109 | , mtarget = b |
|---|
| 110 | , sort_map = Map.empty |
|---|
| 111 | , op_map = Map.empty |
|---|
| 112 | , pred_map = Map.empty |
|---|
| 113 | , extended_map = extEm } |
|---|
| 114 | |
|---|
| 115 | symbTypeToKind :: SymbType -> SYMB_KIND |
|---|
| 116 | symbTypeToKind st = case st of |
|---|
| 117 | OpAsItemType _ -> Ops_kind |
|---|
| 118 | PredAsItemType _ -> Preds_kind |
|---|
| 119 | SortAsItemType -> Sorts_kind |
|---|
| 120 | |
|---|
| 121 | symbolToRaw :: Symbol -> RawSymbol |
|---|
| 122 | symbolToRaw = ASymbol |
|---|
| 123 | |
|---|
| 124 | idToRaw :: Id -> RawSymbol |
|---|
| 125 | idToRaw = AKindedSymb Implicit |
|---|
| 126 | |
|---|
| 127 | rawSymName :: RawSymbol -> Id |
|---|
| 128 | rawSymName rs = case rs of |
|---|
| 129 | ASymbol sym -> symName sym |
|---|
| 130 | AKindedSymb _ i -> i |
|---|
| 131 | |
|---|
| 132 | symOf :: Sign f e -> SymbolSet |
|---|
| 133 | symOf sigma = let |
|---|
| 134 | sorts = Set.map idToSortSymbol $ sortSet sigma |
|---|
| 135 | ops = Set.fromList $ |
|---|
| 136 | concatMap (\ (i, ts) -> map ( \ t -> idToOpSymbol i t) $ Set.toList ts) |
|---|
| 137 | $ Map.toList $ opMap sigma |
|---|
| 138 | preds = Set.fromList $ |
|---|
| 139 | concatMap (\ (i, ts) -> map ( \ t -> idToPredSymbol i t) |
|---|
| 140 | $ Set.toList ts) $ Map.toList $ predMap sigma |
|---|
| 141 | in Set.unions [sorts, ops, preds] |
|---|
| 142 | |
|---|
| 143 | checkSymbList :: [SYMB_OR_MAP] -> [Diagnosis] |
|---|
| 144 | checkSymbList l = case l of |
|---|
| 145 | Symb (Symb_id a) : Symb (Qual_id b t _) : r -> mkDiag Warning |
|---|
| 146 | ("profile '" ++ showDoc t "' does not apply to '" |
|---|
| 147 | ++ showId a "' but only to") b : checkSymbList r |
|---|
| 148 | _ : r -> checkSymbList r |
|---|
| 149 | [] -> [] |
|---|
| 150 | |
|---|
| 151 | statSymbMapItems :: [SYMB_MAP_ITEMS] -> Result RawSymbolMap |
|---|
| 152 | statSymbMapItems sl = do |
|---|
| 153 | let st (Symb_map_items kind l _) = do |
|---|
| 154 | appendDiags $ checkSymbList l |
|---|
| 155 | fmap concat $ mapM (symbOrMapToRaw kind) l |
|---|
| 156 | insertRsys m1 (rsy1, rsy2) = case Map.lookup rsy1 m1 of |
|---|
| 157 | Nothing -> return $ Map.insert rsy1 rsy2 m1 |
|---|
| 158 | Just rsy3 -> if rsy2 == rsy3 then return m1 else |
|---|
| 159 | plain_error m1 ("Symbol " ++ showDoc rsy1 " mapped twice to " |
|---|
| 160 | ++ showDoc rsy2 " and " ++ showDoc rsy3 "") nullRange |
|---|
| 161 | ls <- mapM st sl |
|---|
| 162 | foldM insertRsys Map.empty (concat ls) |
|---|
| 163 | |
|---|
| 164 | symbOrMapToRaw :: SYMB_KIND -> SYMB_OR_MAP -> Result [(RawSymbol, RawSymbol)] |
|---|
| 165 | symbOrMapToRaw k sm = do |
|---|
| 166 | case sm of |
|---|
| 167 | Symb s -> do |
|---|
| 168 | v <- symbToRaw k s |
|---|
| 169 | return [(v, v)] |
|---|
| 170 | Symb_map s t _ -> do |
|---|
| 171 | appendDiags $ case (s, t) of |
|---|
| 172 | (Symb_id a, Symb_id b) | a == b -> |
|---|
| 173 | [mkDiag Hint "unneeded identical mapping of" a] |
|---|
| 174 | _ -> [] |
|---|
| 175 | w <- symbToRaw k s |
|---|
| 176 | x <- symbToRaw k t |
|---|
| 177 | let mkS = AKindedSymb Sorts_kind |
|---|
| 178 | case (s, t) of |
|---|
| 179 | (Qual_id _ t1 _, Qual_id _ t2 _) -> case (t1, t2) of |
|---|
| 180 | (O_type (Op_type k1 args1 res1 _), O_type (Op_type k2 args2 res2 _)) |
|---|
| 181 | | length args1 == length args2 && k2 <= k1 -> |
|---|
| 182 | return $ (w, x) : (mkS res1, mkS res2) |
|---|
| 183 | : zipWith (\ s1 s2 -> (mkS s1, mkS s2)) args1 args2 |
|---|
| 184 | (P_type (Pred_type args1 _), P_type (Pred_type args2 _)) |
|---|
| 185 | | length args1 == length args2 -> |
|---|
| 186 | return $ (w, x) |
|---|
| 187 | : zipWith (\ s1 s2 -> (mkS s1, mkS s2)) args1 args2 |
|---|
| 188 | (O_type (Op_type Partial [] res1 _), A_type s2) -> |
|---|
| 189 | return [(w, x), (mkS res1, mkS s2)] |
|---|
| 190 | _ -> fail $ "profiles '" ++ showDoc t1 "' and '" |
|---|
| 191 | ++ showDoc t2 "' do not match" |
|---|
| 192 | _ -> return [(w, x)] |
|---|
| 193 | |
|---|
| 194 | statSymbItems :: [SYMB_ITEMS] -> Result [RawSymbol] |
|---|
| 195 | statSymbItems sl = |
|---|
| 196 | let st (Symb_items kind l _) = do |
|---|
| 197 | appendDiags $ checkSymbList $ map Symb l |
|---|
| 198 | mapM (symbToRaw kind) l |
|---|
| 199 | in fmap concat (mapM st sl) |
|---|
| 200 | |
|---|
| 201 | symbToRaw :: SYMB_KIND -> SYMB -> Result RawSymbol |
|---|
| 202 | symbToRaw k si = case si of |
|---|
| 203 | Symb_id idt -> return $ AKindedSymb k idt |
|---|
| 204 | Qual_id idt t _ -> typedSymbKindToRaw k idt t |
|---|
| 205 | |
|---|
| 206 | typedSymbKindToRaw :: SYMB_KIND -> Id -> TYPE -> Result RawSymbol |
|---|
| 207 | typedSymbKindToRaw k idt t = let |
|---|
| 208 | err = plain_error (AKindedSymb Implicit idt) |
|---|
| 209 | (showDoc idt ":" ++ showDoc t |
|---|
| 210 | "does not have kind" ++ showDoc k "") nullRange |
|---|
| 211 | aSymb = ASymbol $ case t of |
|---|
| 212 | O_type ot -> idToOpSymbol idt $ toOpType ot |
|---|
| 213 | P_type pt -> idToPredSymbol idt $ toPredType pt |
|---|
| 214 | -- in case of ambiguity, return a constant function type |
|---|
| 215 | -- this deviates from the CASL summary !!! |
|---|
| 216 | A_type s -> |
|---|
| 217 | let ot = OpType {opKind = Total, opArgs = [], opRes = s} |
|---|
| 218 | in idToOpSymbol idt ot |
|---|
| 219 | in case k of |
|---|
| 220 | Implicit -> case t of |
|---|
| 221 | A_type _ -> do |
|---|
| 222 | appendDiags [mkDiag Warning "qualify name as pred or op" idt] |
|---|
| 223 | return aSymb |
|---|
| 224 | _ -> return aSymb |
|---|
| 225 | Sorts_kind -> err |
|---|
| 226 | Ops_kind -> case t of |
|---|
| 227 | P_type _ -> err |
|---|
| 228 | _ -> return aSymb |
|---|
| 229 | Preds_kind -> case t of |
|---|
| 230 | O_type _ -> err |
|---|
| 231 | A_type s -> return $ ASymbol $ |
|---|
| 232 | let pt = PredType {predArgs = [s]} |
|---|
| 233 | in idToPredSymbol idt pt |
|---|
| 234 | P_type _ -> return aSymb |
|---|
| 235 | |
|---|
| 236 | symbMapToMorphism :: m -> Sign f e -> Sign f e |
|---|
| 237 | -> SymbolMap -> Result (Morphism f e m) |
|---|
| 238 | symbMapToMorphism extEm sigma1 sigma2 smap = let |
|---|
| 239 | sort_map1 = Set.fold mapMSort Map.empty (sortSet sigma1) |
|---|
| 240 | mapMSort s m = |
|---|
| 241 | case Map.lookup Symbol {symName = s, symbType = SortAsItemType} smap |
|---|
| 242 | of Just sym -> let t = symName sym in if s == t then m else |
|---|
| 243 | Map.insert s t m |
|---|
| 244 | Nothing -> m |
|---|
| 245 | op_map1 = Map.foldWithKey mapOp Map.empty (opMap sigma1) |
|---|
| 246 | pred_map1 = Map.foldWithKey mapPred Map.empty (predMap sigma1) |
|---|
| 247 | mapOp i ots m = Set.fold (insOp i) m ots |
|---|
| 248 | insOp i ot m = |
|---|
| 249 | case Map.lookup Symbol {symName = i, symbType = OpAsItemType ot} smap |
|---|
| 250 | of Just sym -> let j = symName sym in case symbType sym of |
|---|
| 251 | OpAsItemType oty -> let k = opKind oty in |
|---|
| 252 | if j == i && opKind ot == k then m |
|---|
| 253 | else Map.insert (i, ot {opKind = Partial}) (j, k) m |
|---|
| 254 | _ -> m |
|---|
| 255 | _ -> m |
|---|
| 256 | mapPred i pts m = Set.fold (insPred i) m pts |
|---|
| 257 | insPred i pt m = |
|---|
| 258 | case Map.lookup Symbol {symName = i, symbType = PredAsItemType pt} smap |
|---|
| 259 | of Just sym -> let j = symName sym in case symbType sym of |
|---|
| 260 | PredAsItemType _ -> if i == j then m else Map.insert (i, pt) j m |
|---|
| 261 | _ -> m |
|---|
| 262 | _ -> m |
|---|
| 263 | in return (embedMorphism extEm sigma1 sigma2) |
|---|
| 264 | { sort_map = sort_map1 |
|---|
| 265 | , op_map = op_map1 |
|---|
| 266 | , pred_map = pred_map1 } |
|---|
| 267 | |
|---|
| 268 | morphismToSymbMap :: Morphism f e m -> SymbolMap |
|---|
| 269 | morphismToSymbMap = morphismToSymbMapAux False |
|---|
| 270 | |
|---|
| 271 | morphismToSymbMapAux :: Bool -> Morphism f e m -> SymbolMap |
|---|
| 272 | morphismToSymbMapAux b mor = let |
|---|
| 273 | src = msource mor |
|---|
| 274 | sorts = sort_map mor |
|---|
| 275 | ops = op_map mor |
|---|
| 276 | preds = pred_map mor |
|---|
| 277 | sortSymMap = Set.fold |
|---|
| 278 | (\ s -> let t = mapSort sorts s in |
|---|
| 279 | if b && s == t then id else |
|---|
| 280 | Map.insert (idToSortSymbol s) $ idToSortSymbol t) |
|---|
| 281 | Map.empty $ sortSet src |
|---|
| 282 | opSymMap = Map.foldWithKey |
|---|
| 283 | ( \ i s m -> Set.fold |
|---|
| 284 | ( \ t -> let (j, k) = mapOpSym sorts ops (i, t) in |
|---|
| 285 | if b && i == j && opKind k == opKind t then id else |
|---|
| 286 | Map.insert (idToOpSymbol i t) $ idToOpSymbol j k) |
|---|
| 287 | m s) Map.empty $ opMap src |
|---|
| 288 | predSymMap = Map.foldWithKey |
|---|
| 289 | ( \ i s m -> Set.fold |
|---|
| 290 | ( \ t -> let (j, k) = mapPredSym sorts preds (i, t) in |
|---|
| 291 | if b && i == j then id else |
|---|
| 292 | Map.insert (idToPredSymbol i t) $ idToPredSymbol j k) |
|---|
| 293 | m s) Map.empty $ predMap src |
|---|
| 294 | in foldr Map.union sortSymMap [opSymMap, predSymMap] |
|---|
| 295 | |
|---|
| 296 | matches :: Symbol -> RawSymbol -> Bool |
|---|
| 297 | matches x@(Symbol idt k) rs = case rs of |
|---|
| 298 | ASymbol y -> x == y |
|---|
| 299 | AKindedSymb rk di -> let res = idt == di in case (k, rk) of |
|---|
| 300 | (_, Implicit) -> res |
|---|
| 301 | (SortAsItemType, Sorts_kind) -> res |
|---|
| 302 | (OpAsItemType _, Ops_kind) -> res |
|---|
| 303 | (PredAsItemType _, Preds_kind) -> res |
|---|
| 304 | _ -> False |
|---|
| 305 | |
|---|
| 306 | idMor :: m -> Sign f e -> Morphism f e m |
|---|
| 307 | idMor extEm sigma = embedMorphism extEm sigma sigma |
|---|
| 308 | |
|---|
| 309 | composeM :: (Eq e, Eq f) => (m -> m -> Result m) |
|---|
| 310 | -> Morphism f e m -> Morphism f e m -> Result (Morphism f e m) |
|---|
| 311 | composeM comp mor1 mor2 = if mtarget mor1 == msource mor2 then do |
|---|
| 312 | let sMap1 = sort_map mor1 |
|---|
| 313 | src = msource mor1 |
|---|
| 314 | tar = mtarget mor2 |
|---|
| 315 | oMap1 = op_map mor1 |
|---|
| 316 | pMap1 = pred_map mor1 |
|---|
| 317 | sMap2 = sort_map mor2 |
|---|
| 318 | oMap2 = op_map mor2 |
|---|
| 319 | pMap2 = pred_map mor2 |
|---|
| 320 | sMap = if Map.null sMap2 then sMap1 else Set.fold ( \ i -> |
|---|
| 321 | let j = mapSort sMap2 (mapSort sMap1 i) in |
|---|
| 322 | if i == j then id else Map.insert i j) |
|---|
| 323 | Map.empty $ sortSet src |
|---|
| 324 | oMap = if Map.null oMap2 then oMap1 else |
|---|
| 325 | Map.foldWithKey ( \ i t m -> |
|---|
| 326 | Set.fold ( \ ot -> |
|---|
| 327 | let (ni, nt) = mapOpSym sMap2 oMap2 $ |
|---|
| 328 | mapOpSym sMap1 oMap1 (i, ot) |
|---|
| 329 | k = opKind nt |
|---|
| 330 | in assert (mapOpTypeK sMap k ot == nt) $ |
|---|
| 331 | if i == ni && opKind ot == k then id else |
|---|
| 332 | Map.insert (i, ot {opKind = Partial }) (ni, k)) m t) |
|---|
| 333 | Map.empty $ opMap src |
|---|
| 334 | pMap = if Map.null pMap2 then pMap1 else |
|---|
| 335 | Map.foldWithKey ( \ i t m -> |
|---|
| 336 | Set.fold ( \ pt -> |
|---|
| 337 | let (ni, nt) = mapPredSym sMap2 pMap2 $ |
|---|
| 338 | mapPredSym sMap1 pMap1 (i, pt) |
|---|
| 339 | in assert (mapPredType sMap pt == nt) $ |
|---|
| 340 | if i == ni then id else Map.insert (i, pt) ni) m t) |
|---|
| 341 | Map.empty $ predMap src |
|---|
| 342 | extComp <- comp (extended_map mor1) $ extended_map mor2 |
|---|
| 343 | let emb = embedMorphism extComp src tar |
|---|
| 344 | return $ emb |
|---|
| 345 | { sort_map = sMap |
|---|
| 346 | , op_map = oMap |
|---|
| 347 | , pred_map = pMap } |
|---|
| 348 | else fail "target of first and source of second morphism are different" |
|---|
| 349 | |
|---|
| 350 | legalSign :: Sign f e -> Bool |
|---|
| 351 | legalSign sigma = |
|---|
| 352 | Map.foldWithKey (\s sset b -> b && legalSort s && all legalSort |
|---|
| 353 | (Set.toList sset)) |
|---|
| 354 | True (Rel.toMap (sortRel sigma)) |
|---|
| 355 | && Map.fold (\ts b -> b && all legalOpType (Set.toList ts)) |
|---|
| 356 | True (opMap sigma) |
|---|
| 357 | && Map.fold (\ts b -> b && all legalPredType (Set.toList ts)) |
|---|
| 358 | True (predMap sigma) |
|---|
| 359 | where sorts = sortSet sigma |
|---|
| 360 | legalSort s = Set.member s sorts |
|---|
| 361 | legalOpType t = legalSort (opRes t) |
|---|
| 362 | && all legalSort (opArgs t) |
|---|
| 363 | legalPredType = all legalSort . predArgs |
|---|
| 364 | |
|---|
| 365 | -- | the image of a signature morphism |
|---|
| 366 | imageOfMorphism :: Morphism f e m -> Sign f e |
|---|
| 367 | imageOfMorphism mor = |
|---|
| 368 | let src = msource mor |
|---|
| 369 | sm = sort_map mor |
|---|
| 370 | om = op_map mor |
|---|
| 371 | ms = mapSort sm |
|---|
| 372 | msorts = Set.map ms |
|---|
| 373 | in (mtarget mor) |
|---|
| 374 | { sortSet = msorts $ sortSet src |
|---|
| 375 | , sortRel = Rel.map ms $ sortRel src |
|---|
| 376 | , emptySortSet = msorts $ emptySortSet src |
|---|
| 377 | , opMap = inducedOpMap sm om $ opMap src |
|---|
| 378 | , assocOps = inducedOpMap sm om $ assocOps src |
|---|
| 379 | , predMap = inducedPredMap sm (pred_map mor) $ predMap src } |
|---|
| 380 | |
|---|
| 381 | inducedOpMap :: Sort_map -> Op_map -> OpMap -> OpMap |
|---|
| 382 | inducedOpMap sm fm = Map.foldWithKey |
|---|
| 383 | ( \ i -> flip $ Set.fold ( \ ot -> |
|---|
| 384 | let (j, nt) = mapOpSym sm fm (i, ot) |
|---|
| 385 | in Rel.setInsert j nt)) Map.empty |
|---|
| 386 | |
|---|
| 387 | inducedPredMap :: Sort_map -> Pred_map -> Map.Map Id (Set.Set PredType) |
|---|
| 388 | -> Map.Map Id (Set.Set PredType) |
|---|
| 389 | inducedPredMap sm pm = Map.foldWithKey |
|---|
| 390 | ( \ i -> flip $ Set.fold ( \ ot -> |
|---|
| 391 | let (j, nt) = mapPredSym sm pm (i, ot) |
|---|
| 392 | in Rel.setInsert j nt)) Map.empty |
|---|
| 393 | |
|---|
| 394 | legalMor :: Morphism f e m -> Bool |
|---|
| 395 | legalMor mor = |
|---|
| 396 | let s1 = msource mor |
|---|
| 397 | s2 = mtarget mor |
|---|
| 398 | sm = sort_map mor |
|---|
| 399 | msorts = Set.map $ mapSort sm |
|---|
| 400 | in legalSign s1 |
|---|
| 401 | && Set.isSubsetOf (msorts $ sortSet s1) (sortSet s2) |
|---|
| 402 | && Set.isSubsetOf (msorts $ emptySortSet s1) (emptySortSet s2) |
|---|
| 403 | && isSubOpMap (inducedOpMap sm (op_map mor) $ opMap s1) (opMap s2) |
|---|
| 404 | && isSubMapSet (inducedPredMap sm (pred_map mor) $ predMap s1) (predMap s2) |
|---|
| 405 | && legalSign s2 |
|---|
| 406 | |
|---|
| 407 | isInclOpMap :: Op_map -> Bool |
|---|
| 408 | isInclOpMap = all (\ ((i, _), (j, k)) -> i == j && k == Total) . Map.toList |
|---|
| 409 | |
|---|
| 410 | idOrInclMorphism :: (e -> e -> Bool) -> Morphism f e m -> Morphism f e m |
|---|
| 411 | idOrInclMorphism isSubExt m = |
|---|
| 412 | let src = msource m |
|---|
| 413 | tar = mtarget m |
|---|
| 414 | in if isSubSig isSubExt tar src then m |
|---|
| 415 | else let diffOpMap = diffMapSet (opMap src) $ opMap tar in |
|---|
| 416 | m { op_map = Map.fromList $ concatMap (\ (i, s) -> |
|---|
| 417 | map (\ t -> ((i, t), (i, Total))) |
|---|
| 418 | $ Set.toList s) $ Map.toList diffOpMap } |
|---|
| 419 | |
|---|
| 420 | sigInclusion :: (Pretty f, Pretty e) |
|---|
| 421 | => m -- ^ computed extended morphism |
|---|
| 422 | -> (e -> e -> Bool) -- ^ subsignature test of extensions |
|---|
| 423 | -> (e -> e -> e) -- ^ difference of signature extensions |
|---|
| 424 | -> Sign f e -> Sign f e -> Result (Morphism f e m) |
|---|
| 425 | sigInclusion extEm isSubExt diffExt sigma1 sigma2 = |
|---|
| 426 | if isSubSig isSubExt sigma1 sigma2 then |
|---|
| 427 | return $ idOrInclMorphism isSubExt $ embedMorphism extEm sigma1 sigma2 |
|---|
| 428 | else Result [Diag Error |
|---|
| 429 | ("Attempt to construct inclusion between non-subsignatures:\n" |
|---|
| 430 | ++ showDoc (diffSig diffExt sigma1 sigma2) "") nullRange] Nothing |
|---|
| 431 | |
|---|
| 432 | addSigM :: Monad m => (e -> e -> m e) -> Sign f e -> Sign f e -> m (Sign f e) |
|---|
| 433 | addSigM f a b = do |
|---|
| 434 | e <- f (extendedInfo a) $ extendedInfo b |
|---|
| 435 | return $ addSig (const $ const e) a b |
|---|
| 436 | |
|---|
| 437 | morphismUnion :: (m -> m -> m) -- ^ join morphism extensions |
|---|
| 438 | -> (e -> e -> e) -- ^ join signature extensions |
|---|
| 439 | -> Morphism f e m -> Morphism f e m -> Result (Morphism f e m) |
|---|
| 440 | morphismUnion uniteM addSigExt = |
|---|
| 441 | morphismUnionM uniteM (\ e -> return . addSigExt e) |
|---|
| 442 | |
|---|
| 443 | morphismUnionM :: (m -> m -> m) -- ^ join morphism extensions |
|---|
| 444 | -> (e -> e -> Result e) -- ^ join signature extensions |
|---|
| 445 | -> Morphism f e m -> Morphism f e m -> Result (Morphism f e m) |
|---|
| 446 | -- consider identity mappings but filter them eventually |
|---|
| 447 | morphismUnionM uniteM addSigExt mor1 mor2 = |
|---|
| 448 | let smap1 = sort_map mor1 |
|---|
| 449 | smap2 = sort_map mor2 |
|---|
| 450 | s1 = msource mor1 |
|---|
| 451 | s2 = msource mor2 |
|---|
| 452 | us1 = Set.difference (sortSet s1) $ Map.keysSet smap1 |
|---|
| 453 | us2 = Set.difference (sortSet s2) $ Map.keysSet smap2 |
|---|
| 454 | omap1 = op_map mor1 |
|---|
| 455 | omap2 = op_map mor2 |
|---|
| 456 | uo1 = foldr delOp (opMap s1) $ Map.keys omap1 |
|---|
| 457 | uo2 = foldr delOp (opMap s2) $ Map.keys omap2 |
|---|
| 458 | delOp (n, ot) m = diffMapSet m $ Map.singleton n $ |
|---|
| 459 | Set.fromList [ot {opKind = Partial}, ot {opKind = Total}] |
|---|
| 460 | uo = addOpMapSet uo1 uo2 |
|---|
| 461 | pmap1 = pred_map mor1 |
|---|
| 462 | pmap2 = pred_map mor2 |
|---|
| 463 | up1 = foldr delPred (predMap s1) $ Map.keys pmap1 |
|---|
| 464 | up2 = foldr delPred (predMap s2) $ Map.keys pmap2 |
|---|
| 465 | up = addMapSet up1 up2 |
|---|
| 466 | delPred (n, pt) m = diffMapSet m $ Map.singleton n $ Set.singleton pt |
|---|
| 467 | (sds, smap) = foldr ( \ (i, j) (ds, m) -> case Map.lookup i m of |
|---|
| 468 | Nothing -> (ds, Map.insert i j m) |
|---|
| 469 | Just k -> if j == k then (ds, m) else |
|---|
| 470 | (Diag Error |
|---|
| 471 | ("incompatible mapping of sort " ++ showId i " to " |
|---|
| 472 | ++ showId j " and " ++ showId k "") |
|---|
| 473 | nullRange : ds, m)) ([], smap1) |
|---|
| 474 | (Map.toList smap2 ++ map (\ a -> (a, a)) |
|---|
| 475 | (Set.toList $ Set.union us1 us2)) |
|---|
| 476 | (ods, omap) = foldr ( \ (isc@(i, ot), jsc@(j, t)) (ds, m) -> |
|---|
| 477 | case Map.lookup isc m of |
|---|
| 478 | Nothing -> (ds, Map.insert isc jsc m) |
|---|
| 479 | Just (k, p) -> if j == k then if p == t then (ds, m) |
|---|
| 480 | else (ds, Map.insert isc (j, Total) m) else |
|---|
| 481 | (Diag Error |
|---|
| 482 | ("incompatible mapping of op " ++ showId i ":" |
|---|
| 483 | ++ showDoc ot { opKind = t } " to " |
|---|
| 484 | ++ showId j " and " ++ showId k "") nullRange : ds, m)) |
|---|
| 485 | (sds, omap1) (Map.toList omap2 ++ concatMap |
|---|
| 486 | ( \ (a, s) -> map ( \ ot -> ((a, ot {opKind = Partial}), |
|---|
| 487 | (a, opKind ot))) |
|---|
| 488 | $ Set.toList s) (Map.toList uo)) |
|---|
| 489 | (pds, pmap) = foldr ( \ (isc@(i, pt), j) (ds, m) -> |
|---|
| 490 | case Map.lookup isc m of |
|---|
| 491 | Nothing -> (ds, Map.insert isc j m) |
|---|
| 492 | Just k -> if j == k then (ds, m) else |
|---|
| 493 | (Diag Error |
|---|
| 494 | ("incompatible mapping of pred " ++ showId i ":" |
|---|
| 495 | ++ showDoc pt " to " ++ showId j " and " |
|---|
| 496 | ++ showId k "") nullRange : ds, m)) (ods, pmap1) |
|---|
| 497 | (Map.toList pmap2 ++ concatMap ( \ (a, s) -> map |
|---|
| 498 | ( \ pt -> ((a, pt), a)) $ Set.toList s) (Map.toList up)) |
|---|
| 499 | in if null pds then do |
|---|
| 500 | s3 <- addSigM addSigExt s1 s2 |
|---|
| 501 | s4 <- addSigM addSigExt (mtarget mor1) $ mtarget mor2 |
|---|
| 502 | let o3 = opMap s3 |
|---|
| 503 | return |
|---|
| 504 | (embedMorphism (uniteM (extended_map mor1) $ extended_map mor2) s3 s4) |
|---|
| 505 | { sort_map = Map.filterWithKey (/=) smap |
|---|
| 506 | , op_map = Map.filterWithKey |
|---|
| 507 | (\ (i, ot) (j, k) -> i /= j || k == Total && Set.member ot |
|---|
| 508 | (Map.findWithDefault Set.empty i o3)) omap |
|---|
| 509 | , pred_map = Map.filterWithKey (\ (i, _) j -> i /= j) pmap } |
|---|
| 510 | else Result pds Nothing |
|---|
| 511 | |
|---|
| 512 | isSortInjective :: Morphism f e m -> Bool |
|---|
| 513 | isSortInjective m = |
|---|
| 514 | let ss = sortSet $ msource m |
|---|
| 515 | in Set.size ss == Set.size (Set.map (mapSort $ sort_map m) ss) |
|---|
| 516 | |
|---|
| 517 | sumSize :: Map.Map a (Set.Set b) -> Int |
|---|
| 518 | sumSize = sum . map Set.size . Map.elems |
|---|
| 519 | |
|---|
| 520 | -- morphism extension m is not considered here |
|---|
| 521 | isInjective :: Morphism f e m -> Bool |
|---|
| 522 | isInjective m = isSortInjective m && let |
|---|
| 523 | src = msource m |
|---|
| 524 | sm = sort_map m |
|---|
| 525 | os = opMap src |
|---|
| 526 | ps = predMap src |
|---|
| 527 | in sumSize os == sumSize (inducedOpMap sm (op_map m) os) |
|---|
| 528 | && sumSize ps == sumSize (inducedPredMap sm (pred_map m) ps) |
|---|
| 529 | |
|---|
| 530 | instance Pretty RawSymbol where |
|---|
| 531 | pretty rsym = case rsym of |
|---|
| 532 | ASymbol sy -> pretty sy |
|---|
| 533 | AKindedSymb k i -> pretty k <+> pretty i |
|---|
| 534 | |
|---|
| 535 | printMorphism :: (f -> Doc) -> (e -> Doc) -> (m -> Doc) -> Morphism f e m |
|---|
| 536 | -> Doc |
|---|
| 537 | printMorphism fF fE fM mor = |
|---|
| 538 | let src = msource mor |
|---|
| 539 | tar = mtarget mor |
|---|
| 540 | ops = op_map mor |
|---|
| 541 | prSig s = specBraces (space <> printSign fF fE s) |
|---|
| 542 | srcD = prSig src |
|---|
| 543 | in if isInclusionMorphism (const True) mor then |
|---|
| 544 | if isSubSig (\ _ _ -> True) tar src then |
|---|
| 545 | fsep [text "identity morphism over", srcD] |
|---|
| 546 | else fsep |
|---|
| 547 | [ text "inclusion morphism of", srcD |
|---|
| 548 | , fsep $ if Map.null ops then |
|---|
| 549 | [ text "extended with" |
|---|
| 550 | , pretty $ Set.difference (symOf tar) $ symOf src ] |
|---|
| 551 | else |
|---|
| 552 | [ text "by totalizing" |
|---|
| 553 | , pretty $ Set.map (uncurry idToOpSymbol) $ Map.keysSet ops ]] |
|---|
| 554 | else fsep |
|---|
| 555 | [ pretty (morphismToSymbMapAux True mor) |
|---|
| 556 | $+$ fM (extended_map mor) |
|---|
| 557 | , colon <+> srcD, mapsto <+> prSig tar ] |
|---|
| 558 | |
|---|
| 559 | instance (Pretty e, Pretty f, Pretty m) => |
|---|
| 560 | Pretty (Morphism f e m) where |
|---|
| 561 | pretty = printMorphism pretty pretty pretty |
|---|