[Draft] Resolving operator precedence conflicts

There have been complaints on current syntax of operator declarations:

infix operator <> { associativity left precedence 100 assignment }

It looks like a collection of random words. Dictionary syntax would suit
better here. Additionally, `assignment` has been deprecated for a long
time, but not removed.

Many syntaxes were suggested. For example:

#operator(<>, fixity: infix, associativity: left, precedence: 100)

*But* Joe Groff uncovered a deeper problem. Current operators cannot be
given precedence and associativity per concrete operator function.

Moreover, it makes more sense for operators to only allow parenthesis
omission for some other operators. (C/C++ gives warnings for relying on
precedence for unrelated operators.)

Operator declarations may lie in different modules and not know anything
about each other, but they will create a conflict if their names happen to
be identical.

The following is my attempt at solving the problem.

1.
All operators are aliases for functions.

#operator(+, name: numericAdd, fixity: infix, associativity: left)

func numericAdd(left: Int, _ right: Int) -> Int

#operator(+, name: numericUnaryPlus, fixity: prefix)

func unaryPlus(right: Int) -> Int

+1 + 2 // same as numericAdd(numericUnaryPlus(1), 2)

2.
Operators with same "operator form" use overloading, modified to accomodate
associativity and precedence.

#operator(+, name: append, fixity: infix)

func append<T>(left: [T], right: T) -> [T]

var arr = [1, 2, 3]
1 + 2 + 3 //=> 6
[1, 2] + 3 //=> 1 2 3
[1, 2] + 3 + 4 // error

Compiler must try to apply rules of both `numericAdd` and `append` in all
combinations. Complexity of this should not be exponential: most branches
will be cut off fast, starting from the inside.

In 1 + 2 + 3, `append` cannot be applied both to 1+2 and to 2+3, so we are
left with `numericAdd`.
In [1,2] + 3 + 4, `numericAdd` cannot be applied to [1,2] + 3, and `append`
cannot be applied to 3 + 4. But if we assume `append` and `numericAdd`,
then no precedence rule is defined between `numericAdd` and `append`.

Overall, algorithm for compiler is to be developed.

3.
Operators can define precedence (omission of parentheses), only compared to
other specific operators.

#precedence(append, lessThan: numericAdd)

#precedence(numericAdd, equalTo: numericSubtract)

4.
Precedence applies to unary operators as well:

let v: Bool? = false
let u = !v! // error, precedence between logicalNot and forceUnwrap is not
defined

#precedence(forceUnwrap, greaterThan: logicalNot)

let u = !v! // true

That said, precedence of unary operators is always higher than of any
binary operator.

- Anton

I agree that operator syntax needs to be reworked, but I prefer that
whatever proposal ends up being accepted not abuse the word 'fixity' to
mean something it doesn't.

···

On Tue, Mar 8, 2016 at 12:13 PM, Антон Жилин <swift-evolution@swift.org> wrote:

There have been complaints on current syntax of operator declarations:

infix operator <> { associativity left precedence 100 assignment }

It looks like a collection of random words. Dictionary syntax would suit
better here. Additionally, `assignment` has been deprecated for a long
time, but not removed.

Many syntaxes were suggested. For example:

#operator(<>, fixity: infix, associativity: left, precedence: 100)

*But* Joe Groff uncovered a deeper problem. Current operators cannot be
given precedence and associativity per concrete operator function.

Moreover, it makes more sense for operators to only allow parenthesis
omission for some other operators. (C/C++ gives warnings for relying on
precedence for unrelated operators.)

Operator declarations may lie in different modules and not know anything
about each other, but they will create a conflict if their names happen to
be identical.

The following is my attempt at solving the problem.

1.
All operators are aliases for functions.

#operator(+, name: numericAdd, fixity: infix, associativity: left)

func numericAdd(left: Int, _ right: Int) -> Int

#operator(+, name: numericUnaryPlus, fixity: prefix)

func unaryPlus(right: Int) -> Int

+1 + 2 // same as numericAdd(numericUnaryPlus(1), 2)

