[swift-evolution] [Draft] Resolving operator precedence conflicts
Charles Kissinger
crk at akkyra.com
Wed Mar 9 13:07:06 CST 2016
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 at 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 at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
More information about the swift-evolution
mailing list