On IRC, we had a discussion some days ago where it was found that ABCL
doesn't use unique tag-identifications in tagbody, leading to somewhat
dynamically scoped tagbodies, instead of perfectly lexically scoped.
BLOCK also uses non-unique names (think NIL), leading to the same
issue. Both the compiler and the interpreter exhibit the problem.
Consider the following code:
(labels ((p (b)
(tagbody
(if (not b)
(p #'(lambda () (go :foo)))
(funcall b))
(return-from p :bar)
:foo
(return-from p :foo))))
(p nil))
It should return :foo, but returns :bar on ABCL's interpreter instead.
(The fact that the compiler works, means there's probably a bug in it
somewhere, because there's no explanation why it would.)
I'm now thinking of ways to make the tags/blocknames unique. The one
way I could come up with for the interpreter is this:
Adding a second identifier (created using "new Object();") to the
blocks and tags registered in the interpreter environment. Then, when
a Go or Return is thrown, it should include the identifier. The
catching tagbodies and blocks can verify that the Go or Return is
meant for that block by checking the identifier.
The approach above requires an additional "identifier" field in the
Binding object.
For the compiler, this could work similarly, except that the
identifier can't be stored in the environment (because there is none),
meaning it should probably be stored in a closure variable which any
throwing function can then use when creating the Go or Return object.
Any comments?
Bye,
Erik.