2.
Operators with same "operator form" use overloading, modified to
accomodate associativity and precedence.

#operator(+, name: append, fixity: infix)

func append<T>(left: [T], right: T) -> [T]

var arr = [1, 2, 3]
1 + 2 + 3 //=> 6
[1, 2] + 3 //=> 1 2 3
[1, 2] + 3 + 4 // error

Compiler must try to apply rules of both `numericAdd` and `append` in all
combinations. Complexity of this should not be exponential: most branches
will be cut off fast, starting from the inside.

In 1 + 2 + 3, `append` cannot be applied both to 1+2 and to 2+3, so we are
left with `numericAdd`.
In [1,2] + 3 + 4, `numericAdd` cannot be applied to [1,2] + 3, and
`append` cannot be applied to 3 + 4. But if we assume `append` and
`numericAdd`, then no precedence rule is defined between `numericAdd` and
`append`.

Overall, algorithm for compiler is to be developed.

3.
Operators can define precedence (omission of parentheses), only compared
to other specific operators.

#precedence(append, lessThan: numericAdd)

#precedence(numericAdd, equalTo: numericSubtract)

4.
Precedence applies to unary operators as well:

let v: Bool? = false
let u = !v! // error, precedence between logicalNot and forceUnwrap is
not defined

#precedence(forceUnwrap, greaterThan: logicalNot)

let u = !v! // true

That said, precedence of unary operators is always higher than of any
binary operator.

- Anton

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I agree that operator syntax needs to be reworked, but I prefer that whatever proposal ends up being accepted not abuse the word 'fixity' to mean something it doesn’t.

I can’t say with certainty whether “fixity” is cromulent or incromulent ;-), but how about: “position” or “placement”?

···

On Mar 8, 2016, at 12:33 PM, Austin Zheng via swift-evolution <swift-evolution@swift.org> wrote:

On Tue, Mar 8, 2016 at 12:13 PM, Антон Жилин <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
There have been complaints on current syntax of operator declarations:

infix operator <> { associativity left precedence 100 assignment }

It looks like a collection of random words. Dictionary syntax would suit better here. Additionally, `assignment` has been deprecated for a long time, but not removed.

Many syntaxes were suggested. For example:

#operator(<>, fixity: infix, associativity: left, precedence: 100)

*But* Joe Groff uncovered a deeper problem. Current operators cannot be given precedence and associativity per concrete operator function.

Moreover, it makes more sense for operators to only allow parenthesis omission for some other operators. (C/C++ gives warnings for relying on precedence for unrelated operators.)

Operator declarations may lie in different modules and not know anything about each other, but they will create a conflict if their names happen to be identical.

The following is my attempt at solving the problem.

1.
All operators are aliases for functions.

#operator(+, name: numericAdd, fixity: infix, associativity: left)

func numericAdd(left: Int, _ right: Int) -> Int

#operator(+, name: numericUnaryPlus, fixity: prefix)

func unaryPlus(right: Int) -> Int

+1 + 2 // same as numericAdd(numericUnaryPlus(1), 2)

2.
Operators with same "operator form" use overloading, modified to accomodate associativity and precedence.

#operator(+, name: append, fixity: infix)

func append<T>(left: [T], right: T) -> [T]

var arr = [1, 2, 3]
1 + 2 + 3 //=> 6
[1, 2] + 3 //=> 1 2 3
[1, 2] + 3 + 4 // error

Compiler must try to apply rules of both `numericAdd` and `append` in all combinations. Complexity of this should not be exponential: most branches will be cut off fast, starting from the inside.

In 1 + 2 + 3, `append` cannot be applied both to 1+2 and to 2+3, so we are left with `numericAdd`.
In [1,2] + 3 + 4, `numericAdd` cannot be applied to [1,2] + 3, and `append` cannot be applied to 3 + 4. But if we assume `append` and `numericAdd`, then no precedence rule is defined between `numericAdd` and `append`.

Overall, algorithm for compiler is to be developed.

3.
Operators can define precedence (omission of parentheses), only compared to other specific operators.

#precedence(append, lessThan: numericAdd)

