[/] [trunk/] [src/] [cmdlang/] [ntautil.sml] - Blame information for rev 19

Line No. Rev Author Line
1 4 tbourke
(* $Id: ntautil.sml 19 2007-11-27 00:20:37Z tbourke $ *)
2
 
3
(* TODO:
4
    * Make error handling more descriptive:
5
        -catch the exception
6
        -name the template and state
7
        -show the bad transitions.
8
    * Tidy this whole file up. Try to effect more structure and reuse.
9
      Shift generic functions into xml/nta parse/parsed-nta.
10
 
11
 *)
12
 
13
local structure P    = ParsedNta
14
            and E    = UppaalParse.Expression
15
            and ECvt = UppaalParse.ExpressionCvt
16
            and Env  = UppaalParse.Environment
17
in
18
 
19
structure NtaUtil : NTA_UTIL
20
=
21
struct
22
  (* shortcuts over Atom and AtomSet *)
23 18 tbourke
  infix <+ <- ++ <\ \ =:= ; open Symbol
24 4 tbourke
 
25
  exception InvalidId of int
26
  exception CannotSplitChannelArrays
27
 
28 17 tbourke
  fun actions (P.Template {transitions, ...}) = let
29 4 tbourke
      fun insert ((nm, dir), []) = [(nm, dir)]
30
        | insert ((nm, dir),  (x as (nm', dir'))::xs) =
31
            if nm=:=nm' andalso dir=dir' then x::xs else x::insert ((nm, dir), xs)
32
 
33 17 tbourke
      fun addAct (P.Transition {sync=(NONE, _), ...}, l) = l
34
        | addAct (P.Transition {sync=(SOME (nm, dir, _), _), ...}, l)
35 4 tbourke
              = insert ((nm, dir), l)
36 17 tbourke
    in foldl addAct [] transitions end
37 4 tbourke
 
38 17 tbourke
  fun channelSet (P.Template {transitions, ...}) = let
39
      fun addSync (P.Transition {sync=(NONE, _), ...}          , s) = s
40
        | addSync (P.Transition {sync=(SOME (c, _, _), _), ...}, s) = s <+ c
41
    in foldl addSync AtomSet.empty transitions end
42
 
43
  fun channels t = AtomSet.listItems (channelSet t)
44
 
45 4 tbourke
  fun warnIfCommitted t =
46
     if List.exists P.Location.isCommitted (P.Template.selLocations t)
47
     then Util.warn [P.Template.selName t,
48
                     " contains a committed location (not supported)."] else ()
49
 
50
  fun warnOnChannels (t as P.Template {declaration=env,...}) = let
51 17 tbourke
      fun checkChannel nm = let
52 4 tbourke
          val pre = Atom.toString nm
53
        in case Env.findVal env nm of
54
             NONE => SOME [pre, " not in scope."]
55
           | SOME (Env.VarEntry{ty,ref=r,...}) => (case #1 (E.stripArray ty) of
56
                E.CHANNEL {broadcast,...} =>
57
                  if broadcast
58
                  then SOME [pre,"is broadcast (not supported)"]
59
                  else if r
60
                       then SOME [pre,"is passed by reference (not supported)"]
61
                       else NONE
62
              | _ => NONE)
63
 
64
           | _   => SOME [pre, " not a channel."]
65
        end
66 17 tbourke
    in List.app Util.warn (List.mapPartial checkChannel (channels t)) end
67 4 tbourke
 
68
  local
69
    structure PLoc = P.Location
70
          and PTra = P.Transition
71
          and PTem = P.Template
72
  in
73
  fun split (tplate as P.Template {transitions, locations, ...}, actmap) = let
74
      fun addT (tp, ts) = PTem.addTransitions tp ts
75
 
76
      fun findLoc l = List.find (fn (P.Location {id,...})=>id = l) locations
77
 
78
      fun midPoint ((sx, sy), (tx, ty)) = ((sx + tx) div 2, (sy + ty) div 2)
79
 
80
      fun findPos ((src, dst), []) = let
81
              val sposo = Option.mapPartial PLoc.selPos (findLoc src)
82
              val dposo = Option.mapPartial PLoc.selPos (findLoc dst)
83
            in case (sposo, dposo) of
84
                 (SOME spos, SOME dpos) => (SOME (midPoint (spos,dpos)),[],[])
85
               | _ => (NONE,[],[])
86
            end
87
 
88
        | findPos ((src, dst), nails) = let
89
          val l = length nails
90
          val m = (l + 1) div 2
91
        in
92
          if l mod 2 = 1
93
          then (SOME (List.nth (nails, m-1)), List.take (nails, m-1),
94
                                              List.drop (nails, m))
95
          else (SOME (midPoint (List.nth (nails, m-1), List.nth (nails, m))),
96
                List.take (nails, m), List.drop (nails, m))
97
        end
98
 
99
      fun spl (tr as P.Transition {sync=(NONE, _), ...}, tp) = addT (tp, [tr])
100
        | spl (tr as P.Transition {sync=(SOME (nm,dir,[]), _),
101
                                  source, target, nails, ...}, tp) = let in
102
            case ActionMap.find (actmap, (nm, dir)) of
