OK, we're on the same wavelength. I'm glad you said "This issue [i.e. passthrough] is orthogonal to how the multiple values are passed" -- that's the same conclusion I've come to.
Now I wonder if we can fix the global variable (GV) design. Naive GV had no way to suppress incorrect passthrough. But if it can be corrected, a GV implementation would probably be simpler and more efficient than foo.mv/arguments.callee.mv.
The foo.mv way suppresses passthrough by default and turns it on by instrumenting tail calls. What about the inverse? Use a GV to enable passthrough by default and turn it off by instrumenting *non* tail calls. Something like:
(defun foo (x y z) (values x y z))
(defun baz () (foo))
(defun bar () (foo) (baz))
var EXTRAS = null; // global variable for MV returns
function foo(x, y, z) { EXTRAS = [y, z]; return x; }
function baz() { return foo(); // passthrough enabled by default }
function bar () { foo(); EXTRAS = null; // instrumentation to suppress passthrough return baz(); // transitive passthrough is free }
You'd want "EXTRAS = null" after each MULTIPLE-VALUE-BIND as well, but maybe you get this for free since the function call in a MULTIPLE-VALUE-BIND is by definition not a tail call.
We can summarize this proposal similarly to the other one:
1. Pass multiple values using a global variable 2. Instrument every non-tail call.
It may still be too naive but it at least fixes the examples that broke GV earlier in the thread. So, is there an example that works in foo.mv but fails in GV as described above?
Dan
p.s. I also wonder if the recursion difficulty disappears now that we understand passthrough better. The example was:
(defun foo (x) (if (= x 1) (values 1 2) (1+ (foo (1- x)))))
In both the GV and foo.mv designs, shouldn't foo(2) do the right thing now? That recursion is a non-tail call, so GV would suppress MV passthrough and foo.mv wouldn't enable it.
On Fri, Sep 7, 2012 at 12:46 PM, Vladimir Sedach vsedach@gmail.com wrote:
Hi Dan,
The only easy implementation I can think of is to mv-instrument every tail call in the program, but that is surely overkill.
Yes, that's currently the only way I see to do it. This issue is orthogonal to how the multiple values are passed - in principle I could have implemented the multiple value passing instrumentation right after adding the return instrumentation code, but it didn't occur to me at the time.
So to clarify, my proposal has two separate components:
- Pass multiple values on the callee function object
- Instrument every tail call
Vladimir
parenscript-devel mailing list parenscript-devel@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel