Hi Philipp,
That sounds like a good plan.
From my current vantage point, this seems like step
three. I just got done with at step one. Step two
is for me to get acquainted with the parenscript
codebase.
I will get a feel the existing code base and then we
can take the next steps from there.
I already cloned the git repository to my local
development machine. The current commit for branch
master seems to be:
commit 1fd720bc4e2bc5ed92064391b730b9d4db35462a (HEAD -> master)
| Author: Vladimir Sedach <
vas@oneofus.la>
| Date: Wed Jun 17 20:29:19 2020 -0700
Regarding tail-call optimization in JavaScript:
Jason Miller also recommended that. Unfortunately, I
dug up information indicating that it is unsupported
in Google's V8 JavaScript implementation, see
[
stackoverflow.com (2017)].
Quoting part of my reply to Jason for the benefit of
future readers of this specific email:
[...] This seems to necessitate a (loop (case ...))
based approach, because SERIES may be used for loops
with iteration counts greater than the stack size.
Nevertheless, not all is lost.
PARENSCRIPT already compiles
(block nil ((lambda () (return 3)))) as catch/throw
correctly. Note, the call in the body of the BLOCK.
So at least some dynamic ((lambda () (go ...))) calls
should be compilable; hopefully all of them. Even if
it only captures 70% of all use cases, that is way
more than zero.
Cheers,
Andrew
[
stackoverflow.com (2017)], Answer by T.J. Crowder:
TITLE:
ES6 Tail Recursion Optimisation Stack Overflow,
URL:
https://stackoverflow.com/questions/42788139/es6-tail-recursion-optimisation-stack-overflowOn Sat, May 21, 2022 at 10:58:57AM +0200, Philipp Marek wrote:
Hi Andrew,
first of all -- how about registering on gitlab.common-lisp.net,
so that you can become a developer for [1] and work with a branch
using a Merge Request?
It would be much easier to track your progress (and individual changes)
that way.
I have started to implement TAGBODY for PARENSCRIPT
[A,B,C]. The general idea is to imitate a jump table
by looping over a switch-case. A GO (C-terminology:
jump) then sets the switch-variable to the next jump
destination. The loop subsequently causes the switch
to branch to the jump target in the switch-variable.
Leaving the tagbody means leaving the loop.
Hmmm, okay.
My first thought would've been to use a function for each
part and just do tail recursion... but it seems that
this isn't really supported in Javascript?!
There are complications. Common Lisp allows nested
tagbody-forms. Common Lisp allows go-tags to be
referenced within the lexical scope *and* the dynamic
extent of a tagbody form. This means that a LAMBDA
can close over a go-tag and jump there, see an
example in [B], of how inconvenient this can become
for compilation to JavaScript.
Yeah... that would be a good reason for simple function
calls and tail recursion.
1. I need a code review of the algorithm.
The implementation in [B] seems to be
satisfactory. There are some test cases and
examples. Most there is the most hairy example I
could find up to now. I may have missed crucial
details.
I'll take a look - but please let's try to get it into
the git repo first, so that any discussions have some
common state to refer to.
2. My understanding of the CL:TAGBODY definition in
the CLHS [4] may be wrong. Which alternate
interpretations does anybody here know of?
What are your questions, or points of confusion?
Ad 1: https://gitlab.common-lisp.net/parenscript/parenscript