root/trunk/CASL/Sign.hs @ 11204

Revision 11204, 15.5 kB (checked in by maeder, 11 months ago)

followed hlint hints

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