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

SCM Repository

[diderot] Annotation of /branches/pure-cfg/src/compiler/cl-target/tree-to-cl.sml
ViewVC logotype

Annotation of /branches/pure-cfg/src/compiler/cl-target/tree-to-cl.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1423 - (view) (download)

1 : lamonts 1244 (* tree-to-c.sml
2 : jhr 918 *
3 :     * COPYRIGHT (c) 2011 The Diderot Project (http://diderot-language.cs.uchicago.edu)
4 :     * All rights reserved.
5 :     *
6 : lamonts 1244 * Translate TreeIL to the C version of CLang.
7 : jhr 918 *)
8 :    
9 :     structure TreeToCL : sig
10 :    
11 :     datatype var = V of (CLang.ty * CLang.var)
12 :    
13 :     type env = var TreeIL.Var.Map.map
14 :    
15 :     val trType : TreeIL.Ty.ty -> CLang.ty
16 :    
17 :     val trBlock : env * (env * TreeIL.exp list * CLang.stm -> CLang.stm list) * TreeIL.block -> CLang.stm
18 :    
19 : lamonts 1244 val trFragment : env * TreeIL.block -> env * CLang.stm list
20 :    
21 : jhr 918 val trAssign : env * TreeIL.var * TreeIL.exp -> CLang.stm list
22 :    
23 :     val trExp : env * TreeIL.exp -> CLang.exp
24 :    
25 : jhr 1273 (* vector indexing support. Arguments are: vector, index *)
26 :     val vecIndex : CLang.exp * int -> CLang.exp
27 : jhr 918
28 :     end = struct
29 :    
30 :     structure CL = CLang
31 :     structure RN = RuntimeNames
32 :     structure IL = TreeIL
33 :     structure Op = IL.Op
34 :     structure Ty = IL.Ty
35 :     structure V = IL.Var
36 :    
37 : jhr 1285 datatype var = datatype CLang.typed_var
38 : jhr 918
39 :     type env = var TreeIL.Var.Map.map
40 :    
41 :     fun lookup (env, x) = (case V.Map.find (env, x)
42 : lamonts 1399 of SOME(V(_, x')) => x'
43 :     | NONE => raise Fail(concat["lookup(_, ", V.name x, ")"])
44 :     (* end case *))
45 : jhr 918
46 :     (* integer literal expression *)
47 : jhr 1314 fun intExp (i : int) = CL.mkInt(IntInf.fromInt i)
48 : jhr 918
49 : jhr 1401 (* the type of an image-data pointer. *)
50 :     fun imageDataPtrTy rTy = CL.T_Qual("__global", CL.T_Ptr(CL.T_Num rTy))
51 :    
52 : jhr 918 (* translate TreeIL types to CLang types *)
53 :     fun trType ty = (case ty
54 : jhr 1401 of Ty.BoolTy => CLang.T_Named "bool"
55 :     | Ty.StringTy => CL.charPtr
56 :     | Ty.IVecTy 1 => !RN.gIntTy
57 :     | Ty.IVecTy n => CL.T_Named(RN.ivecTy n)
58 :     | Ty.TensorTy[] => !RN.gRealTy
59 :     | Ty.TensorTy[n] => CL.T_Named(RN.vecTy n)
60 :     | Ty.TensorTy[n, m] => CL.T_Named(RN.matTy(n,m))
61 :     | Ty.AddrTy(ImageInfo.ImgInfo{ty=(_, rTy), ...}) => imageDataPtrTy rTy
62 :     | Ty.ImageTy(ImageInfo.ImgInfo{dim, ...}) => CL.T_Named(RN.imageTy dim)
63 :     | _ => raise Fail(concat["TreeToC.trType(", Ty.toString ty, ")"])
64 :     (* end case *))
65 : jhr 918
66 :     (* generate new variables *)
67 :     local
68 :     val count = ref 0
69 :     fun freshName prefix = let
70 : jhr 1401 val n = !count
71 :     in
72 :     count := n+1;
73 :     concat[prefix, "_", Int.toString n]
74 :     end
75 : jhr 918 in
76 :     fun tmpVar ty = freshName "tmp"
77 :     fun freshVar prefix = freshName prefix
78 :     end (* local *)
79 :    
80 :     (* translate IL basis functions *)
81 : jhr 1422 fun trApply (f, args) = CL.mkApply(ILBasis.toString f, args)
82 : jhr 918
83 : jhr 1273 (* vector indexing support. Arguments are: vector, index *)
84 :     local
85 :     val fields = Vector.fromList [
86 :     "s0", "s1", "s2", "s3",
87 :     "s4", "s5", "s6", "s7",
88 :     "s8", "s9", "sa", "sb",
89 :     "sc", "sd", "se", "sf"
90 :     ]
91 :     in
92 :     fun vecIndex (v, ix) = CL.mkSelect(v, Vector.sub(fields, ix))
93 :     end
94 : jhr 918
95 :     (* translate a variable use *)
96 :     fun trVar (env, x) = (case V.kind x
97 : jhr 1401 of IL.VK_Global => CL.mkIndirect(CL.E_Var RN.globalsVarName, lookup(env, x))
98 :     | IL.VK_State strand => CL.mkIndirect(CL.mkVar "selfIn", lookup(env, x))
99 :     | IL.VK_Local => CL.mkVar(lookup(env, x))
100 :     (* end case *))
101 : jhr 918
102 : jhr 1419 fun castArgs ty = List.map (fn e => CL.mkCast(ty, e))
103 :    
104 : jhr 918 (* Translate a TreeIL operator application to a CLang expression *)
105 :     fun trOp (rator, args) = (case (rator, args)
106 : jhr 1401 of (Op.Add ty, [a, b]) => CL.mkBinOp(a, CL.#+, b)
107 :     | (Op.Sub ty, [a, b]) => CL.mkBinOp(a, CL.#-, b)
108 :     | (Op.Mul ty, [a, b]) => CL.mkBinOp(a, CL.#*, b)
109 :     | (Op.Div ty, [a, b]) => CL.mkBinOp(a, CL.#/, b)
110 :     | (Op.Neg ty, [a]) => CL.mkUnOp(CL.%-, a)
111 :     | (Op.Abs(Ty.IVecTy 1), args) => CL.mkApply("abs", args)
112 :     | (Op.Abs(Ty.TensorTy[]), args) => CL.mkApply(RN.fabs, args)
113 :     | (Op.Abs(Ty.TensorTy[_]), args) => CL.mkApply(RN.fabs, args)
114 :     | (Op.Abs ty, [a]) => raise Fail(concat["Abs<", Ty.toString ty, ">"])
115 :     | (Op.LT ty, [a, b]) => CL.mkBinOp(a, CL.#<, b)
116 :     | (Op.LTE ty, [a, b]) => CL.mkBinOp(a, CL.#<=, b)
117 :     | (Op.EQ ty, [a, b]) => CL.mkBinOp(a, CL.#==, b)
118 :     | (Op.NEQ ty, [a, b]) => CL.mkBinOp(a, CL.#!=, b)
119 :     | (Op.GTE ty, [a, b]) => CL.mkBinOp(a, CL.#>=, b)
120 :     | (Op.GT ty, [a, b]) => CL.mkBinOp(a, CL.#>, b)
121 :     | (Op.Not, [a]) => CL.mkUnOp(CL.%!, a)
122 : jhr 1419 | (Op.Max, args) => CL.mkApply(RN.max, castArgs (!RN.gRealTy) args)
123 :     | (Op.Min, args) => CL.mkApply(RN.min, castArgs (!RN.gRealTy) args)
124 : jhr 1401 | (Op.Clamp ty, [lo, hi, x]) => CL.mkApply(RN.clamp, [x, lo, hi])
125 :     | (Op.Lerp ty, args) => (case ty
126 : lamonts 1423 of Ty.TensorTy[] => CL.mkApply(RN.lerp, castArgs (!RN.gRealTy) args)
127 :     | Ty.TensorTy[n] => CL.mkApply(RN.lerp, castArgs (CL.T_Named(RN.vecTy n)) args)
128 : jhr 1401 | _ => raise Fail(concat[
129 :     "lerp<", Ty.toString ty, "> not supported"
130 :     ])
131 :     (* end case *))
132 :     | (Op.Dot d, args) => CL.E_Apply(RN.dot, args)
133 :     | (Op.MulVecMat(m, n), args) =>
134 :     if (1 < m) andalso (m < 4) andalso (m = n)
135 :     then CL.E_Apply(RN.mulVecMat(m,n), args)
136 :     else raise Fail "unsupported vector-matrix multiply"
137 :     | (Op.MulMatVec(m, n), args) =>
138 :     if (1 < m) andalso (m < 4) andalso (m = n)
139 :     then CL.E_Apply(RN.mulMatVec(m,n), args)
140 :     else raise Fail "unsupported matrix-vector multiply"
141 :     | (Op.MulMatMat(m, n, p), args) =>
142 :     if (1 < m) andalso (m < 4) andalso (m = n) andalso (n = p)
143 :     then CL.E_Apply(RN.mulMatMat(m,n,p), args)
144 :     else raise Fail "unsupported matrix-matrix multiply"
145 :     | (Op.Cross, args) => CL.E_Apply(RN.cross, args)
146 :     | (Op.Select(Ty.IVecTy n, i), [a]) => vecIndex (a, i)
147 :     | (Op.Select(Ty.TensorTy[n], i), [a]) => vecIndex (a, i)
148 :     | (Op.Norm(Ty.TensorTy[n]), args) => CL.E_Apply(RN.length, args)
149 :     | (Op.Norm(Ty.TensorTy[m,n]), args) => CL.E_Apply(RN.norm(m,n), args)
150 :     | (Op.Normalize d, args) => CL.E_Apply(RN.normalize, args)
151 :     | (Op.Scale(Ty.TensorTy[n]), [s, v]) => CL.mkBinOp(s, CL.#*, v)
152 :     | (Op.PrincipleEvec ty, _) => raise Fail "PrincipleEvec unimplemented"
153 :     | (Op.Subscript(Ty.IVecTy n), [v, CL.E_Int(ix, _)]) => vecIndex (v, Int.fromLarge ix)
154 :     | (Op.Subscript(Ty.IVecTy n), [v, ix]) => let
155 :     val unionTy = CL.T_Named(concat["union", Int.toString n, !RN.gIntSuffix, "_t"])
156 :     val vecExp = CL.mkSelect(CL.mkCast(unionTy, v), "i")
157 :     in
158 :     CL.mkSubscript(vecExp, ix)
159 :     end
160 :     | (Op.Subscript(Ty.TensorTy[n]), [v, CL.E_Int(ix, _)]) => vecIndex (v, Int.fromLarge ix)
161 :     | (Op.Subscript(Ty.TensorTy[n]), [v, ix]) => let
162 :     val unionTy = CL.T_Named(concat["union", Int.toString n, !RN.gRealSuffix, "_t"])
163 :     val vecExp = CL.mkSelect(CL.mkCast(unionTy, v), "r")
164 :     in
165 :     CL.mkSubscript(vecExp, ix)
166 :     end
167 :     | (Op.Subscript(Ty.TensorTy[_,_]), [m, ix, CL.E_Int(jx, _)]) =>
168 :     vecIndex(CL.mkSubscript(m, ix), Int.fromLarge jx)
169 :     | (Op.Subscript(Ty.TensorTy[_,n]), [m, ix, jx]) => let
170 :     val unionTy = CL.T_Named(concat["union", Int.toString n, !RN.gRealSuffix, "_t"])
171 :     val vecExp = CL.mkSelect(CL.mkCast(unionTy, CL.mkSubscript(m, ix)), "r")
172 :     in
173 :     CL.mkSubscript(vecExp, jx)
174 :     end
175 :     | (Op.Subscript ty, t::(ixs as _::_)) =>
176 :     raise Fail(concat["Subscript<", Ty.toString ty, "> unsupported"])
177 :     | (Op.Ceiling d, args) => CL.mkApply("ceil", args)
178 :     | (Op.Floor d, args) => CL.mkApply("floor", args)
179 :     | (Op.Round d, args) => CL.mkApply("round", args)
180 :     | (Op.Trunc d, args) => CL.mkApply("trunc", args)
181 :     | (Op.IntToReal, [a]) => CL.mkCast(!RN.gRealTy, a)
182 :     | (Op.RealToInt 1, [a]) => CL.mkCast(!RN.gIntTy, a)
183 :     | (Op.RealToInt d, args) =>
184 :     CL.mkApply(RN.vecftoi d, args)
185 : jhr 918 (* FIXME: need type info *)
186 : jhr 1401 | (Op.ImageAddress(ImageInfo.ImgInfo{ty=(_,rTy), ...}), [a as CL.E_Indirect(_,field)]) => let
187 :     val cTy = imageDataPtrTy rTy
188 :     in
189 :     CL.mkCast(cTy,
190 :     CL.mkSelect(CL.mkVar RN.globalImageDataName, RN.imageDataName field))
191 :     end
192 :     | (Op.LoadVoxels(info, 1), [a]) => let
193 :     val realTy as CL.T_Num rTy = !RN.gRealTy
194 :     val a = CL.E_UnOp(CL.%*, a)
195 :     in
196 :     if (rTy = ImageInfo.sampleTy info)
197 :     then a
198 :     else CL.E_Cast(realTy, a)
199 :     end
200 :     | (Op.LoadVoxels _, [a]) =>
201 :     raise Fail("impossible " ^ Op.toString rator)
202 :     | (Op.PosToImgSpace(ImageInfo.ImgInfo{dim, ...}), [img, pos]) =>
203 :     CL.mkApply(RN.toImageSpace dim, [CL.mkUnOp(CL.%&,img), pos])
204 :     | (Op.TensorToWorldSpace(info, ty), [v, x]) =>
205 : lamonts 1423 CL.mkApply(RN.toWorldSpace ty, [CL.mkUnOp(CL.%&,v), x])
206 : jhr 1401 | (Op.LoadImage info, [a]) =>
207 :     raise Fail("impossible " ^ Op.toString rator)
208 :     | (Op.Inside(ImageInfo.ImgInfo{dim, ...}, s), [pos, img]) =>
209 :     CL.mkApply(RN.inside dim, [pos, CL.mkUnOp(CL.%&,img), intExp s])
210 :     | (Op.Input(ty, name, desc), []) =>
211 :     raise Fail("impossible " ^ Op.toString rator)
212 :     | (Op.InputWithDefault(ty, name, desc), [a]) =>
213 :     raise Fail("impossible " ^ Op.toString rator)
214 :     | _ => raise Fail(concat[
215 :     "unknown or incorrect operator ", Op.toString rator
216 :     ])
217 :     (* end case *))
218 : jhr 918
219 :     fun trExp (env, e) = (case e
220 : jhr 1401 of IL.E_Var x => trVar (env, x)
221 :     | IL.E_Lit(Literal.Int n) => CL.mkIntTy(n, !RN.gIntTy)
222 :     | IL.E_Lit(Literal.Bool b) => CL.mkBool b
223 :     | IL.E_Lit(Literal.Float f) => CL.mkFlt(f, !RN.gRealTy)
224 :     | IL.E_Lit(Literal.String s) => CL.mkStr s
225 :     | IL.E_Op(rator, args) => trOp (rator, trExps(env, args))
226 :     | IL.E_Apply(f, args) => trApply(f, trExps(env, args))
227 :     | IL.E_Cons(Ty.TensorTy[n], args) => CL.mkApply(RN.mkVec n, trExps(env, args))
228 :     | IL.E_Cons(ty, _) => raise Fail(concat["E_Cons(", Ty.toString ty, ", _) in expression"])
229 :     (* end case *))
230 : jhr 918
231 :     and trExps (env, exps) = List.map (fn exp => trExp(env, exp)) exps
232 :    
233 :     fun trAssign (env, lhs, rhs) = let
234 : jhr 1400 val lhs = (case V.kind lhs
235 :     of IL.VK_Global => CL.mkIndirect(CL.E_Var (RN.globalsVarName),lookup(env, lhs))
236 :     | IL.VK_State strand => CL.mkIndirect(CL.mkVar "selfOut", lookup(env, lhs))
237 :     | IL.VK_Local => CL.mkVar(lookup(env, lhs))
238 :     (* end case *))
239 : lamonts 1399 in
240 : jhr 1400 (* certain rhs forms, such as those that return a matrix,
241 :     * require a function call instead of an assignment
242 :     *)
243 :     case rhs
244 :     of IL.E_Op(Op.Add(Ty.TensorTy[m,n]), args) =>
245 :     [CL.mkCall(RN.addMat(m,n), lhs :: trExps(env, args))]
246 :     | IL.E_Op(Op.Sub(Ty.TensorTy[m,n]), args) =>
247 :     [CL.mkCall(RN.subMat(m,n), lhs :: trExps(env, args))]
248 :     | IL.E_Op(Op.Neg(Ty.TensorTy[m,n]), args) =>
249 :     [CL.mkCall(RN.scaleMat(m,n), lhs :: intExp ~1 :: trExps(env, args))]
250 :     | IL.E_Op(Op.Scale(Ty.TensorTy[m,n]), args) =>
251 :     [CL.mkCall(RN.scaleMat(m,n), lhs :: trExps(env, args))]
252 :     | IL.E_Op(Op.MulMatMat(m,n,p), args) =>
253 :     [CL.mkCall(RN.mulMatMat(m,n,p), lhs :: trExps(env, args))]
254 :     | IL.E_Op(Op.Identity n, args) =>
255 :     [CL.mkCall(RN.identityMat n, [lhs])]
256 :     | IL.E_Op(Op.Zero(Ty.TensorTy[m,n]), args) =>
257 :     [CL.mkCall(RN.zeroMat(m,n), [lhs])]
258 : lamonts 1423 | IL.E_Op(Op.TensorToWorldSpace(info, ty as Ty.TensorTy[_,_]), [img,src]) =>
259 :     [CL.mkCall(RN.toWorldSpace ty, lhs :: [CL.mkUnOp(CL.%&,trExp(env, img)),trExp(env, src)] )]
260 : jhr 1400 | IL.E_Op(Op.LoadVoxels(info, n), [a]) =>
261 :     if (n > 1)
262 :     then let
263 :     val stride = ImageInfo.stride info
264 :     val rTy = ImageInfo.sampleTy info
265 :     val vp = freshVar "vp"
266 :     val needsCast = (CL.T_Num rTy <> !RN.gRealTy)
267 :     fun mkLoad i = let
268 :     val e = CL.mkSubscript(CL.mkVar vp, intExp(i*stride))
269 :     in
270 :     if needsCast then CL.mkCast(!RN.gRealTy, e) else e
271 :     end
272 :     in [
273 : jhr 1401 CL.mkDecl(imageDataPtrTy rTy, vp, SOME(CL.I_Exp(trExp(env, a)))),
274 : jhr 1400 CL.mkAssign(lhs,
275 :     CL.mkApply(RN.mkVec n, List.tabulate (n, mkLoad)))
276 :     ] end
277 :     else [CL.mkAssign(lhs, trExp(env, rhs))]
278 :     | IL.E_Cons(Ty.TensorTy[n,m], args) => let
279 :     (* matrices are represented as arrays of union<d><ty>_t vectors *)
280 :     fun doRows (_, []) = []
281 :     | doRows (i, e::es) =
282 : jhr 1402 CL.mkAssign(CL.mkSubscript(lhs, intExp i), e)
283 :     :: doRows (i+1, es)
284 : jhr 1400 in
285 :     doRows (0, trExps(env, args))
286 :     end
287 :     | IL.E_Var x => (case IL.Var.ty x
288 :     of Ty.TensorTy[n,m] => [CL.mkCall(RN.copyMat(n,m), [lhs, trVar(env, x)])]
289 :     | _ => [CL.mkAssign(lhs, trVar(env, x))]
290 :     (* end case *))
291 :     | _ => [CL.mkAssign(lhs, trExp(env, rhs))]
292 :     (* end case *)
293 : lamonts 1399 end
294 : jhr 918
295 : lamonts 1244 fun trLocals (env : env, locals) =
296 : jhr 1400 List.foldl
297 :     (fn (x, env) => V.Map.insert(env, x, V(trType(V.ty x), V.name x)))
298 :     env locals
299 : lamonts 1244
300 :     (* generate code to check the status of runtime-system calls *)
301 :     fun checkSts mkDecl = let
302 : jhr 1400 val sts = freshVar "sts"
303 :     in
304 :     mkDecl sts @
305 :     [CL.mkIfThen(
306 :     CL.mkBinOp(CL.mkVar "DIDEROT_OK", CL.#!=, CL.mkVar sts),
307 :     CL.mkCall("exit", [intExp 1]))]
308 :     end
309 : lamonts 1244
310 :     fun trStms (env, saveState, stms) = let
311 : jhr 1400 fun trStmt (env, stm) = (case stm
312 :     of IL.S_Comment text => [CL.mkComment text]
313 :     | IL.S_Assign(x, exp) => trAssign (env, x, exp)
314 :     | IL.S_IfThen(cond, thenBlk) =>
315 :     [CL.mkIfThen(trExp(env, cond), trBlk(env, saveState, thenBlk))]
316 :     | IL.S_IfThenElse(cond, thenBlk, elseBlk) =>
317 :     [CL.mkIfThenElse(trExp(env, cond),
318 :     trBlk(env, saveState, thenBlk),
319 :     trBlk(env, saveState, elseBlk))]
320 :     | IL.S_New _ => raise Fail "new not supported yet" (* FIXME *)
321 : jhr 1250 (* FIXME: I think that S_LoadImage should never happen in OpenCL code [jhr] *)
322 : jhr 1400 | IL.S_LoadImage(lhs, dim, name) => checkSts (fn sts => let
323 :     val lhs = lookup(env, lhs)
324 :     val name = trExp(env, name)
325 :     val imgTy = CL.T_Named(RN.imageTy dim)
326 :     val loadFn = RN.loadImage dim
327 :     in [
328 :     CL.mkDecl(
329 :     CL.T_Named RN.statusTy, sts,
330 :     SOME(CL.I_Exp(CL.E_Apply(loadFn, [name, CL.mkUnOp(CL.%&, CL.E_Var lhs)]))))
331 :     ] end)
332 : jhr 1250 (* FIXME: I think that S_Input should never happen in OpenCL code [jhr] *)
333 : jhr 1400 | IL.S_Input(lhs, name, desc, optDflt) => checkSts (fn sts => let
334 :     val inputFn = RN.input(V.ty lhs)
335 :     val lhs = lookup(env, lhs)
336 :     val lhs = CL.E_Var lhs
337 :     val (initCode, hasDflt) = (case optDflt
338 :     of SOME e => ([CL.mkAssign(lhs, trExp(env, e))], true)
339 :     | NONE => ([], false)
340 :     (* end case *))
341 :     val code = [
342 :     CL.mkDecl(
343 :     CL.T_Named RN.statusTy, sts,
344 :     SOME(CL.I_Exp(CL.E_Apply(inputFn, [
345 :     CL.E_Str name, CL.mkUnOp(CL.%&, lhs), CL.mkBool hasDflt
346 :     ]))))
347 :     ]
348 :     in
349 :     initCode @ code
350 :     end)
351 :     | IL.S_Exit args =>
352 :     saveState (env, args, CL.mkReturn NONE)
353 : lamonts 1399 | IL.S_Active args =>
354 : jhr 1400 saveState (env, args, CL.mkReturn(SOME(CL.mkVar RN.kActive)))
355 :     | IL.S_Stabilize args =>
356 :     saveState (env, args, CL.mkReturn(SOME(CL.mkVar RN.kStabilize)))
357 :     | IL.S_Die => [CL.mkReturn(SOME(CL.mkVar RN.kDie))]
358 :     (* end case *))
359 :     in
360 :     List.foldr (fn (stm, stms) => trStmt(env, stm)@stms) [] stms
361 :     end
362 : jhr 918
363 : lamonts 1244 and trBlk (env, saveState, IL.Block{locals, body}) = let
364 : jhr 1400 val env = trLocals (env, locals)
365 :     val stms = trStms (env, saveState, body)
366 :     fun mkDecl (x, stms) = (case V.Map.find (env, x)
367 :     of SOME(V(ty, x')) => CL.mkDecl(ty, x', NONE) :: stms
368 :     | NONE => raise Fail(concat["mkDecl(", V.name x, ", _)"])
369 :     (* end case *))
370 :     val stms = List.foldr mkDecl stms locals
371 :     in
372 :     CL.mkBlock stms
373 :     end
374 : lamonts 1244
375 :     fun trFragment (env, IL.Block{locals, body}) = let
376 : jhr 1400 val env = trLocals (env, locals)
377 :     val stms = trStms (env, fn _ => raise Fail "exit in fragment", body)
378 :     fun mkDecl (x, stms) = (case V.Map.find (env, x)
379 :     of SOME(V(ty, x')) => CL.mkDecl(ty, x', NONE) :: stms
380 :     | NONE => raise Fail(concat["mkDecl(", V.name x, ", _)"])
381 :     (* end case *))
382 :     val stms = List.foldr mkDecl stms locals
383 :     in
384 :     (env, stms)
385 :     end
386 : lamonts 1244
387 :     val trBlock = trBlk
388 :    
389 : jhr 918 end

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