root/trunk/CASL/Sign.hs @ 11216

Revision 11216, 15.0 kB (checked in by maeder, 11 months ago)

extended symbol kinds i.e. for CspCASL

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1{- |
2Module      :  $Header$
3Description :  CASL signatures and local environments for basic analysis
4Copyright   :  (c) Christian Maeder and Uni Bremen 2002-2006
5License     :  similar to LGPL, see HetCATS/LICENSE.txt or LIZENZ.txt
6
7Maintainer  :  Christian.Maeder@dfki.de
8Stability   :  provisional
9Portability :  portable
10
11CASL signatures also serve as local environments for the basic static analysis
12-}
13
14module CASL.Sign where
15
16import CASL.AS_Basic_CASL
17import CASL.ToDoc ()
18import qualified Data.Map as Map
19import qualified Data.Set as Set
20import qualified Common.Lib.Rel as Rel
21import qualified Common.Lib.State as State
22import Common.Keywords
23import Common.Id
24import Common.Result
25import Common.AS_Annotation
26import Common.GlobalAnnotations
27import Common.Doc
28import Common.DocUtils
29
30import Data.List (isPrefixOf)
31import Control.Monad (when, unless)
32
33-- constants have empty argument lists
34data OpType = OpType {opKind :: OpKind, opArgs :: [SORT], opRes :: SORT}
35              deriving (Show, Eq, Ord)
36
37data PredType = PredType {predArgs :: [SORT]} deriving (Show, Eq, Ord)
38
39type OpMap = Map.Map Id (Set.Set OpType)
40
41data SymbType = SortAsItemType
42              | OtherTypeKind String
43              | OpAsItemType OpType
44                -- since symbols do not speak about totality, the totality
45                -- information in OpType has to be ignored
46              | PredAsItemType PredType
47                deriving (Show, Eq, Ord)
48
49data Symbol = Symbol {symName :: Id, symbType :: SymbType}
50              deriving (Show, Eq, Ord)
51
52instance GetRange Symbol where
53    getRange = getRange . symName
54
55idToSortSymbol :: Id -> Symbol
56idToSortSymbol idt = Symbol idt SortAsItemType
57
58idToOpSymbol :: Id -> OpType -> Symbol
59idToOpSymbol idt = Symbol idt . OpAsItemType
60
61idToPredSymbol :: Id -> PredType -> Symbol
62idToPredSymbol idt = Symbol idt . PredAsItemType
63
64dummy :: Sign f s -> a -> ()
65dummy _ _ = ()
66
67dummyMin :: b -> c -> Result ()
68dummyMin _ _ = return ()
69
70type CASLSign = Sign () ()
71
72data Sign f e = Sign
73    { sortSet :: Set.Set SORT
74    , emptySortSet :: Set.Set SORT
75    -- a subset of the sort set of possibly empty sorts
76    , sortRel :: Rel.Rel SORT
77    , opMap :: OpMap
78    , assocOps :: OpMap
79    , predMap :: Map.Map Id (Set.Set PredType)
80    , varMap :: Map.Map SIMPLE_ID SORT
81    , sentences :: [Named (FORMULA f)]
82    , declaredSymbols :: Set.Set Symbol
83    , envDiags :: [Diagnosis]
84    , annoMap :: Map.Map Symbol (Set.Set Annotation)
85    , globAnnos :: GlobalAnnos
86    , extendedInfo :: e
87    } deriving Show
88
89-- better ignore assoc flags for equality
90instance (Eq f, Eq e) => Eq (Sign f e) where
91    e1 == e2 =
92        sortSet e1 == sortSet e2 &&
93        emptySortSet e1 == emptySortSet e2 &&
94        sortRel e1 == sortRel e2 &&
95        opMap e1 == opMap e2 &&
96        predMap e1 == predMap e2 &&
97        extendedInfo e1 == extendedInfo e2
98
99emptySign :: e -> Sign f e
100emptySign e = Sign
101    { sortSet = Set.empty
102    , emptySortSet = Set.empty
103    , sortRel = Rel.empty
104    , opMap = Map.empty
105    , assocOps = Map.empty
106    , predMap = Map.empty
107    , varMap = Map.empty
108    , sentences = []
109    , declaredSymbols = Set.empty
110    , envDiags = []
111    , annoMap = Map.empty
112    , globAnnos = emptyGlobalAnnos
113    , extendedInfo = e }
114
115-- | proper subsorts (possibly excluding input sort)
116subsortsOf :: SORT -> Sign f e -> Set.Set SORT
117subsortsOf s e = Rel.predecessors (sortRel e) s
118
119-- | proper supersorts (possibly excluding input sort)
120supersortsOf :: SORT -> Sign f e -> Set.Set SORT
121supersortsOf s e = Rel.succs (sortRel e) s
122
123toOP_TYPE :: OpType -> OP_TYPE
124toOP_TYPE OpType { opArgs = args, opRes = res, opKind = k } =
125    Op_type k  args res nullRange
126
127toPRED_TYPE :: PredType -> PRED_TYPE
128toPRED_TYPE PredType { predArgs = args } = Pred_type args nullRange
129
130toOpType :: OP_TYPE -> OpType
131toOpType (Op_type k args r _) = OpType k args r
132
133toPredType :: PRED_TYPE -> PredType
134toPredType (Pred_type args _) = PredType args
135
136instance Pretty OpType where
137  pretty = pretty . toOP_TYPE
138
139instance Pretty PredType where
140  pretty = pretty . toPRED_TYPE
141
142instance (Pretty f, Pretty e) => Pretty (Sign f e) where
143    pretty = printSign pretty pretty
144
145instance Pretty Symbol where
146  pretty sy = let n = pretty (symName sy) in
147    case symbType sy of
148       SortAsItemType -> n
149       PredAsItemType pt -> let p = n <+> colon <+> pretty pt in
150         case predArgs pt of
151           [_] -> text predS <+> p
152           _ -> p
153       OpAsItemType ot -> let o = n <+> colon <> pretty ot in
154         case opArgs ot of
155           [] | opKind ot == Total -> text opS <+> o
156           _ -> o
157
158instance Pretty SymbType where
159  pretty st = case st of
160     OpAsItemType ot -> pretty ot
161     PredAsItemType pt -> space <> pretty pt
162     SortAsItemType -> empty
163
164printSign :: (f -> Doc) -> (e -> Doc) -> Sign f e -> Doc
165printSign _ fE s = let
166  printRel (supersort, subsorts) =
167            ppWithCommas (Set.toList subsorts) <+> text lessS <+>
168               idDoc supersort
169  esorts = emptySortSet s
170  nsorts = Set.difference (sortSet s) esorts in
171    (if Set.null nsorts then empty else text (sortS++sS) <+>
172       sepByCommas (map idDoc (Set.toList nsorts))) $+$
173    (if Set.null esorts then empty else text (esortS++sS) <+>
174       sepByCommas (map idDoc (Set.toList esorts))) $+$
175    (if Rel.null (sortRel s) then empty
176      else text (sortS++sS) <+>
177       (fsep $ punctuate semi $ map printRel $ Map.toList
178                       $ Rel.toMap $ Rel.transpose $ sortRel s))
179    $+$ printSetMap (text opS) empty (opMap s)
180    $+$ printSetMap (text predS) space (predMap s)
181    $+$ fE (extendedInfo s)
182
183-- working with Sign
184
185diffRel :: Ord a => Rel.Rel a -> Rel.Rel a -> Rel.Rel a
186diffRel a = Rel.irreflex . Rel.transClosure . Rel.difference a
187
188diffSig :: (e -> e -> e) -> Sign f e -> Sign f e -> Sign f e
189diffSig dif a b = let s = sortSet a `Set.difference` sortSet b in a
190  { sortSet = s
191  , emptySortSet = Set.difference s
192      $ nonEmptySortSet a `Set.difference` nonEmptySortSet b
193  , sortRel = diffRel (sortRel a) $ sortRel b
194  , opMap = opMap a `diffOpMapSet` opMap b
195  , assocOps = assocOps a `diffOpMapSet` assocOps b
196  , predMap = predMap a `diffMapSet` predMap b
197  , annoMap = annoMap a `diffMapSet` annoMap b
198  , extendedInfo = dif (extendedInfo a) $ extendedInfo b }
199  -- transClosure needed:  {a < b < c} - {a < c; b}
200  -- is not transitive!
201
202diffOpMapSet :: OpMap -> OpMap -> OpMap
203diffOpMapSet m = diffMapSet m . Map.map (rmOrAddParts False)
204
205diffMapSet :: (Ord a, Ord b) => Map.Map a (Set.Set b)
206           -> Map.Map a (Set.Set b) -> Map.Map a (Set.Set b)
207diffMapSet = Map.differenceWith
208    (\ s t -> let d = Set.difference s t in
209              if Set.null d then Nothing else Just d)
210
211addMapSet :: (Ord a, Ord b) => Map.Map a (Set.Set b) -> Map.Map a (Set.Set b)
212          -> Map.Map a (Set.Set b)
213addMapSet = Map.unionWith Set.union
214
215makePartial :: Set.Set OpType -> Set.Set OpType
216makePartial = Set.mapMonotonic (\ o -> o { opKind = Partial })
217
218--  | remove (True) or add (False) partial op if it is included as total
219rmOrAddParts :: Bool -> Set.Set OpType -> Set.Set OpType
220rmOrAddParts b s =
221  let t = makePartial $ Set.filter ((== Total) . opKind) s
222  in (if b then Set.difference else Set.union) s t
223
224addOpMapSet :: OpMap -> OpMap -> OpMap
225addOpMapSet m = Map.map (rmOrAddParts True). addMapSet m
226
227interMapSet :: (Ord a, Ord b) => Map.Map a (Set.Set b) -> Map.Map a (Set.Set b)
228            -> Map.Map a (Set.Set b)
229interMapSet m =
230  Map.filter (not . Set.null) . Map.intersectionWith Set.intersection m
231
232interOpMapSet :: OpMap -> OpMap -> OpMap
233interOpMapSet m = Map.filter (not . Set.null)
234  . Map.intersectionWith
235  (\ s t -> rmOrAddParts True $ Set.intersection (rmOrAddParts False s)
236   $ rmOrAddParts False t) m
237
238uniteCASLSign :: Sign () () -> Sign () () -> Sign () ()
239uniteCASLSign = addSig (\_ _ -> ())
240
241addRel :: Ord a => Rel.Rel a -> Rel.Rel a -> Rel.Rel a
242addRel a = Rel.irreflex . Rel.transClosure . Rel.union a
243
244nonEmptySortSet :: Sign f e -> Set.Set Id
245nonEmptySortSet s = Set.difference (sortSet s) $ emptySortSet s
246
247addSig :: (e -> e -> e) -> Sign f e -> Sign f e -> Sign f e
248addSig ad a b = let s = sortSet a `Set.union` sortSet b in a
249  { sortSet = s
250  , emptySortSet = Set.difference s
251      $ nonEmptySortSet a `Set.union` nonEmptySortSet b
252  , sortRel = addRel (sortRel a) $ sortRel b
253  , opMap = addOpMapSet (opMap a) $ opMap b
254  , assocOps = addOpMapSet (assocOps a) $ assocOps b
255  , predMap = addMapSet (predMap a) $ predMap b
256  , annoMap = addMapSet (annoMap a) $ annoMap b
257  , extendedInfo = ad (extendedInfo a) $ extendedInfo b }
258
259interRel :: Ord a => Rel.Rel a -> Rel.Rel a -> Rel.Rel a
260interRel a = Rel.irreflex . Rel.transClosure . Rel.fromSet
261  . Set.intersection (Rel.toSet a) . Rel.toSet
262
263interSig :: (e -> e -> e) -> Sign f e -> Sign f e -> Sign f e
264interSig ef a b = let s = sortSet a `Set.intersection` sortSet b in a
265  { sortSet = s
266  , emptySortSet = Set.difference s
267      $ nonEmptySortSet a `Set.intersection` nonEmptySortSet b
268  , sortRel = interRel (sortRel a) $ sortRel b
269  , opMap = interOpMapSet (opMap a) $ opMap b
270  , assocOps = interOpMapSet (assocOps a) $ assocOps b
271  , predMap = interMapSet (predMap a) $ predMap b
272  , annoMap = interMapSet (annoMap a) $ annoMap b
273  , extendedInfo = ef (extendedInfo a) $ extendedInfo b }
274
275isEmptySig :: (e -> Bool) -> Sign f e -> Bool
276isEmptySig ie s =
277    Set.null (sortSet s) &&
278    Rel.null (sortRel s) &&
279    Map.null (opMap s) &&
280    Map.null (predMap s) && ie (extendedInfo s)
281
282isSubMapSet :: (Ord a, Ord b) => Map.Map a (Set.Set b) -> Map.Map a (Set.Set b)
283            -> Bool
284isSubMapSet = Map.isSubmapOfBy Set.isSubsetOf
285
286isSubOpMap :: OpMap -> OpMap -> Bool
287isSubOpMap = Map.isSubmapOfBy $ \ s t ->
288  Set.fold ( \ e r -> r && (Set.member e t || case opKind e of
289    Partial -> Set.member e {opKind = Total} t
290    Total -> False)) True s
291
292isSubSig :: (e -> e -> Bool) -> Sign f e -> Sign f e -> Bool
293isSubSig isSubExt a b = Set.isSubsetOf (sortSet a) (sortSet b)
294  && Rel.isSubrelOf (sortRel a) (sortRel b)
295         -- ignore empty sort sorts
296  && isSubOpMap (opMap a) (opMap b)
297         -- ignore associativity properties!
298  && isSubMapSet (predMap a) (predMap b)
299  && isSubExt (extendedInfo a) (extendedInfo b)
300
301addDiags :: [Diagnosis] -> State.State (Sign f e) ()
302addDiags ds = do
303  e <- State.get
304  State.put e { envDiags = reverse ds ++ envDiags e }
305
306addAnnoSet :: Annoted a -> Symbol -> State.State (Sign f e) ()
307addAnnoSet a s = do
308  addSymbol s
309  let v = Set.union (Set.fromList $ l_annos a) $ Set.fromList $ r_annos a
310  unless (Set.null v) $ do
311    e <- State.get
312    State.put e { annoMap = Map.insertWith Set.union s v $ annoMap e }
313
314addSymbol :: Symbol -> State.State (Sign f e) ()
315addSymbol s = do
316  e <- State.get
317  State.put e { declaredSymbols = Set.insert s $ declaredSymbols e }
318
319addSort :: SortsKind -> Annoted a -> SORT -> State.State (Sign f e) ()
320addSort sk a s = do
321  e <- State.get
322  let m = sortSet e
323      em = emptySortSet e
324      known = Set.member s m
325  if known then addDiags [mkDiag Hint "redeclared sort" s]
326    else do
327      State.put e { sortSet = Set.insert s m }
328      addDiags $ checkNamePrefix s
329  case sk of
330    NonEmptySorts -> when (Set.member s em) $ do
331        e2 <- State.get
332        State.put e2 { emptySortSet = Set.delete s em }
333        addDiags [mkDiag Warning "redeclared sort as non-empty" s]
334    PossiblyEmptySorts -> if known then
335      addDiags [mkDiag Warning "non-empty sort remains non-empty" s]
336      else do
337        e2 <- State.get
338        State.put e2 { emptySortSet = Set.insert s em }
339  addAnnoSet a $ Symbol s SortAsItemType
340
341hasSort :: Sign f e -> SORT -> [Diagnosis]
342hasSort e s =
343    [ mkDiag Error "unknown sort" s
344    | not $ Set.member s $ sortSet e ]
345
346checkSorts :: [SORT] -> State.State (Sign f e) ()
347checkSorts s = do
348  e <- State.get
349  addDiags $ concatMap (hasSort e) s
350
351addSubsort :: SORT -> SORT -> State.State (Sign f e) ()
352addSubsort = addSubsortOrIso True
353
354addSubsortOrIso :: Bool -> SORT -> SORT -> State.State (Sign f e) ()
355addSubsortOrIso b super sub = do
356  when b $ checkSorts [super, sub]
357  e <- State.get
358  let r = sortRel e
359  State.put e { sortRel = (if b then id else Rel.insert super sub)
360                $ Rel.insert sub super r }
361  let p = posOfId sub
362      rel = " '" ++
363        showDoc sub (if b then " < " else " = ") ++ showDoc super "'"
364  if super == sub then addDiags [mkDiag Warning "void reflexive subsort" sub]
365    else if b then
366      if Rel.path super sub r then
367        if  Rel.path sub super r
368        then addDiags [Diag Warning ("sorts are isomorphic" ++ rel) p]
369        else addDiags [Diag Warning ("added subsort cycle by" ++ rel) p]
370      else when (Rel.path sub super r)
371           $ addDiags [Diag Hint ("redeclared subsort" ++ rel) p]
372    else if Rel.path super sub r then
373      if Rel.path sub super r
374      then addDiags [Diag Hint ("redeclared isomoprhic sorts" ++ rel) p]
375      else addDiags [Diag Warning ("subsort '" ++
376        showDoc super "' made isomorphic by" ++ rel) $ posOfId super]
377    else when (Rel.path sub super r)
378         $ addDiags [Diag Warning ("subsort  '" ++
379           showDoc sub "' made isomorphic by" ++ rel) p]
380
381closeSubsortRel :: State.State (Sign f e) ()
382closeSubsortRel=
383    do e <- State.get
384       State.put e { sortRel = Rel.transClosure $ sortRel e }
385
386checkNamePrefix :: Id -> [Diagnosis]
387checkNamePrefix i =
388    [ mkDiag Warning "identifier may conflict with generated names" i
389    | isPrefixOf genNamePrefix $ showId i ""]
390
391alsoWarning :: String -> String -> Id -> [Diagnosis]
392alsoWarning new old i = let is = ' ' : showId i "'" in
393    [Diag Warning ("new '" ++ new ++ is ++ " is also known as '" ++ old ++ is)
394     $ posOfId i]
395
396checkWithOtherMap :: String -> String -> Map.Map Id a -> Id -> [Diagnosis]
397checkWithOtherMap s1 s2 m i =
398    case Map.lookup i m of
399    Nothing -> []
400    Just _ -> alsoWarning s1 s2 i
401
402addVars :: VAR_DECL -> State.State (Sign f e) ()
403addVars (Var_decl vs s _) = do
404    checkSorts [s]
405    mapM_ (addVar s) vs
406
407addVar :: SORT -> SIMPLE_ID -> State.State (Sign f e) ()
408addVar s v =
409    do e <- State.get
410       let m = varMap e
411           i = simpleIdToId v
412           ds = case Map.lookup v m of
413                Just _ -> [mkDiag Hint "known variable shadowed" v]
414                Nothing -> []
415       State.put e { varMap = Map.insert v s m }
416       addDiags $ ds ++ checkWithOtherMap varS opS (opMap e) i
417                ++ checkWithOtherMap varS predS (predMap e) i
418                ++ checkNamePrefix i
419
420addOpTo :: Id -> OpType -> OpMap -> OpMap
421addOpTo k v m =
422    let l = Map.findWithDefault Set.empty k m
423    in Map.insert k (Set.insert v l) m
424
425-- | extract the sort from an analysed term
426sortOfTerm :: TERM f -> SORT
427sortOfTerm t = case t of
428    Qual_var _ ty _ -> ty
429    Application (Qual_op_name _ ot _) _ _ -> res_OP_TYPE ot
430    Sorted_term _ ty _ -> ty
431    Cast _ ty _ -> ty
432    Conditional t1 _ _ _ -> sortOfTerm t1
433    _ -> genName "unknown"
434
435-- | create binding if variables are non-null
436mkForall :: [VAR_DECL] -> FORMULA f -> Range -> FORMULA f
437mkForall vl f ps = if null vl then f else Quantification Universal vl f ps
438
439-- | convert a singleton variable declaration into a qualified variable
440toQualVar :: VAR_DECL -> TERM f
441toQualVar (Var_decl v s ps) =
442    if isSingle v then Qual_var (head v) s ps else error "toQualVar"
443
444
Note: See TracBrowser for help on using the browser.