Hello Michael:
I like your proposal in general. Almost from the day I started programming in
C, I've disliked the fact that the bitwise operators have lower precedence than
relational operators. The note from Dennis Ritchie is helpful in understanding
why C ended up that way, but no good reason to keep it. Chapel is enough
different from C/C++ that we should not be constrained by a (poor) choice made
40+ years ago.
However, I have some fine-tuning suggestions to offer: I'd like the bitwise and
operator '&' to have lower precedence than addition/subtraction, and I'd like
bitwise exclusive-or '^' to have lower precedence than bitwise or '|'.
The justification for my first suggestion is that '&' might be useful in
simulating word-widths that are smaller than the natural or chosen integer
width. For example, given var x:int:
x = x + 1 & 0xffffffff;
would be equivalent to
x = (x + 1) : int(8);
On the converse,
z = x & 0xff00 + y & 0x00ff; // Non-overlapping bit-strings
can also be coded as
z = x & 0xff00 | y & 0x00ff;
while
z = x & 0x0ff0 + y & 0x00ff; // Overlapping bit-strings
most likely represents a programming error, and will be harder to debug if '+'
is used in preference to '|'.
The justification for my second suggestion is borrowed from a text on logic.
There, the stated precedence for (single-bit) logical operators is: not, and,
or, if, iff. Iff is Boolean equivalence. Looking at a single bit,
exclusive-or is Boolean non-equivalence. By analogy with arithmetic
equivalence and non-equivalence having the same precedence, bitwise
non-equivalence should bind more loosely than bitwise-or.
At least the "tradition" argument holds, if a logician wants to manipulate two
vectors of logical values: the bitwise operators would provide the precedence
he expects.
As far as practicality is concerned, the judgement call is whether
(x ^ y) | (z ^ t)
is more or less likely than
(x | y) ^ (z | t)
(the more common case being the one in which you can omit the parentheses).
The utility of exclusive-or in comparing bit strings might tip the balance:
if (system_settings | user_settings | command_line_settings |
runtime_settings ^ ~ VERY_SPECIAL_CASE) then
/* Do something for very special case */;
That is, if the union of the various settings exactly matches the very special
case then do something.
For what it's worth,
Tom Hildebrandt
________________________________________
From: Michael Ferguson [[email protected]]
Sent: Wednesday, January 15, 2014 7:31 AM
To: [email protected]
Subject: operator precedence
Hi Chapel Users -
Over on chapel-developers, we have been discussing changing the Chapel
language operator precedence - especially to fix the order of bitwise
operators in relation to equality operators.
We'd like to know if Chapel users have any objections to this change.
Why? I learned recently that even the creators of C (or at least,
Dennis Ritchie) think that the bitwise operator precedence rules are wrong.
See
http://www.lysator.liu.se/c/dmr-on-or.html
I did a little survey of languages.
The C way : C C++ Java Objective-C PHP C# Javascript;
in these languages, bitwise operations have lower precedence than ==.
GO: shift, bitwise and with multiply, bitwise or xor with +
Erlang: bitwise and with *; all others bitwise ops with +
Perl 6, Python, Ruby, Dart: bitwise operators looser than + but tighter than ==
I'm proposing that Chapel follow Go on this point,
since shifting also means multiply by a power of 2.
Note that Go has very few precedence levels; Chapel has more.
At least for now, I have preserved the order of precedence within the
bitwise operations, add/multiply/divide, and comparison operators, even
though I'm not (yet) convinced that the different precedence levels are
always justified. The change here is to make them mix differently (so
would only change the interpretation of expressions that combine operators
from 2 or more of those classes).
Some examples.
These work both under the old and new rules:
right-rotate: x >> 1 | x & 1
left-rotate: x << 1 | x >> 63
append bits to number: x << 7 | new_bits
extract bit i: x & 1 << i
These work under the new precedence rules only:
check mask set: if x & MASK == MASK
check mask bit: if x & MASK != 0
shift-as-multiply: 17 + x << 2 // ie same as 17 + x * 4
check bit i: x & 1 << i != 0
Compare ranges: 1..10 == 1..10
More details below (and in the chapel-developers thread).
Comments?
Thanks,
-michael
The Chapel precedence table now (from loosest-binding to tightest-binding):
else
,
for forall if atomic sync single
align by #
in
..
||
&&
|
^
&
== !=
<= >= < >
<< >>
+ - (binary)
+ - (unary)
* / %
~ !
reduce scan dmapped
**
:
new
.member call() access[] {}
The proposed Chapel precedence table (from loosest-binding to tightest-binding):
else
,
for forall if atomic sync single
in
align by hash
||
&&
== !=
<= >= < >
..
|
^
+ - (binary)
&
<< >>
+ - (unary)
* / %
~ !
reduce scan dmapped
**
:
new
.member call() access[] {}
------------------------------------------------------------------------------
CenturyLink Cloud: The Leader in Enterprise Cloud Services.
Learn Why More Businesses Are Choosing CenturyLink Cloud For
Critical Workloads, Development Environments & Everything In Between.
Get a Quote or Start a Free Trial Today.
http://pubads.g.doubleclick.net/gampad/clk?id=119420431&iu=/4140/ostg.clktrk
_______________________________________________
Chapel-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-users
------------------------------------------------------------------------------
CenturyLink Cloud: The Leader in Enterprise Cloud Services.
Learn Why More Businesses Are Choosing CenturyLink Cloud For
Critical Workloads, Development Environments & Everything In Between.
Get a Quote or Start a Free Trial Today.
http://pubads.g.doubleclick.net/gampad/clk?id=119420431&iu=/4140/ostg.clktrk
_______________________________________________
Chapel-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-users