#precedence(numericAdd, equalTo: numericSubtract)

4.
Precedence applies to unary operators as well:

let v: Bool? = false
let u = !v! // error, precedence between logicalNot and forceUnwrap is not defined

#precedence(forceUnwrap, greaterThan: logicalNot)

let u = !v! // true

That said, precedence of unary operators is always higher than of any binary operator.

- Anton

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

'Fixity' already has a non-technical meaning ("the state of being unchanged
and permanent"), and an unrelated technical one (a synonym for
associativity; search "assocativity fixity operator" for examples). If
we're using it in this different way, I respectfully submit that we should
reconsider.

Best,
Austin

···

On Tue, Mar 8, 2016 at 1:48 PM, Erica Sadun <erica@ericasadun.com> wrote:

cite The Swift Programming Language (Swift 2.2)

Imgur: The magic of the Internet

-- E

On Mar 8, 2016, at 2:42 PM, Charles Kissinger via swift-evolution < > swift-evolution@swift.org> wrote:

On Mar 8, 2016, at 12:33 PM, Austin Zheng via swift-evolution < > swift-evolution@swift.org> wrote:

I agree that operator syntax needs to be reworked, but I prefer that
whatever proposal ends up being accepted not abuse the word 'fixity' to
mean something it doesn’t.

I can’t say with certainty whether “fixity” is cromulent or incromulent
;-), but how about: “position” or “placement”?

cite The Swift Programming Language (Swift 2.2)

Imgur

-- E

···

On Mar 8, 2016, at 2:42 PM, Charles Kissinger via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 8, 2016, at 12:33 PM, Austin Zheng via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I agree that operator syntax needs to be reworked, but I prefer that whatever proposal ends up being accepted not abuse the word 'fixity' to mean something it doesn’t.

I can’t say with certainty whether “fixity” is cromulent or incromulent ;-), but how about: “position” or “placement”?

I'm not a compiler implementor, but I think changing that would be next
to impossible. We need to be able to parse the code before we can do
type-dependent analysis such as overload resolution.

···

on Tue Mar 08 2016, Антон Жилин <swift-evolution@swift.org> wrote:

There have been complaints on current syntax of operator declarations:

infix operator <> { associativity left precedence 100 assignment }

It looks like a collection of random words. Dictionary syntax would suit
better here. Additionally, `assignment` has been deprecated for a long
time, but not removed.

Many syntaxes were suggested. For example:

#operator(<>, fixity: infix, associativity: left, precedence: 100)

*But* Joe Groff uncovered a deeper problem. Current operators cannot be
given precedence and associativity per concrete operator function.

--
-Dave

Anton,

Could your idea be simplified by having an operator attribute that applies only to the following function declaration rather than referring to one by name?

#operator(fixity: infix, associativity: left)
func +(left: Int, _ right: Int) -> Int

#operator(fixity: prefix)
func +(right: Int) -> Int

—CK

···

On Mar 8, 2016, at 12:13 PM, Антон Жилин via swift-evolution <swift-evolution@swift.org> wrote:

There have been complaints on current syntax of operator declarations:

infix operator <> { associativity left precedence 100 assignment }

It looks like a collection of random words. Dictionary syntax would suit better here. Additionally, `assignment` has been deprecated for a long time, but not removed.

Many syntaxes were suggested. For example:

#operator(<>, fixity: infix, associativity: left, precedence: 100)

*But* Joe Groff uncovered a deeper problem. Current operators cannot be given precedence and associativity per concrete operator function.

Moreover, it makes more sense for operators to only allow parenthesis omission for some other operators. (C/C++ gives warnings for relying on precedence for unrelated operators.)

Operator declarations may lie in different modules and not know anything about each other, but they will create a conflict if their names happen to be identical.

The following is my attempt at solving the problem.

1.
All operators are aliases for functions.

#operator(+, name: numericAdd, fixity: infix, associativity: left)

func numericAdd(left: Int, _ right: Int) -> Int

#operator(+, name: numericUnaryPlus, fixity: prefix)

func unaryPlus(right: Int) -> Int

