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

SCM Repository

[diderot] Annotation of /branches/vis15/src/compiler/simplify/simplify.sml
ViewVC logotype

Annotation of /branches/vis15/src/compiler/simplify/simplify.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3452 - (view) (download)

1 : jhr 3437 (* simplify.sml
2 :     *
3 :     * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu)
4 :     *
5 :     * COPYRIGHT (c) 2015 The University of Chicago
6 :     * All rights reserved.
7 :     *
8 :     * Simplify the AST representation.
9 :     *)
10 :    
11 :     structure Simplify : sig
12 :    
13 :     val transform : Error.err_stream * AST.program -> Simple.program
14 :    
15 :     end = struct
16 :    
17 :     structure TU = TypeUtil
18 :     structure S = Simple
19 : jhr 3445 structure STy = SimpleTypes
20 :     structure Ty = Types
21 : jhr 3437 structure VMap = Var.Map
22 :    
23 : jhr 3445 (* convert a Types.ty to a SimpleTypes.ty *)
24 :     fun cvtTy ty = (case ty
25 :     of Ty.T_Var(Ty.TV{bind, ...}) => (case !bind
26 :     of NONE => raise Fail "unresolved type variable"
27 :     | SOME ty => cvtTy ty
28 :     (* end case *))
29 :     | Ty.T_Bool => STy.T_Bool
30 :     | Ty.T_Int => STy.T_Int
31 :     | Ty.T_String => STy.T_String
32 :     | Ty.T_Sequence(ty, NONE) => STy.T_Sequence(cvtTy ty, NONE)
33 : jhr 3452 | Ty.T_Sequence(ty, SOME dim) => STy.T_Sequence(cvtTy ty, SOME(TU.monoDim dim))
34 : jhr 3445 | Ty.T_Named id => STy.T_Named id
35 :     | Ty.T_Kernel n => STy.T_Kernel(TU.monoDiff n)
36 :     | Ty.T_Tensor shape => STy.T_Tensor(TU.monoShape shape)
37 :     | Ty.T_Image{dim, shape} => STy.T_Image{
38 :     dim = TU.monoDim dim,
39 :     shape = TU.monoShape shape
40 :     }
41 :     | Ty.T_Field{diff, dim, shape} => STy.T_Field{
42 :     diff = TU.monoDiff diff,
43 :     dim = TU.monoDim dim,
44 :     shape = TU.monoShape shape
45 :     }
46 : jhr 3452 | Ty.T_Fun(tys1, ty2) => STy.T_Fun(List.map cvtTy tys1, cvtTy ty2)
47 : jhr 3445 (* end case *))
48 : jhr 3437
49 :     fun newTemp ty = SimpleVar.new ("_t", SimpleVar.LocalVar, ty)
50 :    
51 : jhr 3452 datatype env = E of {
52 :     errStrm : Error.err_stream,
53 :     vMap : SimpleVar.t VMap.map
54 :     }
55 :    
56 :     fun newEnv errStrm = E{errStrm=errStrm, vMap=VMap.empty}
57 :    
58 :     fun errStream (E{errStrm, ...}) = errStrm
59 :    
60 : jhr 3437 (* convert an AST variable to a Simple variable *)
61 : jhr 3452 fun cvtVar (E{errStrm, vMap}, x) = let
62 :     val x' = SimpleVar.new (Var.nameOf x, Var.kindOf x, cvtTy(Var.monoTypeOf x))
63 : jhr 3437 in
64 : jhr 3452 (x', E{errStrm=errStrm, vMap=VMap.insert(vMap, x, x')})
65 : jhr 3437 end
66 :    
67 :     fun cvtVars (env, xs) = List.foldr
68 :     (fn (x, (xs, env)) => let
69 :     val (x', env) = cvtVar(env, x)
70 :     in
71 :     (x'::xs, env)
72 :     end) ([], env) xs
73 :    
74 : jhr 3452 fun lookupVar (E{vMap, ...}, x) = (case VMap.find (vMap, x)
75 : jhr 3437 of SOME x' => x'
76 :     | NONE => raise Fail(concat["lookupVar(", Var.uniqueNameOf x, ")"])
77 :     (* end case *))
78 :    
79 :     (* make a block out of a list of statements that are in reverse order *)
80 :     fun mkBlock stms = S.Block(List.rev stms)
81 :    
82 : jhr 3452 fun inputImage (env, nrrd, dim, shape) = (
83 :     case ImageInfo.fromNrrd(NrrdInfo.getInfo(errStream env, nrrd), dim, shape)
84 : jhr 3437 of NONE => raise Fail(concat["nrrd file \"", nrrd, "\" does not have expected type"])
85 : jhr 3452 | SOME info => S.Proxy(nrrd, info)
86 : jhr 3437 (* end case *))
87 :    
88 :     datatype 'a ctl_flow_info
89 :     = EXIT (* stm sequence always exits; no pruning so far *)
90 :     | PRUNE of 'a (* stm sequence always exits at last stm in argument, which
91 : jhr 3445 * is either a block or stm list *)
92 : jhr 3437 | CONT (* stm sequence falls through *)
93 :     | EDIT of 'a (* pruned code that has non-exiting paths *)
94 :    
95 :     fun pruneUnreachableCode (blk as S.Block stms) = let
96 :     fun isExit S.S_Die = true
97 :     | isExit S.S_Stabilize = true
98 :     | isExit (S.S_Return _) = true
99 :     | isExit _ = false
100 :     fun pruneStms [] = CONT
101 :     | pruneStms [S.S_IfThenElse(x, blk1, blk2)] = (
102 :     case pruneIf(x, blk1, blk2)
103 :     of EXIT => EXIT
104 :     | PRUNE stm => PRUNE[stm]
105 :     | CONT => CONT
106 :     | EDIT stm => EDIT[stm]
107 :     (* end case *))
108 :     | pruneStms [stm] = if isExit stm then EXIT else CONT
109 :     | pruneStms ((stm as S.S_IfThenElse(x, blk1, blk2))::stms) = (
110 :     case pruneIf(x, blk1, blk2)
111 :     of EXIT => PRUNE[stm]
112 :     | PRUNE stm => PRUNE[stm]
113 :     | CONT => (case pruneStms stms
114 :     of PRUNE stms => PRUNE(stm::stms)
115 :     | EDIT stms => EDIT(stm::stms)
116 :     | EXIT => EXIT (* different instances of ctl_flow_info *)
117 :     | CONT => CONT
118 :     (* end case *))
119 :     | EDIT stm => (case pruneStms stms
120 :     of PRUNE stms => PRUNE(stm::stms)
121 :     | EDIT stms => EDIT(stm::stms)
122 :     | _ => EDIT(stm::stms)
123 :     (* end case *))
124 :     (* end case *))
125 :     | pruneStms (stm::stms) = if isExit stm
126 :     then PRUNE[stm]
127 :     else (case pruneStms stms
128 :     of PRUNE stms => PRUNE(stm::stms)
129 :     | EDIT stms => EDIT(stm::stms)
130 :     | info => info
131 :     (* end case *))
132 :     and pruneIf (x, blk1, blk2) = (case (pruneBlk blk1, pruneBlk blk2)
133 :     of (EXIT, EXIT ) => EXIT
134 :     | (CONT, CONT ) => CONT
135 :     | (CONT, EXIT ) => CONT
136 :     | (EXIT, CONT ) => CONT
137 :     | (CONT, EDIT blk2 ) => EDIT(S.S_IfThenElse(x, blk1, blk2))
138 :     | (EDIT blk1, CONT ) => EDIT(S.S_IfThenElse(x, blk1, blk2))
139 :     | (CONT, PRUNE blk2) => EDIT(S.S_IfThenElse(x, blk1, blk2))
140 :     | (PRUNE blk1, CONT ) => EDIT(S.S_IfThenElse(x, blk1, blk2))
141 :     | (EXIT, EDIT blk2 ) => EDIT(S.S_IfThenElse(x, blk1, blk2))
142 :     | (EDIT blk1, EXIT ) => EDIT(S.S_IfThenElse(x, blk1, blk2))
143 :     | (EDIT blk1, EDIT blk2 ) => EDIT(S.S_IfThenElse(x, blk1, blk2))
144 :     | (EDIT blk1, PRUNE blk2) => EDIT(S.S_IfThenElse(x, blk1, blk2))
145 :     | (PRUNE blk1, EDIT blk2 ) => EDIT(S.S_IfThenElse(x, blk1, blk2))
146 :     | (EXIT, PRUNE blk2) => PRUNE(S.S_IfThenElse(x, blk1, blk2))
147 :     | (PRUNE blk1, EXIT ) => PRUNE(S.S_IfThenElse(x, blk1, blk2))
148 :     | (PRUNE blk1, PRUNE blk2) => PRUNE(S.S_IfThenElse(x, blk1, blk2))
149 :     (* end case *))
150 :     and pruneBlk (S.Block stms) = (case pruneStms stms
151 :     of PRUNE stms => PRUNE(S.Block stms)
152 :     | EDIT stms => EDIT(S.Block stms)
153 :     | EXIT => EXIT (* different instances of ctl_flow_info *)
154 :     | CONT => CONT
155 :     (* end case *))
156 :     in
157 :     case pruneBlk blk
158 :     of PRUNE blk => blk
159 :     | EDIT blk => blk
160 :     | _=> blk
161 :     (* end case *)
162 :     end
163 :    
164 :     (* simplify a statement into a single statement (i.e., a block if it expands
165 :     * into more than one new statement).
166 :     *)
167 : jhr 3452 fun simplifyBlock env stm = mkBlock (#1 (simplifyStmt (env, stm, [])))
168 : jhr 3437
169 :     (* simplify the statement stm where stms is a reverse-order list of preceeding simplified
170 :     * statements. This function returns a reverse-order list of simplified statements.
171 :     * Note that error reporting is done in the typechecker, but it does not prune unreachable
172 :     * code.
173 :     *)
174 :     and simplifyStmt (env, stm, stms) = (case stm
175 :     of AST.S_Block body => let
176 :     fun simplify (_, [], stms) = stms
177 :     | simplify (env', stm::r, stms) = let
178 :     val (stms, env') = simplifyStmt (env', stm, stms)
179 :     in
180 :     simplify (env', r, stms)
181 :     end
182 :     in
183 :     (simplify (env, body, stms), env)
184 :     end
185 : jhr 3452 | AST.S_Decl(x, NONE) => let
186 :     val (x', env) = cvtVar(env, x)
187 :     in
188 :     (* QUESTION: where do we declare x? *)
189 :     (stms, env)
190 :     end
191 :     | AST.S_Decl(x, SOME e) => let
192 : jhr 3437 val (stms, e') = simplifyExp (env, e, stms)
193 :     val (x', env) = cvtVar(env, x)
194 :     in
195 :     (S.S_Assign(x', e') :: stms, env)
196 :     end
197 :     | AST.S_IfThenElse(e, s1, s2) => let
198 :     val (stms, x) = simplifyExpToVar (env, e, stms)
199 : jhr 3452 val s1 = simplifyBlock env s1
200 :     val s2 = simplifyBlock env s2
201 : jhr 3437 in
202 :     (S.S_IfThenElse(x, s1, s2) :: stms, env)
203 :     end
204 : jhr 3452 | AST.S_Assign((x, _), e) => let
205 : jhr 3437 val (stms, e') = simplifyExp (env, e, stms)
206 :     in
207 :     (S.S_Assign(lookupVar(env, x), e') :: stms, env)
208 :     end
209 :     | AST.S_New(name, args) => let
210 :     val (stms, xs) = simplifyExpsToVars (env, args, stms)
211 :     in
212 :     (S.S_New(name, xs) :: stms, env)
213 :     end
214 :     | AST.S_Continue => (S.S_Continue :: stms, env)
215 :     | AST.S_Die => (S.S_Die :: stms, env)
216 :     | AST.S_Stabilize => (S.S_Stabilize :: stms, env)
217 :     | AST.S_Return e => let
218 :     val (stms, x) = simplifyExpToVar (env, e, stms)
219 :     in
220 :     (S.S_Return x :: stms, env)
221 :     end
222 :     | AST.S_Print args => let
223 :     val (stms, xs) = simplifyExpsToVars (env, args, stms)
224 :     in
225 :     (S.S_Print xs :: stms, env)
226 :     end
227 :     (* end case *))
228 :    
229 :     and simplifyExp (env, exp, stms) = let
230 : jhr 3452 fun doPrimApply (f, tyArgs, args, ty) = let
231 : jhr 3437 val (stms, xs) = simplifyExpsToVars (env, args, stms)
232 :     in
233 :     case Var.kindOf f
234 : jhr 3452 of Var.BasisVar => let
235 : jhr 3437 fun cvtTyArg (Types.TYPE tv) = S.TY(cvtTy(TU.resolve tv))
236 :     | cvtTyArg (Types.DIFF dv) = S.DIFF(TU.monoDiff(TU.resolveDiff dv))
237 :     | cvtTyArg (Types.SHAPE sv) = S.SHAPE(TU.monoShape(TU.resolveShape sv))
238 :     | cvtTyArg (Types.DIM dv) = S.DIM(TU.monoDim(TU.resolveDim dv))
239 :     val tyArgs = List.map cvtTyArg tyArgs
240 :     in
241 :     (stms, S.E_Prim(f, tyArgs, xs, cvtTy ty))
242 :     end
243 : jhr 3452 | _ => raise Fail "bogus prim application"
244 : jhr 3437 (* end case *)
245 :     end
246 :     in
247 :     case exp
248 : jhr 3452 of AST.E_Var(x, _) => (case Var.kindOf x
249 : jhr 3437 of Var.BasisVar => let
250 :     val ty = cvtTy(Var.monoTypeOf x)
251 :     val x' = newTemp ty
252 :     val stm = S.S_Assign(x', S.E_Prim(x, [], [], ty))
253 :     in
254 :     (stm::stms, S.E_Var x')
255 :     end
256 :     | _ => (stms, S.E_Var(lookupVar(env, x)))
257 :     (* end case *))
258 :     | AST.E_Lit lit => (stms, S.E_Lit lit)
259 : jhr 3452 | AST.E_Prim(rator, tyArgs, args as [AST.E_Lit(Literal.Int n)], ty) =>
260 : jhr 3437 (* constant-fold negation of integer literals *)
261 :     if Var.same(BasisVars.neg_i, rator)
262 :     then (stms, S.E_Lit(Literal.Int(~n)))
263 : jhr 3452 else doPrimApply (rator, tyArgs, args, ty)
264 :     | AST.E_Prim(rator, tyArgs, args as [AST.E_Lit(Literal.Real f)], ty as Types.T_Tensor sh) =>
265 : jhr 3437 (* constant-fold negation of real literals *)
266 :     if Var.same(BasisVars.neg_i, rator) andalso List.null(TU.monoShape sh)
267 : jhr 3452 then (stms, S.E_Lit(Literal.Real(RealLit.negate f)))
268 :     else doPrimApply (rator, tyArgs, args, ty)
269 :     | AST.E_Prim(f, tyArgs, args, ty) => doPrimApply (f, tyArgs, args, ty)
270 :     | AST.E_Apply((f, _), args, ty) => let
271 :     val (stms, xs) = simplifyExpsToVars (env, args, stms)
272 :     in
273 :     case Var.kindOf f
274 :     of Var.FunVar => (stms, S.E_Apply(lookupVar(env, f), xs, cvtTy ty))
275 :     | _ => raise Fail "bogus application"
276 :     (* end case *)
277 :     end
278 :     | AST.E_Tensor(es, ty) => let
279 : jhr 3437 val (stms, xs) = simplifyExpsToVars (env, es, stms)
280 :     in
281 : jhr 3452 (stms, S.E_Tensor(xs, cvtTy ty))
282 : jhr 3437 end
283 :     | AST.E_Seq(es, ty) => let
284 :     val (stms, xs) = simplifyExpsToVars (env, es, stms)
285 :     in
286 :     (stms, S.E_Seq(xs, cvtTy ty))
287 :     end
288 :     | AST.E_Slice(e, indices, ty) => let (* tensor slicing *)
289 :     val (stms, x) = simplifyExpToVar (env, e, stms)
290 :     fun f ([], ys, stms) = (stms, List.rev ys)
291 :     | f (NONE::es, ys, stms) = f (es, NONE::ys, stms)
292 :     | f (SOME e::es, ys, stms) = let
293 :     val (stms, y) = simplifyExpToVar (env, e, stms)
294 :     in
295 :     f (es, SOME y::ys, stms)
296 :     end
297 :     val (stms, indices) = f (indices, [], stms)
298 :     in
299 :     (stms, S.E_Slice(x, indices, cvtTy ty))
300 :     end
301 :     | AST.E_Cond(e1, e2, e3, ty) => let
302 :     (* a conditional expression gets turned into an if-then-else statememt *)
303 :     val result = newTemp(cvtTy ty)
304 :     val (stms, x) = simplifyExpToVar (env, e1, S.S_Var result :: stms)
305 :     fun simplifyBranch e = let
306 :     val (stms, e) = simplifyExp (env, e, [])
307 :     in
308 :     mkBlock (S.S_Assign(result, e)::stms)
309 :     end
310 :     val s1 = simplifyBranch e2
311 :     val s2 = simplifyBranch e3
312 :     in
313 :     (S.S_IfThenElse(x, s1, s2) :: stms, S.E_Var result)
314 :     end
315 :     | AST.E_LoadNrrd(_, nrrd, ty) => (case cvtTy ty
316 : jhr 3452 of ty as SimpleTypes.T_Sequence(_, NONE) => (stms, S.E_LoadSeq(ty, nrrd))
317 : jhr 3437 | ty as SimpleTypes.T_Image{dim, shape} => (
318 : jhr 3452 case ImageInfo.fromNrrd(NrrdInfo.getInfo(errStream env, nrrd), dim, shape)
319 : jhr 3437 of NONE => raise Fail(concat[
320 :     "nrrd file \"", nrrd, "\" does not have expected type"
321 :     ])
322 :     | SOME info => (stms, S.E_LoadImage(ty, nrrd, info))
323 :     (* end case *))
324 :     | _ => raise Fail "bogus type for E_LoadNrrd"
325 :     (* end case *))
326 :     | AST.E_Coerce{srcTy, dstTy, e} => let
327 :     val (stms, x) = simplifyExpToVar (env, e, stms)
328 :     val dstTy = cvtTy dstTy
329 :     val result = newTemp dstTy
330 :     val rhs = S.E_Coerce{srcTy = cvtTy srcTy, dstTy = dstTy, x = x}
331 :     in
332 :     (S.S_Assign(result, rhs)::stms, S.E_Var result)
333 :     end
334 :     (* end case *)
335 :     end
336 :    
337 :     and simplifyExpToVar (env, exp, stms) = let
338 :     val (stms, e) = simplifyExp (env, exp, stms)
339 :     in
340 :     case e
341 :     of S.E_Var x => (stms, x)
342 :     | _ => let
343 :     val x = newTemp (S.typeOf e)
344 :     in
345 :     (S.S_Assign(x, e)::stms, x)
346 :     end
347 :     (* end case *)
348 :     end
349 :    
350 :     and simplifyExpsToVars (env, exps, stms) = let
351 :     fun f ([], xs, stms) = (stms, List.rev xs)
352 :     | f (e::es, xs, stms) = let
353 :     val (stms, x) = simplifyExpToVar (env, e, stms)
354 :     in
355 :     f (es, x::xs, stms)
356 :     end
357 :     in
358 :     f (exps, [], stms)
359 :     end
360 :    
361 : jhr 3452 fun simplifyStrand (env, AST.Strand{name, params, state, initM, updateM, stabilizeM}) = let
362 :     val (params', env) = cvtVars (env, params)
363 :     fun simplifyState (env, [], xs, stms) = (List.rev xs, mkBlock stms, env)
364 :     | simplifyState (env, (x, optE) :: r, xs, stms) = let
365 :     val (x', env') = cvtVar(env, x)
366 :     in
367 :     case optE
368 :     of NONE => simplifyState (env', r, x'::xs, stms)
369 :     | SOME e => let
370 :     val (stms, e') = simplifyExp (env, e, stms)
371 :     in
372 :     simplifyState (env', r, x'::xs, S.S_Assign(x', e') :: stms)
373 :     end
374 :     (* end case *)
375 :     end
376 :     val (xs, stm, env) = simplifyState (env, state, [], [])
377 : jhr 3437 in
378 : jhr 3452 S.Strand{
379 :     name = name,
380 :     params = params',
381 :     state = xs, stateInit = stm,
382 :     initM = Option.map (simplifyBlock env) initM,
383 :     updateM = simplifyBlock env updateM,
384 :     stabilizeM = Option.map (simplifyBlock env) stabilizeM
385 :     }
386 : jhr 3437 end
387 :    
388 : jhr 3452 fun transform (errStrm, prog) = let
389 :     val AST.Program{
390 :     props, const_dcls, input_dcls, globals, init, strand, create, update
391 :     } = prog
392 :     val inputs' = ref[]
393 :     val globals' = ref[]
394 :     val globalInit = ref[]
395 :     val funcs = ref[]
396 :     fun simplifyConstDcl ((x, SOME e), env) = ??
397 :     fun simplifyInputDcl (((x, optE), desc), env) = ??
398 :     fun simplifyGlobalDcl (AST.D_Var(x, optE), env) = let
399 :     val (x', env) = cvtVar(env, x)
400 :     in
401 :     case optE
402 :     of NONE => (globals' := x' :: !globals'; env)
403 :     | SOME e => let
404 :     val (stms, e') = simplifyExp (env, e, [])
405 :     in
406 :     globals' := x' :: !globals';
407 :     globalInit := S.S_Assign(x', e') :: (stms @ !globalInit);
408 :     env
409 :     end
410 :     (* end case *)
411 :     end
412 :     | simplifyGlobalDcl (AST.D_Func(f, params, body), env) = let
413 :     val (f', env) = cvtVar(env, f)
414 :     val (params', env) = cvtVars (env, params)
415 :     val body' = pruneUnreachableCode (simplifyBlock env body)
416 :     in
417 :     funcs := S.Func{f=f', params=params', body=body'} :: !funcs;
418 :     env
419 :     end
420 :    
421 :     (*
422 :     of AST.D_Input(x, desc, NONE) => let
423 :     val (x', env) = cvtVar(env, x)
424 :     val (ty, init) = (case SimpleVar.typeOf x'
425 :     of ty as SimpleTypes.T_Image{dim, shape} => let
426 :     val info = ImageInfo.mkInfo(dim, shape)
427 :     in
428 :     (ty, SOME(S.Image info))
429 :     end
430 :     | ty => (ty, NONE)
431 :     (* end case *))
432 :     val inp = S.INP{
433 :     ty = ty,
434 :     name = SimpleVar.nameOf x',
435 :     desc = desc,
436 :     init = init
437 :     }
438 :     in
439 :     inputs := (x', inp) :: !inputs;
440 :     env
441 :     end
442 :     | AST.D_Input(x, desc, SOME(AST.E_LoadNrrd(tvs, nrrd, ty))) => let
443 :     val (x', env) = cvtVar(env, x)
444 :     (* load the nrrd proxy here *)
445 :     val info = NrrdInfo.getInfo nrrd
446 :     val (ty, init) = (case SimpleVar.typeOf x'
447 :     of ty as SimpleTypes.T_Seq(_, NONE) => (ty, S.DynSeq nrrd)
448 :     | ty as SimpleTypes.T_Image{dim, shape} =>
449 :     (ty, inputImage(env, nrrd, dim, shape))
450 :     | _ => raise Fail "impossible"
451 :     (* end case *))
452 :     val inp = S.INP{
453 :     ty = ty,
454 :     name = SimpleVar.nameOf x',
455 :     desc = desc,
456 :     init = SOME init
457 :     }
458 :     in
459 :     inputs := (x', inp) :: !inputs;
460 :     env
461 :     end
462 :     | AST.D_Input(x, desc, SOME e) => let
463 :     val (x', env) = cvtVar(env, x)
464 :     val (stms, e') = simplifyExp (env, e, [])
465 :     val inp = S.INP{
466 :     ty = SimpleVar.typeOf x',
467 :     name = SimpleVar.nameOf x',
468 :     desc = desc,
469 :     init = NONE
470 :     }
471 :     in
472 :     inputs := (x', inp) :: !inputs;
473 :     inputInit := S.S_Assign(x', e') :: (stms @ !inputInit);
474 :     env
475 :     end
476 :     *)
477 :     val env = newEnv errStrm
478 :     val env = List.foldl simplifyConstDcl env const_dcls
479 :     val env = List.foldl simplifyInputDcl env input_dcls
480 :     val env = List.foldl simplifyGlobalDcl env globals
481 :     in
482 :     S.Program{
483 :     props = props,
484 :     inputs = List.rev(!inputs'),
485 :     globals = List.rev(!globals'),
486 :     init = mkBlock (!globalInit),
487 :     funcs = List.rev(!funcs),
488 :     strand = simplifyStrand (env, strand),
489 :     create = ??,
490 :     update = ??
491 :     }
492 :     end
493 :    
494 : jhr 3437 end

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