cps & contification

Stephen Weeks MLton@sourcelight.com
Mon, 15 Jan 2001 09:30:50 -0800 (PST)


> ...  The current continuation based analysis only
> determined that a function could be prefixed onto another continuation;
> the new analysis is also determining that a function could be contified
> within another function (i.e., it's added as a local function definition).
> This caused problems because this type of replacement adds a new Jump.t,
> which wasn't in the set of local functions defined in globals.   ...

This last bit doesn't make sense to me.  The globals do not contain local
function definitions.  The call "shrinkExp globals" is just making global
definitions of variables available to the calls to shrinkExp that happen later,
to the results of walkExp.  Those later calls are being made on the complete
body of a CPS function definition, which should not contain any undefined jumps.
It is an undefined jump that is causing the error.

Also, the previous analyses already determined cases where toplevel functions
are turned into local functions.  I don't see the difference with the new
analysis (although I haven't yet read the code you sent).

> I solved(?) the problem by removing the call to shrinkExp on the result of
> walkExp and added a call to shrink on the resulting program; I think this
> has the same effect, at the expense of building up the whole program once
> and then sending it to the shrinker which will rebuild the program.

Aha.  Now I think I understand.  The problem is in this code

			     val body = shrinkExp (walkExp (name, body, NONE))
			     val body =
				case !prefixes of
				   NONE => body
				 | SOME fs =>
				      let val {decs, transfer} = Exp.dest body
				      in Exp.make {decs = nest (fs, NONE, decs),
						   transfer = transfer}
				      end

It looks to me like there is a bug in the original contify.  The code should
probably be the following.

			     val body = walkExp (name, body, NONE)
			     val body =
				case !prefixes of
				   NONE => body
				 | SOME fs =>
				      let val {decs, transfer} = Exp.dest body
				      in Exp.make {decs = nest (fs, NONE, decs),
						   transfer = transfer}
				      end
			     val body = shrinkExp body

That will make all the local functions available in the expression being
shrunk.  I have no idea how it worked before.