[squeak-dev] stepping over non local return in a protected block

Jaromir Matas m at jaromir.net
Tue May 25 19:51:59 UTC 2021

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:
	[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.

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].

What do you think? Would this be clean?

^[^ Jaromir
Sent from: http://forum.world.st/Squeak-Dev-f45488.html

More information about the Squeak-dev mailing list