2 ms·
There wasn't a setjmp()/longjmp() type functionality? That's how I cheated implementing a Lisp in C. When tail recursing I'd let the stack grow a while, nuke it
by User23 3y ago
There wasn't a setjmp()/longjmp() type functionality? That's how I cheated implementing a Lisp in C. When tail recursing I'd let the stack grow a while, nuke it with longjmp(), and keep going.
That was a long time ago and I didn't know nearly as much about PL design and implementation as I do now, but it set me on the path. Funny thing was I started that project just to prove to myself that I could still write C since I'd been doing a ton of Perl.
- all2 3y agoOooh, there's definitely a "goto" in the lexicon [0]. I suppose I could do something like that. This project is almost 3 years old now. I might have to pull it out and dust it off. :D [0] https://ttssh2.osdn.jp/manual/4/en/macro/command/goto.html https://ttssh2.osdn.jp/manual/4/en/macro/command/goto.html
- kazinator 3y agoIf you discovered that trick yourself, you're very clever. It was documented by Henry Baker and is implemented in Chicken Scheme. The basic ideas are: 1. All allocations (e.g. consing) take from the stack. 2. Tail calls are stack calls, so we keep consuming stack. 3. No function ever returns; all calls are tail calls. The Lisp code is CPS-transformed. (Since functions in the compiled code don't actually return even when appearing to, the stack-allocated objects remain nicely valid.) 4. When the stack reaches a certain limit, we rewind it. At that point, all the data which we consed on that stack which is still reachable is relocated to the heap, so they remain valid while we clobber the original stack.