1 (* Copyright (C
) 1999-2006 Henry Cejtin
, Matthew Fluet
, Suresh
2 * Jagannathan
, and Stephen Weeks
.
4 * MLton is released under a BSD
-style license
.
5 * See the file MLton
-LICENSE for details
.
8 structure IntermediateComputation
: INTERMEDIATE_COMPUTATION
=
12 structure Int = Pervasive
.Int
18 | Return
of unit
-> Layout
.t
29 structure Computation
=
33 datatype t
= T
of callResult list
34 withtype callResult
= {name
: string,
35 layoutArg
: unit
-> Layout
.t
,
46 fun layoutName({name
, ...}:t
) = str(name ^
" ")
48 fun layoutCall(cr
as {layoutArg
, ...}:t
) =
49 seq
[layoutName cr
, layoutArg()]
51 val darrow
= str
"==> "
53 fun layoutDarrow _
= darrow
55 fun layoutTime({time
, ...}:t
) =
57 SOME t
=> Time
.layout t
60 fun layoutReturn({result
, ...}:t
) =
61 seq
[darrow
, Result
.layout result
]
64 fun time(T crs
) = List.fold(crs
, Time
.zero
, fn ({time
, ...}, t
) =>
67 | SOME t
' => Time
.+(t
, t
'))
69 fun keepAll(c
, pred
) =
73 fn ({name
, body
, layoutArg
, time
, result
}, crs
) =>
74 let val body
as T crs
' = keepAll body
76 then {name
= name
, body
= body
,
77 layoutArg
= layoutArg
, time
= time
,
78 result
= result
} :: crs
84 fun makeOutputs(pre
, post
, filter
) out
=
85 let val indentation
= ref
0
87 fun left() = indentation
:= !indentation
- space
88 fun right() = indentation
:= !indentation
+ space
89 fun print l
= (Layout
.output(Layout
.indent(l
, !indentation
), out
)
91 fun output(T crs
) = List.foreach(crs
, outputCr
)
92 and outputCr(cr
as {body
, ...}) =
93 let val printCr
= filter cr
95 then (print(pre cr
); right())
98 ; if printCr
then (left(); print(post cr
)) else ()
100 in (output
, outputCr
)
104 makeOutputs(CR
.layoutCall
, CR
.layoutReturn
, fn _
=> true)
105 fun output(c
, out
) = #
1(makeOutput out
) c
106 fun outputCr(cr
, out
) = #
2(makeOutput out
) cr
108 val makeOutputCalls
=
109 makeOutputs(CR
.layoutName
, CR
.layoutDarrow
, fn _
=> true)
110 fun outputCalls(c
, out
) = #
1(makeOutputCalls out
) c
111 fun outputCrCalls(cr
, out
) = #
2(makeOutputCalls out
) cr
113 fun outputTimes(c
, out
) =
114 #
1(makeOutputs(CR
.layoutName
, CR
.layoutTime
,
118 | SOME _
=> true) out
) c
122 val print
= Out
.outputc out
129 fun input i
= (In
.ignoreSpaces i
130 ; (case fromString(In
.inputToSpace i
) of
134 fun inputBetween
{ins
, error
: unit
-> unit
, min
, max
} =
137 let fun continue() = (error() ; loop())
138 in let val n
= input ins
139 in if min
<= n
andalso n
<= max
142 end handle Input
=> continue()
147 val layout
= Layout
.str
o toString
150 fun inputBetween(min
, max
) =
151 Int.inputBetween
{ins
= In
.standard
,
152 error
= fn () => Out
.output(out
, "? "),
153 min
= min
, max
= max
}
155 fun choose (choices
: (string * 'a
) list
): 'a
=
158 List.fold(choices
, 0, fn ((name
, _
),n
) =>
159 (Layout
.output(Int.layout n
, out
)
160 ; print(concat
[". ", name
, "\n"])
162 val _
= Out
.output(out
, "? ")
163 val m
= inputBetween(0,n
-1)
164 in #
2(List.nth(choices
, m
))
167 fun chooseThunk cs
= choose
cs ()
172 val standardChoices
= [("quit", fn () => raise Quit
),
173 ("back", fn () => raise Back
)]
175 fun inspect(c
as T crs
) =
183 @
[("skip raises", fn () =>
184 (skipRaises c
; raise Back
)),
185 ("output", fn () => output(c
, out
)),
187 fn () => outputCalls(c
, out
))]
190 in loop() handle Back
=> ()
193 List.map(crs
, fn cr
as {name
, ...} =>
194 (" " ^ name
, fn () => inspectCr cr
))
195 and inspectCr(cr
as {name
, layoutArg
, body
, result
, time
= _
}) =
196 (print(concat
["Call to ", name
, "\n"])
201 @
[("skip raises", fn () =>
202 (skipRaisesCr cr
; raise Back
)),
205 ("output calls", fn () =>
206 outputCrCalls(cr
, out
)),
207 ("argument", fn () =>
208 (Layout
.output(layoutArg(), out
)
211 (Layout
.output(Result
.layout result
, out
)
215 in loop() handle Back
=> ()
217 and skipRaises(c
as T crs
) =
220 | _
=> (skipRaisesCr(List.last crs
)
222 and skipRaisesCr(cr
as {result
, body
, ...}) =
224 Result
.Raise
=> skipRaises body
225 | Result
.Return _
=> ()
227 in val inspect
= fn c
=> inspect c
handle Quit
=> ()
232 (*---------------------------------------------------*)
234 (*---------------------------------------------------*)
237 T
of {calls
: {name
: string,
238 layoutArg
: unit
-> Layout
.t
,
239 prev
: Computation
.callResult list
} list ref
,
240 after
: Computation
.callResult list ref
}
242 fun empty() = T
{calls
= ref
[],
245 fun atTopLevel(T
{calls
, ...}) = List.isEmpty(!calls
)
247 fun call(T
{calls
, after
},name
, layoutArg
) =
248 (List.push(calls
, {name
= name
, layoutArg
= layoutArg
, prev
= !after
})
251 fun return(T
{calls
, after
}, result
, time
) =
253 [] => Error
.bug
"IntermediateComputation.return: without a call"
254 |
{name
, layoutArg
, prev
} :: cs
=>
256 ; after
:= {name
= name
, layoutArg
= layoutArg
,
257 result
= result
, time
= time
,
258 body
= Computation
.T(List.rev(!after
))} :: prev
)
260 fun raisee(c
, t
) = return(c
, Result
.Raise
, t
)
261 val return
= fn (c
, r
, t
) => return(c
, Result
.Return r
, t
)
263 fun finish(c
as T
{calls
, after
}) =
267 [] => Computation
.T(List.rev(!after
))
268 | _
=> (raisee(c
, NONE
); loop())