1 (* Copyright (C) 1999-2006 Henry Cejtin, Matthew Fluet, Suresh
2 * Jagannathan, and Stephen Weeks.
3 * Copyright (C) 1997-2000 NEC Research Institute.
5 * MLton is released under a BSD-style license.
6 * See the file MLton-LICENSE for details.
9 functor CallCount(S: CALL_COUNT_STRUCTS): CALL_COUNT =
15 fun instrument(program as Program.T{datatypes, body}, passName: string) =
16 if !Control.instrument
21 | Lam of int (* for curried lambdas, how many arrows remain *)
24 val {get = kind: Var.t -> kind, set} =
25 Property.new(Var.plist, Property.initConst None)
27 fun makeLam(l: Lambda.t): kind =
30 let val {decs, result} = Exp.dest(Lambda.body l)
32 [MonoVal{var, exp = Lambda l, ...}] =>
33 if Var.equals(var, VarExp.var result)
41 fun inc(name: string) : unit -> Dec.t =
45 {prim = Prim.newNullary(concat["MLTON_inc", passName, name]),
46 targs = [], args = []}
48 MonoVal{var = Var.newNoname(), ty = Type.unit, exp = exp}
51 val incCount = inc "Unknown"
52 val incObvious = inc "Known"
54 val program = Program.T{datatypes = datatypes,
56 fun loopExp(e: Exp.t): Exp.t =
57 let val {decs, result} = Exp.dest e
58 in Exp.new{decs = loopDecs decs,
61 and loopDecs(ds: Dec.t list): Dec.t list =
66 MonoVal{var, ty, exp} =>
69 MonoVal{var = var, ty = ty, exp = exp}
73 let fun rest() = d :: loopDecs ds
74 in case kind(VarExp.var func) of
75 None => incCount() :: rest()
78 then set(var, Lam(n - 1))
80 ; incObvious() :: rest())
84 case Exp.decs(Lambda.body l) of
85 [MonoVal{exp = PrimApp _, ...}] => Prim
87 ; keep(Lambda(loopLambda l)))
88 | Case{test, cases, default} =>
91 cases = List.map(cases, fn (p, e) =>
93 default = Option.map loopExp default})
94 | Handle{try, catch, handler} =>
95 keep(Handle{try = loopExp try,
97 handler = loopExp handler})
98 | _ => d :: loopDecs ds
100 | PolyVal{var, tyvars, ty, exp} =>
101 PolyVal{var = var, tyvars = tyvars, ty = ty,
104 | Fun{tyvars, decs} =>
105 (List.foreach(decs, fn {var, lambda, ...} =>
106 set(var, makeLam lambda))
107 ; Fun{tyvars = tyvars,
108 decs = List.map(decs, fn {var, ty, lambda} =>
110 lambda = loopLambda lambda})}
112 | Exception _ => d :: loopDecs ds
113 and loopLambda(l: Lambda.t): Lambda.t =
114 let val {arg, argType, body} = Lambda.dest l
115 in Lambda.new{arg = arg, argType = argType,
119 val program = Program.T{datatypes = datatypes,
122 in Program.clear program