Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] Diff of /branches/lamont/src/compiler/tree-il/var-analysis.sml
ViewVC logotype

Diff of /branches/lamont/src/compiler/tree-il/var-analysis.sml

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1232, Mon May 16 23:37:52 2011 UTC revision 1640, Wed Nov 16 02:19:51 2011 UTC
# Line 3  Line 3 
3   * COPYRIGHT (c) 2011 The Diderot Project (http://diderot-language.cs.uchicago.edu)   * COPYRIGHT (c) 2011 The Diderot Project (http://diderot-language.cs.uchicago.edu)
4   * All rights reserved.   * All rights reserved.
5   *   *
6   * The variable analysis phase does four things:   * The variable analysis phase does the following things:
7   *   *
8   *   1) determine which variables that are bound at global level are used in strand   *   1) determine which variables that are bound at global level are used in strand
9   *      or method scopes.   *      or method scopes.
# Line 11  Line 11 
11   *   2) determine which strand parameters are used in methods (and thus have to be   *   2) determine which strand parameters are used in methods (and thus have to be
12   *      shadowed by instance variables).   *      shadowed by instance variables).
13   *   *
14   *   3) determine which instance variables are invariant over all strands, and thus   *   3) determine which strand state variables are invariant across the strand
15   *      can be lifted to global scope, and which strand variables are invariant across   *      execution.
  *      the strand execution.  
16   *   *
17   *   4) eliminate unused and useless variables.   *   4) eliminate unused and useless variables.
18     *
19     * TODO
20     *
21     *   5) determine which state variables are invariant over all strands and thus
22     *      can be lifted to global scope
23     *
24     *   6) determine which state variables are not used and thus can be eliminated.
25   *)   *)
26    
27  structure VarAnalysis : sig  structure VarAnalysis : sig
28    
29      structure IL : SSA      structure IL : SSA
30    
   (* the scope of a variable describes the extent of its use. *)  
     datatype scope  
       = Global                  (* bound globally and used in strands *)  
       | StrandParam             (* parameter to strand creation *)  
       | StrandConstState        (* state variable that is invariant over strand execution *)  
       | StrandState             (* strand state variable *)  
       | Local                   (* local binding not used in nested scopes *)  
   
     val scopeToString : scope -> string  
   
     val varScope : IL.var -> scope  
   
     val isGlobal : IL.var -> bool  
   
31      val optimize : IL.program -> IL.program      val optimize : IL.program -> IL.program
32    
33      (* returns true if the state variable is invariant over strand execution *)
34        val isVarying : IL.state_var -> bool
35    
36    end = struct    end = struct
37    
38      structure IL = LowIL      structure IL = LowIL
39      structure V = IL.Var      structure V = IL.Var
40        structure StV = IL.StateVar
41      structure VMap = V.Map      structure VMap = V.Map
42    
     datatype scope  
       = Global                  (* bound globally and used in strands *)  
       | StrandParam             (* parameter to strand creation *)  
       | StrandConstState        (* state variable that is invariant over strand execution *)  
       | StrandState             (* strand state variable *)  
       | Local                   (* local binding not used in nested scopes *)  
   
     fun scopeToString s = (case s  
            of Global => "Global"  
             | StrandParam => "StrandParam"  
             | StrandConstState => "StrandConstState"  
             | StrandState => "StrandState"  
             | Local => "Local"  
           (* end case *))  
   
43    (* nesting depths of scopes *)    (* nesting depths of scopes *)
44      val undefinedScope = 0      val undefinedScope = 0
45      val globalScope = 1         (* global initialization *)      val globalScope = 1         (* global initialization *)
# Line 73  Line 54 
54            V.newProp (fn x => raise Fail("no binding depth set for " ^ V.toString x))            V.newProp (fn x => raise Fail("no binding depth set for " ^ V.toString x))
55    
56    (* property that maps variables to the maximum depth where they are used *)    (* property that maps variables to the maximum depth where they are used *)
57      val {peekFn=peekUseDepth : IL.var -> int option, setFn=setUseDepth, clrFn=clrUseDepth, ...} =      val {peekFn=peekUseDepth, getFn=getUseDepth, setFn=setUseDepth, clrFn=clrUseDepth, ...} =
58            V.newProp (fn x => raise Fail("no use depth set for " ^ V.toString x))            V.newProp (fn x => undefinedScope)
     fun getUseDepth x = (case peekUseDepth x  
            of NONE => undefinedScope  
             | SOME d => d  
           (* end case *))  
   
   (* property that maps variables to their assigned scope *)  
     val {getFn=varScope : IL.var -> scope, setFn=setVarScope, ...} = V.newProp (fn x => Local)  
