In nautilus I get an error MNU: RBBlockNode>>method When I select several groups and select merge mergeGroups: aCollection aCollection ifNotEmpty: [:groups || group | group := groups reduce: [:a :b | a or: [b]]. ^^^^^^^^^^^^ a is a dynamicClassGroup and its superclass defines or: groups do: [:gp | gp removable ifTrue: [self groupsManager removeAGroupSilently: gp]]. ^ group]. ^ nil RBBlockNode(Object)>>doesNotUnderstand: #method RBBlockNode>>sourceNodeForPC: DynamicClassGroup(Object)>>mustBeBooleanInMagic: DynamicClassGroup(Object)>>mustBeBoolean [ :a :b | a or: [ b ] ] in [ :groups | | group | group := groups reduce: [ :a :b | a or: [ b ] ]. groups do: [ :gp | gp removable ifTrue: [ self groupsManager removeAGroupSilently: gp ] ]. ^ group ] in PackageTreeNautilusUI(AbstractTool)>>mergeGroups: in Block: [ :a :b | a or: [ b ] ] [ :index | arguments replaceFrom: 2 to: arguments size with: self startingAt: index; at: 1 put: (aBlock valueWithArguments: arguments) ] in Array(SequenceableCollection)>>reduceLeft: in Block: [ :index | ... SmallInteger(Number)>>to:by:do: Array(SequenceableCollection)>>reduceLeft: Array(SequenceableCollection)>>reduce: [ :groups | | group | group := groups reduce: [ :a :b | a or: [ b ] ]. groups do: [ :gp | gp removable ifTrue: [ self groupsManager removeAGroupSilently: gp ] ]. ^ group ] in PackageTreeNautilusUI(AbstractTool)>>mergeGroups: in Block: [ :groups | ... BlockClosure>>cull: Array(Collection)>>ifNotEmpty: PackageTreeNautilusUI(AbstractTool)>>mergeGroups: PackageTreeNautilusUI(AbstractNautilusUI)>>mergeGroups [ target mergeGroups ] in AbstractNautilusUI class>>groupsMenu: in Block: [ target mergeGroups ] BlockClosure>>cull: [ | selArgCount | "show cursor in case item opens a new MVC window" (selArgCount := selector numArgs) = 0 ifTrue: [ target perform: selector ] ifFalse: [ selArgCount = arguments size ifTrue: [ target perform: selector withArguments: arguments ] ifFalse: [ target perform: selector withArguments: (arguments copyWith: evt) ] ]. self changed ] in ToggleMenuItemMorph(MenuItemMorph)>>invokeWithEvent: in Block: [ ... BlockClosure>>ensure: CursorWithMask(Cursor)>>showWhile: ToggleMenuItemMorph(MenuItemMorph)>>invokeWithEvent: ToggleMenuItemMorph(MenuItemMorph)>>mouseUp: ToggleMenuItemMorph(MenuItemMorph)>>handleMouseUp: MouseButtonEvent>>sentTo: ToggleMenuItemMorph(Morph)>>handleEvent: MorphicEventDispatcher>>dispatchDefault:with: MorphicEventDispatcher>>handleMouseUp: MouseButtonEvent>>sentTo: [ ^ anEvent sentTo: self ] in MorphicEventDispatcher>>dispatchEvent:with: in Block: [ ^ anEvent sentTo: self ] BlockClosure>>ensure: MorphicEventDispatcher>>dispatchEvent:with:
You cannot easily redefine these selectors: #(#caseOf: #to:do: #ifNotNil: #ifNil:ifNotNil: #whileTrue: #ifNotNil:ifNil: #ifFalse: #timesRepeat: #whileTrue #caseOf:otherwise: #whileFalse: #ifNil: #to:by:do: #ifTrue: #ifFalse:ifTrue: #or: #whileFalse #ifTrue:ifFalse: #and:) You can redefine those selectors but depending on the send site, the redefined method is used or not. One trick is to have the send site in a method / class with compilation options disabling the inlining of the selectors you want. Another trick is to use a pattern different slightly that the optimized pattern, for example, I believe that Marcus changed #and: so: a and: [ b ] -> and: is optimized at compile time, send site won't use overridden method. a and: [ :x | b ] -> and: is not optimized at compile time, send site will use overridden method. Maybe it works with #or: too. 2015-04-30 21:47 GMT+02:00 stepharo <stepharo@free.fr>:
In nautilus I get an error MNU: RBBlockNode>>method When I select several groups and select merge
mergeGroups: aCollection
aCollection ifNotEmpty: [:groups || group | group := groups reduce: [:a :b | a or: [b]]. ^^^^^^^^^^^^
a is a dynamicClassGroup and its superclass defines or:
groups do: [:gp | gp removable ifTrue: [self groupsManager removeAGroupSilently: gp]]. ^ group]. ^ nil
RBBlockNode(Object)>>doesNotUnderstand: #method RBBlockNode>>sourceNodeForPC: DynamicClassGroup(Object)>>mustBeBooleanInMagic: DynamicClassGroup(Object)>>mustBeBoolean [ :a :b | a or: [ b ] ] in [ :groups | | group | group := groups reduce: [ :a :b | a or: [ b ] ]. groups do: [ :gp | gp removable ifTrue: [ self groupsManager removeAGroupSilently: gp ] ]. ^ group ] in PackageTreeNautilusUI(AbstractTool)>>mergeGroups: in Block: [ :a :b | a or: [ b ] ] [ :index | arguments replaceFrom: 2 to: arguments size with: self startingAt: index; at: 1 put: (aBlock valueWithArguments: arguments) ] in Array(SequenceableCollection)>>reduceLeft: in Block: [ :index | ... SmallInteger(Number)>>to:by:do: Array(SequenceableCollection)>>reduceLeft: Array(SequenceableCollection)>>reduce: [ :groups | | group | group := groups reduce: [ :a :b | a or: [ b ] ]. groups do: [ :gp | gp removable ifTrue: [ self groupsManager removeAGroupSilently: gp ] ]. ^ group ] in PackageTreeNautilusUI(AbstractTool)>>mergeGroups: in Block: [ :groups | ... BlockClosure>>cull: Array(Collection)>>ifNotEmpty: PackageTreeNautilusUI(AbstractTool)>>mergeGroups: PackageTreeNautilusUI(AbstractNautilusUI)>>mergeGroups [ target mergeGroups ] in AbstractNautilusUI class>>groupsMenu: in Block: [ target mergeGroups ] BlockClosure>>cull: [ | selArgCount | "show cursor in case item opens a new MVC window" (selArgCount := selector numArgs) = 0 ifTrue: [ target perform: selector ] ifFalse: [ selArgCount = arguments size ifTrue: [ target perform: selector withArguments: arguments ] ifFalse: [ target perform: selector withArguments: (arguments copyWith: evt) ] ]. self changed ] in ToggleMenuItemMorph(MenuItemMorph)>>invokeWithEvent: in Block: [ ... BlockClosure>>ensure: CursorWithMask(Cursor)>>showWhile: ToggleMenuItemMorph(MenuItemMorph)>>invokeWithEvent: ToggleMenuItemMorph(MenuItemMorph)>>mouseUp: ToggleMenuItemMorph(MenuItemMorph)>>handleMouseUp: MouseButtonEvent>>sentTo: ToggleMenuItemMorph(Morph)>>handleEvent: MorphicEventDispatcher>>dispatchDefault:with: MorphicEventDispatcher>>handleMouseUp: MouseButtonEvent>>sentTo: [ ^ anEvent sentTo: self ] in MorphicEventDispatcher>>dispatchEvent:with: in Block: [ ^ anEvent sentTo: self ] BlockClosure>>ensure: MorphicEventDispatcher>>dispatchEvent:with:
On Fri, May 1, 2015 at 4:31 AM, Clément Bera <bera.clement@gmail.com> wrote:
You cannot easily redefine these selectors:
#(#caseOf: #to:do: #ifNotNil: #ifNil:ifNotNil: #whileTrue: #ifNotNil:ifNil: #ifFalse: #timesRepeat: #whileTrue #caseOf:otherwise: #whileFalse: #ifNil: #to:by:do: #ifTrue: #ifFalse:ifTrue: #or: #whileFalse #ifTrue:ifFalse: #and:)
You can redefine those selectors but depending on the send site, the redefined method is used or not.
One trick is to have the send site in a method / class with compilation options disabling the inlining of the selectors you want.
Another trick is to use a pattern different slightly that the optimized pattern, for example, I believe that Marcus changed #and: so: a and: [ b ] -> and: is optimized at compile time, send site won't use overridden method. a and: [ :x | b ] -> and: is not optimized at compile time, send site will use overridden method.
Maybe it works with #or: too.
That seems a bit exotic and complicate ongoing maintenance. I hope its use is heavily commented. But a naive question, why not something intention revealing like #myAnd: or #unoptimisedAnd: or #slowAnd: cheers -ben
Clement thanks for the information. I thought about that. From a language perspective what you describe is plain bad. Implementation should not creep in the language semantics. As a normal developer I do not want to know how I can redefine special optimized selectors. either the compiler should raise a warning when I redefine them or forbid it. As a normal developer I should not have to deal and understand such issues. Stef Le 30/4/15 22:31, Clément Bera a écrit :
You cannot easily redefine these selectors:
#(#caseOf: #to:do: #ifNotNil: #ifNil:ifNotNil: #whileTrue: #ifNotNil:ifNil: #ifFalse: #timesRepeat: #whileTrue #caseOf:otherwise: #whileFalse: #ifNil: #to:by:do: #ifTrue: #ifFalse:ifTrue: #or: #whileFalse #ifTrue:ifFalse: #and:)
You can redefine those selectors but depending on the send site, the redefined method is used or not.
One trick is to have the send site in a method / class with compilation options disabling the inlining of the selectors you want.
Another trick is to use a pattern different slightly that the optimized pattern, for example, I believe that Marcus changed #and: so: a and: [ b ] -> and: is optimized at compile time, send site won't use overridden method. a and: [ :x | b ] -> and: is not optimized at compile time, send site will use overridden method.
Maybe it works with #or: too.
2015-04-30 21:47 GMT+02:00 stepharo <stepharo@free.fr <mailto:stepharo@free.fr>>:
In nautilus I get an error MNU: RBBlockNode>>method When I select several groups and select merge
mergeGroups: aCollection
aCollection ifNotEmpty: [:groups || group | group := groups reduce: [:a :b | a or: [b]]. ^^^^^^^^^^^^
a is a dynamicClassGroup and its superclass defines or:
groups do: [:gp | gp removable ifTrue: [self groupsManager removeAGroupSilently: gp]]. ^ group]. ^ nil
RBBlockNode(Object)>>doesNotUnderstand: #method RBBlockNode>>sourceNodeForPC: DynamicClassGroup(Object)>>mustBeBooleanInMagic: DynamicClassGroup(Object)>>mustBeBoolean [ :a :b | a or: [ b ] ] in [ :groups | | group | group := groups reduce: [ :a :b | a or: [ b ] ]. groups do: [ :gp | gp removable ifTrue: [ self groupsManager removeAGroupSilently: gp ] ]. ^ group ] in PackageTreeNautilusUI(AbstractTool)>>mergeGroups: in Block: [ :a :b | a or: [ b ] ] [ :index | arguments replaceFrom: 2 to: arguments size with: self startingAt: index; at: 1 put: (aBlock valueWithArguments: arguments) ] in Array(SequenceableCollection)>>reduceLeft: in Block: [ :index | ... SmallInteger(Number)>>to:by:do: Array(SequenceableCollection)>>reduceLeft: Array(SequenceableCollection)>>reduce: [ :groups | | group | group := groups reduce: [ :a :b | a or: [ b ] ]. groups do: [ :gp | gp removable ifTrue: [ self groupsManager removeAGroupSilently: gp ] ]. ^ group ] in PackageTreeNautilusUI(AbstractTool)>>mergeGroups: in Block: [ :groups | ... BlockClosure>>cull: Array(Collection)>>ifNotEmpty: PackageTreeNautilusUI(AbstractTool)>>mergeGroups: PackageTreeNautilusUI(AbstractNautilusUI)>>mergeGroups [ target mergeGroups ] in AbstractNautilusUI class>>groupsMenu: in Block: [ target mergeGroups ] BlockClosure>>cull: [ | selArgCount | "show cursor in case item opens a new MVC window" (selArgCount := selector numArgs) = 0 ifTrue: [ target perform: selector ] ifFalse: [ selArgCount = arguments size ifTrue: [ target perform: selector withArguments: arguments ] ifFalse: [ target perform: selector withArguments: (arguments copyWith: evt) ] ]. self changed ] in ToggleMenuItemMorph(MenuItemMorph)>>invokeWithEvent: in Block: [ ... BlockClosure>>ensure: CursorWithMask(Cursor)>>showWhile: ToggleMenuItemMorph(MenuItemMorph)>>invokeWithEvent: ToggleMenuItemMorph(MenuItemMorph)>>mouseUp: ToggleMenuItemMorph(MenuItemMorph)>>handleMouseUp: MouseButtonEvent>>sentTo: ToggleMenuItemMorph(Morph)>>handleEvent: MorphicEventDispatcher>>dispatchDefault:with: MorphicEventDispatcher>>handleMouseUp: MouseButtonEvent>>sentTo: [ ^ anEvent sentTo: self ] in MorphicEventDispatcher>>dispatchEvent:with: in Block: [ ^ anEvent sentTo: self ] BlockClosure>>ensure: MorphicEventDispatcher>>dispatchEvent:with:
On 01 May 2015, at 10:10, stepharo <stepharo@free.fr> wrote:
Clement
thanks for the information. I thought about that.
From a language perspective what you describe is plain bad. Implementation should not creep in the language semantics.
Yes, this is why we implemented the #mustBebooleanMagic. It now just works: when the optimised contruct is used on a non-boolean, we recompile the expression and execute is without optimization.
As a normal developer I do not want to know how I can redefine special optimized selectors.
Yes, you can⦠this was the whole point of the mustBebooleanMagic machinery. Marcus
On 01 May 2015, at 10:17, Marcus Denker <marcus.denker@inria.fr> wrote:
On 01 May 2015, at 10:10, stepharo <stepharo@free.fr> wrote:
Clement
thanks for the information. I thought about that.
From a language perspective what you describe is plain bad. Implementation should not creep in the language semantics.
Yes, this is why we implemented the #mustBebooleanMagic.
It now just works: when the optimised contruct is used on a non-boolean, we recompile the expression and execute is without optimization.
As a normal developer I do not want to know how I can redefine special optimized selectors.
Yes, you can⦠this was the whole point of the mustBebooleanMagic machinery.
Maybe I explain again. Historically, Smalltalk makes interpretation fast by cheating: come selectors are just hard coded into jumps. (ifTrue:, or: â¦). But not always (e.g. not when the parameter is not a block). This is very confusing. Therefore, we implemented a fall-back: when the VM executes the optimised construct on a non-boolean, it raises an exception. We catch that and just do what the expression was supposed to do: send the message. This means now there is no problem anymore in overriding all these. The problem has been fixed. Marcus
On 30 Apr 2015, at 21:47, stepharo <stepharo@free.fr> wrote:
In nautilus I get an error MNU: RBBlockNode>>method When I select several groups and select merge
mergeGroups: aCollection
aCollection ifNotEmpty: [:groups || group | group := groups reduce: [:a :b | a or: [b]]. ^^^^^^^^^^^^
a is a dynamicClassGroup and its superclass defines or:
The mistake is the block around the b. or: in DynamicGroup is defined as or: aGroup and if you do not put a block, the compiler will not optimise or: â> it will be send. (and the or: in DynamicGroup will just raise an error when it gets passed a block, it expects a group). But there is a second error: the mustBeBooleanInMagic: normally should work. (the VM executes the optimised construct â> raised an exception â> we recompile the expression with no optimisation -> execute. There is tiny bug there (it should be #methodNode). I will commit a fix for that⦠(I hope this is understandable.. as two bugs are involved this might be a bit complex.
RBBlockNode(Object)>>doesNotUnderstand: #method RBBlockNode>>sourceNodeForPC: DynamicClassGroup(Object)>>mustBeBooleanInMagic: D
Marcus
But there is a second error: the mustBeBooleanInMagic: normally should work. (the VM executes the optimised construct â> raised an exception â> we recompile the expression with no optimisation -> execute.
There is tiny bug there (it should be #methodNode). I will commit a fix for thatâ¦
https://pharo.fogbugz.com/f/cases/15458/fix-mustBeBoolean-handling-for-or <https://pharo.fogbugz.com/f/cases/15458/fix-mustBeBoolean-handling-for-or> Marcus
Thanks. Le 30/4/15 22:57, Marcus Denker a écrit :
On 30 Apr 2015, at 21:47, stepharo <stepharo@free.fr> wrote:
In nautilus I get an error MNU: RBBlockNode>>method When I select several groups and select merge
mergeGroups: aCollection
aCollection ifNotEmpty: [:groups || group | group := groups reduce: [:a :b | a or: [b]]. ^^^^^^^^^^^^
a is a dynamicClassGroup and its superclass defines or:
The mistake is the block around the b.
or: in DynamicGroup is defined as
or: aGroup
and if you do not put a block, the compiler will not optimise or: â> it will be send. (and the or: in DynamicGroup will just raise an error when it gets passed a block, it expects a group).
But there is a second error: the mustBeBooleanInMagic: normally should work. (the VM executes the optimised construct â> raised an exception â> we recompile the expression with no optimisation -> execute.
There is tiny bug there (it should be #methodNode). I will commit a fix for thatâ¦
(I hope this is understandable.. as two bugs are involved this might be a bit complex.
RBBlockNode(Object)>>doesNotUnderstand: #method RBBlockNode>>sourceNodeForPC: DynamicClassGroup(Object)>>mustBeBooleanInMagic: D
Marcus
Marcus we should add a rule for the or: [b] Stef Le 30/4/15 22:57, Marcus Denker a écrit :
On 30 Apr 2015, at 21:47, stepharo <stepharo@free.fr> wrote:
In nautilus I get an error MNU: RBBlockNode>>method When I select several groups and select merge
mergeGroups: aCollection
aCollection ifNotEmpty: [:groups || group | group := groups reduce: [:a :b | a or: [b]]. ^^^^^^^^^^^^
a is a dynamicClassGroup and its superclass defines or:
The mistake is the block around the b.
or: in DynamicGroup is defined as
or: aGroup
and if you do not put a block, the compiler will not optimise or: â> it will be send. (and the or: in DynamicGroup will just raise an error when it gets passed a block, it expects a group).
But there is a second error: the mustBeBooleanInMagic: normally should work. (the VM executes the optimised construct â> raised an exception â> we recompile the expression with no optimisation -> execute.
There is tiny bug there (it should be #methodNode). I will commit a fix for thatâ¦
(I hope this is understandable.. as two bugs are involved this might be a bit complex.
RBBlockNode(Object)>>doesNotUnderstand: #method RBBlockNode>>sourceNodeForPC: DynamicClassGroup(Object)>>mustBeBooleanInMagic: D
Marcus
We should at least have a rules stating "pay attentino you use an optimised selector". Im not sure what should be form of the warning but we should make progress I see two cases - the dev uses a non optimized version and the warning tell him that it would be better to use the optimised ifNil....of whatever case - when defining a method with such selector: warn them because we should avoid them. Stef Le 1/5/15 10:15, Marcus Denker a écrit :
On 01 May 2015, at 10:08, stepharo <stepharo@free.fr> wrote:
Marcus we who uld add a rule for the or: [b]
Not possible as it is correct if the receiver is a boolean.
Marcus
On 01 May 2015, at 11:46, stepharo <stepharo@free.fr> wrote:
We should at least have a rules stating "pay attentino you use an optimised selector". Im not sure what should be form of the warning but we should make progress
why?
I see two cases - the dev uses a non optimized version and the warning tell him that it would be better to use the optimised ifNil....of whatever case
- when defining a method with such selector: warn them because we should avoid them.
Why? Marcus
On 30 Apr 2015, at 22:57, Marcus Denker <marcus.denker@inria.fr> wrote:
On 30 Apr 2015, at 21:47, stepharo <stepharo@free.fr> wrote:
In nautilus I get an error MNU: RBBlockNode>>method When I select several groups and select merge
mergeGroups: aCollection
aCollection ifNotEmpty: [:groups || group | group := groups reduce: [:a :b | a or: [b]]. ^^^^^^^^^^^^
a is a dynamicClassGroup and its superclass defines or:
The mistake is the block around the b.
or: in DynamicGroup is defined as
or: aGroup
and if you do not put a block, the compiler will not optimise or: â> it will be send. (and the or: in DynamicGroup will just raise an error when it gets passed a block, it expects a group).
But there is a second error: the mustBeBooleanInMagic: normally should work. (the VM executes the optimised construct â> raised an exception â> we recompile the expression with no optimisation -> execute.
There is tiny bug there (it should be #methodNode). I will commit a fix for thatâ¦
(I hope this is understandable.. as two bugs are involved this might be a bit complex.
To make the whole thing easier to understand we need to distinguish the two bugs. 1) or: is somehow special. No, it is not. We fixed that, but the fix was broken. This is now fixed in 50026. 2) someone wrote or: [] where no block was supposed to be. The reason for that is lint rule RBIfTrueBlocksRule, which statically enforces blocks as parameters for all of or: and: and ifTrue:⦠we should: - remove the [] in that method - remove the rule RBIfTrueBlocksRule as it makes no sense anymore, it is from a time when or: was special. DONE. Marcus
To make the whole thing easier to understand we need to distinguish the two bugs.
1) or: is somehow special. No, it is not. We fixed that, but the fix was broken.
See my other mail. I would add two different kind of rules to help people and slow the use of redefinition of special selectors.
This is now fixed in 50026.
2) someone wrote or: [] where no block was supposed to be.
The reason for that is lint rule RBIfTrueBlocksRule, which statically enforces blocks as parameters for all of or: and: and ifTrue:⦠we should:
- remove the [] in that method - remove the rule RBIfTrueBlocksRule as it makes no sense anymore, it is from a time when or: was special.
DONE.
Marcus
On 01 May 2015, at 11:48, stepharo <stepharo@free.fr> wrote:
To make the whole thing easier to understand we need to distinguish the two bugs.
1) or: is somehow special. No, it is not. We fixed that, but the fix was broken.
See my other mail. I would add two different kind of rules to help people and slow the use of redefinition of special selectors.
I do not understand why. Marcus
Le 01/05/2015 11:50, Marcus Denker a écrit :
On 01 May 2015, at 11:48, stepharo <stepharo@free.fr> wrote:
To make the whole thing easier to understand we need to distinguish the two bugs.
1) or: is somehow special. No, it is not. We fixed that, but the fix was broken.
See my other mail. I would add two different kind of rules to help people and slow the use of redefinition of special selectors.
I do not understand why.
I side with Marcus there. Why? You now have a compiler which does not make those selectors special, and you want to keep them special? Thierry
Marcus
2015-05-01 11:58 GMT+02:00 Thierry Goubier <thierry.goubier@gmail.com>:
Le 01/05/2015 11:50, Marcus Denker a écrit :
On 01 May 2015, at 11:48, stepharo <stepharo@free.fr> wrote:
To make the whole thing easier to understand we need to distinguish the two bugs.
1) or: is somehow special. No, it is not. We fixed that, but the fix was broken.
This is wrong. They are special for non compiler developer. I explain why below.
See my other mail.
I would add two different kind of rules to help people and slow the use of redefinition of special selectors.
I do not understand why.
I side with Marcus there. Why?
Why ? Because you can't debug them normally. If they're executed normally, you cannot step into sends using these selectors on the contrary to any other send because they are inlined, which is light because most of the time you don't want to step into these selectors. If they're executed on non boolean, the debugger shows the whole #mustBeBoolean, #mustBeBooleanIn: and #ExecuteUnoptimizedIn: stack of noise, and that's assuming the ExecuteUnoptimizedIn: would work in any case without errors. They are very special because they can't be debugged as other selectors. And I'm not talking about rare cases which make these selectors only slightly special, like for example where you run out of literals in a method, the method is not shown in the list of senders of the special selectors it uses. Debugging has already become much harder now that we have slots: the debugger highlights an instance variable in a frame whereas there are frames below, so you now have to understand slots to debug code. It is not possible to make the debugger compliant with slots because the debugger has access only to the bottom 20 frames of the active stack for other good reasons such as a very deep recursive stack, and if the instance variable access with a slot is not in these bottom 20 frames, the debugger can't detect it. Now in addition, you're telling me that for some selectors in specific cases instead of the regular stack I will have #mustBeBoolean, #mustBeBooleanIn: and #ExecuteUnoptimizedIn: inserted into the stack. So to debug code, you have to understand this hack too. What is the next step ? Do you want the debugger to show a stack mainly unrelated to what the programmer wrote that only compiler developers can understand ? Are we also in Pharo in the philosophy where we don't care about how bad is the debugger ? I agree with Stef that there should be a warning telling you that shouldn't override such selectors if you don't know what you are doing. Btw control flow selectors are not the only special selectors. You cannot override #== anywhere in Pharo too.
You now have a compiler which does not make those selectors special, and you want to keep them special?
They're kept special in any case, for compiler developers and non compiler developers. We do not have a compiler and a VM that do not make those selectors special (Yes, this is not only a compiler problem, it's a VM + compiler problem). As far as I know, only the Self VMs and compilers do not keep those selectors special.
Thierry
Marcus
Le 01/05/2015 13:43, Clément Bera a écrit :
2015-05-01 11:58 GMT+02:00 Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>:
Le 01/05/2015 11:50, Marcus Denker a écrit :
On 01 May 2015, at 11:48, stepharo <stepharo@free.fr <mailto:stepharo@free.fr>> wrote:
To make the whole thing easier to understand we need to distinguish the two bugs.
1) or: is somehow special. No, it is not. We fixed that, but the fix was broken.
This is wrong. They are special for non compiler developer. I explain why below.
See my other mail. I would add two different kind of rules to help people and slow the use of redefinition of special selectors.
I do not understand why.
I side with Marcus there. Why?
Why ?
Because you can't debug them normally. If they're executed normally, you cannot step into sends using these selectors on the contrary to any other send because they are inlined, which is light because most of the time you don't want to step into these selectors. If they're executed on non boolean, the debugger shows the whole #mustBeBoolean, #mustBeBooleanIn: and #ExecuteUnoptimizedIn: stack of noise, and that's assuming the ExecuteUnoptimizedIn: would work in any case without errors.
They are very special because they can't be debugged as other selectors. And I'm not talking about rare cases which make these selectors only slightly special, like for example where you run out of literals in a method, the method is not shown in the list of senders of the special selectors it uses.
Debugging has already become much harder now that we have slots: the debugger highlights an instance variable in a frame whereas there are frames below, so you now have to understand slots to debug code. It is not possible to make the debugger compliant with slots because the debugger has access only to the bottom 20 frames of the active stack for other good reasons such as a very deep recursive stack, and if the instance variable access with a slot is not in these bottom 20 frames, the debugger can't detect it.
Now in addition, you're telling me that for some selectors in specific cases instead of the regular stack I will have #mustBeBoolean, #mustBeBooleanIn: and #ExecuteUnoptimizedIn: inserted into the stack. So to debug code, you have to understand this hack too.
What is the next step ? Do you want the debugger to show a stack mainly unrelated to what the programmer wrote that only compiler developers can understand ? Are we also in Pharo in the philosophy where we don't care about how bad is the debugger ?
Well, we need to have that discussion then, since we can't roll back: the slots are already there, and I guess that with the Meta links, we will have to do something about it. So, what would it take to improve the debugger? Do we need to consider that the execution model shown in the debugger needs to be a bit further away from the vm execution model? Thierry
I agree with Stef that there should be a warning telling you that shouldn't override such selectors if you don't know what you are doing.
Btw control flow selectors are not the only special selectors. You cannot override #== anywhere in Pharo too.
You now have a compiler which does not make those selectors special, and you want to keep them special?
They're kept special in any case, for compiler developers and non compiler developers. We do not have a compiler and a VM that do not make those selectors special (Yes, this is not only a compiler problem, it's a VM + compiler problem). As far as I know, only the Self VMs and compilers do not keep those selectors special.
Thierry
Marcus
Well, we need to have that discussion then, since we can't roll back: the slots are already there, and I guess that with the Meta links, we will have to do something about it.
So, what would it take to improve the debugger?
Since you can add meta links to any ast node the best approach would be to change the debugger to work at the AST level and not the bytecode level. Right now stepOver steps over a bytecode instruction and then calls #stepToSendOrReturn. I made an attempt to gave the debugger step over slot writes/reads but it is not nice at all. In a debugger at the ast level we can have actions like stepInto/Over Slot, stepInto/Over metalink, etc
Do we need to consider that the execution model shown in the debugger needs to be a bit further away from the vm execution model?
In moose we have two views for the debugger: one is the default one and the other the bytecode view. In the bytecode view you always step over one bytecode intruction and see the real stack with no hidden contexts. Cheers, Andrei
Thierry
I agree with Stef that there should be a warning telling you that
shouldn't override such selectors if you don't know what you are doing.
Btw control flow selectors are not the only special selectors. You cannot override #== anywhere in Pharo too.
You now have a compiler which does not make those selectors special, and you want to keep them special?
They're kept special in any case, for compiler developers and non compiler developers. We do not have a compiler and a VM that do not make those selectors special (Yes, this is not only a compiler problem, it's a VM + compiler problem). As far as I know, only the Self VMs and compilers do not keep those selectors special.
Thierry
Marcus
2015-05-01 13:59 GMT+02:00 Thierry Goubier <thierry.goubier@gmail.com>:
Le 01/05/2015 13:43, Clément Bera a écrit :
2015-05-01 11:58 GMT+02:00 Thierry Goubier <thierry.goubier@gmail.com <mailto:thierry.goubier@gmail.com>>:
Le 01/05/2015 11:50, Marcus Denker a écrit :
On 01 May 2015, at 11:48, stepharo <stepharo@free.fr <mailto:stepharo@free.fr>> wrote:
To make the whole thing easier to understand we need to distinguish the two bugs.
1) or: is somehow special. No, it is not. We fixed that, but the fix was broken.
This is wrong. They are special for non compiler developer. I explain why below.
See my other mail. I would add two different kind of rules to help people and slow the use of redefinition of special selectors.
I do not understand why.
I side with Marcus there. Why?
Why ?
Because you can't debug them normally. If they're executed normally, you cannot step into sends using these selectors on the contrary to any other send because they are inlined, which is light because most of the time you don't want to step into these selectors. If they're executed on non boolean, the debugger shows the whole #mustBeBoolean, #mustBeBooleanIn: and #ExecuteUnoptimizedIn: stack of noise, and that's assuming the ExecuteUnoptimizedIn: would work in any case without errors.
They are very special because they can't be debugged as other selectors. And I'm not talking about rare cases which make these selectors only slightly special, like for example where you run out of literals in a method, the method is not shown in the list of senders of the special selectors it uses.
Debugging has already become much harder now that we have slots: the debugger highlights an instance variable in a frame whereas there are frames below, so you now have to understand slots to debug code. It is not possible to make the debugger compliant with slots because the debugger has access only to the bottom 20 frames of the active stack for other good reasons such as a very deep recursive stack, and if the instance variable access with a slot is not in these bottom 20 frames, the debugger can't detect it.
Now in addition, you're telling me that for some selectors in specific cases instead of the regular stack I will have #mustBeBoolean, #mustBeBooleanIn: and #ExecuteUnoptimizedIn: inserted into the stack. So to debug code, you have to understand this hack too.
What is the next step ? Do you want the debugger to show a stack mainly unrelated to what the programmer wrote that only compiler developers can understand ? Are we also in Pharo in the philosophy where we don't care about how bad is the debugger ?
Well, we need to have that discussion then, since we can't roll back: the slots are already there, and I guess that with the Meta links, we will have to do something about it.
So, what would it take to improve the debugger?
Do we need to consider that the execution model shown in the debugger needs to be a bit further away from the vm execution model?
That's the way to go. I think some people like Camille are already working on it. Basically, you need abstraction over what is happening which is implemented in the image instead of the VM for simplicity and maintenance, and what the programmer wants to see which is relevant for him. For optimized selectors, one could mark the methods with pragmas as 'Do not show in debugger' and in addition rewire the bytecode to source code mapping from the method compiled on-the-fly executed in ExecuteUnoptimizedIn: to the regular method. But as I stated for Slots, it is more complicated. The debugger cannot detect if the stack is currently in a slot access, as it has access only to the bottom 20 frames. Having the debugger access the full stack is a bad idea as it would slow it considerably, making the debugger unusable on devices such as the raspberry pie, and hard to use to debug recursive code. Maybe a solution could be that if the compiled bytecode for a slot has an interrupt point (branch, back jump, send), then it could change a state in the process, probably encoded in the process instance variables, and as the debugger has access to the process it is showing it would know.
Thierry
I agree with Stef that there should be a warning telling you that
shouldn't override such selectors if you don't know what you are doing.
Btw control flow selectors are not the only special selectors. You cannot override #== anywhere in Pharo too.
You now have a compiler which does not make those selectors special, and you want to keep them special?
They're kept special in any case, for compiler developers and non compiler developers. We do not have a compiler and a VM that do not make those selectors special (Yes, this is not only a compiler problem, it's a VM + compiler problem). As far as I know, only the Self VMs and compilers do not keep those selectors special.
Thierry
Marcus
Kind of because we got or: Boolean * block -> Object and now we have Object * Object -> Object I already discussed by emails too mcuh this point with marcus. Since we do not have even the start of a process to document the design rationale behind such decisions I will not discuss it. But I do not like that we have such ad-hoc process and I do not think that the ratio of impact and interest is valuable. Sure now we can define or: in our class and try to find its senders by browsing at least on of the 1590 senders (quite pratical). And if one day we will have a type inferencer for Pharo code we just removed some of the few cases where we could do something. (and this is true that Booleans are not the basis for building types analysis). Stef Le 1/5/15 11:58, Thierry Goubier a écrit :
Le 01/05/2015 11:50, Marcus Denker a écrit :
On 01 May 2015, at 11:48, stepharo <stepharo@free.fr> wrote:
To make the whole thing easier to understand we need to distinguish the two bugs.
1) or: is somehow special. No, it is not. We fixed that, but the fix was broken.
See my other mail. I would add two different kind of rules to help people and slow the use of redefinition of special selectors.
I do not understand why.
I side with Marcus there. Why?
You now have a compiler which does not make those selectors special, and you want to keep them special?
Thierry
Marcus
participants (6)
-
Andrei Chis -
Ben Coman -
Clément Bera -
Marcus Denker -
stepharo -
Thierry Goubier