103
              NONE             => addT (tp, [tr])
104
            | SOME (nm', dir') => let
105
                  val (mpos, preNs, postNs) = findPos ((source, target), nails)
106
 
107
                  val (tp', sloc) = PLoc.new tp ""
108
                  val slocId = PLoc.selId sloc
109
                  val tp' = PTem.updLocation tp'
110
                              (PLoc.updPos (PLoc.mkCommitted sloc) mpos)
111
 
112
                  val fromSloc = PTra.updSync
113
                                   (PTra.new (slocId, target))
114
                                   (SOME (nm', dir', []))
115
                  val fromSloc = PTra.updNails fromSloc postNs
116
                in
117
                  addT (tp', [PTra.updNails
118
                                (PTra.updEndPoints tr (source,slocId)) preNs,
119
                              fromSloc])
120
                end
121
            end
122
        | spl _ = raise CannotSplitChannelArrays
123
 
124
    in foldl spl (PTem.updTransitions tplate []) transitions end
125
  end (* local *)
126
 
127
  local
128
    structure IMap = IntBinaryMap
129
 
130
    fun remap m i = case IMap.find (m, i) of
131
                       NONE    => raise InvalidId i
132
                     | SOME ni => P.LocId ni
133
    fun stripLocId (P.LocId i) = i
134
  in
135
  fun shiftTemplateIds (P.Template {name as (n,_), parameter, declaration,
136
                                    initial, locations, transitions}, start) =
137
    let
138
      fun uLoc (P.Location {id=P.LocId i, position, color, name, invariant,
139
                            comments, urgent, committed}, (done, m, ni)) =
140
        let
141
          val nloc = P.Location {id=P.LocId ni, position=position,
142
                                 color=color, name=name, invariant=invariant,
143
                                 comments=comments, urgent=urgent,
144
                                 committed=committed}
145
        in (nloc::done, IMap.insert (m, i, ni), ni + 1) end
146
 
147
      fun uTrans m (P.Transition {id, source=P.LocId si, target=P.LocId ti,
148
                                  select, guard, sync, update, comments,
149
                                  position, color, nails}, (done, ni)) =
150
        let
151
          val (nid, ni) = case id
152
                of NONE               => (NONE, ni)
153
                 | SOME (P.TransId i) => (SOME (P.TransId ni), ni + 1)
154
          val ntr = P.Transition {id=nid,
155
                                  source=remap m si,
156
                                  target=remap m ti,
157
                                  select=select, guard=guard,
158
                                  sync=sync, update=update,
159
                                  comments=comments, position=position,
160
                                  color=color, nails=nails}
161
        in  (ntr::done, ni) end
162
 
