2 * Partial-application elimination.
4 * The input to this stage is an IR program where the function arities
5 * are completely uncorrelated. For example, ((int, int, int) -> int) =
6 * ((int) -> ((int) -> ((int) -> int))). What we want is a program
7 * where function arities are exact: if a function type has n arguments,
8 * the value of that type is a real function expecting exactly n
11 * To do this, we basically punt, and each escaping function is
12 * curried: it takes one argument at a time. We convert all the types
13 * in the program so that higher-order function types are curried;
14 * we convert applications so that they apply the right number of
15 * arguments; and we build curry functions to convert normal
16 * functions into curried ones.
18 * Note, we could be smarter than this. One method would be to
19 * look at the function body and see how functions are applied.
20 * However, this gets harder to do when we import some of the
21 * functions. All of those will have to be curried anyway.
23 * ----------------------------------------------------------------
26 * Copyright (C) 2002 Jason Hickey, Caltech
28 * This program is free software; you can redistribute it and/or
29 * modify it under the terms of the GNU General Public License
30 * as published by the Free Software Foundation; either version 2
31 * of the License, or (at your option) any later version.
33 * This program is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 * GNU General Public License for more details.
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
42 * Author: Jason Hickey
43 * @email{jyh@cs.caltech.edu}
57 module Pos
= MakePos
(struct let name = "Aml_ir_partial" end)
60 (************************************************************************
62 ************************************************************************)
65 * The environment keeps track of the names of the curried functions.
67 type cenv
= var
SymbolTable.t
72 let cenv_empty = SymbolTable.empty
75 * Lookup a curry function based on its index.
77 let cenv_add_fun = SymbolTable.add
80 * Test for membership.
82 let cenv_mem_fun = SymbolTable.mem
85 * Lookup a fun, don't trap Not_found.
87 let cenv_lookup_fun = SymbolTable.find
89 (************************************************************************
91 ************************************************************************)
96 let rec curry_type_esc ty
=
97 let pos = string_pos
"curry_type_esc" (type_exp_pos ty
) in
98 let loc = loc_of_type ty
in
99 match dest_type_core ty
with
110 make_type
loc (TyFun
([], curry_type_esc ty
))
111 | TyFun
(ty_args
, ty_res
) ->
112 curry_fun_type
loc ty_args ty_res
115 make_type
loc (TyTuple
(curry_types_esc tyl
))
117 make_type
loc (TyArray
(curry_type_esc ty
))
119 | TyAll
(vars
, ty
) ->
120 make_type
loc (TyAll
(vars
, curry_type_esc ty
))
121 | TyExists
(vars
, ty
) ->
122 make_type
loc (TyExists
(vars
, curry_type_esc ty
))
124 | TyApply
(ty_var
, tyl
) ->
125 make_type
loc (TyApply
(ty_var
, curry_types_esc tyl
))
126 | TyUnion
(ty_var
, tyl
, s
) ->
127 make_type
loc (TyUnion
(ty_var
, curry_types_esc tyl
, s
))
128 | TyRecord
(ty_var
, tyl
) ->
129 make_type
loc (TyRecord
(ty_var
, curry_types_esc tyl
))
130 | TyFrame
(ty_var
, tyl
) ->
131 make_type
loc (TyFrame
(ty_var
, curry_types_esc tyl
))
132 | TyModule
(ty_var
, tyl
) ->
133 make_type
loc (TyModule
(ty_var
, curry_types_esc tyl
))
134 | TyTag
(ty_var
, tyl
) ->
135 make_type
loc (TyTag
(ty_var
, curry_types_esc tyl
))
136 | TyDTuple
(ty_var
, tyl_opt
) ->
137 make_type
loc (TyDTuple
(ty_var
, curry_types_opt_esc tyl_opt
))
139 | TyExternal
(ty
, s
) ->
140 make_type
loc (TyExternal
(curry_type_esc ty
, s
))
141 | TyFormat
(ty1
, ty2
, ty3
) ->
142 make_type
loc (TyFormat
(curry_type_esc ty1
, curry_type_esc ty2
, curry_type_esc ty3
))
144 and curry_fun_type
loc ty_args ty_res
=
145 let ty_res = curry_type_esc ty_res in
146 List.fold_right
(fun ty_arg
ty_res ->
147 make_type
loc (TyFun
([curry_type_esc ty_arg
], ty_res))) ty_args
ty_res
149 and curry_types_esc tyl
=
150 List.map
curry_type_esc tyl
152 and curry_types_opt_esc tyl_opt
=
154 Some tyl
-> Some
(curry_types_esc tyl
)
158 * For a non-escaping function, do not curry the outermost
161 let rec curry_type ty
=
162 let loc = loc_of_type ty
in
163 match dest_type_core ty
with
165 make_type
loc (TyAll
(vars
, curry_type ty
))
166 | TyFun
(ty_args
, ty_res) ->
167 make_type
loc (TyFun
(curry_types_esc ty_args
, curry_type_esc ty_res))
168 | TyExternal
(ty
, _
) ->
173 let curry_types tyl
=
174 List.map
curry_type tyl
179 let curry_record_tydef fields
=
180 FieldTable.map
(fun (mflag
, ty
) ->
181 mflag
, curry_type_esc ty
) fields
183 let curry_union_tydef fields
=
184 FieldTable.map curry_types_esc fields
186 let curry_module_tydef names fields
=
187 let fields = SymbolTable.map
curry_type_esc fields in
190 let curry_tydef tydef
=
191 let { tydef_inner
= inner
} = tydef
in
192 let loc = loc_of_tydef_inner inner
in
194 match dest_tydef_inner_core
inner with
196 TyDefLambda
(curry_type_esc ty
)
197 | TyDefUnion
fields ->
198 TyDefUnion
(curry_union_tydef fields)
199 | TyDefRecord
fields ->
200 TyDefRecord
(curry_record_tydef fields)
201 | TyDefFrame
fields ->
202 TyDefFrame
(curry_record_tydef fields)
203 | TyDefModule
(names
, fields) ->
204 let names, fields = curry_module_tydef names fields in
205 TyDefModule
(names, fields)
206 | TyDefDTuple ty_var
->
209 { tydef
with tydef_inner
= make_tydef_inner
loc inner }
211 (************************************************************************
213 ************************************************************************)
216 * Build a curry function.
217 * This is what the function looks like for n=3:
219 * let f_curry3_1 arg1 =
220 * let f_curry3_2 arg2 =
221 * let f_curry3_3 arg3 =
222 * let v = f(arg1, arg2, arg3) in
229 let build_curry_fun genv venv cenv
pos loc f ty_vars ty_fun vars
=
230 let pos = string_pos
"build_curry_fun" pos in
231 let ty_args, ty_res = dest_fun_type genv
pos ty_fun
in
232 let s = Symbol.to_string f
in
233 let f_curry = cenv_lookup_fun cenv f
in
234 let len1 = List.length
ty_args in
235 let len2 = List.length vars
in
238 raise
(IRException
(pos, TypeArityMismatch
(ty_fun
, len1, len2)))
241 (* Build a curried function type *)
242 let build_fun_type ty_args ty_res =
243 List.fold_right
(fun ty_arg
ty_res ->
244 make_type
loc (TyFun
([ty_arg
], ty_res))) ty_args ty_res
247 (* Build the expression *)
248 let rec build vars_list ty_args_list i
=
249 match vars_list
, ty_args_list
with
250 v :: vars
, ty_arg
:: ty_args ->
251 (* Build the function that takes the next argument *)
252 let ty_fun = build_fun_type ty_args_list
ty_res in
253 let body = build vars
ty_args (succ i
) in
254 let f_curry_var = new_symbol_string
(Printf.sprintf
"%s.curry%d" s i
) in
255 let f_atom = AtomVar
f_curry_var in
256 make_exp
loc (LetFuns
([f_curry_var, loc, FunGlobalClass
, [], ty_fun, [v], body],
257 make_exp
loc (Return
f_atom)))
260 (* The final block just applies the function *)
261 let v = new_symbol_string
"res" in
262 let args = List.map
(fun v -> AtomVar
v) vars
in
263 let ty_fun = make_type
loc (TyFun
(ty_args, ty_res)) in
264 make_exp
loc (LetApply
(v, ty_res, AtomVar f
, args,
265 make_exp
loc (Return
(AtomVar
v))))
267 raise
(Invalid_argument
"Aml_ir_partial.build_curry_fun.build")
269 let ty_fun = build_fun_type ty_args ty_res in
270 match vars
, ty_args with
271 v :: vars
, ty_arg
:: ty_args ->
272 (* Build the function that takes the next argument *)
273 let f_curry_var = cenv_lookup_fun cenv f
in
274 let body = build vars
ty_args 2 in
275 ((f_curry_var, loc, FunGlobalClass
, ty_vars
, ty_fun, [v], body) : fundef
)
277 raise
(Invalid_argument
"Aml_ir_partial.build_curry_fun")
279 (************************************************************************
281 ************************************************************************)
284 * This variable is about to escape.
285 * If it is a function, use the curried version.
287 let coerce_var_esc cenv
v =
288 try cenv_lookup_fun cenv
v with
293 * Check if an atom is escaped.
295 let rec is_atom_esc cenv a
=
299 | AtomTyConstrain
(a
, _)
300 | AtomTyApply
(a
, _, _)
307 * Coerce an atom that is about to escape.
308 * All we really care about are functions.
310 let rec coerce_atom_esc cenv a
=
317 | AtomModuleLabel
_ ->
320 AtomVar
(coerce_var_esc cenv
v)
322 AtomNil
(curry_type_esc ty
)
323 | AtomTyConstrain
(a
, ty
) ->
324 AtomTyConstrain
(coerce_atom_esc cenv a
, curry_type_esc ty
)
325 | AtomTyApply
(a
, ty
, tyl
) ->
326 AtomTyApply
(coerce_atom_esc cenv a
, curry_type_esc ty
, curry_types_esc tyl
)
327 | AtomTyPack
(v, ty
, tyl
) ->
328 AtomTyPack
(coerce_var_esc cenv
v, curry_type_esc ty
, curry_types_esc tyl
)
330 AtomTyUnpack
(coerce_var_esc cenv
v)
331 | AtomConst
(ty
, ty_var
, const_var
) ->
332 AtomConst
(curry_type_esc ty
, ty_var
, const_var
)
333 | AtomUnop
(op
, a
) ->
334 AtomUnop
(op
, coerce_atom_esc cenv a
)
335 | AtomBinop
(op
, a1
, a2
) ->
336 AtomBinop
(op
, coerce_atom_esc cenv a1
, coerce_atom_esc cenv a2
)
338 let coerce_atom_esc_list cenv atoms
=
339 List.map
(coerce_atom_esc cenv
) atoms
342 * Coerce an atom this is not escaping.
343 * Type arguments are always curried.
345 let rec coerce_atom cenv a
=
357 AtomNil
(curry_type ty
)
358 | AtomTyConstrain
(a
, ty
) ->
359 AtomTyConstrain
(coerce_atom cenv a
, curry_type ty
)
360 | AtomTyApply
(a
, ty
, tyl
) ->
361 AtomTyApply
(coerce_atom cenv a
, curry_type ty
, curry_types_esc tyl
)
362 | AtomTyPack
(v, ty
, tyl
) ->
363 AtomTyPack
(v, curry_type ty
, curry_types_esc tyl
)
364 | AtomConst
(ty
, ty_var
, const_var
) ->
365 AtomConst
(curry_type_esc ty
, ty_var
, const_var
)
366 | AtomUnop
(op
, a
) ->
367 AtomUnop
(op
, coerce_atom_esc cenv a
)
368 | AtomBinop
(op
, a1
, a2
) ->
369 AtomBinop
(op
, coerce_atom_esc cenv a1
, coerce_atom_esc cenv a2
)
371 let coerce_atom_opt cenv a_opt
=
373 Some a
-> Some
(coerce_atom cenv a
)
376 let coerce_atom_list cenv atoms
=
377 List.map
(coerce_atom cenv
) atoms
379 (************************************************************************
381 ************************************************************************)
384 * Coerce an allocation.
385 * All the vars in the block escape.
387 let coerce_alloc_op cenv op
=
389 AllocTuple
(ty_vars
, ty
, args) ->
390 AllocTuple
(ty_vars
, curry_type_esc ty
, coerce_atom_esc_list cenv
args)
391 | AllocUnion
(ty_vars
, ty
, ty_var
, const_var
, args) ->
392 AllocUnion
(ty_vars
, curry_type_esc ty
, ty_var
, const_var
, coerce_atom_esc_list cenv
args)
393 | AllocRecord
(ty_vars
, ty
, ty_var
, fields) ->
394 let fields = List.map
(fun (label
, a
) -> label
, coerce_atom_esc cenv a
) fields in
395 AllocRecord
(ty_vars
, curry_type_esc ty
, ty_var
, fields)
396 | AllocDTuple
(ty
, ty_var
, tag_var
, args) ->
397 AllocDTuple
(curry_type_esc ty
, ty_var
, tag_var
, coerce_atom_esc_list cenv
args)
398 | AllocArray
(ty
, args) ->
399 AllocArray
(curry_type_esc ty
, coerce_atom_esc_list cenv
args)
400 | AllocVArray
(ty
, a1
, a2
) ->
401 AllocVArray
(curry_type_esc ty
, coerce_atom_esc cenv a1
, coerce_atom_esc cenv a2
)
402 | AllocModule
(ty
, ty_var
, fields) ->
403 let fields = SymbolTable.map
(coerce_atom_esc cenv
) fields in
404 AllocModule
(curry_type_esc ty
, ty_var
, fields)
405 | AllocFrame
(ty
, ty_var
, tyl
) ->
406 AllocFrame
(curry_type_esc ty
, ty_var
, curry_types_esc tyl
)
409 * Now coerce an expression.
411 let rec coerce_exp genv venv cenv e
=
412 let pos = string_pos
"coerce_exp" (exp_pos e
) in
413 let loc = loc_of_exp e
in
414 match dest_exp_core e
with
415 LetAtom
(v, ty
, a
, e
) ->
417 if is_atom_esc cenv a
then
418 (* Add the escaped version *)
419 let ty = curry_type_esc ty in
420 let a = coerce_atom_esc cenv
a in
421 let v'
= new_symbol_string
(Symbol.to_string
v ^
"_curry") in
422 let venv = venv_add_var
venv v'
ty in
423 let cenv = cenv_add_fun cenv v v'
in
424 let e = coerce_exp genv
venv cenv e in
425 make_exp
loc (LetAtom
(v'
, ty, a, e))
427 coerce_exp genv
venv cenv e
429 let ty = curry_type ty in
430 let a = coerce_atom cenv a in
431 let venv = venv_add_var
venv v ty in
432 make_exp
loc (LetAtom
(v, ty, a, e))
433 | LetExt
(v, ty1
, s, ty2
, ty_args, args, e) ->
434 let ty1 = curry_type_esc ty1 in
435 let ty2 = curry_type ty2 in
436 let ty_args = curry_types_esc
ty_args in
437 let args = coerce_atom_esc_list cenv args in
438 let venv = venv_add_var
venv v ty1 in
439 let e = coerce_exp genv
venv cenv e in
440 make_exp
loc (LetExt
(v, ty1, s, ty2, ty_args, args, e))
441 | TailCall
(a, args) ->
442 let a = coerce_atom cenv a in
443 let args = coerce_atom_list cenv args in
444 make_exp
loc (TailCall
(a, args))
445 | Match
(a, cases
) ->
446 let a = coerce_atom cenv a in
447 let cases = List.map
(fun (s, e) -> s, coerce_exp genv
venv cenv e) cases in
448 make_exp
loc (Match
(a, cases))
449 | MatchDTuple
(a, cases) ->
450 let a = coerce_atom cenv a in
451 let cases = List.map
(fun (a_opt
, e) -> coerce_atom_opt cenv a_opt
, coerce_exp genv
venv cenv e) cases in
452 make_exp
loc (MatchDTuple
(a, cases))
453 | LetAlloc
(v, op
, e) ->
454 let op = coerce_alloc_op cenv op in
455 let venv = venv_add_var
venv v (type_of_alloc_op
op) in
456 let e = coerce_exp genv
venv cenv e in
457 make_exp
loc (LetAlloc
(v, op, e))
458 | SetSubscript
(a1
, a2
, a3
, ty, e) ->
459 (* This value escapes *)
460 let a1 = coerce_atom cenv a1 in
461 let a2 = coerce_atom cenv a2 in
462 let a3 = coerce_atom_esc cenv a3 in
463 let ty = curry_type_esc ty in
464 let e = coerce_exp genv
venv cenv e in
465 make_exp
loc (SetSubscript
(a1, a2, a3, ty, e))
466 | LetSubscript
(v, ty, a1, a2, e) ->
467 (* This value escapes *)
468 let ty = curry_type_esc ty in
469 let a1 = coerce_atom cenv a1 in
470 let a2 = coerce_atom cenv a2 in
471 let venv = venv_add_var
venv v ty in
472 let e = coerce_exp genv
venv cenv e in
473 make_exp
loc (LetSubscript
(v, ty, a1, a2, e))
474 | SetGlobal
(v, ty, a, e) ->
475 (* This value escapes *)
476 let ty = curry_type_esc ty in
477 let a = coerce_atom_esc cenv a in
478 let e = coerce_exp genv
venv cenv e in
479 make_exp
loc (SetGlobal
(v, ty, a, e))
480 | LetRec
(fields, e) ->
481 let fields = List.map
(fun (v, e, ty) -> v, coerce_exp genv
venv cenv e, curry_type ty) fields in
482 let e = coerce_exp genv
venv cenv e in
483 make_exp
loc (LetRec
(fields, e))
484 | LetFuns
(funs
, e) ->
485 (* Add curried functions to the list *)
486 coerce_funs_exp genv
venv cenv pos loc funs
e
487 | LetApply
(v, ty, a, args, e) ->
488 (* Partial applications use the curried form *)
489 coerce_apply_exp genv
venv cenv pos loc v ty a args e
491 (* This value escapes *)
492 let a = coerce_atom_esc cenv a in
493 make_exp
loc (Return
a)
495 let e1 = coerce_exp genv
venv cenv e1 in
496 let e2 = coerce_exp genv
venv cenv e2 in
497 make_exp
loc (Try
(e1, v, e2))
499 (* This value escapes *)
500 let a = coerce_atom_esc cenv a in
501 let ty = curry_type_esc ty in
502 make_exp
loc (Raise
(a, ty))
504 raise
(IRException
(pos, InternalError
))
507 * For each global function, build a curried form
508 * and add the name to the curry environment.
510 and coerce_funs_exp genv
venv cenv pos loc funs
e =
511 let pos = string_pos
"coerce_funs_exp" pos in
513 (* Build the new cenv *)
515 List.fold_left
(fun cenv (f
, _, gflag
, _, _, _, _) ->
520 let f_curry = new_symbol_string
(Symbol.to_string f ^
"_curry") in
521 cenv_add_fun cenv f
f_curry
527 (* Convert all the function types *)
529 List.map
(fun (f
, loc, gflag
, ty_vars
, ty_fun, vars
, e) ->
530 let ty_fun = curry_type ty_fun in
531 f
, loc, gflag
, ty_vars
, ty_fun, vars
, e) funs
534 (* Add to the variable environment *)
536 List.fold_left
(fun venv (f
, loc, _, ty_vars
, ty, _, _) ->
537 venv_add_var
venv f
(make_type
loc (TyAll
(ty_vars
, ty)))) venv funs
540 (* Convert all the funs *)
542 List.map
(fun (f
, loc, gflag
, ty_vars
, ty_fun, vars
, e) ->
543 let e = coerce_exp genv
venv cenv e in
544 f
, loc, gflag
, ty_vars
, ty_fun, vars
, e) funs
547 (* Add all the curried versions *)
549 List.fold_left
(fun cfuns (f
, loc, gflag
, ty_vars
, ty_fun, vars
, _) ->
554 let fundef = build_curry_fun genv
venv cenv pos loc f ty_vars
ty_fun vars
in
561 (* Convert the body *)
562 let e = coerce_exp genv
venv cenv e in
565 make_exp
loc (LetFuns
(cfuns, e))
569 let e = make_exp
loc (LetFuns
(funs, e)) in
573 * Apply a function. There are several cases to consider.
575 * If this is a partial application, use the curried function,
576 * and apply one argument at a time.
578 * If this application has too many arguments, apply only as
579 * many as the function will take.
581 and coerce_apply_exp genv
venv cenv pos loc v ty f
args e =
582 let pos = string_pos
"coerce_apply_exp" pos in
583 let ty = curry_type_esc ty in
584 let venv = venv_add_var
venv v ty in
585 let e = coerce_exp genv
venv cenv e in
587 (* All the arguments escape *)
588 let args = coerce_atom_esc_list cenv args in
590 (* The function doesn't escape *)
591 let f = coerce_atom cenv f in
593 (* See how many arguments the function wants *)
594 let ty_fun = type_of_atom genv
venv pos loc f in
595 let ty_args, ty_res = dest_fun_type genv
pos ty_fun in
596 let len1 = List.length
ty_args in
597 let len2 = List.length
args in
599 make_exp
loc (LetApply
(v, ty, f, args, e))
600 else if len1 < len2 then
601 coerce_apply_too_many genv
venv cenv pos loc v ty f len1 ty_args ty_res args e
603 coerce_apply_partial genv
venv cenv pos loc v ty f len1 ty_args ty_res args e
606 * We have too many arguments.
607 * Apply as many as possible at once, then recurse.
609 and coerce_apply_too_many genv
venv cenv pos loc v ty f len
ty_args ty_res args e =
610 let pos = string_pos
"coerce_apply_too_many" pos in
611 let args1, args2
= Mc_list_util.split len
args in
612 let ty_args1, ty_args2
= Mc_list_util.split len
ty_args in
613 let ty_fun = make_type
loc (TyFun
(ty_args1, make_type
loc (TyFun
(ty_args2
, ty_res)))) in
615 (* Get a name for the new function *)
616 let f'
= new_symbol_string
"partial" in
617 let venv = venv_add_var
venv f'
ty_fun in
619 (* Build the expression *)
620 let e = coerce_apply_exp genv
venv cenv pos loc v ty (AtomVar
f'
) args2
e in
621 make_exp
loc (LetApply
(f'
, ty_fun, f, args1, e))
624 * We have too few arguments.
625 * Define v as a function that will take the rest of the
626 * arguments and apply f to them.
628 and coerce_apply_partial genv
venv cenv pos loc v ty f len
ty_args ty_res args1 e =
629 let pos = string_pos
"coerce_apply_partial" pos in
630 let ty_args2 = Mc_list_util.nth_tl len
ty_args in
631 let vars2 = List.map
(fun _ -> new_symbol_string
"arg") ty_args2 in
632 let args2 = List.map
(fun v -> AtomVar
v) vars2 in
634 (* Define v as a new function *)
636 make_exp
loc (LetApply
(v, ty_res, f, args1 @ args2,
637 make_exp
loc (Return
(AtomVar
v))))
639 make_exp
loc (LetFuns
([v, loc, FunGlobalClass
, [], ty, vars2, body], e))
641 (************************************************************************
642 * CONVERT THE PROGRAM
643 ************************************************************************)
648 let coerce_init cenv init
=
653 InitAtom
(coerce_atom cenv a)
655 InitAlloc
(coerce_alloc_op cenv op)
658 * Convert partial applications in the program.
660 let partial_prog prog
=
661 let { prog_types
= types
;
662 prog_globals
= globals
;
664 prog_import
= import
;
665 prog_export
= export
;
670 (* Convert the outermost types *)
671 let types = SymbolTable.map
curry_tydef types in
673 SymbolTable.map
(fun (ty, init
) ->
674 curry_type_esc ty, init
) globals
677 SymbolTable.map
(fun (ty_var
, tyl
) ->
678 ty_var
, curry_types_esc tyl
) tags
681 SymbolTable.map
(fun import ->
682 { import with import_type
= curry_type_esc import.import_type
}) import
685 SymbolTable.map
(fun export ->
686 { export with export_type
= curry_type_esc export.export_type
}) export
689 SymbolTable.map
(fun (loc, gflag
, ty_vars
, ty, vars
, e) ->
690 loc, gflag
, ty_vars
, curry_type ty, vars
, e) funs
693 (* Rebuild the prog *)
695 { prog with prog_types
= types;
696 prog_globals
= globals;
698 prog_import
= import;
699 prog_export
= export;
704 (* Build environments *)
705 let genv = genv_of_prog
prog in
706 let venv = venv_of_prog
prog in
707 let cenv = SymbolTable.empty
in
709 (* Convert the function bodies *)
711 SymbolTable.map
(fun (loc, gflag
, ty, ty_vars
, vars
, e) ->
712 loc, gflag
, ty, ty_vars
, vars
, coerce_exp genv venv cenv e) funs
715 (* Now convert the parts *)
717 SymbolTable.mapi
(fun v (ty, init
) ->
718 let init = coerce_init cenv init in
722 (* Rebuild the prog *)
724 { prog with prog_globals
= globals;
735 * Caml-master: "compile"