Dear parenscript-devel,
please find attached three patches to the implementation of looping constructs in Parenscript. The first provides a more complete support for CL-LOOP conditional clauses, so that it becomes possible to write, e. g.:
(loop for i :from 0 :to 5 for x := (foo i) when x collect x and if (oddp x) collect (1+ x) else collect (/ x 2) end and do (alert x))
The second patch implements WITH clauses with implicit initialization (though not with TYPE-SPECs), e. g.
(loop for i :from 0 :to 5 with x unless (foo i) do (return (setf x i)))
Formerly, this produced incorrect code, because PS-LOOP required explicit initialization of such variables, but failed to properly assert that the entity following the variable name is the keyword := .
The third patch implements NAMED and RETURN clauses. Also, it fixes the problem that PS-LOOP (contrary to CL-LOOP) did not establish an implicit BLOCK, which used to cause "Returning from unknown block nilBlock" warnings when RETURN forms were used inside LOOPs.
The fourth patch fixes fallacious generated returns in JavaScript code where RETURN or RETURN-FROM are used inside conditional expressions inside loops, as in:
(block nil (dotimes (i 10) (if (test i) (return i))) (return -1))
This produced the following JavaScript:
(function () { var loopResultVar1 = null; for (var i = 0; i < 10; i += 1) { if (test(i)) { loopResultVar1 = i; break; }; }; return loopResultVar1; return -1; })();
If test() fails for all values of i, this code evaluates to null. The meaning of the original code, however, is for the expression to evaluate to -1.
So it goes. Yours, — B. Smilga.
On Mon, Jul 16, 2012 at 3:43 PM, Boris Smilga boris.smilga@gmail.com wrote:
please find attached three patches
s/three/four/
Hi Boris,
Thank you for the patches, the code makes sense.
I've applied 0001 and 0002. Because patch 0003 causes all LOOPs to be wrapped in blocks, and loop is used in various places, this means that this code:
(defun hello-world (&key ((:my-name-key my-name) 1)) my-name)
Used to look like:
function helloWorld() { var _js2 = arguments.length; for (var n1 = 0; n1 < _js2; n1 += 2) { switch (arguments[n1]) { case 'my-name-key': myName = arguments[n1 + 1]; }; }; var myName = 'undefined' === typeof myName ? 1 : myName; return myName; };
And now looks like:
function helloWorld() { nilBlock: { var _js2 = arguments.length; for (var n1 = 0; n1 < _js2; n1 += 2) { switch (arguments[n1]) { case 'my-name-key': myName = arguments[n1 + 1]; }; }; }; var myName = 'undefined' === typeof myName ? 1 : myName; return myName; };
I need a bit of time to think about the right way to fix that (probably by fixing block not to emit if the body contains no return, since it is all lexical), but in the meantime I haven't pushed patches 0003 and 0004.
BTW, I noticed this when I ran the tests: (asdf:load-system :parenscript.test) (ps-test:run-tests)
Currently there's not a lot of tests for LOOP itself, so if anyone wants to contribute some test cases, that would be great.
Thank you, Vladimir
PS - I'm back and I'll try to address the other threads that came up on the mailing list soon.
On Mon, Jul 16, 2012 at 11:45 AM, Boris Smilga boris.smilga@gmail.com wrote:
On Mon, Jul 16, 2012 at 3:43 PM, Boris Smilga boris.smilga@gmail.com wrote:
please find attached three patches
s/three/four/
parenscript-devel mailing list parenscript-devel@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
parenscript-devel@common-lisp.net