Fixity Declarations

Given a function f, the standard syntax for applying f to an argument v is f(v); for two arguments v1 and v2, the syntax is f(v1, v2). However, it is allowed in ATS to use infix notation for a binary function application, and prefix/postifix notation for a unary function application.

Each identifier in ATS can be assigned one of the following fixities: prefix, infix and postfix. The fixity declarations for many commonly used identifiers can be found in prelude/fixity.ats. Often, the name operator is used to refer to an identifier that is assigned a fixity. For instance, the following syntax declares that + and - are infix operators of a precedence value equal to 50:

infixl 50 + -

After this declaration, we can write an expression like 1 + 2 - 3, which is parsed into -(+(1, 2), 3) in terms of the standard syntax for function application.

The keyword infixl indicates that the declared infix operators are left-associative. For right-associative and non-associative infix operators, please use the keywords infixr and infix, respectively. If the precedence value is omitted in a fixity declaration, it is assumed to be equal to 0.

We can also use the following syntax to declare that iadd, fadd, padd and uadd are left-associative infix operators with a precedence value equal to that of the operator +:

infixl (+) iadd fadd padd uadd

This is useful as it is difficult in practice to remember the precedence values of (a large collection of) declared operators. Sometimes, we may need to specify that the precedence value of one operator in relation to that of another one. For instance, the following syntax declares that opr2 is a left-associative infix operator and its precedence value is that of opr1 plus 10:

infixl (opr1 + 10) opr2

If the plus sign (+) is changed to the minus sign (-), then the precedence value of opr2 is that of opr1 minus 10.

We can also turn an identifier opr into a non-associative infix operator (of precedence value 0) by putting the backslash symbol (\) in front of it. For instance, the expression exp1 \opr exp2 stands for opr (exp1, exp2), where exp1 and exp2 refer to some expressions, either static or dynamic. The syntax for declaring (unary) prefix and postfix operators are similar. For instance, the following syntax declares that ~ and ? are prefix and postfix operators of precedence values 61 and 69, respectively:

prefix 61 ~
postfix 69 ?

As an example, a postfix operator is involved in the following 3-line program:

postfix (imul + 10) !!
extern fun !! (x: int): int
implement !! (x) = if x >= 2 then x * (x - 2)!! else 1

For a given occurrence of an operator, we can deprive it of its assigned fixity status by simply putting the keyword op in front of it. For instance 1 + 2 - 3 can be writen as op- (op+ (1, 2), 3). It is also possible to (permanently) deprive an operator of its assigned fixity status. For instance, the following syntax does so to the operators iadd, fadd, padd and uadd:

nonfix iadd fadd padd uadd

Lastly, please note that each fixity declaration is only effective within its own legal scope.