+1 + 2 // same as numericAdd(numericUnaryPlus(1), 2)

2.
Operators with same "operator form" use overloading, modified to accomodate associativity and precedence.

#operator(+, name: append, fixity: infix)

func append<T>(left: [T], right: T) -> [T]

var arr = [1, 2, 3]
1 + 2 + 3 //=> 6
[1, 2] + 3 //=> 1 2 3
[1, 2] + 3 + 4 // error

Compiler must try to apply rules of both `numericAdd` and `append` in all combinations. Complexity of this should not be exponential: most branches will be cut off fast, starting from the inside.

In 1 + 2 + 3, `append` cannot be applied both to 1+2 and to 2+3, so we are left with `numericAdd`.
In [1,2] + 3 + 4, `numericAdd` cannot be applied to [1,2] + 3, and `append` cannot be applied to 3 + 4. But if we assume `append` and `numericAdd`, then no precedence rule is defined between `numericAdd` and `append`.

Overall, algorithm for compiler is to be developed.

3.
Operators can define precedence (omission of parentheses), only compared to other specific operators.

#precedence(append, lessThan: numericAdd)

#precedence(numericAdd, equalTo: numericSubtract)

4.
Precedence applies to unary operators as well:

let v: Bool? = false
let u = !v! // error, precedence between logicalNot and forceUnwrap is not defined

#precedence(forceUnwrap, greaterThan: logicalNot)

let u = !v! // true

That said, precedence of unary operators is always higher than of any binary operator.

- Anton
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

'Fixity' already has a non-technical meaning ("the state of being unchanged and permanent"), and an unrelated technical one (a synonym for associativity; search "assocativity fixity operator" for examples). If we're using it in this different way, I respectfully submit that we should reconsider.

You are correct, of course, but a subset of computer scientists have been abusing the term in this way for at least a couple of decades. Their novel usage of “fixity” now has a degree of fixity, so it may be too late to fix "fixity".

···

On Mar 8, 2016, at 1:52 PM, Austin Zheng <austinzheng@gmail.com> wrote:

Best,
Austin

On Tue, Mar 8, 2016 at 1:48 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:
cite The Swift Programming Language (Swift 2.2)

Imgur: The magic of the Internet

-- E

On Mar 8, 2016, at 2:42 PM, Charles Kissinger via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Mar 8, 2016, at 12:33 PM, Austin Zheng via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I agree that operator syntax needs to be reworked, but I prefer that whatever proposal ends up being accepted not abuse the word 'fixity' to mean something it doesn’t.

I can’t say with certainty whether “fixity” is cromulent or incromulent ;-), but how about: “position” or “placement”?

It's become a termity of art.

-- E

···

On Mar 9, 2016, at 12:10 PM, Charles Kissinger <crk@akkyra.com> wrote:

On Mar 8, 2016, at 1:52 PM, Austin Zheng <austinzheng@gmail.com <mailto:austinzheng@gmail.com>> wrote:

'Fixity' already has a non-technical meaning ("the state of being unchanged and permanent"), and an unrelated technical one (a synonym for associativity; search "assocativity fixity operator" for examples). If we're using it in this different way, I respectfully submit that we should reconsider.

You are correct, of course, but a subset of computer scientists have been abusing the term in this way for at least a couple of decades. Their novel usage of “fixity” now has a degree of fixity, so it may be too late to fix "fixity".

1 Like

Isn’t this essentially describing it’s expression-ness? Why not just use “expression” like:

expression: infix
expression: postfix
expression: prefix

l8r
Sean

···

On Mar 9, 2016, at 1:12 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 9, 2016, at 12:10 PM, Charles Kissinger <crk@akkyra.com> wrote:

On Mar 8, 2016, at 1:52 PM, Austin Zheng <austinzheng@gmail.com> wrote:

'Fixity' already has a non-technical meaning ("the state of being unchanged and permanent"), and an unrelated technical one (a synonym for associativity; search "assocativity fixity operator" for examples). If we're using it in this different way, I respectfully submit that we should reconsider.

