[squeak-dev] The Inbox: Kernel-ct.1405.mcz

mail at jaromir.net mail at jaromir.net
Wed Nov 17 20:54:33 UTC 2021


Hi Christoph,

I've addressed your comments regarding the BlockCannotReturn behavior in [1] and copy my comments here (and expand a bit):

> Isn't that ProceedBlockCannotReturn tautologous? I think that by actively proceeding from a BlockCannotReturn error users already accept that they are going to resume execution in another way.

Well, the very proceeding from a BlockCannotReturn error sort of violates common sense but during our lengthy discussion you convinced me it makes a very good sense when troubleshooting :) The idea is by no means trivial - unlike hitting Proceed :) So an extra warning can't hurt...

But more importantly, I need something to know the user let the process continue after reaching the BlockCannotReturn error - thus the new ProceedBlockCannotReturn exception which allows Process >> #complete:to: to deal with the new course of events.

It's just that introducing ProceedBlockCannotReturn seemed the least intrusive to the code and it's working. It allowed me to remove the extra state I introduced earlier and hated it :)

> Apart from that, the message text of your new warning is not correct if self pc <= self endPC. :-)

Yes, and I'd like to make the warning message more verbose so even if someone hit Proceed without much thinking they could get an idea what's about to happen :) Should the warning interfere with some potential automation efforts we could come up with some alternative way.

Handling BlockCannotReturn error is no doubt a separate issue from #terminate and I included your patch in Kernel-jar.1414 along with the main termination code because it perfectly complements it and prevents the disastrous crashes while allowing to Proceed the BCR error when troubleshooting (or maybe even for exception handling, I'll have to refresh my memory: I'm referring to your example:

```
"Both statements need to be executed separately in a Workspace"
a := [true ifTrue: [^ 1] yourself]
[a value] on: BlockCannotReturn do: [:ex | ex resume]
```
). 

To your other great example:

```
	sender := thisContext swapSender: nil.
	true ifTrue: [^ 1]. "Proceed the BlockCannotReturn"
	thisContext privSender: sender.
	^ 2
```

> I think this should eventually answer 2. Apparently, the VM already has reset the pc in this example so we are helpless here.

> [...] the computation terminated is also wrong, IMO, you should get a BlockCannotReturn here.

Yes, I agree; your example clearly shows there's definitely more to the problem that needs to be studied and discussed :) I don't like the 'computation terminated' message either; it's seems to me a bit out of place (I mean calling the Debugger directly rather than raisin an exception - it confuses me) and maybe even the whole #cannotReturn: should be simplified - I just didn't want to start messing with this when working on #terminate :) 

I very much look forward to your further comments and ideas.

Best,

Jaromir

[1] http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-November/216999.html


