sqrmax@cvtci.com.ar wrote:
Hi.
I've got a misbehaving block. I evaluate it, and because what's inside it is in beta, it crashes and burns. So I open the debugger and "of course, I forgot the caret" or so. So I close the debugger, fix it, and when I try to evaluate the block again an error pops up because the block is still evaluating itself?!?!... no debugger window is visible (and no debugger shows up in find window). If I recreate the block, I can evaluate it but when it crashes once, it renders itself into a rebel block again!!!
All I can see is that the primitive that evaluates the block fails just after nil DoIt. What's going on?
Andres.
BlockContexts in Squeak are not reentrant. A block that is executing--or whose execution is not properly terminated--cannot be evaluated. The VM will refuse to evaluate any BlockContext whose program counter is not at the beginning of the block (its "pc" instance variable must be equal to the value of the instance variable "startpc", otherwise the #value primitive will fail).
The primitive failure actually provides an opportunity to do something about this problem. Specifically, when the #value primitive fails, one can simply make a copy of the block, set the copy's pc to startpc, and then reevaluate the block. It is also a good idea to send the message #fixTemps to the copy, since it is very likely that reentrant use of a block will want closure semantics for the block.
Here's the actual code to execute the strategy outlined above:
BlockContext>reset pc := startpc
BlockContext>copy ^self shallowCopy postCopy
BlockContext>postCopy "If you want a copy of the block, you will also want: the copy to bind to the current values of its outer references, and the program counter of the copy to be reset to the beginning" self reset. self fixTemps
BlockContext>basicValue <primitive: 81> ^self basicValueWithArguments: #()
BlockContext>basicValueWithArguments: anArray <primitive: 82> ^self valueError
BlockContext>valueWithArguments: anArray <primitive: 82> ^anArray size == 0 ifTrue: [self copy basicValue "the primitive may have failed because the argArray was size 0"] ifFalse: [self copy basicValueWithArguments: anArray]
With the changes above, the following code can be executed successfully:
| block | block := [:index | index > 0 ifTrue: [block value: index - 1]]. block value: 10.
--Alan
squeak-dev@lists.squeakfoundation.org