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.
On Sun, Sep 27, 2009 at 11:37 PM, Erik Huelsmann ehuels@gmail.com wrote:
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.
Actually, to be specific: BLOCK is a compiler issue (as it turns out BLOCK does do the right thing in the interpreter), TAGBODY is an interpreter and compiler issue.
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))
Or, for BLOCK, consider the following:
(labels ((p (b) (block nil (if (not b) (p #'(lambda () (return :foo))) (funcall b)) (return-from p :bar)))) (p nil))
It should return :foo, but return :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.)
The BLOCK code returns :BAR on 0.16.0.
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:
[ snip ]
I committed a change for BLOCK which replaces a static symbol with the content of a closure variable. This variable is set up upon entry of the block form and contains a unique identifier by allocating a specific LispObject, but *only* if the block contains non-local RETURN-FROMs.
I'm thinking of the right way to do the same with TAGBODY.
Bye,
Erik.
On Mon, Sep 28, 2009 at 10:04 PM, Erik Huelsmann ehuels@gmail.com wrote:
On Sun, Sep 27, 2009 at 11:37 PM, Erik Huelsmann ehuels@gmail.com wrote:
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.
Actually, to be specific: BLOCK is a compiler issue (as it turns out BLOCK does do the right thing in the interpreter), TAGBODY is an interpreter and compiler issue.
BLOCK was fixed yesterday. While working on the resolution for TAGBODY, I discovered the tagbody-processing code is duplicated in the code for DO*/DO. I'll resolve that situation before continuing to resolve the TAGBODY issue.
This mail is to notify that I'm actually working on it.
Bye,
Erik.
armedbear-devel@common-lisp.net