59    
60    (* boolean flag on strand-state variables that vary across method executions *)    (* boolean flag on strand-state variables that vary across method executions *)
61      val {getFn=isVarying, setFn=setVarying} = V.newFlag ()      val {getFn=isVarying, setFn=setVarying} = StV.newFlag ()
   
     fun isGlobal x = (varScope x = Global)  
62    
63    (* walk the program determining the binding and maximum use depths of all variables *)    (* walk the program determining the binding and maximum use depths of all variables *)
64      fun assignDepths (IL.Program{      fun assignDepths (IL.Program{
65              props,
66            globalInit,            globalInit,
67            initially = IL.Initially{rangeInit, iters, create, ...},            initially = IL.Initially{rangeInit, iters, create, ...},
68            strands            strands
69          }) = let          }) = let
70            fun setMaxUse depth x = (case peekUseDepth x            fun setMaxUse depth x = if (depth > getUseDepth x)
71                   of NONE => setUseDepth(x, depth)                  then setUseDepth(x, depth)
72                    | SOME d => if (depth > d) then setUseDepth(x, depth) else ()                  else ()
                 (* end case *))  
73            fun doNode depth nd = (case IL.Node.kind nd            fun doNode depth nd = (case IL.Node.kind nd
74                   of IL.EXIT{kind, live, ...} => (case kind                   of IL.EXIT{kind, live, ...} => (case kind
75                         of ExitKind.FRAGMENT => List.app (setMaxUse depth) live                         of ExitKind.FRAGMENT => List.app (setMaxUse depth) live
                         | ExitKind.SINIT => List.app (setMaxUse depth) live  
76                          | ExitKind.RETURN => List.app (setMaxUse depth) live                          | ExitKind.RETURN => List.app (setMaxUse depth) live
77                          | _ => () (* we don't count ACTIVE, etc. as uses *)                          | _ => () (* we don't count ACTIVE, etc. as uses *)
78                        (* end case *))                        (* end case *))
# Line 110  Line 81 
81                        List.app (fn x => setBindDepth(x, depth)) (IL.Node.defs nd))                        List.app (fn x => setBindDepth(x, depth)) (IL.Node.defs nd))
82                  (* end case *))                  (* end case *))
83            fun doCFG (depth, cfg) = IL.CFG.apply (doNode depth) cfg            fun doCFG (depth, cfg) = IL.CFG.apply (doNode depth) cfg
84            fun assignDepthsForMethod state (IL.Method{stateIn, body, ...}) = let            fun assignDepthsForMethod state (IL.Method{body, ...}) = let
85                  val stateInVec = Vector.fromList stateIn                (* check to see which state variables are invariant *)
86                (* check to see which state variables are invariant on the path from                  fun doMethodNode nd = (case IL.Node.kind nd
87                 * the method entry to this point.                         of IL.SAVE{lhs, rhs, ...} => let
88                 *)                              fun varying () = (
89                  fun chk (_, []) = ()                                    setVarying(lhs, true);
90                    | chk (i, x::xs) = let                                    setMaxUse methodScope rhs)
                       val x' = Vector.sub(stateInVec, i)  
91                        in                        in
92                          if V.same(x, x')                              (* check to see if the state variable is varying on the path to
93                            then ()                               * this node.
94                            else setVarying (x', true);                               *)
95                          chk (i+1, xs)                                case V.binding rhs
96                                   of IL.VB_RHS(IL.STATE x) =>
97                                        if StV.same(x, lhs)
98                                        (* we don't count non-varying save uses of variables as setting
99                                         * the scope of a variable.  This will allow us to determine
100                                         * which state variables are actually used in a method, since
101                                         * those will be bound to variables with methodScope.
102                                         *)
103                                          then setMaxUse strandScope rhs
104                                          else varying()
105                                    | _ => varying()
106                                  (* end case *)
107                         end                         end
                 fun doMethodNode nd = (case IL.Node.kind nd  
                        of IL.EXIT{live, ...} => chk (0, live)  
108                          | _ => doNode methodScope nd                          | _ => doNode methodScope nd
109                        (* end case *))                        (* end case *))
110                (* this function is used to propagate info from stateIn variables to state *)                  in
111                  fun propInfo ((_, x), x') = (                    IL.CFG.apply doMethodNode body
                       if isVarying x' then setVarying(x, true) else ();  
                       setMaxUse (getUseDepth x') x)  
                 in  
                   List.app (fn x => setBindDepth(x, methodStateScope)) stateIn;  
                   IL.CFG.apply doMethodNode body;  
                 (* need to propagate maxUse from stateIn variables to state variables *)  
                   ListPair.appEq propInfo (state, stateIn)  
112                  end                  end
           fun copyDepthsForMethod state (IL.Method{stateIn, ...}) =  
                 ListPair.appEq (fn ((_, x), x') => setUseDepth(x', getUseDepth x)) (state, stateIn)  
113          (* assign use depths for a strand.  The state variables are a bit tricky.  We first          (* assign use depths for a strand.  The state variables are a bit tricky.  We first
114           * propagate information from the stateInit and methods up to the state-variable           * propagate information from the stateInit and methods up to the state-variable
115           * list.  Then we copy the accumulated use-depth information back down to the           * list.  Then we copy the accumulated use-depth information back down to the
# Line 147  Line 117 
117           *)           *)
118            fun doStrand (IL.Strand{params, state, stateInit, methods, ...}) = (            fun doStrand (IL.Strand{params, state, stateInit, methods, ...}) = (
119                  List.app (fn x => setBindDepth(x, paramScope)) params;                  List.app (fn x => setBindDepth(x, paramScope)) params;
               (* output state variables are marked as methodStateScope *)  
                 List.app (fn (true, x) => setUseDepth(x, methodStateScope) | _ => ()) state;  
120                (* assign depths for the stateInit code *)                (* assign depths for the stateInit code *)
121                  doCFG (strandScope, stateInit);                  doCFG (strandScope, stateInit);
122                (* propagate maxUse from exit variables of stateInit to the state-variable list *)                (* examine the methods *)
123                  ListPair.appEq                  List.app (assignDepthsForMethod state) methods)
                   (fn ((_, x), x') => setMaxUse (getUseDepth x') x)  
                     (state, IL.CFG.liveAtExit stateInit);  
                 List.app (assignDepthsForMethod state) methods;  
               (* now we propagate use info back down *)  
                 ListPair.appEq  
                   (fn ((_, x), x') => setUseDepth(x', getUseDepth x))  
                     (state, IL.CFG.liveAtExit stateInit);  
                 List.app (copyDepthsForMethod state) methods)  
124            in            in
125              doCFG (globalScope, globalInit);              doCFG (globalScope, globalInit);
126            (* do initially code *)            (* do initially code *)
# Line 182  Line 142 
142     * really global.  The others are local.     * really global.  The others are local.
143     *)     *)
144      fun assignScopeForGlobalInit globalInit = let      fun assignScopeForGlobalInit globalInit = let
145            fun doNode nd = let            fun isGlobal x = (getUseDepth x > globalScope)
                 fun setBindDepth x = let  
                       val scope = if getUseDepth x > globalScope then Global else Local  
                       in  
                         setVarScope (x, scope)  
                       end  
                 in  
                   List.app setBindDepth (IL.Node.defs nd)  
                 end  
           val _ = IL.CFG.apply doNode globalInit  
146            in            in
147            (* create a new exit node that only has those globals with Global scope *)            (* create a new exit node that only has those globals with Global scope *)
148              IL.CFG.updateExit (globalInit, fn live => List.filter isGlobal live)              IL.CFG.updateExit (globalInit, fn live => List.filter isGlobal live)
149            end            end
150    
151    (* Assign variable scopes to variables that are initialized in the initial-strand creation    (* insert a sequence of statements (initCFG) between the entry node of cfg and its
152     * code.  Since the scoping rules for Diderot limit these variables to be used in this     * successor.
    * scope, all of them are marked as having Local scope,  
153     *)     *)
154      fun assignScopeForInitially (initially as IL.Initially{rangeInit, iters, create, ...}) = let      fun prependCFG (initCFG, cfg) =
155            fun setScope x = setVarScope(x, Local)            if IL.CFG.isEmpty initCFG
156            fun doNode nd = List.app setScope (IL.Node.defs nd)              then cfg
157            in              else let
158              IL.CFG.apply doNode rangeInit;                val initEntry = IL.CFG.entry cfg
159              List.app (fn (i, _, _) => setScope i) iters;                val IL.ENTRY{succ as ref fstNd}  = IL.Node.kind initEntry
160              IL.CFG.apply doNode (#1 create);                val IL.CFG{entry, exit} = initCFG
161              initially                in
162                    IL.Node.replaceInEdge {src = initEntry, oldDst = fstNd, dst = entry};
163                    IL.Node.replaceOutEdge {oldSrc = initEntry, src = exit, dst = fstNd};
164                    cfg
165            end            end
166    
167    (* Assign variable scopes to variables that are used in a strand *)    (* Assign variable scopes to variables that are used in a strand *)
168      fun assignScopeForStrand (strand as IL.Strand{name, params, state, stateInit, methods}) = let      fun assignScopeForStrand (strand as IL.Strand{name, params, state, stateInit, methods}) = let
169          (* assign variable scopes for variables that are defined in the stateInit code *)  (* FIXME: strand state variables that are only used in the stateInit code can be replaced by local vars *)
           val _ = let  
                 fun doVar x = if (getUseDepth x > strandScope)  
                       then setVarScope(x, StrandState)  
                       else setVarScope(x, Local)  
                 fun doNode nd = List.app doVar (IL.Node.defs nd)  
                 in  
                   IL.CFG.apply doNode stateInit  
                 end  
         (* assign variable scope for the state variables; state variables (other than the  
          * output) that are not used in the strand methods can be reclassified as Local.  
          * Note that this pass may change some of the assignments from the processing of stateInit.  
          *)  
           val filteredState = let  
                 fun setScope (isOut, x) =  
                       if isVarying x  
                         then (setVarScope(x, StrandState); true)  
                       else if isOut orelse (getUseDepth x > strandScope)  
                         then (setVarScope(x, StrandConstState); true)  
                         else (  
                           setVarScope(x, Local);  
                           false)  
                 in  
                   List.filter setScope state  
                 end  
170          (* for any parameter that is used inside methods, we need to introduce a          (* for any parameter that is used inside methods, we need to introduce a
171           * shadow state variable.  Here we compute the list of parameters that are           * shadow state variable.  Here we compute the list of parameters that are
172           * used inside strand methods, the new state variables that we create to           * used inside strand methods, the new state variables that we create to
173           * shadow them, and the statements to initialize the shadow variables.           * shadow them, and the statements to initialize the shadow variables.
174           *)           *)
175            val (usedParams, shadowVars, initShadowVars) = let            val (usedParams, shadowVars, initShadowVars) = let
176                  fun chkParam (x, (usedParams, shadowVars, inits)) = (                  fun chkParam (x, (usedParams, shadowVars, initCFG)) = (
                       setVarScope (x, StrandParam);  (* set the scope while we're at it *)  
177                        if getUseDepth x > strandScope                        if getUseDepth x > strandScope
178                          then let                          then let
179                            val x' = V.copy x                            val x' = StV.new(false, V.name x, V.ty x)
180                            val init = (x', IL.VAR x)                            val initCFG = IL.CFG.appendNode (initCFG, IL.Node.mkSAVE(x', x))
181                            in                            in
182                              LowILCensus.inc x;                              LowILCensus.inc x;
183                              setUseDepth(x', getUseDepth x);                              (x::usedParams, x'::shadowVars, initCFG)
                             setVarScope (x', StrandConstState);  
                             (x::usedParams, (false, x')::shadowVars, init::inits)  
184                            end                            end
185                          else (usedParams, shadowVars, inits))                          else (usedParams, shadowVars, initCFG))
186                  val (xs, ys, stms) = List.foldr chkParam ([], [], []) params                  val (xs, ys, initCFG) = List.foldr chkParam ([], [], IL.CFG.empty) params
187                  in                  in
188                    (xs, ys, IL.CFG.mkBlock stms)                    (xs, ys, initCFG)
189                  end                  end
190          (* prepend the stateInit CFG with the shadow-variable initialization *)          (* prepend the stateInit CFG with the shadow-variable initialization *)
191            val stateInit = if IL.CFG.isEmpty initShadowVars            val stateInit = prependCFG(initShadowVars, stateInit)
                 then stateInit  
                 else let  
                   val initEntry = IL.CFG.entry stateInit  
                   val IL.ENTRY{succ as ref fstNd}  = IL.Node.kind initEntry  
                   val IL.CFG{entry, exit} = initShadowVars  
                   in  
                     IL.Node.replaceInEdge {src = initEntry, oldDst = fstNd, dst = entry};  
                     IL.Node.replaceOutEdge {oldSrc = initEntry, src = exit, dst = fstNd};  
                     stateInit  
                   end  
         (* rewrite the exit node of the stateInit to return only the strand state variables. *)  
           val stateInit = let  
                 fun filterSV ((_, sv), x, xs) = (case varScope sv  
                        of StrandConstState => x::xs  
                         | StrandState => x::xs  
                         | _ => xs  
                       (* end case *))  
                 fun f live = (List.map #2 shadowVars)  
                         @ ListPair.foldrEq filterSV [] (state, live)  
                 in  
                   IL.CFG.updateExit (stateInit, f)  
                 end  
192          (* assign variable scopes for variables in a method and rename uses of the parameters *)          (* assign variable scopes for variables in a method and rename uses of the parameters *)
193            fun doMethod (IL.Method{name, stateIn, body}) = let            fun doMethod (IL.Method{name, body}) = let
194                (* filter out any state variables that have been given Local scope and set                (* create local names for the parameters and the code to read them out from the
195                 * the scope for the local copies of the variables.                 * shadow state variables.
196                 *)                 *)
197                  val filteredStateIn = let                  val (env, loadCFG) = let
198                        fun chk ((_, x), x', xs) = let                        fun f (x::xs, y::ys, env, loadCFG) = let
199                              val scope = varScope x                              val x' = V.copy x
200                                val env = VMap.insert(env, x, x')
201                                val loadCFG = IL.CFG.appendNode (loadCFG, IL.Node.mkASSIGN(x', IL.STATE y))
202                              in                              in
203                                setVarScope (x', scope);                                f (xs, ys, env, loadCFG)
                               if scope = Local then xs else x'::xs  
204                              end                              end
205                            | f ([], [], env, loadCFG) = (env, loadCFG)
206                        in                        in
207                          ListPair.foldrEq chk [] (state, stateIn)                          f (usedParams, shadowVars, VMap.empty, IL.CFG.empty)
                       end  
               (* generate the extra shadow variables and initialize the environment to map  
                * parameters to their shadows.  
                *)  
                 val (env, extraVars) = List.foldr  
                       (fn (x, (env, xs)) => let  
                           val x' = IL.Var.copy x  
                           in  
                             setUseDepth(x', getUseDepth x);  
                             setVarScope (x', StrandConstState);  
                             (VMap.insert(env, x, x'), x'::xs)  
208                            end                            end
209                          ) (VMap.empty, []) usedParams                (* rename used parameters *)
210                  fun rename x = (case VMap.find (env, x)                  fun rename x = (case VMap.find (env, x)
211                         of NONE => x                         of NONE => x
212                          | SOME x' => (                          | SOME x' => (
# Line 319  Line 214 
214                              LowILCensus.dec x; LowILCensus.inc x';                              LowILCensus.dec x; LowILCensus.inc x';
215                              x')                              x')
216                        (* end case *))                        (* end case *))
217                (* set the variable scope for variables defined in a method *)                (* process method-body nodes.  We rename parameters to the local variable that
218                  fun setScope x = if getUseDepth x > methodScope                 * is read out from the shadow state variable and we remove save nodes for non-varying
219                        then setVarScope (x, StrandState)                 * state variables.
220                        else setVarScope (x, Local)                 *)
               (* in case the exit node get rewritten, we need to reset it *)  
                 val exitNd = ref(IL.CFG.exit body)  
               (* do we need to filter the output states of methods? *)  
                 val outStateNeedsFiltering = List.exists (fn (_, x) => varScope x <> StrandState) state  
               (* rewrite a node if necessary *)  
221                  fun doNode nd = let                  fun doNode nd = let
222                        fun changed x = VMap.inDomain(env, x)                        fun changed x = VMap.inDomain(env, x)
223                        val renameList = List.map rename                        val renameList = List.map rename
224                        in                        in
225                          case IL.Node.kind nd                          case IL.Node.kind nd
226                           of IL.JOIN{phis, ...} => let                           of IL.JOIN{phis, ...} => let
227                                fun doPhi (lhs, rhs) = (                                fun doPhi (lhs, rhs) = (lhs, renameList rhs)
                                     setScope lhs;  
                                     (lhs, renameList rhs))  
228                                in                                in
229                                  phis := List.map doPhi (!phis)                                  phis := List.map doPhi (!phis)
230                                end                                end
# Line 357  Line 245 
245                            | IL.ASSIGN{stm=(lhs, rhs), ...} => let                            | IL.ASSIGN{stm=(lhs, rhs), ...} => let
246                                fun replace rhs = IL.CFG.replaceNode(nd, IL.Node.mkASSIGN(lhs, rhs))                                fun replace rhs = IL.CFG.replaceNode(nd, IL.Node.mkASSIGN(lhs, rhs))
247                                in                                in
                                 setScope lhs;  
248                                  case rhs                                  case rhs
249                                   of IL.VAR x => if changed x                                   of IL.STATE x => ()
250                                      | IL.VAR x => if changed x
251                                        then replace (IL.VAR(rename x))                                        then replace (IL.VAR(rename x))
252                                        else ()                                        else ()
253                                    | IL.LIT _ => ()                                    | IL.LIT _ => ()
# Line 374  Line 262 
262                                        else ()                                        else ()
263                                  (* end case *)                                  (* end case *)
264                                end                                end
265                              | IL.MASSIGN{stm=(lhs, rator, args), ...} =>
266                                  if List.exists changed args
267                                    then IL.CFG.replaceNode(nd, IL.Node.mkMASSIGN(lhs, rator, renameList args))
268                                    else ()
269                            | IL.NEW{strand, args, ...} =>                            | IL.NEW{strand, args, ...} =>
270                                if List.exists changed args                                if List.exists changed args
271                                  then IL.CFG.replaceNode(                                  then IL.CFG.replaceNode(
272                                    nd,                                    nd,
273                                    IL.Node.mkNEW{strand=strand, args=renameList args})                                    IL.Node.mkNEW{strand=strand, args=renameList args})
274                                  else ()                                  else ()
275                            | IL.EXIT{kind=ExitKind.DIE, ...} => ()                            | IL.SAVE{lhs, rhs, ...} => if (isVarying lhs)
276                            | IL.EXIT{kind, live, ...} =>                                then ()
277                                if outStateNeedsFiltering                                else IL.CFG.deleteNode nd
                                 then let (* filter out StrandConstState and Local vars *)  
                                   fun chkVar ((_, x), x', xs) = if (varScope x <> StrandState)  
                                         then xs  
                                         else x' :: xs  
                                   val live' = ListPair.foldrEq chkVar [] (state, live)  
                                   val newNd = IL.Node.mkEXIT(kind, live')  
                                   in  
                                     if IL.Node.same(nd, !exitNd)  
                                       then exitNd := newNd  
                                       else ();  
                                     IL.CFG.replaceNode (nd, newNd)  
                                   end  
                                 else ()  
278                            | _ => ()                            | _ => ()
279                          (* end case *)                          (* end case *)
280                        end                        end
# Line 403  Line 282 
282                  in                  in
283                    IL.Method{                    IL.Method{
284                        name = name,                        name = name,
285                        stateIn = extraVars @ filteredStateIn,                        body = prependCFG (loadCFG, body)
                       body = IL.CFG{entry = IL.CFG.entry body, exit = !exitNd}  
286                      }                      }
287                  end                  end
288            in            in
289              IL.Strand{              IL.Strand{
290                  name = name,                  name = name,
291                  params = params,                  params = params,
292                  state = shadowVars @ filteredState,                  state = shadowVars @ state,
293                  stateInit = stateInit,                  stateInit = stateInit,
294                  methods = List.map doMethod methods                  methods = List.map doMethod methods
295                }                }
296            end            end
297    
298      fun optimize prog = let      fun optimize prog = let
299            val IL.Program{globalInit, initially, strands} = prog            val IL.Program{props, globalInit, initially, strands} = prog
300          (* first we compute binding and use depths *)          (* first we compute binding and use depths *)
301            val _ = assignDepths prog            val _ = assignDepths prog
302            (* then rewrite the code *)
303            val globalInit = assignScopeForGlobalInit globalInit            val globalInit = assignScopeForGlobalInit globalInit
           val initially = assignScopeForInitially initially  
304            val strands = List.map assignScopeForStrand strands            val strands = List.map assignScopeForStrand strands
305            in            in
306              IL.Program{globalInit=globalInit, initially=initially, strands=strands}              IL.Program{props=props, globalInit=globalInit, initially=initially, strands=strands}
307            end            end
308    
309    end    end

Legend:
Removed from v.1232  
changed lines
  Added in v.1640

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0