Hi All,<div><br></div><div>    I just got bittenhard (not for the first time) by &amp; and | (implemented both by integers and booleans) being translated into &amp;&amp; (== and:) and || (== or:).  So the following in constant folding in the StackToRegisterMappingCogit</div>
<div><br></div><div><div><span class="Apple-tab-span" style="white-space:pre">        </span>(argIsInt and: [rcvrIsInt]) ifTrue:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>[rcvrInt := objectMemory integerValueOf: rcvrInt.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span> argInt := objectMemory integerValueOf: argInt.</div><div><span class="Apple-tab-span" style="white-space:pre">                </span> primDescriptor opcode caseOf: {</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>[AddRR]<span class="Apple-tab-span" style="white-space:pre">        </span>-&gt; [result := rcvrInt + argInt].</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>[SubRR]<span class="Apple-tab-span" style="white-space:pre">        </span>-&gt; [result := rcvrInt - argInt].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>[AndRR]<span class="Apple-tab-span" style="white-space:pre">        </span>-&gt; [result := rcvrInt &amp;: argInt].</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>[OrRR]<span class="Apple-tab-span" style="white-space:pre">        </span>-&gt; [result := rcvrInt | argInt] }.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>(objectMemory isIntegerValue: result) ifTrue:</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>[&quot;Must annotate the bytecode for correct pc mapping.&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>self annotateBytecode: self Label.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>^self ssPop: 2; ssPushConstant: (objectMemory integerObjectOf: result)].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>^self genSpecialSelectorSend].</div></div><div><br></div><div>produced valid results in the simulator, but was translated to</div><div><br></div><div><div>
    if (argIsInt</div><div>     &amp;&amp; (rcvrIsInt)) {</div><div>        rcvrInt = (rcvrInt &gt;&gt; 1);</div><div>        argInt = (argInt &gt;&gt; 1);</div><div><br></div><div>        switch ((primDescriptor-&gt;opcode)) {</div>
<div>        case AddRR:</div><div>                        result = rcvrInt + argInt;</div><div>            break;</div><div>        case SubRR:</div><div>                        result = rcvrInt - argInt;</div><div>            break;</div>
<div>        case AndRR:</div><div>                        result = rcvrInt &amp;&amp; argInt;</div><div>            break;</div><div>        case OrRR:</div><div>                        result = rcvrInt || argInt;</div><div>
            break;</div><div>        default:</div><div>            error(&quot;Case not found and no otherwise clause&quot;);</div><div>        }</div><div>        if (isIntegerValue(result)) {</div><div>            annotateBytecode(gLabel());</div>
<div>            return ssPop(2),ssPushConstant(((result &lt;&lt; 1) | 1));</div><div>        }</div><div>        return genSpecialSelectorSend();</div><div>    }</div></div><div><br></div><div>and so e.g. 16r4000 bitOr: 16r8000 evaluated to 1, not 49152.</div>
<div><br></div><div>Three approaches come to mind, </div><div>a) emit a warning when &amp; and | are used with variables and/or literals as opposed to message sends, e.g. warn for 1 | 2, var | var et al, but not for (a &gt; b) | (b &gt; c) et al</div>
<div>b) translate | to | and &amp; to &amp;</div><div>c) translate expr | expr to expr || expr and expr &amp; expr to expr &amp;&amp; expr, but translate varOrLiteral | anything to varOrLiteral | anything and varOrLiteral &amp; anything to varOrLiteral &amp; anything, and vice verse.</div>
<div><br></div><div>I&#39;m for b) since a relational expression such as a &gt; 1 is defined in C to be either 1 or 0, and so in C (oneOrZero | oneOrZero) == (oneOrZero || oneOrZero) and (oneOrZero &amp; oneOrZero) == (oneOrZero &amp;&amp; oneOrZero).</div>
<div><br></div><div>Thoughts, opinions?</div><div><br></div><div>best (hurting),</div><div>Eliot</div>