<br><br><div class="gmail_quote">On Tue, Mar 3, 2009 at 11:58 AM, John M McIntosh <span dir="ltr">&lt;<a href="mailto:johnmci@smalltalkconsulting.com">johnmci@smalltalkconsulting.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
Er, well the shift left/right assembler operations are signed or unsigned, but TYPED languages usually figure out which one to use based on the type of the operators.</blockquote><div><br></div><div>Forget about assembler.  In C &quot;signed &gt;&gt; expr&quot; is an arithmetic (signed) shift; &quot;unsigned &gt;&gt; expr&quot; is a logical (unsigned) one.  In Smalltalk &quot;negative bitShift: negative&quot; is an arithmetic shift, &quot;non-negative bitShift: negative&quot; is a logical one.  These are perfectly compatible, and both are useful.  In Smalltalk you can always write</div>
<div>       (foo bitAnd: (1 bitShift: preShiftFieldWidth) - 1) bitShift: expr</div><div>if you want to perform a logical shift.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
But since Smalltalk is type-less,</blockquote><div><br></div><div>No, that&#39;s not it.  In fact, Smalltalk is strongly typed.  Try bit shifting true.  Quite possible in C; not possible in Smalltalk.  Smalltalk has infinite precision so an unsigned value is simply a non-negative one.  The reason, I think, that Slang casts to unsigned is a hack to do with the default type of oops being sqInt (signed).  But this is a mistake.  Look at the definition of primitiveBitShift and ask yourself why this even works?</div>
<div><br></div><div><div>primitiveBitShift </div><div><span class="Apple-tab-span" style="white-space:pre">        </span>| integerReceiver integerArgument shifted |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>integerArgument := self popInteger.</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>integerReceiver := self popPos32BitInteger.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>self successful ifTrue: [</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>integerArgument &gt;= 0 ifTrue: [</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>&quot;Left shift -- must fail if we lose bits beyond 32&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>self success: integerArgument &lt;= 31.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>shifted := integerReceiver &lt;&lt; integerArgument.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>self success: (shifted &gt;&gt; integerArgument) = integerReceiver.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>] ifFalse: [</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>&quot;Right shift -- OK to lose bits&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>self success: integerArgument &gt;= -31.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>shifted := integerReceiver bitShift: integerArgument.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>].</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>self successful</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [self push: (self positive32BitIntegerFor: shifted)]</div><div>
<span class="Apple-tab-span" style="white-space:pre">                </span>ifFalse: [self unPop: 2]</div><div><br></div><div>It took me a few minutes of staring at</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>shifted := integerReceiver bitShift: integerArgument.</div>
<div>(which can&#39;t possibly work for negative values if Slang, as it does, casts to unsigned) before I realised that</div><div><br></div><div><span class="Apple-tab-span" style="white-space: pre; ">        </span>integerReceiver := self popPos32BitInteger.</div>
<div><br></div><div>means the primitive simply fails for negative receivers (!!!!!!!!!!!!!).</div><div><br></div><div>I&#39;ve noticed this before and I&#39;ve forgotten it (I&#39;m a bit like a goldfish in that regard) and I find it no less shocking each time I trip over it.</div>
</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">What if you code up a unsigned shift operator so there is no question that you want to do unsigned shifting, which also makes the  SLANG coder just a bit more aware he has a choice to make, casting is ok, but people forget. Also I can do senders of, then later wonder why am I not doing that here/there?</blockquote>
<div><br></div><div>Right.  I&#39;ve recently added #asUnsignedInteger as a concise cast to unsigned.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Having been bitten by signed shifting issues in the past, I can agree it&#39;s unpleasant.</blockquote><div><br></div><div><br></div><div><br></div><div>So look, surely shifts should be signed by default and be unsigned if the argument is unsigned, e.g./i.e.</div>
<div><br></div><div><div>!Integer methodsFor: &#39;*VMMaker-interpreter simulator&#39; stamp: &#39;eem 2/19/2009 18:33&#39;!</div><div>asUnsignedInteger</div><div><span class="Apple-tab-span" style="white-space: pre; ">        </span>self assert: self &gt;= 0.</div>
<div><span class="Apple-tab-span" style="white-space: pre; ">        </span>^self! !</div><div><br></div><div>and in CCodeGenerator&gt;&gt;initializeCTranslationDictionary:</div><div>    ...</div><div><span class="Apple-tab-span" style="white-space: pre; ">        </span>#asUnsignedInteger<span class="Apple-tab-span" style="white-space: pre; ">                        </span>#generateAsUnsignedInteger:on:indent:</div>
<div>    ...</div><div><br></div><div>and</div><div><div>!CCodeGenerator methodsFor: &#39;C translation&#39; stamp: &#39;eem 2/15/2009 16:38&#39;!</div><div>generateAsUnsignedInteger: msgNode on: aStream indent: level</div>
<div><span class="Apple-tab-span" style="white-space: pre; ">        </span>&quot;Generate the C code for this message onto the given stream.&quot;</div><div><br></div><div><span class="Apple-tab-span" style="white-space: pre; ">        </span>aStream nextPutAll:&#39;((usqInt)&#39;.</div>
<div><span class="Apple-tab-span" style="white-space: pre; ">        </span>self emitCExpression: msgNode receiver on: aStream.</div><div><span class="Apple-tab-span" style="white-space: pre; ">        </span>aStream nextPut: $)! !</div>
<div><br></div></div></div><div>and I autochange all senders of &gt;&gt; and bitShift: throughout the plugins, primitives and Interpreter to use asUnsignedInteger.  Do I dare?  Am I insane?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
<br>
PS I note we have methods  to  do unsigned compare logic when dealing with oop address so that *we* know we are doing something special, since people just couldn&#39;t manage the casts correctly.<div><div></div><div class="h5">
<br>
<br>
On 3-Mar-09, at 11:50 AM, Eliot Miranda wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi All,<br>
<br>
    I&#39;m being bitten by Slang&#39;s treatment of bitShift: &amp; &gt;&gt;.  In both cases (generateBitShift:on:indent: &amp; generateShiftRight:on:indent:) Slang generates an unsigned shift by explicitly casting the shifted expression to usqInt.  I can understand the benefit of having an unsigned shift.  But there are times when one really needs a signed shift.  Further, the Smalltalk versions of both bitShift: and &gt;&gt; are signed shifts.<br>

<br>
Dare I change e.g. generateShiftRight:on:indent: to leave the expression alone and generate either a signed or an unsigned shift based on the variable&#39;s declaration?  Or must I live with a maddening cCode: &#39;(signed)&#39; inSmalltalk: [] carbuncle?<br>

<br>
E.<br>
</blockquote>
<br></div></div><font color="#888888">
--<br>
===========================================================================<br>
John M. McIntosh &lt;<a href="mailto:johnmci@smalltalkconsulting.com" target="_blank">johnmci@smalltalkconsulting.com</a>&gt;<br>
Corporate Smalltalk Consulting Ltd.  <a href="http://www.smalltalkconsulting.com" target="_blank">http://www.smalltalkconsulting.com</a><br>
===========================================================================<br>
<br>
<br>
<br>
</font></blockquote></div><br>