root/trunk/CspCASL/StatAnaCSP.hs @ 11201

Revision 11201, 25.5 kB (checked in by maeder, 11 months ago)

renamed funs in CASL to ops

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1{- |
2Module      :  $Id$
3Description :  Static analysis of CspCASL
4Copyright   :  (c) Andy Gimblett, Markus Roggenbach, Swansea University 2008
5License     :  similar to LGPL, see HetCATS/LICENSE.txt or LIZENZ.txt
6
7Maintainer  :  a.m.gimblett@swansea.ac.uk
8Stability   :  provisional
9Portability :  portable
10
11Static analysis of CSP-CASL specifications, following "Tool Support
12for CSP-CASL", MPhil thesis by Andy Gimblett, 2008.
13<http://www.cs.swan.ac.uk/~csandy/mphil/>
14
15-}
16
17module CspCASL.StatAnaCSP where
18
19import qualified Control.Monad as Monad
20import qualified Data.Map as Map
21import qualified Data.Maybe as Maybe
22import qualified Data.Set as S
23
24import CASL.AS_Basic_CASL (FORMULA(..), OpKind(..), SORT, TERM(..), VAR,
25                           VAR_DECL(..))
26import CASL.MixfixParser (emptyMix, Mix(..), makeRules, mkIdSets,
27                          resolveFormula, resolveMixfix, unite)
28import CASL.Overload (minExpFORMULA, oneExpTerm)
29import CASL.Sign
30import CASL.StaticAna (allOpIds, allPredIds)
31import Common.AS_Annotation
32import Common.Result
33import Common.GlobalAnnotations
34import Common.ConvertGlobalAnnos
35import qualified Common.Lib.Rel as Rel
36import Common.Id (getRange, Id, simpleIdToId, nullRange, mkSimpleId)
37import Common.Lib.State
38import Common.ExtSign
39
40import CspCASL.AS_CspCASL
41import CspCASL.AS_CspCASL_Process
42import CspCASL.LocalTop (Obligation(..), unmetObs)
43import CspCASL.Print_CspCASL ()
44import CspCASL.SignCSP
45
46basicAnalysisCspCASL :: (CspBasicSpec, CspCASLSign, GlobalAnnos)
47        -> Result (CspBasicSpec, ExtSign CspCASLSign (),
48                   [Named CspCASLSentence])
49basicAnalysisCspCASL (cc, sigma, ga) = do
50    let Result es mga = mergeGlobalAnnos ga $ globAnnos sigma
51        (_, accSig) = runState (ana_BASIC_CSP cc) $ case mga of
52              Nothing -> sigma
53              Just nga -> sigma { globAnnos = nga }
54        ds = reverse $ envDiags accSig
55    Result (es ++ ds) (Just ()) -- insert diagnostics
56    return (cc, mkExtSign accSig, [makeNamed "empty_sentence" emptyCCSentence,
57                                   makeNamed "StopProcSen"  stopProc,
58                                   makeNamed "GParProcSen"  gParProc,
59                                   makeNamed "AParProcSen"  aParProc,
60                                   makeNamed "StopProcSen"  seqProc])
61    where
62      stopProc = CspCASLSentence (mkSimpleId "stopProc") [] (Stop nullRange)
63      seqProc = CspCASLSentence (mkSimpleId "seqProc") []
64                                       (Sequential (Stop nullRange)
65                                        (Stop nullRange) nullRange)
66      gParProc = CspCASLSentence (mkSimpleId "gParProc") []
67                                       (GeneralisedParallel (Stop nullRange)
68                                        (EventSet [mkSimpleId "S"] nullRange)
69                                        (Skip nullRange) nullRange)
70      aParProc = CspCASLSentence (mkSimpleId "gParProc") []
71                                     (AlphabetisedParallel (Stop nullRange)
72                                      (EventSet [mkSimpleId "T"] nullRange)
73                                      (EventSet [mkSimpleId "U"] nullRange)
74                                      (Skip nullRange) nullRange)
75
76ana_BASIC_CSP :: CspBasicSpec -> State CspCASLSign ()
77ana_BASIC_CSP cc = do checkLocalTops
78                      mapM anaChanDecl (channels cc)
79                      mapM anaProcItem (proc_items cc)
80                      return ()
81
82-- Analysis of local top elements
83
84-- | Check a CspCASL signature for local top elements in its subsort
85-- relation.
86checkLocalTops :: State CspCASLSign ()
87checkLocalTops = do
88    sig <- get
89    let obs = unmetObs $ Rel.toList $ Rel.transClosure $ sortRel sig
90    addDiags (map lteError obs)
91    return ()
92
93-- | Add diagnostic error message for every unmet local top element
94-- obligation.
95lteError :: Obligation SORT -> Diagnosis
96lteError (Obligation x y z) = mkDiag Error msg ()
97    where msg = ("local top element obligation ("
98                 ++ (show x) ++ "<" ++ (show y) ++ "," ++ (show z)
99                 ++ ") unfulfilled")
100
101-- Static analysis of channel declarations
102
103-- | Statically analyse a CspCASL channel declaration.
104anaChanDecl :: CHANNEL_DECL -> State CspCASLSign CHANNEL_DECL
105anaChanDecl (ChannelDecl chanNames chanSort) = do
106    checkSorts [chanSort] -- check channel sort is known
107    sig <- get
108    let ext = extendedInfo sig
109        oldChanMap = chans ext
110    newChanMap <- Monad.foldM (anaChannelName chanSort) oldChanMap chanNames
111    vds <- gets envDiags
112    put sig { extendedInfo = ext { chans = newChanMap }
113            , envDiags = vds
114            }
115    return (ChannelDecl chanNames chanSort)
116
117-- | Statically analyse a CspCASL channel name.
118anaChannelName :: SORT -> ChanNameMap -> CHANNEL_NAME ->
119                    State CspCASLSign ChanNameMap
120anaChannelName s m chanName = do
121    sig <- get
122    if (show chanName) `S.member` (S.map show (sortSet sig))
123      then do let err = "channel name already in use as a sort name"
124              addDiags [mkDiag Error err chanName]
125              return m
126      else case Map.lookup chanName m of
127             Nothing -> return (Map.insert chanName s m) -- insert new.
128             Just e ->
129               if e == s
130                 then do let warn = "channel redeclared with same sort"
131                         addDiags [mkDiag Warning warn chanName]
132                         return m -- already declared with this sort.
133                 else do let err = "channel declared with multiple sorts"
134                         addDiags [mkDiag Error err chanName]
135                         return m
136
137-- Static analysis of process items
138
139-- | Statically analyse a CspCASL process item.
140anaProcItem :: PROC_ITEM -> State CspCASLSign ()
141anaProcItem procItem =
142    case procItem of
143      (Proc_Decl name argSorts alpha) -> anaProcDecl name argSorts alpha
144      (Proc_Eq parmProcName procTerm) -> anaProcEq parmProcName procTerm
145
146-- Static analysis of process declarations
147
148-- | Statically analyse a CspCASL process declaration.
149anaProcDecl :: PROCESS_NAME -> PROC_ARGS -> PROC_ALPHABET
150            -> State CspCASLSign ()
151anaProcDecl name argSorts (ProcAlphabet commTypes _) = do
152    sig <- get
153    let ext = extendedInfo sig
154        oldProcDecls = procSet ext
155    newProcDecls <-
156      if name `Map.member` oldProcDecls
157        then do -- duplicate process declaration
158                let err = "process name declared more than once"
159                addDiags [mkDiag Error err name]
160                return oldProcDecls
161        else do -- new process declation
162                checkSorts argSorts -- check argument sorts are known
163                -- build alphabet: set of CommType values
164                alpha <- Monad.foldM (anaCommType sig) S.empty commTypes
165                let profile = (ProcProfile argSorts alpha)
166                return (Map.insert name profile oldProcDecls)
167    vds <- gets envDiags
168    put sig { extendedInfo = ext {procSet = newProcDecls }
169            , envDiags = vds
170            }
171    return ()
172
173-- Static analysis of process equations
174
175-- | Statically analyse a CspCASL process equation.
176anaProcEq :: PARM_PROCNAME -> PROCESS -> State CspCASLSign ()
177anaProcEq (ParmProcname pn vs) proc = do
178    sig <- get
179    let ext = extendedInfo sig
180        procDecls = procSet ext
181        prof = pn `Map.lookup` procDecls
182    case prof of
183      -- Only analyse a process if its name (and thus profile) is known
184      Just (ProcProfile procArgs procAlpha) ->
185        do gVars <- anaProcVars pn procArgs vs -- compute global vars
186           termAlpha <- anaProcTerm proc gVars Map.empty
187           checkCommAlphaSub termAlpha procAlpha proc "process equation"
188           return ()
189      Nothing ->
190        do addDiags [mkDiag Error "process equation for unknown process" pn]
191           return ()
192    vds <- gets envDiags
193    put sig { envDiags = vds }
194    return ()
195
196-- | Statically analyse a CspCASL process equation's global variable
197-- names.
198anaProcVars :: PROCESS_NAME -> [SORT] -> [VAR] -> State CspCASLSign ProcVarMap
199anaProcVars pn ss vs = do
200    case (compare (length ss) (length vs)) of
201       LT -> do addDiags [mkDiag Error "too many process arguments" pn]
202                return Map.empty
203       GT -> do addDiags [mkDiag Error "not enough process arguments" pn]
204                return Map.empty
205       EQ -> Monad.foldM anaProcVar Map.empty (zip vs ss)
206
207-- | Statically analyse a CspCASL process-global variable name.
208anaProcVar :: ProcVarMap -> (VAR, SORT) -> State CspCASLSign ProcVarMap
209anaProcVar old (v, s) = do
210    if v `Map.member` old
211       then do addDiags [mkDiag Error "process arg declared more than once" v]
212               return old
213       else return (Map.insert v s old)
214
215-- Static analysis of process terms
216
217-- | Statically analyse a CspCASL process term.
218anaProcTerm :: PROCESS -> ProcVarMap -> ProcVarMap ->
219               State CspCASLSign CommAlpha
220anaProcTerm proc gVars lVars = case proc of
221    NamedProcess name args _ ->
222        do addDiags [mkDiag Debug "Named process" proc]
223           al <- anaNamedProc proc name args (lVars `Map.union` gVars)
224           return al
225    Skip _ ->
226        do addDiags [mkDiag Debug "Skip" proc]
227           return S.empty
228    Stop _ ->
229        do addDiags [mkDiag Debug "Stop" proc]
230           return S.empty
231    Div _ ->
232        do addDiags [mkDiag Debug "Div" proc]
233           return S.empty
234    Run es _ ->
235        do addDiags [mkDiag Debug "Run" proc]
236           comms <- anaEventSet es
237           return comms
238    Chaos es _ ->
239        do addDiags [mkDiag Debug "Chaos" proc]
240           comms <- anaEventSet es
241           return comms
242    PrefixProcess e p _ ->
243        do addDiags [mkDiag Debug "Prefix" proc]
244           (evComms, rcvMap) <- anaEvent e (lVars `Map.union` gVars)
245           comms <- anaProcTerm p gVars (rcvMap `Map.union` lVars)
246           return (comms `S.union` evComms)
247    InternalPrefixProcess v s p _ ->
248        do addDiags [mkDiag Debug "Internal prefix" proc]
249           checkSorts [s] -- check sort is known
250           comms <- anaProcTerm p gVars (Map.insert v s lVars)
251           return (S.insert (CommTypeSort s) comms)
252    ExternalPrefixProcess v s p _ ->
253        do addDiags [mkDiag Debug "External prefix" proc]
254           checkSorts [s] -- check sort is known
255           comms <- anaProcTerm p gVars (Map.insert v s lVars)
256           return (S.insert (CommTypeSort s) comms)
257    Sequential p q _ ->
258        do addDiags [mkDiag Debug "Sequential" proc]
259           pComms <- anaProcTerm p gVars lVars
260           qComms <- anaProcTerm q gVars Map.empty
261           return (pComms `S.union` qComms)
262    InternalChoice p q _ ->
263        do addDiags [mkDiag Debug "InternalChoice" proc]
264           pComms <- anaProcTerm p gVars lVars
265           qComms <- anaProcTerm q gVars lVars
266           return (pComms `S.union` qComms)
267    ExternalChoice p q _ ->
268        do addDiags [mkDiag Debug "ExternalChoice" proc]
269           pComms <- anaProcTerm p gVars lVars
270           qComms <- anaProcTerm q gVars lVars
271           return (pComms `S.union` qComms)
272    Interleaving p q _ ->
273        do addDiags [mkDiag Debug "Interleaving" proc]
274           pComms <- anaProcTerm p gVars lVars
275           qComms <- anaProcTerm q gVars lVars
276           return (pComms `S.union` qComms)
277    SynchronousParallel p q _ ->
278        do addDiags [mkDiag Debug "Synchronous" proc]
279           pComms <- anaProcTerm p gVars lVars
280           qComms <- anaProcTerm q gVars lVars
281           return (pComms `S.union` qComms)
282    GeneralisedParallel p es q _ ->
283        do addDiags [mkDiag Debug "Generalised parallel" proc]
284           pComms <- anaProcTerm p gVars lVars
285           synComms <- anaEventSet es
286           qComms <- anaProcTerm q gVars lVars
287           return (S.unions [pComms, qComms, synComms])
288    AlphabetisedParallel p esp esq q _ ->
289        do addDiags [mkDiag Debug "Alphabetised parallel" proc]
290           pComms <- anaProcTerm p gVars lVars
291           pSynComms <- anaEventSet esp
292           checkCommAlphaSub pSynComms pComms proc
293                                 "alphabetised parallel, left"
294           qSynComms <- anaEventSet esq
295           qComms <- anaProcTerm q gVars lVars
296           checkCommAlphaSub qSynComms qComms proc
297                                 "alphabetised parallel, right"
298           return (pComms `S.union` qComms)
299    Hiding p es _ ->
300        do addDiags [mkDiag Debug "Hiding" proc]
301           pComms <- anaProcTerm p gVars lVars
302           hidComms <- anaEventSet es
303           return (pComms `S.union` hidComms)
304    RenamingProcess p r _ ->
305        do addDiags [mkDiag Debug "Renaming" proc]
306           pComms <- anaProcTerm p gVars lVars
307           renAlpha <- anaRenaming r
308           return (pComms `S.union` renAlpha)
309    ConditionalProcess f p q _ ->
310        do addDiags [mkDiag Debug "Conditional" proc]
311           pComms <- anaProcTerm p gVars lVars
312           qComms <- anaProcTerm q gVars lVars
313           mfs <- anaFormulaCspCASL (gVars `Map.union` lVars) f
314           let fComms = case mfs of
315                          Nothing -> S.empty
316                          Just fs -> formulaComms fs
317           return (S.unions [pComms, qComms, fComms])
318
319-- | Statically analyse a CspCASL "named process" term.
320anaNamedProc :: PROCESS -> PROCESS_NAME -> [TERM ()] -> ProcVarMap ->
321                State CspCASLSign CommAlpha
322anaNamedProc proc pn terms procVars = do
323    sig <- get
324    let ext = extendedInfo sig
325        procDecls = procSet ext
326        prof = pn `Map.lookup` procDecls
327    case prof of
328      Just (ProcProfile varSorts permAlpha) ->
329        if (length terms) == (length varSorts)
330          then do mapM (anaNamedProcTerm procVars) (zip terms varSorts)
331                  return permAlpha
332          else do let err = "wrong number of arguments in named process"
333                  addDiags [mkDiag Error err proc]
334                  return S.empty
335      Nothing ->
336        do addDiags [mkDiag Error "unknown process name" proc]
337           return S.empty
338
339-- | Statically analysis a CASL term occurring in a CspCASL "named
340-- process" term.
341anaNamedProcTerm :: ProcVarMap -> ((TERM ()), SORT) -> State CspCASLSign ()
342anaNamedProcTerm pm (t, expSort) = do
343    mt <- anaTermCspCASL pm t
344    case mt of
345      Nothing -> return () -- CASL term analysis failed
346      (Just at) -> do ccTermCast at expSort -- attempt cast; don't need result
347                      return ()
348
349-- Static analysis of event sets and communication types
350
351-- | Statically analyse a CspCASL event set.
352anaEventSet :: EVENT_SET -> State CspCASLSign CommAlpha
353anaEventSet (EventSet es _) = do
354  sig <- get
355  comms <- Monad.foldM (anaCommType sig) S.empty es
356  vds <- gets envDiags
357  put sig { envDiags = vds }
358  return comms
359
360-- | Statically analyse a CspCASL communication type.
361anaCommType :: CspCASLSign -> CommAlpha -> COMM_TYPE ->
362               State CspCASLSign CommAlpha
363anaCommType sig alpha ct =
364    if ctSort `S.member` (sortSet sig)
365      then -- ct is a sort name; insert sort into alpha
366        do return (S.insert (CommTypeSort ctSort) alpha)
367      else -- ct not a sort name, so should be a channel name
368        case Map.lookup ct (chans $ extendedInfo sig) of
369          Just s -> -- ct is a channel name; insert typed chan name into alpha
370                    return (S.insert (mkTypedChan ct s) alpha)
371          Nothing -> do let err = "not a sort or channel name"
372                        addDiags [mkDiag Error err ct]
373                        return alpha
374        where ctSort = simpleIdToId ct
375              mkTypedChan c s = CommTypeChan $ TypedChanName c s
376
377-- Static analysis of events
378
379-- | Statically analyse a CspCASL event.
380anaEvent :: EVENT -> ProcVarMap -> State CspCASLSign (CommAlpha, ProcVarMap)
381anaEvent e vars = case e of
382                    TermEvent t _ -> anaTermEvent t vars
383                    ChanSend c t _ -> anaChanSend c t vars
384                    ChanNonDetSend c v s _ -> anaChanBinding c v s
385                    ChanRecv c v s _ -> anaChanBinding c v s
386
387-- | Statically analyse a CspCASL term event.
388anaTermEvent :: (TERM ()) -> ProcVarMap ->
389                State CspCASLSign (CommAlpha, ProcVarMap)
390anaTermEvent t vars = do
391  mt <- anaTermCspCASL vars t
392  let alpha = case mt of
393                Just at -> [(CommTypeSort (sortOfTerm at))]
394                Nothing -> []
395  return (S.fromList alpha, Map.empty)
396
397-- | Statically analyse a CspCASL channel send event.
398anaChanSend :: CHANNEL_NAME -> (TERM ()) -> ProcVarMap ->
399                State CspCASLSign (CommAlpha, ProcVarMap)
400anaChanSend c t vars = do
401  sig <- get
402  let ext = extendedInfo sig
403  case c `Map.lookup` (chans ext) of
404    Nothing -> do
405      addDiags [mkDiag Error "unknown channel" c]
406      return (S.empty, Map.empty)
407    Just chanSort -> do
408      mt <- anaTermCspCASL vars t
409      case mt of
410        Nothing -> -- CASL analysis failed
411                   return (S.empty, Map.empty)
412        (Just at) ->
413            do mc <- ccTermCast at chanSort
414               case mc of
415                 Nothing -> -- cast failed
416                            return (S.empty, Map.empty)
417                 (Just ct) ->
418                     do let castSort = sortOfTerm ct
419                            alpha = [CommTypeSort castSort
420                                    ,CommTypeChan $ TypedChanName c castSort
421                                    ]
422                        return (S.fromList alpha, Map.empty)
423
424-- | Statically analyse a CspCASL "binding" channel event (which is
425-- either a channel nondeterministic send event or a channel receive
426-- event).
427anaChanBinding :: CHANNEL_NAME -> VAR -> SORT ->
428                   State CspCASLSign (CommAlpha, ProcVarMap)
429anaChanBinding c v s = do
430  checkSorts [s] -- check sort is known
431  sig <- get
432  let ext = extendedInfo sig
433  case c `Map.lookup` (chans ext) of
434    Nothing -> do
435      addDiags [mkDiag Error "unknown channel" c]
436      return (S.empty, Map.empty)
437    Just chanSort -> do
438      if s `S.member` (chanSort `S.insert` (subsorts chanSort))
439        then do let alpha = [CommTypeSort s
440                            ,CommTypeChan (TypedChanName c s)]
441                let binding = [(v, s)]
442                return (S.fromList alpha, Map.fromList binding)
443        else do let err = "sort not a subsort of channel's sort"
444                addDiags [mkDiag Error err s]
445                return (S.empty, Map.empty)
446            where subsorts = Rel.predecessors (sortRel sig)
447
448-- Static analysis of renaming and renaming items
449
450-- | Statically analyse a CspCASL renaming.
451anaRenaming :: RENAMING -> State CspCASLSign CommAlpha
452anaRenaming r = do al <- Monad.foldM anaRenamingItem S.empty r
453                   return al
454
455-- | Statically analyse a CspCASL renaming item.
456anaRenamingItem :: CommAlpha -> Id -> State CspCASLSign CommAlpha
457anaRenamingItem inAl ri = do
458    totOps <- getUnaryOpsById ri Total
459    if (not $ S.null totOps)
460      then return (inAl `S.union` totOps)
461      else do parOps <- getUnaryOpsById ri Partial
462              if (not $ S.null parOps)
463                then return (inAl `S.union` parOps)
464                else do preds <- getBinPredsById ri
465                        if (not $ S.null preds)
466                          then return (inAl `S.union` preds)
467                          else do let err = ("renaming item not a binary " ++
468                                             "operation or predicate name")
469                                  addDiags [mkDiag Error err ri]
470                                  return inAl
471
472-- | Given a CASL identifier and a `function kind' (total or partial),
473-- find all unary operations of that kind with that name in the CASL
474-- signature, and return a set of corresponding communication types
475-- for those operations.
476getUnaryOpsById :: Id -> OpKind -> State CspCASLSign (S.Set CommType)
477getUnaryOpsById ri kind = do
478    sig <- get
479    let opsWithId = Map.findWithDefault S.empty ri (opMap sig)
480        binOpsKind = S.filter (isBin kind) opsWithId
481        cts = S.map CommTypeSort $ S.fold opSorts S.empty binOpsKind
482    return cts
483      where isBin k ot = (k == opKind ot) && (1 == (length (opArgs ot)))
484            opSorts o inS = inS `S.union` (S.fromList ((opArgs o) ++ [opRes o]))
485
486-- | Given a CASL identifier find all binary predicates with that name
487-- in the CASL signature, and return a set of corresponding
488-- communication types for those predicates.
489getBinPredsById :: Id -> State CspCASLSign (S.Set CommType)
490getBinPredsById ri = do
491    sig <- get
492    let predsWithId = Map.findWithDefault S.empty ri (predMap sig)
493        binPreds = S.filter isBin predsWithId
494        cts = S.map CommTypeSort $ S.fold predSorts S.empty binPreds
495    return cts
496      where isBin ot = (2 == (length (predArgs ot)))
497            predSorts p inS = inS `S.union` (S.fromList (predArgs p))
498
499-- | Given two CspCASL communication alphabets, check that the first's
500-- subsort closure is a subset of the second's subsort closure.
501checkCommAlphaSub :: CommAlpha -> CommAlpha -> PROCESS -> String ->
502                     State CspCASLSign ()
503checkCommAlphaSub sub super proc context = do
504  sig <- get
505  let extras = ((closeCspCommAlpha sig sub) `S.difference`
506                (closeCspCommAlpha sig super))
507  if S.null extras
508    then do return ()
509    else do let err = ("Communication alphabet subset violations (" ++
510                       context ++ "): " ++ (show $ S.toList extras))
511            addDiags [mkDiag Error err proc]
512            return ()
513
514-- Static analysis of CASL terms occurring in CspCASL process terms.
515
516-- | Statically analyse a CASL term appearing in a CspCASL process;
517-- any in-scope process variables are added to the signature before
518-- performing the analysis.
519anaTermCspCASL :: ProcVarMap -> (TERM ()) ->
520                  State CspCASLSign (Maybe (TERM ()))
521anaTermCspCASL pm t = do
522    sig <- get
523    let newVars = Map.union pm (varMap sig)
524        sigext = sig { varMap = newVars }
525        Result ds mt = anaTermCspCASL' sigext t
526    addDiags ds
527    return mt
528
529-- | Statically analyse a CASL term in the context of a CspCASL
530-- signature.  If successful, returns a fully-qualified term.
531anaTermCspCASL' :: CspCASLSign -> TERM () -> Result (TERM ())
532anaTermCspCASL' sig trm = do
533    let allIds = unite [mkIdSets (allOpIds sig) $ allPredIds sig]
534        ga = globAnnos sig
535        mix = emptyMix { mixRules = makeRules ga allIds }
536    resT <- resolveMixfix (putParen mix) (mixResolve mix)
537                 ga (mixRules mix) trm
538    oneExpTerm (const return) sig resT
539
540-- | Attempt to cast a CASL term to a particular CASL sort.
541ccTermCast :: (TERM ()) -> SORT -> State CspCASLSign (Maybe (TERM ()))
542ccTermCast t cSort =
543    if termSort == (cSort)
544      then return (Just t)
545      else do sig <- get
546              if Rel.member termSort cSort (sortRel sig)
547                then do let err = "upcast term to " ++ (show cSort)
548                        addDiags [mkDiag Debug err t]
549                        return (Just (Sorted_term t cSort (getRange t)))
550                else if Rel.member cSort termSort (sortRel sig)
551                       then do let err = "downcast term to " ++ (show cSort)
552                               addDiags [mkDiag Debug err t]
553                               return (Just (Cast t cSort (getRange t)))
554                       else do let err = "can't cast term to sort " ++
555                                           (show cSort)
556                               addDiags [mkDiag Error err t]
557                               return Nothing
558        where termSort = (sortOfTerm t)
559
560-- Static analysis of CASL formulae occurring in CspCASL process
561-- terms.
562
563-- | Statically analyse a CASL formula appearing in a CspCASL process;
564-- any in-scope process variables are added to the signature before
565-- performing the analysis.
566anaFormulaCspCASL :: ProcVarMap -> (FORMULA ()) ->
567                     State CspCASLSign (Maybe (FORMULA ()))
568anaFormulaCspCASL pm f = do
569    addDiags [mkDiag Debug "anaFormulaCspCASL" ()]
570    sig <- get
571    let newVars = Map.union pm (varMap sig)
572        sigext = sig { varMap = newVars }
573        Result ds mt = anaFormulaCspCASL' sigext f
574    addDiags ds
575    return mt
576
577-- | Statically analyse a CASL formula in the context of a CspCASL
578-- signature.  If successful, returns a fully-qualified formula.
579anaFormulaCspCASL' :: CspCASLSign -> FORMULA () -> Result (FORMULA ())
580anaFormulaCspCASL' sig frm = do
581    let allIds = unite [mkIdSets (allOpIds sig) $ allPredIds sig]
582        ga = globAnnos sig
583        mix = emptyMix { mixRules = makeRules ga allIds }
584    resF <- resolveFormula (putParen mix) (mixResolve mix)
585                 ga (mixRules mix) frm
586    minExpFORMULA (const return) sig resF
587
588-- | Compute the communication alphabet arising from a formula
589-- occurring in a CspCASL process term.
590formulaComms :: (FORMULA ()) -> CommAlpha
591formulaComms f = case f of
592    Quantification _ varDecls f' _ ->
593        (formulaComms f') `S.union` S.fromList vdSorts
594            where vdSorts = (map (CommTypeSort . vdSort) varDecls)
595                  vdSort (Var_decl _ s _) = s
596    Conjunction fs _ -> S.unions (map formulaComms fs)
597    Disjunction fs _ -> S.unions (map formulaComms fs)
598    Implication f1 f2 _ _ -> (formulaComms f1) `S.union` (formulaComms f2)
599    Equivalence f1 f2 _ -> (formulaComms f1) `S.union` (formulaComms f2)
600    Negation f' _ -> formulaComms f'
601    True_atom _ -> S.empty
602    False_atom _ -> S.empty
603    Predication _ _ _ -> S.empty
604    Definedness t _ -> S.singleton (CommTypeSort (sortOfTerm t))
605    Existl_equation t1 t2 _ -> S.fromList [CommTypeSort (sortOfTerm t1),
606                                           CommTypeSort (sortOfTerm t2)]
607    Strong_equation t1 t2 _ -> S.fromList [CommTypeSort (sortOfTerm t1),
608                                           CommTypeSort (sortOfTerm t2)]
609    Membership t s _ -> S.fromList [CommTypeSort (sortOfTerm t),
610                                    CommTypeSort s]
611    Mixfix_formula t -> S.singleton (CommTypeSort (sortOfTerm t))
612    Unparsed_formula _ _ -> S.empty
613    Sort_gen_ax _ _ -> S.empty
614    ExtFORMULA _ -> S.empty
Note: See TracBrowser for help on using the browser.