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.