Hi Daniel,
I'm glad to be part of the discussion :)
Hi Red,I was hoping you'd chime in. I'll see your scenario 3 and raise you a3a and a 3b:Scenario 3a: A non-Parenscript function that calls a mv-returningParenscript function but only needs its first return value;Scenario 3b: A non-Parenscript function that calls a mv-returningParenscript function and needs all its return values.3a works fine as long as the MV implementation is careful to use anormal JS return to pass the first return value back to the caller.That's true both of what PS does today and of the global-var proposal.As for 3b (the scenario, not the hacker!), seems to me this can't workat all and there's no need to support it. If you're a non-PS functionthen by definition you can't use PS's MULTIPLE-VALUE-BIND to accessthe additional return values because the MV construct only exists inPS. I suppose if you really wanted to you could manually write JS todo whatever PS does to supply those values to the caller, but thenyou're not really a non-PS function anymore, so much as amanually-compiled PS function.Daniel
On Tue, Aug 28, 2012 at 8:46 PM, Red Daly <reddaly@gmail.com> wrote:
On Tue, Aug 28, 2012 at 7:20 PM, Vladimir Sedach <vsedach@gmail.com> wrote:
The counter-example to using a global variable as I remember it from
the last discussion was this case:The last discussion: http://lists.common-lisp.net/pipermail/parenscript-devel/2009-October/000639.html(some-random-js-function))
(defun blah ()
(values 1 2 3))
(defun foo ()
(blah)
Now a call to bar returns 6, when it shouldn't. I think it might be
(defun bar ()
(multiple-value-bind (a b c) (foo)
(+ a b c)))
possible to use another global variable as a flag that's set and
checked by multiple-value aware PS functions, but I need to think
about how to make it work.
Vladimir
On Tue, Aug 28, 2012 at 10:07 PM, Daniel Gackle <danielgackle@gmail.com> wrote:
> Those test failures make sense now - thanks. Also, this comment
> reminded me of something:
>
> < the callee.caller property for functions, which multiple value return
> depends on >
>
> I dislike our implementation for multiple value return. Stuffing the
> values in callee.caller is complicated and doesn't feel right (I think
> I may have been the one who came up with it; it was a bad idea), plus
> it relies on one of the shakiest aspects if not of JS itself than
> certainly of the JS implementations.
>
> A simpler way occurred to me the other day and I'd like to know where
> it breaks. The argument goes like this: since JS is single-threaded
> and functions have to return synchronously, there can be only one
> function return in play at any given time, therefore there can be only
> one multiple-return-value list at any time, therefore why not just
> store it in a global variable?My guess at why your proposal won't work: It ignores knowledge of the call stack, which is practically necessary.Imagine a form (multiple-values-bind (a b c ...) (FOO ...)). Any solution of this with global variables will take the form:step 1: Do some stuff with global variable manipulationstep 2: Call FOOstep 3: Do some stuff to clean up.Pretty much any code can execute inside FOO. This includes a few scenarios:Scenario 1: A simple JS function, native or not, that doesn't call anything that returns multiple values. Your solution works.Scenario 2: A Parenscript function, written to manipulate your global variables properly. Your solution works.Scenario 3: A non-Parenscript function that calls a mv-returning Parenscript function.Can your solution handle Scenario 3? My guess is it cannot because it ignores the call stack.Just my quick guess.- Red>
> Say this variable is called *spillover*. Then this:
>
> (defun blah ()
> (values 1 2 3))
>
> (defun callblah ()
> (multiple-value-bind (a b c) (blah)
> (+ a b c)))
>
> ...might compile to:
>
> function blah() {
> SPILLOVER = [2, 3];
> return 1;
> };
> function callblah() {
> var a = blah();
> var b = SPILLOVER[1];
> var c = SPILLOVER[2];
> return a + b + c;
> };
>
> There might be complicating factors that would make the JS more
> involved in practice, but I don't remember what they are.
>
> Apart from being so much simpler, this implementation has two
> advantages. First, it's "morally" better in Eugenia Cheng's sense
> (http://cheng.staff.shef.ac.uk/morality/morality.pdf). The multiple
> return values don't belong to caller or callee, but to the call
> itself. Caller and callee are functions that persist across many calls
> and ought not to have information about a specific call attached to
> them. That's why PS is forced to add ugly code to save the previous
> value attached to callee and restore it using a try/finally at the end.
>
> Second, it would fix a known problem. PS breaks when you have an
> interloper like FOO here:
>
> (defun blah ()
> (values 1 2 3))
>
> (defun foo ()
> (blah))
>
> (defun bar ()
> (multiple-value-bind (a b c) (foo)
> (+ a b c)))
>
> BAR should return 6, and does in CL, but in PS it returns 1, because
> FOO doesn't return multiple values, so B and C are null and "1 + null +
> null"
> is 1 in JS. But the *spillover* hack would make BAR return 6.
>
> Could we get away with this, or what am I missing?
>
> Daniel
>
>
> On Tue, Aug 28, 2012 at 6:00 PM, Vladimir Sedach <vsedach@gmail.com> wrote:
>>
>> Hi Daniel,
>>
>> Yes, those two failures in the eval test suite are expected.
>> CL-JavaScript doesn't have the callee.caller property for functions,
>> which multiple value return depends on. I wasn't sure where to comment
>> those tests out, so I left them in to remind myself to add
>> callee.caller to CL-JavaScript (I've already talked to Marijn
>> Haverbeke about that).
>>
>> Thank you,
>> Vladimir
>>
>> On Mon, Aug 27, 2012 at 11:58 PM, Daniel Gackle <danielgackle@gmail.com>
>> wrote:
>> > I've rebased my PS LOOP extensions [1] onto the latest commit
>> > (7be9b45) and recompiled Skysheet. The generated JS looks fine. There
>> > was one glitch that I'll report separately along with a workaround.
>> > Before pushing the LOOP extensions onto master, though, I want to
>> > update any relevant PS tests. Some will fail because the LOOP output
>> > has changed quite a bit. Unfortunately I'm also seeing failures when I
>> > run the tests in 7be9b45, which is prior to any of these LOOP
>> > changes. I've pasted the output below [2]. It doesn't look like these
>> > failures are related to work in ps-loop.lisp, so I'll just ignore them
>> > for the time being, but Vladimir can you please comment on whether you
>> > know about them or whether there's something unexpected going on?
>> >
>> > Daniel
>> >
>> > [1] These are the constructs FOR..OF and MAP..TO, plus a change to
>> > FOR..ON, that I described in my email to this list on April 11. They
>> > are currently sitting in the "loop" branch. Rebasing them was
>> > nontrivial because of Boris' additions to ps-loop.lisp, but it seems
>> > to have all gone ok. Boris, if you're reading this, please look out for
>> > any
>> > regressions once I push these changes and let us know if you notice
>> > anything.
>> >
>> > [2] Running output tests:
>> >
>> > ........................................................................................................................................................................................................................................................................................................................................................................................................................................
>> > Did 424 checks.
>> > Pass: 424 (100%)
>> > Skip: 0 ( 0%)
>> > Fail: 0 ( 0%)
>> > Running package system tests:
>> > .........
>> > Did 9 checks.
>> > Pass: 9 (100%)
>> > Skip: 0 ( 0%)
>> > Fail: 0 ( 0%)
>> > Running CL-JavaScript eval tests:
>> > ...........................f...............X......................
>> > Did 66 checks.
>> > Pass: 64 (96%)
>> > Skip: 0 ( 0%)
>> > Fail: 2 ( 3%)
>> > Failure Details:
>> > --------------------------------
>> > mv-return1 []:
>> > Unexpected Error: #<cl-js:js-condition #x30200155257D>
>> > [js] TypeError: undefined has no properties...
>> > --------------------------------
>> > --------------------------------
>> > dynamic-extent-function-return-values []:
>> > (funcall (if (typep #:g36204 'structure-object) #'equalp #'equal)
>> > #:g36204 (jsarray '(1 2 3))) was NIL..
>> > --------------------------------
>> >
>> >
>> > _______________________________________________
>> > parenscript-devel mailing list
>> > parenscript-devel@common-lisp.net
>> > http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
>> >
>>
>> _______________________________________________
>> parenscript-devel mailing list
>> parenscript-devel@common-lisp.net
>> http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
>
>
> Those test failures make sense now - thanks. Also, this comment
> reminded me of something:
>
> < the callee.caller property for functions, which multiple value return
> depends on >
>
> I dislike our implementation for multiple value return. Stuffing the
> values in callee.caller is complicated and doesn't feel right (I think
> I may have been the one who came up with it; it was a bad idea), plus
> it relies on one of the shakiest aspects if not of JS itself than
> certainly of the JS implementations.
>
> A simpler way occurred to me the other day and I'd like to know where
> it breaks. The argument goes like this: since JS is single-threaded
> and functions have to return synchronously, there can be only one
> function return in play at any given time, therefore there can be only
> one multiple-return-value list at any time, therefore why not just
> store it in a global variable?
>
> Say this variable is called *spillover*. Then this:
>
> (defun blah ()
> (values 1 2 3))
>
> (defun callblah ()
> (multiple-value-bind (a b c) (blah)
> (+ a b c)))
>
> ...might compile to:
>
> function blah() {
> SPILLOVER = [2, 3];
> return 1;
> };
> function callblah() {
> var a = blah();
> var b = SPILLOVER[1];
> var c = SPILLOVER[2];
> return a + b + c;
> };
>
> There might be complicating factors that would make the JS more
> involved in practice, but I don't remember what they are.
>
> Apart from being so much simpler, this implementation has two
> advantages. First, it's "morally" better in Eugenia Cheng's sense
> (http://cheng.staff.shef.ac.uk/morality/morality.pdf). The multiple
> return values don't belong to caller or callee, but to the call
> itself. Caller and callee are functions that persist across many calls
> and ought not to have information about a specific call attached to
> them. That's why PS is forced to add ugly code to save the previous
> value and restore it using a try/finally at the end.
>
> Second, it would fix a known problem. PS breaks when you introduce an
> interloper like FOO here:
>
> (defun blah ()
> (values 1 2 3))
>
> (defun foo ()
> (blah))
>
> (defun bar ()
> (multiple-value-bind (a b c) (foo)
> (+ a b c)))
>
> BAR should return 6, and does in CL, but in PS it returns 1, because
> FOO doesn't return multiple values, so B and C are null and "1 + null +
> null"
> is 1 in JS. But the *spillover* hack would make BAR return 6.
>
> Could we get away with this, or what am I missing?
>
> Daniel
>
>
> _______________________________________________
> parenscript-devel mailing list
> parenscript-devel@common-lisp.net
> http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
>
_______________________________________________
parenscript-devel mailing list
parenscript-devel@common-lisp.net
http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
_______________________________________________
parenscript-devel mailing list
parenscript-devel@common-lisp.net
http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
_______________________________________________
parenscript-devel mailing list
parenscript-devel@common-lisp.net
http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel