[parenscript-devel] Multiple value calls

Red Daly reddaly at gmail.com
Sun Nov 1 20:41:16 UTC 2009


On Sun, Nov 1, 2009 at 9:50 AM, Daniel Gackle <danielgackle at gmail.com>wrote:

> It might help to use a PS special variable and make MULTIPLE-VALUE-BIND
> responsible for cleanup.
>
> (ps (defvar *mv* undefined))
>
> (defpsmacro values (main &rest additional)
>   (with-ps-gensyms (mv)
>     `(let ((,mv (list , at additional)))
>        (when (defined *mv*)
>          (setf *mv* ,mv))
>        (return ,main))))
>
> (defpsmacro multiple-value-bind (vars expr &body body)
>   `(let ((*mv* '()))
>      (let ((,(car vars) ,expr))
>       (destructuring-bind ,(cdr vars) *mv*
>         , at body))))
>
> This works in the obvious cases. I'm not sure it handles Red's scenarios.
> Red, can you supply an example where this breaks?
>


The main case I am concerned about is dealing with non-parenscript functions
that will not manipulate the mv state.  Something like the following would
break the above code:

(defun foo ()
   (let ((my-callback (lambda (x) (values 1 10)))
   (multiple-value-bind (a b)
       (add-to-result my-callback 2)))

=>

// imagine this is a non-Parenscript function that we cannot manipulate with
the
// Parenscript compiler
function addToResult(callback, x) {
   // returns the result of adding x to the result of calling the callback
   return callback() + x;
}

function foo () {
   var myCallback = function (x) {
   if (MV !== undefined)
      MV = [10];
   return 1;
};

   var old_MV = MV; // begin let
   MV = null;
   var a = addToResult(myCallback, 2);
   var b = MV ? MV[0] : null;

   // now b === 10 but it should be nil
   // this is because addToResult did not reset MV

   MV = old_MV; // end let

}

This is why I think you might need to identify the callee  in another
special variable, and for emitted functions reset the MV_CALLEE variable
before returning (and maybe in other places?).


Red




>
> Daniel
>
> p.s. I took the easy way out of making VALUES always prepend RETURN, but
> once Vladimir bestows implicit RETURN upon us we can take that out ;)
>
>
> On Sat, Oct 31, 2009 at 9:53 PM, Red Daly <reddaly at gmail.com> wrote:
>
>> I apologize for sending the first half of this email in error earlier:
>>
>> On Sat, Oct 31, 2009 at 8:35 PM, Red Daly <reddaly at gmail.com> wrote:
>>
>>> Hi Parenscripters,
>>>
>>> As far as I can tell, multiple-value function calls are a unique feature
>>> of lisp.  I would like the ability to perform multiple-value calls in
>>> Parenscript but I don't know if a sane solution exists or not.
>>>
>>> Can anyone come up with a scheme for returning multiple values that
>>> translates well to Javascript?  Ideally such a scheme would not introduce
>>> much overhead for usual functions that do not use or return multiple values
>>> (though perhaps setting some sort of global MV flag might be inexpensive
>>> enough).  Functions that return multiple values should also only appear to
>>> return a single value when called by a function that expects only one return
>>> value (including native javascript functions).
>>>
>>> (defun paren-mv-returner ()
>>>   (return (values 1 2 3)))
>>>
>>> =>
>>>
>>>
>>> function parenMvReturner() {
>>>    /* do some magic with the values 2 and 3 */
>>>    return 1;
>>> }
>>>
>>> // one  implementation might be
>>> var mv = undefined;
>>>
>>> function parenMvReturner() {
>>>    mv = [2, 3];
>>>    return 1;
>>> }
>>>
>>> // this scheme needs to adjust the return statement of every function so
>>> it might not be sufficient
>>> // consider this other function
>>>
>>> function parenMySingleReturner () {
>>>    var x = parenMvReturner();
>>>
>> return x;
>> }
>>
>> // parenMySingleReturner() will appear to return multiple values unless it
>> modifies the mv value itself
>>
>> // correction:
>>
>> function parenMySingleReturner () {
>>    var x = parenMvReturner();
>>    mv = null;
>>    return x;
>> }
>>
>> But it seems like this solution will fall apart for calls to native
>> Javascript functions over which we have no control.  If we pass a
>> multiple-value returning function as an argument to a native function, the
>> native function will not perform the necessary mv-nulling when it returns.
>>
>> someForeignJavascriptFunction( someMVReturningFunction)
>>
>> will return whatever the someForeignJavascriptFunction should return, but
>> it will also appear to return the other values that someMVReturningFunction
>> set in the mv variable, since someForeignJavascriptFunction performs no
>> cleanup.
>>
>> Maybe this limitation can be avoided by having an mv-returning function A
>> set a global variable "mvFunctionReturner" equal to the function A and a
>> mv-receiver can check that mvFunctionReturner is set according to the
>> function it called expecting multiple values.  Does this scheme miss any
>> cases?
>>
>> Anyway I have thought a little bit about this and I thought I would pass
>> it off to the rest of the Parenscripters as a thought experiment.  Assume
>> you can do a lot more semantic analysis than Parenscript currently does and
>> transform the compiled source however you want.  But any compiled functions
>> must still be able to be treated as normal Javascript functions and all and
>> only functions that should return multiple values appear to return them.
>>
>> Cheers,
>> Red
>>
>> _______________________________________________
>> parenscript-devel mailing list
>> parenscript-devel at common-lisp.net
>> http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
>>
>>
>
> _______________________________________________
> parenscript-devel mailing list
> parenscript-devel at common-lisp.net
> http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/parenscript-devel/attachments/20091101/b343d061/attachment.html>


More information about the parenscript-devel mailing list