On Tue, Aug 28, 2012 at 7:20 PM, Vladimir Sedach <[email protected]> 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 > > (defun blah () > (values 1 2 3)) > > (defun foo () > (blah) > (some-random-js-function)) > > (defun bar () > (multiple-value-bind (a b c) (foo) > (+ a b c))) > > Now a call to bar returns 6, when it shouldn't. I think it might be > 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 <[email protected]> > 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 manipulation step 2: Call FOO step 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 <[email protected]> > 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 <[email protected] > > > >> 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 > >> > [email protected] > >> > > http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel > >> > > >> > >> _______________________________________________ > >> parenscript-devel mailing list > >> [email protected] > >> 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 > > [email protected] > > http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel > > > > _______________________________________________ > parenscript-devel mailing list > [email protected] > http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel >
_______________________________________________ parenscript-devel mailing list [email protected] http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
