Posted by
Jaromir Matas on
May 25, 2021; 7:51pm
URL: https://forum.world.st/stepping-over-non-local-return-in-a-protected-block-tp5128777p5130004.html
Hi Nicolas, Christoph,
Nicolas Cellier wrote
> Simulating #aboutToReturn:through: did jump to first unwind context. But
> this first unwind context was determined BEFORE the simulation #ensure:
> has been inserted. This had the effect of skipping the simulation
> machinery protection, and did result in a BlockCannotReturn
> (cannotReturn:) error...
>
> This did prevent the debugger to correctly debug a protected block with
> non local return like this:
>
> [^2] ensure: [Transcript cr; show: 'done'].
What would you think about this approach: because #return:from: supplies the
first unwind context for #aboutToReturn:through: prematurely, how about to
supply nil instead of the first unwind context and let #resume:through: find
the first unwind context at precisely the right time? I.e.:
resume: value through: firstUnwindCtxt
"Unwind thisContext to self and resume with value as result of last send.
Execute any unwind blocks while unwinding.
ASSUMES self is a sender of thisContext."
| ctxt unwindBlock |
self isDead ifTrue: [self cannotReturn: value to: self].
----> ctxt := firstUnwindCtxt ifNil: [thisContext findNextUnwindContextUpTo:
self].
[ctxt isNil] whileFalse:
[(ctxt tempAt: 2) ifNil:
[ctxt tempAt: 2 put: true.
unwindBlock := ctxt tempAt: 1.
thisContext terminateTo: ctxt.
unwindBlock value].
ctxt := ctxt findNextUnwindContextUpTo: self].
thisContext terminateTo: self.
^value
The change is without any adverse effects and deals with all similar
simulated non-local returns.
Here's the modified #return:from:
return: value from: aSender
"For simulation. Roll back self to aSender and return value from it.
Execute any unwind blocks on the way. ASSUMES aSender is a sender of self"
| newTop |
aSender isDead ifTrue:
[^self send: #cannotReturn: to: self with: {value}].
newTop := aSender sender.
(self findNextUnwindContextUpTo: newTop) ifNotNil:
-----> [^self send: #aboutToReturn:through: to: self with: {value. nil}].
self releaseTo: newTop.
newTop ifNotNil: [newTop push: value].
^newTop
What do you think? Would this be clean?
-----
^[^ Jaromir
--
Sent from:
http://forum.world.st/Squeak-Dev-f45488.html
^[^ Jaromir