^[^ Jaromir
  --

Sent from Squeak Inbox Talk

On 2021-08-22T17:33:59+02:00, christoph.thiede at student.hpi.uni-potsdam.de wrote:

> Hi Jaromir,
> 
> sorry, I had already addressed your ProceedBlockCannotReturn warning in [1] instead - but this thread is definitely the better place to continue this discussion. :-)
> 
> As already mentioned there, I doubt that warning the user again after he/she already had deliberately proceeded from an interpreter error makes much sense. But this is also not a strong opinion, so once again I'm calling for a third opinion here!
> 
> ---
> 
> To now address this example:
> 
> > > ```
> > >         sender := thisContext swapSender: nil.
> > >         true ifTrue: [^ 1]. "Proceed the BlockCannotReturn"
> > >         thisContext privSender: sender.
> > >         ^ 2
> > > ```
> 
> Very unfortunately, I cannot reproduce any longer what I have reported there myself. But the computation terminated is also wrong, IMO, you should get a BlockCannotReturn here. closureOrNil is nil here because the compiler does inline the ifTrue instruction - add a yourself behind the [^ 1] and you will get a correct BlockCannotReturn which you also can resume from to return the 2. Anyway, I originally brought the example to illustrate that all the VM optimizations with inlined message sends and whatever else could possibly destroy our assumptions about returnable blocks and contexts. But for the superordinate discussion here, I just would treat this as an imperfect VM implementation but nothing to worry about. :D
> 
> > BUT
> > 
> > if you debug it and:
> > A) step through the ^1 - you get Message not understood
> > B) step into ^1 - you don't get any error and can happily continue
> 
> Ouh, these are several simulator bugs. And if you forego the enclosing [] value and step into the ^1, you get just a different MNU ... This should be addressed, too. :-)
> Without the enclosing [] value, I could fix both buttons by inserting the following in Context >> #return:from: right after the assignment to newTop which you can try out by loading Kernel-ct.1409 frmo the inbox.
> With the enclosing [] value, however, it is not that easy. Case B) you mentioned is worst. In this example, the simulated snippet answers 1 instead of 2! If you debug the simulator ("debug button action" of the "Into" button in the last step), you can see that the difference here is that unless the VM executor, the simulator knows about the home context of the top context even if the latter has a nil sender (see Context >> #methodReturnTop). I can't tell which one of them is wrong, but they are not consistent, this is not good. ^^
> 
> Best,
> Christoph
> 
> [1] http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-August/216211.html
> 
> ---
> Sent from Squeak Inbox Talk
> 
> On 2021-05-30T11:50:52-05:00, m at jaromir.net wrote:
> 
> > Hi Christoph,
> > 
> > >
> > > ... my point here is: Proceeding from an error almost always doesn't seem
> > > "right". :-) It is always a decision by the debugging programmer to
> > > override the default control flow and switch to the "next plausible
> > > alternative control flow", i.e., resume as if the error would have never
> > > been raised. Applied to the attempt to return from a method, for me, this
> > > means to ignore the return (thinking of it in message sends: to ignore the
> > > "thisContext (home) return"). Yeah, and if there is no further statement
> > > after that return, my best understanding of the user's intention to
> > > "proceed" would be to return to the place from where the block has been
> > > invoked ...
> > 
> > Agreed :) The more I think about it the more I like it ;) And well, the
> > non-local return could have been a typo anyways... so actually, this makes
> > the best sense and preserves all options open for the user - perfect!
> > 
> > > Also, can you convince me why you would need some extra state in the
> > > exception for this?
> > 
> > No, I hated adding an extra state :) The only thing I really need for the
> > full #terminate to work correctly is a way to distinguish between normal
> > proceeding the computation and resuming the unwind procedure when the
> > BlockCannotReturn error occurs inside an unwind block currently being
> > evaluated. All I need then is a Warning the computation proceeds beyond the
> > BlockCannotReturn; here's what I mean:
> > 
> > ```
> > cannotReturn: result
> > 
> > ����closureOrNil ifNotNil: [
> > ��������| resumptionValue |
> > ��������resumptionValue := self cannotReturn: result to: self home sender.
> > ��������ProceedBlockCannotReturn new signal: 'This block has ended, continue with
> > sender?'.
> > ��������self pc > self endPC ifTrue: [
> > ������������"This block has ended, continue with sender"
> > ������������thisContext privSender: self sender].
> > ��������^ resumptionValue].
> > ����Processor debugWithTitle: 'Computation has been terminated!' translated
> > full: false
> > ```
> > 
> > So if you're fine with this addition, full #terminate would recognize when
> > it's beyond BlockCannotReturn and would continue unwinding the non-local
> > return accordingly.
> > 
> > I think it's useful to warn the user about such an unusual (and new) option
> > as Proceeding safely beyond BlockCannotReturn anyway :)
> > 
> > >
> > > Argh, here is another example which does not yet match my expectations:
> > > ```
> > > sender := thisContext swapSender: nil.
> > > true ifTrue: [^ 1]. "Proceed the BlockCannotReturn"
> > > thisContext privSender: sender.
> > > ^ 2
> > > ```
> > > I think this should eventually answer 2. Apparently, the VM already has
> > > reset the pc in this example so we are helpless here. 
> > 
> > There's something wrong with this example :) (or my understanding of it)
> > 
> > 1) if you print-it or do-it you get Computation terminated instead of Block
> > cannot return
> > 
> > 2) so I wrapped it in [] value
> > ```
> > [sender := thisContext swapSender: nil.
> > true ifTrue: [^ 1]. "Proceed the BlockCannotReturn"
> > thisContext privSender: sender.
> > ^ 2] value
> > ```
> > Now it raises BlockCannotReturn and returns 2 with your changeset (if
> > Proceeded)...
> > 
> > BUT
> > 
> > if you debug it and:
> > A) step through the ^1 - you get Message not understood
> > B) step into ^1 - you don't get any error and can happily continue
> > 
> > I'm confused...
> > 
> > Many thanks for your comments and your proposed solution to cannot return;
> > I'll update #terminate and remove my previous attempts from the Inbox.
> > best,
> > 
> > 
> > 
> > -----
> > ^[^ Jaromir
> > --
> > Sent from: http://forum.world.st/Squeak-Dev-f45488.html
> > 
> > 
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20210822/29b7f4fa/attachment.html>
> 
> 


More information about the Squeak-dev mailing list