You are correct, of course, but a subset of computer scientists have been abusing the term in this way for at least a couple of decades. Their novel usage of “fixity” now has a degree of fixity, so it may be too late to fix "fixity".

It's become a termity of art.

-- E

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Isn’t this essentially describing it’s expression-ness? Why not just use “expression” like:

expression: infix
expression: postfix
expression: prefix

Are any of these proposals *better* than “infix operator + {“ ?

I’m not claiming that the body of the operator declaration is great, but one nice thing about it is that the required terms are part of the decl modifier, the optional gunk is in the body, and it reads well.

-Chris

···

On Mar 9, 2016, at 11:15 AM, Sean Heber via swift-evolution <swift-evolution@swift.org> wrote:

l8r
Sean

On Mar 9, 2016, at 1:12 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 9, 2016, at 12:10 PM, Charles Kissinger <crk@akkyra.com> wrote:

On Mar 8, 2016, at 1:52 PM, Austin Zheng <austinzheng@gmail.com> wrote:

'Fixity' already has a non-technical meaning ("the state of being unchanged and permanent"), and an unrelated technical one (a synonym for associativity; search "assocativity fixity operator" for examples). If we're using it in this different way, I respectfully submit that we should reconsider.

You are correct, of course, but a subset of computer scientists have been abusing the term in this way for at least a couple of decades. Their novel usage of “fixity” now has a degree of fixity, so it may be too late to fix "fixity".

It's become a termity of art.

-- E

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

TLDR: Previous draft did not carry the idea well, I will rewrite it.

In my original post, I didn't intend to make an accent on syntax. I mainly
tried to rework how operator precedence works.

Consider following example.
Module A defines operator |> that acts on Stream, is left-associative and
has precedence rules X.
Module B defines operator |> that acts on Serializable, is
right-associative and has precedence rules Y.

A and B don't know anything about each other.
Without the proposal, definitions of |> would be in conflict.
With the proposal, there would be no conflict for |>. They would
define different operators with different precedence rules and
associativity.

In expression a + b + c, first and second + would have different precedence
and associativity, depending on #operator directives, types of a,b,c and
available perator functions.

Now I think that probably, having conflicts in operator definitions is
better than to have complex compiler rules for parsing expressions as
simple as a + b + c.

- Anton

···

четверг, 10 марта 2016 г. пользователь Chris Lattner написал:

> On Mar 9, 2016, at 11:15 AM, Sean Heber via swift-evolution < > swift-evolution@swift.org <javascript:;>> wrote:
>
> Isn’t this essentially describing it’s expression-ness? Why not just use
“expression” like:
>
> expression: infix
> expression: postfix
> expression: prefix

Are any of these proposals *better* than “infix operator + {“ ?

I’m not claiming that the body of the operator declaration is great, but
one nice thing about it is that the required terms are part of the decl
modifier, the optional gunk is in the body, and it reads well.

-Chris

>
> l8r
> Sean
>
>
>> On Mar 9, 2016, at 1:12 PM, Erica Sadun via swift-evolution < > swift-evolution@swift.org <javascript:;>> wrote:
>>
>>
>>> On Mar 9, 2016, at 12:10 PM, Charles Kissinger <crk@akkyra.com > <javascript:;>> wrote:
>>>
>>>
>>>> On Mar 8, 2016, at 1:52 PM, Austin Zheng <austinzheng@gmail.com > <javascript:;>> wrote:
>>>>
>>>> 'Fixity' already has a non-technical meaning ("the state of being
unchanged and permanent"), and an unrelated technical one (a synonym for
associativity; search "assocativity fixity operator" for examples). If
we're using it in this different way, I respectfully submit that we should
reconsider.
>>>
>>> You are correct, of course, but a subset of computer scientists have
been abusing the term in this way for at least a couple of decades. Their
novel usage of “fixity” now has a degree of fixity, so it may be too late
to fix "fixity".
>>
>> It's become a termity of art.
>>
>> -- E
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <javascript:;>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org <javascript:;>
> https://lists.swift.org/mailman/listinfo/swift-evolution