<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">Am 06.01.2018 um 19:45 schrieb Eliot Miranda <<a href="mailto:eliot.miranda@gmail.com" class="">eliot.miranda@gmail.com</a>>:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">Hi Norbert, Hi Denis,<div class="gmail_extra"><br class=""><div class="gmail_quote">On Sat, Jan 6, 2018 at 4:06 AM, Norbert Hartl<span class="Apple-converted-space"> </span><span dir="ltr" class=""><<a href="mailto:norbert@hartl.name" target="_blank" class="">norbert@hartl.name</a>></span><span class="Apple-converted-space"> </span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"> <br class=""><div style="word-wrap: break-word;" class=""><br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">Am 05.01.2018 um 16:53 schrieb Clément Bera <<a href="mailto:bera.clement@gmail.com" target="_blank" class="">bera.clement@gmail.com</a>>:</div><br class="gmail-m_-6620910617287063281Apple-interchange-newline"><div class=""><br class="gmail-m_-6620910617287063281Apple-interchange-newline"><br style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" class=""><div class="gmail_quote" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">On Fri, Jan 5, 2018 at 4:05 PM, Norbert Hartl<span class="gmail-m_-6620910617287063281Apple-converted-space"> </span><span dir="ltr" class=""><<a href="mailto:norbert@hartl.name" target="_blank" class="">norbert@hartl.name</a>></span><span class="gmail-m_-6620910617287063281Apple-converted-space"> </span>wro<wbr class="">te:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"> <br class=""><div style="word-wrap: break-word;" class="">You mean<div class=""><br class=""></div><div class=""><div class=""><span class="gmail-m_-6620910617287063281m_8231836668159255930Apple-tab-span" style="white-space: pre-wrap;">    </span><primitive: 174 error: ec></div><div class=""><span class="gmail-m_-6620910617287063281m_8231836668159255930Apple-tab-span" style="white-space: pre-wrap;">  </span>self isReadOnlyObject </div><div class=""><span class="gmail-m_-6620910617287063281m_8231836668159255930Apple-tab-span" style="white-space: pre-wrap;">               </span>ifTrue: [(ModificationForbidden for: self atInstVar: index with: anObject) signal]</div><div class=""><span class="gmail-m_-6620910617287063281m_8231836668159255930Apple-tab-span" style="white-space: pre-wrap;">                </span>ifFalse: [ self primitiveFailed ]</div><div class="">?</div><div class=""><br class=""></div><div class="">Norbert</div></div></div></blockquote><div class=""><br class=""></div><div class="">yes something like that.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Same thing for Object>>#at:put:, floatAt:put: and so on.</div></div></div></blockquote><div class=""><br class=""></div>I’m working on it and came by</div><div class=""><br class=""></div><div class="">Object>>#<wbr class="">primitiveChangeClassTo:</div><div class=""><br class=""></div><div class="">and I wonder what would be the approach here. The ModificationForbidden/<wbr class="">NoModificationError seems to be tight to an index. What would be the case for a class change? Another Exception class? How is that solved in VW? </div></div></blockquote><div class=""><br class=""></div><div class="">I don't think that adding variants of NoModificationError is wise.  One can imagine adding other state changes that read-onliness should prevent, such as unpinning.  So one could end up having to add a lot of subclasses of NoModificationError, each rather inflexible and able to respond to only one specific error.  We would end up with at least InstanceVariableModificationError IndexedVariableModificationError ClassModificationError BecomeIdentotyChangeError etc.  And even then IndexedVariableModificationError would need a message since there are many different kinds of at:put:s, at:put:, byteAt:put: unsignedLongAt:put: etc.</div><div class=""><br class=""></div><div class="">In VW it is handled by the NoModificationError holding a Message that can be used for the retry operation.  i.e.</div><div class=""><br class=""></div><div class="">Object>>noModificationErrorFor: selector index: index value: value</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">   </span>^(NoModificationError receiver: self selector: selector index: index value: value) raiseRequest</div><div class=""><br class=""></div><div class="">(N.B. the following is sent by the VM when an inst var assignment fails due to read-onlyness; see recreateSpecialObjectsArray)</div><div class="">Object>>attemptToAssign: aValue withIndex: index</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">    </span>^self noModificationErrorFor: #instVarAt:put: index: index value: aValue</div><div class=""><br class=""></div><div class="">Object>>at: index put: value</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">       </span>"Store the argument value in the indexable field of the receiver indicated by</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-converted-space"> </span>index. Fail if the index is not an Integer or is out of bounds. Fail if the</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-converted-space"> </span>value is not of the right type for this kind of collection. Answer the</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">     </span><span class="Apple-converted-space"> </span>value that was stored."</div><div class=""><br class=""></div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">        </span><primitive: 61 errorCode: ec></div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">       </span>index isInteger ifTrue:</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">           </span>[(index >= 1 and: [index <= self basicSize])</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">                        </span>ifTrue:</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">                           </span>[self isImmutable</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">                                 </span>ifTrue: [^self noModificationErrorFor: #at:put: index: index value: value]</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">                                        </span>ifFalse: [^self improperStoreError]]</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">                      </span>ifFalse: [^self subscriptBoundsErrorFor: #at:put: index: index value: value]].</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">    </span>index respondsToArithmetic</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">                </span>ifTrue: [^self at: index asSmallInteger put: value]</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">               </span>ifFalse: [^self nonIntegerIndexError: index]</div><div class=""><br class=""></div><div class="">Behavior>>adoptInstance: anObject</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">      </span>"Changes the class of the argument to be that of the receiver provided that</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">  </span><span class="Apple-converted-space"> </span> a)<span class="gmail-Apple-tab-span" style="white-space: pre;">     </span>anObject is not immutable (which includes immediates)</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">     </span><span class="Apple-converted-space"> </span> b)<span class="gmail-Apple-tab-span" style="white-space: pre;">     </span>anObject is bits and the receiver is a bits class, or</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">     </span><span class="Apple-converted-space"> </span> c)<span class="gmail-Apple-tab-span" style="white-space: pre;">     </span>anObject is pointers and the receiver is pointers and anObject has the same</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">               </span>number of inst vars as specified by the receiver, or the receiver is variable and</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">         </span>anObject has at least as many inst vars as specified by the receiver.</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">     </span><span class="Apple-converted-space"> </span>Answers the receiver."</div><div class=""><br class=""></div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;"> </span><primitive: 536 errorCode: errCode></div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;"> </span>^(errCode ~~ nil</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">  </span><span class="Apple-converted-space"> </span>  and: [errCode name = #'no modification'])</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">           </span>ifTrue: [anObject noModificationErrorFor: #changeClassTo: index: nil value: self]</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">         </span>ifFalse: [self primitiveFailed]</div><div class=""><br class=""></div><div class="">etc.  This is much more flexible and works well in practice.  In the vw7.7nc image I looked at there are 20 senders of #noModificationErrorFor:index:value: for variants of 5 operations:</div><div class=""><br class=""></div><div class="">- attempting to assign to an inst var of a read-only object, either directly in code via an inst var assignment or via an instVarAt:put: send</div><div class="">- attempting to assign to an indexed inst var of a read-only object, via an at:put: send (at:put: byteAt:put: unsignedLongAt:put: etc)</div>- attempting to assign to an indexed inst var of a read-only object via a BitBlt primitive (e.g. copyBitsClippedStride:width:atX:y:from:stride:width:atX:y:width:height:rule:)<div class="">- attempting to become a read-only object via two-way become; forwarding become is not considered a modification.</div><div class="">- attempting to change the class of a read-only object</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Digression:</div><div class=""><br class=""></div><div class="">Looking at the above the obvious convenience is to add</div><div class=""><br class=""></div><div class=""><div class="">Object>>noModificationErrorFor: selector value: value</div><div class=""><span class="gmail-Apple-tab-span" style="white-space: pre;">        </span>^(NoModificationError receiver: self selector: selector index: nil value: value) raiseRequest</div></div><div class=""><br class=""></div><div class="">which would be applicable in 8 of the 20 uses, but it would imply adding overrides in subclasses.  #noModificationErrorFor:index:value: is implemented in ProtoObect, Object, Symbol and VariableBinding. The implementations in Symbol and VariableBinding simply provide more explanatory error messages.</div><div class=""><br class=""></div></div></div></div></div></blockquote>Thanks for the detailed answer. I’m not fully convinced that stripping off the quality for variants of forbidden modification is the right way to go. But I also had the gut feeling multiple classes could be over-done. I try and see if I’m satisfied with the single exception. Why I would favor the sublcasses is the fact that modifify the position of an object, modifying the shape of an object and modifying the state of an object are separated concerns that usually don’t go together. So the potential that each of the three can be treated differently could be helpful. </div><div><br class=""></div><div>thanks again,</div><div><br class=""></div><div>Norbert</div><div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">HTH</div><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div style="word-wrap: break-word;" class=""><div class=""><br class=""></div><div class="">Norbert</div><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="gmail_quote" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><div class=""> </div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div style="word-wrap: break-word;" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">Am 05.01.2018 um 14:22 schrieb Clément Bera <<a href="mailto:bera.clement@gmail.com" target="_blank" class="">bera.clement@gmail.com</a>>:</div><br class="gmail-m_-6620910617287063281m_8231836668159255930Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">Hi,</div><div class=""><br class=""></div><div class="">No this is not a bug.</div><div class=""><br class=""></div>This needs to be handled in the primitive failure code in the image, the method should be something like that :<div class=""><br class=""><div class=""><div class=""><font face="monospace, monospace" class="">Object>>instVarAt: index put: anObject</font></div><div class=""><font face="monospace, monospace" class=""><span style="white-space: pre-wrap;" class="">       </span><primitive: 174 error: ec></font></div><div class=""><font face="monospace, monospace" class="">       <span class="gmail-m_-6620910617287063281Apple-converted-space"> </span>self isReadOnlyObject ifTrue: [(ModificationForbidden for: self atInstVar: index with: anObject) signal]</font></div><div class=""><font face="monospace, monospace" class=""><span style="white-space: pre-wrap;" class="">     </span>self primitiveFailed</font></div><div class=""><br class=""></div><div class="">All primitive fall-back code triggering object mutation should be rewritten this way, especially primitives such as #at:put:, #instVarAt:put:, etc.</div><div class=""><br class=""></div></div></div><div class="">Cheers</div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Fri, Jan 5, 2018 at 1:42 PM, Norbert Hartl<span class="gmail-m_-6620910617287063281Apple-converted-space"> </span><span dir="ltr" class=""><<a href="mailto:norbert@hartl.name" target="_blank" class="">norbert@hartl.name</a>></span><span class="gmail-m_-6620910617287063281Apple-converted-space"> </span>wro<wbr class="">te:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"> <br class=""><div style="word-wrap: break-word;" class="">If I do <div class=""><br class=""></div><div class=""><div class="">(#foo -> #bar)</div><div class=""><span class="gmail-m_-6620910617287063281m_8231836668159255930m_-2406158539713268726Apple-tab-span" style="white-space: pre-wrap;">    </span>beReadOnlyObject;</div><div class=""><span class="gmail-m_-6620910617287063281m_8231836668159255930m_-2406158539713268726Apple-tab-span" style="white-space: pre-wrap;">   </span>value: #baz</div></div><div class=""><br class=""></div><div class="">it throws</div><div class=""><br class=""></div><div class=""><b class="">ModificationForbidden:  #foo->#bar is read-only, hence its field 2 cannot be modified with #baz</b></div><div class=""><br class=""></div><div class=""> which is as expected. But if I do</div><div class=""><br class=""></div><div class=""><div class="">(#foo -> #bar)</div><div class=""><span class="gmail-m_-6620910617287063281m_8231836668159255930m_-2406158539713268726Apple-tab-span" style="white-space: pre-wrap;">     </span>beReadOnlyObject;</div><div class=""><span class="gmail-m_-6620910617287063281m_8231836668159255930m_-2406158539713268726Apple-tab-span" style="white-space: pre-wrap;">   </span>instVarNamed: #value put: #baz</div></div><div class=""><br class=""></div><div class="">I get</div><div class=""><br class=""></div><div class=""><b class="">PrimitiveFailed: primitive #instVarAt:put: in Association failed</b></div><div class=""><br class=""></div><div class="">I think this a bug, no?</div><div class=""><br class=""></div><div class="">Norbert</div></div><br class=""></blockquote></div><br class=""><br clear="all" class=""><div class=""><br class=""></div>--<span class="gmail-m_-6620910617287063281Apple-converted-space"> </span><br class=""><div class="gmail-m_-6620910617287063281m_8231836668159255930gmail_signature"><div dir="ltr" class=""><span style="font-size: 12.8px;" class="">Clément Béra</span><div style="font-size: 12.8px;" class="">Pharo consortium engineer</div><div style="font-size: 12.8px;" class=""><a href="https://clementbera.wordpress.com/" target="_blank" class="">https://clementbera.wordpress.<wbr class="">com/</a><br class=""></div><div style="font-size: 12.8px;" class=""><span style="line-height: 16px;" class="">Bâtiment B 40, avenue Halley 59650 </span><span style="font-weight: bold; line-height: 16px;" class="">Villeneuve d'Ascq</span></div></div></div></div></div></blockquote></div><br class=""></div></div><br class=""></blockquote></div><br style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" class=""><br clear="all" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" class=""><div style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" class=""><br class=""></div><span style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; float: none; display: inline;" class="">--<span class="gmail-m_-6620910617287063281Apple-converted-space"> </span></span><br style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" class=""><div class="gmail-m_-6620910617287063281gmail_signature" style="font-family: Helvetica; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><div dir="ltr" class=""><span style="font-size: 12.8px;" class="">Clément Béra</span><div style="font-size: 12.8px;" class="">Pharo consortium engineer</div><div style="font-size: 12.8px;" class=""><a href="https://clementbera.wordpress.com/" target="_blank" class="">https://clementbera.wordpress.<wbr class="">com/</a><br class=""></div><div style="font-size: 12.8px;" class=""><span style="line-height: 16px;" class="">Bâtiment B 40, avenue Halley 59650 </span><span style="font-weight: bold; line-height: 16px;" class="">Villeneuve d'Ascq</span></div></div></div></div></blockquote></div><br class=""></div><br class=""></blockquote></div><br class=""><br clear="all" class=""><div class=""><br class=""></div>--<span class="Apple-converted-space"> </span><br class=""><div class="gmail_signature"><div dir="ltr" class=""><div class=""><span style="font-size: small; border-collapse: separate;" class=""><div class="">_,,,^..^,,,_<br class=""></div><div class="">best, Eliot</div></span></div></div></div></div></div></div></blockquote></div><br class=""></body></html>