First of all, I suggest that we remove `assignment` from Swift 2.2 in any case. It has been deprecated for long enough.
Operator declarations are always global.
Operator declarations of the same operator are always in conflict, even if in different modules.
Therefore, I believe, operators would be best defined using directive syntax:
#operator(<>, fixity: infix, associativity: left, precedence: 100)
#operator(!, fixity: postfix)
It's obvious from this declaration that it must be global and must not be duplicated even in different modules (remember C macros?).
It would allow us to remove operator declaration grammar entirely, add a directive instead. Simplification of grammar and consistency is one of directions for Swift 2.2 and Swift 3.0.
Why not curly braces? Curly braces in Swift declarations are used to declare multiple "child" entities. On the other hand, attributes and directives are used with *preudo-arguments*.
I also want to remind the main difference between attributes and directives in Swift. @-attributes always stand before something and modify it. #-directives are stand-alone things on themselves.
Treating it as a compiler directive is an interesting idea. It certainly doesn't work anything like other declarations in Swift; a compiler directive might drive that point home.
I don't really like this specific design, though—it doesn't really match the look and feel of existing directives. Looking through the Swift book, I believe the only compiler directive that actually *changes* anything is `#setline` (The Directive Formerly Known As `#line`). Its parameters consist of an unmarked list of values with no separator or labeling. Trying to duplicate that style would give us something like this:
#operator <> infix left 100
That's, um, pretty bad. There *is* precedent for function-like constructs, though, so perhaps we could do this:
#operator <> infix(associativity: left, precedence: 100)
#operator ! prefix
That's actually not too bad—it connects the attributes very strongly to the `infix` keyword while still putting those details at the end of the statement so they don't obscure the more important bits.
One other issue is that the compiler directives which are permitted in statement position (rather than expressions like `#line` or `#available(...)`) are "verb-y"—they read as commands, not nouns. It would probably be more consistent to use a verb of some kind:
#addoperator <> infix(associativity: left, precedence: 100)
#defoperator <> infix(associativity: left, precedence: 100)
A space would make that more readable (even if it would break consistency with `#setline`:
#add operator <> infix(associativity: left, precedence: 100)
#def operator <> infix(associativity: left, precedence: 100)
Or, more fancifully:
#invent operator <> infix(associativity: left, precedence: 100)
#adopt operator <> infix(associativity: left, precedence: 100)
In theory, this could become a mechanism to extend the grammar in other ways, like:
// add `foo?.bar()` to grammar
#invent dispatcher ?. infix
// add `if cond { statements } else { statements }` to grammar
#invent statement if controlflow(_: expression, _: block, else: block)
But that's a whole different kind of fanciful.
···
--
Brent Royal-Gordon
Architechies