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 + 7etc. 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
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.125The 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.125Another 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
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.
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 / 5is equivalent to
(3 / 4) / 5which 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 +++ dwould 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 +++ dwould 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.
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