next up previous contents
Next: Defining new infix Up: CHAPTER.4: PROCEDURES IN Previous: Output locals and

Precedence and parentheses

There is a syntactic complication in Pop-11, like most programming languages, which we have so far illustrated without commenting on. Some procedures are run by writing their names before the parentheses, with inputs between parentheses as in the imperative `member(x, list)'.

By contrast some procedures, such as the arithmetic procedures `+', `*', `-', are invoked by writing the name between the inputs, as in

    3 * 5, 77 + 7
etc. These are known as `infix' operators. They are names of ordinary procedures, but have special syntactic properties to simplify their use. If the same expression contains two such infix operators there may be an ambiguity. For instance: how is 3 + 4 * 5 to be understood? One way is to use parentheses to indicate whether the addition or the multiplication is to be done first:

    (3 + 4) * 5 =>
    ** 35

    3 + (4 * 5) =>
    ** 23
Parentheses are also the principal way that we get round Pop-11's requirement that everything be written `linearly'. So the `ordinary' way of writing a division

        7.50 + 19.43
        ____________
            27
becomes

        (7.50 + 19.43)/27 =>
        **  0.99740741
Each of the infix operations of Pop-11 has a `precedence' associated with it. A precedence is a number which determines the order in which the operations are applied. Both `+' and `-' have a precedence of 5. `*', `/', and `//' however have a precedence of 4, indicating that these operations are applied before addition and subtraction where brackets are not used to remove any ambiguity. The concatenator operator `<>' has a precedence of 5.

Because of the precedence rules, in this example:

    3 + 4 * 5 =>
    ** 23
the multiplication is done first because its precedence is lower than that of `+'.

Generally, infix procedures with the LOWEST numerical precedence are evaluated first. The precedence of `*' is 4 and that of `+' is 5 so the above expression is equivalent to `3 + (4 * 5)'.

Note, unlike many other programming languages Pop-11 uses larger precedence to represent larger scope. I.e operators with smallest precedence bind their arguments "most tightly" to themselves. In many other languages the reverse convention is used.

In the case of operators of equal precedence they are applied from left to right, thus, since "*" and "/" have equal precedence:

    6 / 2 * 5 =>
    ** 15
not:

    6 / (2 * 5) =>
    ** 0.6

Precedences of arithmetical operations

The precedence table for arithmetic operations is as shown below.

        Operation       Precedence
        div                2
        rem                2
        mod                2
        **                 3
        * / //             4
        + -                5
        > < >= <=          6
        =                  7
Using this table it can be seen that the result of typing the statement

    3 - 2.5  ** 2 * 1.5 / 3 =>
will be

    ** -0.125
The order of evaluation is as follows:

Original expression                     3 - 2.5 ** 2 * 1.5 / 3
Apply operations of precedence  3       3 - 6.25 * 1.5  /3
Apply operations of precedence  4       3 - 3.125
Apply operations of precedence  5       -0.125
Another way of looking at this is to see that the original expression is transformed into a collection of instructions to Pop-11 that use the stack. I.e.

    3 - 2.5 ** 2 * 1.5 / 3 =>
translates to:

    3, 2.5, 2, **, 1.5, *, 3, /, - =>
Notice how the left right order of operators here corresponds to their numerical precedence.

Pop-11 can be thought of as obeying the above instruction through the following sequence of transformations:

    3, 2.5, 2, **, 1.5, *, 3, /, - =>
    Procedure ** runs, taking two inputs and producing one result
    3, 6.25, 1.5, *, 3, /, - =>
    Procedure * runs, taking two inputs and producing one result
    3, 9.375, 3, /, - =>
    Procedure / runs, taking two inputs and producing one result
    3, 3.125 - =>
    Procedure - runs, taking two inputs and producing one result
    ** -0.125

Parentheses can override operator precedence

The precedence associated with each operation defines an order of evaluation of an expression. If another order is required, parentheses can be used in the conventional way. For example:

    (3 - 2.5) ** 2 * 1.5 / 3 =>
    ** 0.125
The rules of precedence apply to each expression within a pair of parentheses.

Parentheses may be nested to any depth, the expressions within inner parentheses being evaluated first.

Operators associate to left, unless precedence is negative

Where parentheses are not present, and the precedences do not uniquely define an order of evaluation, then evaluation proceeds from left to right. I.e. operations associate to the left. So

    3 / 4 / 5
is equivalent to

    (3 / 4) / 5
which denotes 0.15, unlike

    3 / (4 / 5)
which denotes 3.75.

Otherwise infix procedures with a positive precedence are evaluated left to right.

Thus if +++ were defined as an infix procedure of precedence 3, then

    a +++ b +++ c +++ d
would be equivalent to

    (((a +++ b) +++ c) +++ d)
However, if the precedence is negative, the operation will associate to the right. So if +++ had precedence -3, then

    a +++ b +++ c +++ d
would be equivalent to:

    (a +++ (b +++ (c +++ d)))
For more on precedence see HELP DEFINE

The HELP PRECEDENCE file gives more information on precedences in Pop-11. Precedences in Pop-11 may be positive or negative numbers in the range -12.7 to +12.7.

Using identprops to discover precedence

The procedure called `identprops' can be used to find out the precedence of an operator. For an ordinary variable the precedence is 0. For example:

    vars xx, list3;
    identprops("xx") =>
    ** 0
    identprops("list3") =>
    ** 0
For an infix operator it will be some other number. For a syntax word or macro (see later) identprops produces the word "syntax" or "macro". If applied to something which has not been declared by the user or the system, it produces the result undef. Thus:

    identprops("+") =>
    ** 5

    identprops(">") =>
    ** 6

    identprops("if") =>
    ** syntax

    identprops("help") =>
    ** macro

    vars x;
    identprops("x") =>
    ** 0

    identprops("xxxxx") =>
    ** undef


next up previous contents
Next: Defining new infix Up: CHAPTER.4: PROCEDURES IN Previous: Output locals and



Aaron Sloman
Fri Jan 2 03:17:44 GMT 1998