Re: Implementation of control structures
- From: Eli Gottlieb <eligottlieb@xxxxxxxxx>
- Date: Tue, 04 Apr 2006 00:56:10 GMT
Pascal Bourguignon wrote:
Eli Gottlieb <eligottlieb@xxxxxxxxx> writes:Actually, I'm not implementing Common Lisp. It's too much of a pain in the ass, and a duplication of effort as well.
Frode Vatvedt Fjeld wrote:
Eli Gottlieb <eligottlieb@xxxxxxxxx> writes:
How can I make sure that when return-from is called execution
returns to the correct place?
[...]
This is the general idea. For C etc. I suppose you'd emulate the
catch/throw pattern with setjmp/longjmp. [...]
setjmp() and longjmp()? Hmmm... Rather kludgier than I hoped, but
that should work.
That's a little more complicated than that. You have to unroll a
number of lexical and dynamic bindings when you process RETURN-FROM.
longjmp is a single assembly instruction here.
(block :example
(let ((*print-readably* t)
(a 2)
(potatoe (cons 1 'kg)))
(catch potatoe
(handler-case (let ((a 3))
(unwind-protect (return-from :example 3)
(print :unwound))
(throw potatoe))
(error (err) (format t "~&~A~%~A" a err))))))
; prints:
:|UNWOUND| ; returns:
3
Here, in processing RETURN-FROM:
- the cleanup clauses of UNWIND-PROTECT are executed (:unwound is printed),
- the innermost lexical scope for (a 3) is destroyed,
- the dynamic scope of error handlers is destroyed,
- the dynamic scope of catch is destroyed,
- the lexical scope for (a 2) is destroyed,
- the dynamic scope for *print-readably* is reset,
- and finally the block is exited. (well, here you could use longjmp,
but really you're already here...).
In addition, you may have to process FLET/LABELS lexical scopes too.
Also, if you have an interpreter instead of a compiler, you may have
other scopes to pop, like TAGBODY, MACROLET, and SYMBOL-MACROLET.
For one thing, since it's a lexical construct, you know exactly the
block from which you must return:
(block :name ;1
v
(block :name ;2
x
(return-from :name) ; exits from block 2
y
(return-from :name) ; exits from block 2
z)
(return-from :name) ; exits from block 1
w)
There are two movements to execute RETURN-FROM.
First as described above, you must unwind the scope up to the block
you must exit. In a compiler, you could have a stack offset compiled
in the RETURN-FROM instructions, which would compute the address on
the stack, and the unwinding of the scopes would be complete when the
stack have been poped down to that pointer, or you could keep track of
the number of frames to unwind. Perhaps the later would be easier.
Next, for each block frame you know the address to which the program
must jump to exit from the block. This address could be put on the
stack and returned to, or stored in the RETURN-FROM instructions.
Actually, the later would probably be better, since then you could
avoid stacking block frames altogether. The compiler could choose one
or the other depending on the number of RETURN-FROM in each block.
So you could compile a RETURN-FROM as:
<store-the-result-to-the-multiple-value-registers>
(pop-frames <number-of-frames-to-pop>)
(jump <address-to-jump-to>)
If amongst the frames to be poped there are unwind cleanup forms to
execute, they'll have to save the multiple-value registers.
Second of all, I'm working in an interpreter. Every Lisp function is run by a single Pascal function, which either runs it (compiled primitive) or evals its function expression (defined Lisp function). It then uses its own return value to return an array of values.
Anyway, I was all set to use setjmp()/longjmp() for the implementation until I realized that under my reference-counting system that would probably result in a memory leak. Blargh.
--
The science of economics is the cleverest proof of free will yet constructed.
.
- Follow-Ups:
- Re: Implementation of control structures
- From: Pascal Bourguignon
- Re: Implementation of control structures
- References:
- Implementation of control structures
- From: Eli Gottlieb
- Re: Implementation of control structures
- From: Frode Vatvedt Fjeld
- Re: Implementation of control structures
- From: Eli Gottlieb
- Implementation of control structures
- Prev by Date: Re: Lisp backend protocol
- Next by Date: Re: You all know everything...
- Previous by thread: Re: Implementation of control structures
- Next by thread: Re: Implementation of control structures
- Index(es):
Relevant Pages
|