## D - infix functions as a substitute for operator overloading?

• Richard Krehbiel (33/33) Feb 13 2002 My thinking: Why does operator overloading exist?
• Russ Lewis (19/25) Feb 13 2002 Can you describe why this is impossible with YACC? As I understand it, ...
• Richard Krehbiel (51/71) Feb 13 2002 precedence
• Russ Lewis (9/12) Feb 13 2002 Gotcha! Now I understand.
• OddesE (14/21) Feb 17 2002 always
• Pavel Minayev (5/8) Feb 17 2002 He said "user-defined", not "built-in".
• Russ Lewis (11/14) Feb 18 2002 Right. I would say that any overloading of standard operators (with or
• OddesE (16/30) Feb 18 2002 Oh I'm sorry, I understood wrong.
• Pavel Minayev (4/8) Feb 13 2002 operation,
• Russell Borogove (28/43) Feb 13 2002 For a second, I thought Richard's suggestion was a valuable
• OddesE (9/18) Feb 17 2002 Me too!
• Roland (6/20) Feb 13 2002 I already suggested something like this (see "Operator overloading, ann ...
"Richard Krehbiel" <rich kastle.com> writes:
```My thinking: Why does operator overloading exist?

I think the primary reason is to allow an infix notation for user-defined
functions.

Common compiler construction technology (YACC, PCCTS) requires the syntax be
fixed; the set of infix tokens is fixed, their precedence is fixed, their
associativity is fixed.

But maybe we've progressed beyond that.  What if it were possible for the
user to simply declare a function as "infix?"

infix int plus(int a, int b) { return a + b; }

Now you can code:

int x, y, z;
z = x plus y;

Pretty readable.  Clearly "plus" is a user- (or library-) defined operation,
and I *like* making that clear to the reader.

That leaves precedence and associativity.  Right now I'd guess that it would
be okay if all infix operators would have lower precedence than all built-in
operators.  We can also simplify by giving all infix functions equal
precedence, and make the user group them as needed by parentheses, but it
might be nice to be able to specify their associativity (does "a plus b plus
c" do "b plus c" first, or "a plus b" first?).

Now, ISTR that the current alpha D compiler is a hand-coded
recursive-descent parser, and I'm pretty sure that a smart man like Walter
could in fact code up syntactic analyser that is tolerant of additions to
the infix operator table (eh, Walter?).  But it means you can't build D
compilers with YACC (um, maybe; if you leave out user control of precedence
and associativity, I think it could still be done).  Oh, and it means
feeding back info from semantic analysis into syntax, and I recall reading
that Walter has decided this is bad (the reasoning for his syntactic changes
to type-casting operations).

Well, it was a thought.

--
Richard Krehbiel, Arlington, VA, USA
rich kastle.com (work) or krehbiel3 home.com (personal)
```
Feb 13 2002
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
```Richard Krehbiel wrote:

But it means you can't build D
compilers with YACC (um, maybe; if you leave out user control of precedence
and associativity, I think it could still be done).  Oh, and it means
feeding back info from semantic analysis into syntax, and I recall reading
that Walter has decided this is bad (the reasoning for his syntactic changes
to type-casting operations).

Can you describe why this is impossible with YACC?  As I understand it, what
YACC really sees is
<token> = <token> <token> <token>  ;

Which it would parse into blocks something like
blockA:        x plus y
blockB:        z = <blockA>
blockC:        <blockB>   ;
It's the responsibility of the compiler code supplied with the blockA rule to
determine what those 3 alphanumeric tokens mean.  It's not particularly
different from
foo bar;
which the compiler must deduce (from semantics) is a variable declaration.

Maybe I'm missing something again...

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
```
Feb 13 2002
"Richard Krehbiel" <rich kastle.com> writes:
```"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C6A7779.27137005 deming-os.org...
Richard Krehbiel wrote:

But it means you can't build D
compilers with YACC (um, maybe; if you leave out user control of

precedence
and associativity, I think it could still be done).  Oh, and it means
feeding back info from semantic analysis into syntax, and I recall

reading
that Walter has decided this is bad (the reasoning for his syntactic

changes
to type-casting operations).

Can you describe why this is impossible with YACC?  As I understand it,

what
YACC really sees is
<token> = <token> <token> <token>  ;

Which it would parse into blocks something like
blockA:        x plus y
blockB:        z = <blockA>
blockC:        <blockB>   ;
It's the responsibility of the compiler code supplied with the blockA rule

to
determine what those 3 alphanumeric tokens mean.  It's not particularly
different from
foo bar;
which the compiler must deduce (from semantics) is a variable declaration.

Maybe I'm missing something again...

Here's a YACC (like) expression of some of the C grammar, taken from the
back of K&R's "The C Programming Language:"

shift_expr:
add_expr
| shift_expr '<<' add_expr
| shift_expr '>>' add_expr;

add_expr:
mul_expr
| add_expr '+' mul_expr
| add_expr '-' mul_expr;

mul_expr:
cast_expr
| mul_expr '*' cast_expr
| mul_expr '/' cast_expr
| mul_expr '%' cast_expr;

Precedence is defined in the grammar, that is, the grammar (which can't be
changed at run time) defines that a mul_expr has higher precedence than
add_expr and shift_expr (so "a + b * c" evaluates as "a + (b * c)").

Associativity is also defined in the grammar.  Associativity says that if
you have "a + b - c" it's evaluated as "(a + b) - c" (um, probably; C can
reorder these, and you can tell by side-effects, if it can prove that
otherwise the result is indistinguishable - and if overflow is possible,
then it can be).

Associativity matters a great deal if the side effects matter, like with the
C++ "<<" iostream operator.  When you code 'cout << "result is " << i <<
endl;', the output must go left-to-right.

What I was saying is, if we rule that user-defined infix operators always
and forever have a particular precedence and associativity, then we *can*
build such a compiler with YACC.

Assuming that the above was the top of the "expression" definition (it's
not), we'd add:

user_infix_expr:
shift_expr
| user_infix_expr INFIX_TOKEN shift_expr;

And then, we'd tell the lexer that user-defined infix function names be
returned as INFIX_TOKEN rather than as IDENTIFIER_TOKEN.

Now, with a recursive-descent parser written in plain C, precedence and
associativity rules could also be changed at run time.  But you still need
to know it's an "infix operator", not an "identiier", which means feedback.

(...and I'm sure that *real* compiler designers will correct any of this
that's wrong...)

--
Richard Krehbiel, Arlington, VA, USA
rich kastle.com (work) or krehbiel3 home.com (personal)
```
Feb 13 2002
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
```Richard Krehbiel wrote:

What I was saying is, if we rule that user-defined infix operators always
and forever have a particular precedence and associativity, then we *can*
build such a compiler with YACC.

Gotcha!  Now I understand.

Frankly, it seems like left-to-right precedence/associativity makes sense for
the majority of applications.  Anybody got (good) counterexamples?

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
```
Feb 13 2002
"OddesE" <OddesE_XYZ hotmail.com> writes:
```"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C6A891A.A5881559 deming-os.org...
Richard Krehbiel wrote:

What I was saying is, if we rule that user-defined infix operators

always
and forever have a particular precedence and associativity, then we

*can*
build such a compiler with YACC.

Gotcha!  Now I understand.

Frankly, it seems like left-to-right precedence/associativity makes sense

for
the majority of applications.  Anybody got (good) counterexamples?

CInt256 a = 1, b = 2, c = 5;

a = a + b * c;

// Should yield 11, not 15....

--
Stijn
OddesE_XYZ hotmail.com
http://OddesE.cjb.net
__________________________________________
Remove _XYZ from my address when replying by mail
```
Feb 17 2002
"Pavel Minayev" <evilone omen.ru> writes:
```"OddesE" <OddesE_XYZ hotmail.com> wrote in message
news:a4o5g5\$rgm\$1 digitaldaemon.com...

CInt256 a = 1, b = 2, c = 5;

a = a + b * c;

// Should yield 11, not 15....

He said "user-defined", not "built-in".
For user-defined, I guess we can live with fixed precedence,
using braces where necessary...
```
Feb 17 2002
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
```Pavel Minayev wrote:

He said "user-defined", not "built-in".
For user-defined, I guess we can live with fixed precedence,
using braces where necessary...

Right.  I would say that any overloading of standard operators (with or
without the :'s that have been suggested) should have the same
precedence and left-to-right orientation as the original operators.  But
user-defined infix operators of this type should all have left-to-right
orientation with relatively low precedence.

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
```
Feb 18 2002
"OddesE" <OddesE_XYZ hotmail.com> writes:
```"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C70B980.E4FD2FA1 deming-os.org...
Pavel Minayev wrote:

He said "user-defined", not "built-in".
For user-defined, I guess we can live with fixed precedence,
using braces where necessary...

Right.  I would say that any overloading of standard operators (with or
without the :'s that have been suggested) should have the same
precedence and left-to-right orientation as the original operators.  But
user-defined infix operators of this type should all have left-to-right
orientation with relatively low precedence.

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]

Oh I'm sorry, I understood wrong.
I think user defined infix operations would be cool and I
could live with fixed left to right precedence without a
problem. I thought it was proposed as a substitution for
overloading the standard operators, but I agree that you
shouldn't mess with the precedence of + and *, or many
people will be very confused and that can't be what we
are aiming at with operator overloading.

--
Stijn
OddesE_XYZ hotmail.com
http://OddesE.cjb.net
__________________________________________
Remove _XYZ from my address when replying by mail
```
Feb 18 2002
"Pavel Minayev" <evilone omen.ru> writes:
```"Richard Krehbiel" <rich kastle.com> wrote in message
news:a4dqip\$28i7\$1 digitaldaemon.com...

int x, y, z;
z = x plus y;

Pretty readable.  Clearly "plus" is a user- (or library-) defined

operation,
and I *like* making that clear to the reader.

Hey, I still want to be able to overload + as is! =)
```
Feb 13 2002
Russell Borogove <kaleja estarcion.com> writes:
```Pavel Minayev wrote:
"Richard Krehbiel" <rich kastle.com> wrote in message
news:a4dqip\$28i7\$1 digitaldaemon.com...

int x, y, z;
z = x plus y;

Pretty readable.  Clearly "plus" is a user- (or library-) defined

operation,

and I *like* making that clear to the reader.

Hey, I still want to be able to overload + as is! =)

For a second, I thought Richard's suggestion was a valuable
compromise.

But when you think about it, it just _looks_ like... I
don't know. Baby talk. Training wheels. Writing with crayon.
(No offense intended.)

Once you start trying to write a big hairy expression
with "plus", you're going to want to rename it "pl" then
"p" (or "add", then "a") to save space on the line. At
that point you've hurt readability more than if you had
overloaded the plus sign. Likewise, you still can't
reasonably enforce against writing a "plus" function that,
say, appends to a file on the disk. So who are we kidding?

Unless you're going to vastly alter the way D is specified
now, Walter, there are going to be a million ways to write
misleading and crappy code. Giving us overloaded operators
in the style of C++[1], or not, isn't materially going to
change that. Many people want the overloaded operators. I
don't know what other arguments I can make.

Okay, okay, here's one more.

Bignums. If I want to create a class that manages arbitrary-
precision, arbitrary-magnitude numbers, I want to manipulate
them using the conventional mathematical operators. :+: and
other weirdness isn't going to help readability.

-Russell B

[1] And by that I mean without substantially restricting the
operator list from C++ -- sure, get rid of . and -> and , but
leave the bitwise, logical, and comparison operators in.
```
Feb 13 2002
"OddesE" <OddesE_XYZ hotmail.com> writes:
```"Pavel Minayev" <evilone omen.ru> wrote in message
news:a4duo0\$2ao6\$1 digitaldaemon.com...
"Richard Krehbiel" <rich kastle.com> wrote in message
news:a4dqip\$28i7\$1 digitaldaemon.com...

int x, y, z;
z = x plus y;

Pretty readable.  Clearly "plus" is a user- (or library-) defined

operation,
and I *like* making that clear to the reader.

Hey, I still want to be able to overload + as is! =)

Me too!

--
Stijn
OddesE_XYZ hotmail.com
http://OddesE.cjb.net
__________________________________________
Remove _XYZ from my address when replying by mail
```
Feb 17 2002
Roland <rv ronetech.com> writes:
```Richard Krehbiel a écrit :

My thinking: Why does operator overloading exist?

I think the primary reason is to allow an infix notation for user-defined
functions.

Common compiler construction technology (YACC, PCCTS) requires the syntax be
fixed; the set of infix tokens is fixed, their precedence is fixed, their
associativity is fixed.

But maybe we've progressed beyond that.  What if it were possible for the
user to simply declare a function as "infix?"

infix int plus(int a, int b) { return a + b; }

Now you can code:

int x, y, z;
z = x plus y;

Pretty readable.  Clearly "plus" is a user- (or library-) defined operation,
and I *like* making that clear to the reader.

I already suggested something like this (see "Operator overloading, ann other
idea").
I was not convinced by counter arguments.
So i still support infix notation

Roland
```
Feb 13 2002