163
      val (nlocs, map, start') = foldl uLoc ([], IMap.empty, start) locations
164
 
165
      val _ = Util.debugVeryDetailed (fn()=>let
166
                                     fun s (f, t) = Int.toString f^"->"^
167
                                                    Int.toString t^" "
168
                                   in "shiftTemplateIds (":: n:: ") "::
169
                                      (List.map s (IMap.listItemsi map))
170
                                   end)
171
 
172
      val (ntrs, final) = foldl (uTrans map) ([], start') transitions
173
    in
174
      (P.Template {name=name, parameter=parameter,declaration=declaration,
175
                   initial=Option.map (remap map o stripLocId) initial,
176
                   locations=rev nlocs, transitions=rev ntrs}, final)
177
    end
178
  end
179
 
180
  fun setTransId nid (tr as P.Transition {id, source, target, select, guard,
181
                               sync, update, comments, position, color, nails})
182
      = let
183
          val nochange = case (nid, id) of
184
                           (NONE, NONE)      => true
185
                         | (SOME ni, SOME i) => (ni = i)
186
                         | _                 => false
187
        in
188
          if nochange then tr
189
          else (P.Transition {id=nid, source=source,
190
                              target=target, select=select,
191
                              guard=guard, sync=sync, update=update,
192
                              color=color, comments=comments,
193
                              position=position, nails=nails})
194
        end
195
 
196 19 tbourke
  fun locsWithoutPositions (P.Template {locations,...}) = let
197
      val add = IntBinarySet.add
198
      fun f (P.Location {id=P.LocId i, position=NONE, ...}, s) = add (s, i)
199
        | f (_, s) = s
200
      val locs = foldl f IntBinarySet.empty locations
201
    in fn (P.LocId i) => IntBinarySet.member (locs, i) end
202
 
203 4 tbourke
  fun stripTransitionIds (P.Template  {name, parameter, declaration, initial,
204
                                       locations, transitions}) =
205
      P.Template {name=name, parameter=parameter, declaration=declaration,
206
                  initial=initial, locations=locations,
207
                  transitions=map (setTransId NONE) transitions}
208
 
209
  fun addTransitionIds p (P.Template {name, parameter, declaration, initial,
210
                                      locations, transitions}) =
211
    let
212
      fun biggest (P.Transition {id=NONE, ...}, i) = i
213
        | biggest (P.Transition {id=SOME (P.TransId j), ...}, i) = Int.max (i, j)
214
      val i = ref (foldl biggest 1 transitions)
215
 
216
      fun f trans = if p trans then (setTransId (SOME (P.TransId (!i))) trans)
217
                                    before i := (!i) + 1
218
                    else trans
219
    in
220
      P.Template {name=name, parameter=parameter, declaration=declaration,
221
                  initial=initial, locations=locations,
222
                  transitions=map f transitions}
223
    end
224
 
225
  fun addTransitions (t, newtrans) = P.Template.updTransitions t
226
                                      (newtrans @ P.Template.selTransitions t)
227
 
228
  fun expandUrgentLocs (t as P.Template {name, parameter, initial,
229
                                         declaration=decls,
230
                                         locations, transitions}) =
231
    let
232
      fun addUrgentIds (P.Location {id=P.LocId i, urgent, ...}, s) =
233
                      if urgent then IntBinarySet.add (s, i) else s
234
      val urgentLocs = foldl addUrgentIds IntBinarySet.empty locations
235
    in
236
      if IntBinarySet.isEmpty urgentLocs then t
237
      else let
238
        val uclk     = Env.newId (Atom.atom "c_u", decls)
239
        val uclkvar  = E.VarExpr (E.SimpleVar (uclk, E.nopos))
240
        val uclkcons = E.RelExpr {left=uclkvar, rel=E.LeOp,
241
                                  right=E.IntCExpr 0, pos=E.nopos}
242
        val uclkrst  = E.AssignExpr {var=uclkvar, aop=E.AssignOp,
243
                                     expr=E.IntCExpr 0, pos=E.nopos}
244
 
245
        val decls'   = Env.addId Env.TemplateScope ((uclk, E.CLOCK), decls)
246
 
247
        fun fromUrgent (P.Location {id, position, color, name,
248
                                    invariant=(inv, invP), comments,
249
                                    urgent=true, committed}) =
250
            P.Location {id=id, position=position, color=color, name=name,
251
                        invariant=(E.andexpr (uclkcons, inv), invP),
252
                        comments=comments, urgent=false, committed=committed}
253
          | fromUrgent l = l
254
 
255
        fun addReset (t as P.Transition {target=target as P.LocId dst, id,
256
                                         source, select, guard, sync,
257
                                         update=(upd, updP),
258
                                         comments, position, color, nails}) =
259
            if IntBinarySet.member (urgentLocs, dst)
260
            then P.Transition {id=id, source=source, target=target,
261
                               select=select, guard=guard, sync=sync,
262
                               update=(uclkrst::upd, updP),
263
                               comments=comments, position=position,
264
                               color=color, nails=nails}
265
            else t
266
 
267
      in
268
        P.Template {name=name, parameter=parameter,
269
                    declaration=decls', initial=initial,
270
                    locations=map fromUrgent locations,
271
                    transitions=map addReset transitions}
272
      end
273
    end
274
 
275
  fun makeInputEnabler (actionlist, env) = let
276
      val l = P.LocId 1
277
 
278
      fun newTrans (c, idtys,  ids, tys, dir) = P.Transition {
279
                id=NONE, source=l, target=l, select=(idtys, NONE),
280
                guard=(E.trueExpr, NONE), sync=(SOME (c, dir, ids), NONE),
281
                update=([], NONE), comments=(NONE, NONE),
282
                position=NONE, color=NONE, nails=[]}
283
 
284
      fun selfLoop (nm, dir) = let in
285
          case Option.map E.stripArray (Env.findValType env nm) of
286
            SOME (E.CHANNEL _, tys) => let
287
                val ids = List.tabulate (length tys,
288
                                         fn i=>Atom.atom ("s"^Int.toString i))
289
                val sels = ListPair.map (fn (nm,t)=>E.BoundId (nm,t,E.nopos))
290
                                        (ids, tys)
291
                val eids = map (fn i=>E.VarExpr (E.SimpleVar (i,E.nopos))) ids
292
              in
293
                SOME (newTrans (nm, sels, eids, tys, dir))
294
              end
295
 
296
          | _ => (Util.warn ["channel ",Atom.toString nm,
297
                             " is invalid (skipped)"]; NONE)
298
        end
299
 
300
    in
301
      P.Template {name=("AcceptAll", NONE),
302
                  parameter=([], NONE),
303
                  initial=SOME l,
304
                  declaration=env,
305
                  locations=[P.Location {
306
                               id=l,
307
                               position=SOME (0,0),
308
                               color=NONE,
309
                               name=(NONE, NONE),
310
                               invariant=(E.trueExpr, NONE),
311
                               comments=(NONE, NONE),
312
                               urgent=false,
313
                               committed=false}],
314
                  transitions=List.mapPartial selfLoop actionlist}
315
    end
316
 
317
  fun namesetToLocset (names, P.Template {locations, ...}) = let
318
      fun f (P.Location {name=(NONE, _), ...}, s) = s
319
        | f (P.Location {id=P.LocId i, name=(SOME name, _), ...}, s) =
320
        if (Atom.atom name) <- names then IntBinarySet.add (s, i) else s
321
    in
322
      foldl f IntBinarySet.empty locations
323
    end
324
end
325
end (* local *)
326