lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


("CPS" = "continuation passing style", à la Scheme.)

I notice in section 4.7 of the 5.2.0-work3 manual, we have:

| Suppose the running thread yields while executing the callee
| function. After the thread resumes, it eventually will finish running
| the callee function. However, the callee function cannot return to the
| original function, because its frame in the C stack was destroyed by
| the yield. Instead, Lua calls a continuation function, which was given
| as an argument to the callee function. As the name implies, the
| continuation function should continue the task of the original
| function.

Here's the problem with this: lua_yieldk always destroys the C frame,
and is said to always be invoked as the value of a return from a
lua_CFunction, but lua_callk is declared to return void, and
lua_pcallk may return an error code.  According to the lua_getctx doc,
also:

| When the callee is lua_pcallk, Lua may also call its continuation
| function to handle errors during the call. That is, upon an error in
| the function called by lua_pcallk, Lua may not return lua_pcallk but
| instead may call the continuation function. In that case, a call to
| lua_getctx will return the error code (the value that would be
| returned by lua_pcallk); the value of ctx will be set to the context
| information, as in the case of an yield.

This seems pretty inconsistent and hard to deal with; pcallk _might_
return to you with the error code, or you _might_ get a CPS call
instead.  Similarly you have two places in your C code that you might
come back to from a callk.  Basically the only reasonable way I can
think of to use these most of the time is as return (lua_callk(L,
nargs, nresults, 0, k), k(L)) or thereabouts.  Engh.

Perhaps I'm misunderstanding something?  Or perhaps there's frequently
a good reason to know whether the current thread yielded during the
called function---which would be the only difference dictating which
return control flow gets executed, unless I'm mistaken?  I suppose
there might be optimizations one can do with that information, but I
can't think of cases where one would want to do that and where one
could make it not pretty horrible and fragile using this mechanism in
the absence of additional hooks.

In the absence of misunderstandings in the above, I would tend to
suggest that lua_callk, lua_pcallk, and lua_yieldk all return int,
require being called at the end of a lua_CFunction, and always invoke
the continuation function afterwards.  This would make them truly
consistent CPS flow operations.

What do you folks think?

   ---> Drake Wilson