.\" Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. .St 6 "EXPRESSIONS, TARGETS AND TESTS" .Se 3 6.1 EXPRESSIONS .Xx scratch-pad copy .Xx compound .Tx In \*B, the evaluation of an expression cannot alter the values of targets that currently exist, nor can it create new targets that survive the expression. If an expression appears to alter a target, it effectively modifies a local ``scratch-pad'' \fIcopy\fP of that target, and the change is invisible outside the expression. .Sy 3 .Pr expression 4 .Al single-expression .Al multiple-expression .Pr single-expression 3 .Al basic-expression .Al \*(<:(\*(:> expression \*(<:)\*(:> .Pr basic-expression 3 .Al simple-expression .Al formula .Pr simple-expression 7 .Al constant .Al target-content .Al trimmed-text .Al table-selection .Al display .Al refined-expression .Pr tight-expression 3 .Al simple-expression .Al zeroadic-formula .Al \*(<:(\*(:> expression \*(<:)\*(:> .Pr right-expression 3 .Al tight-expression .Al monadic-formula .Eo 6 basic-:\0\0\k2simple-:\0\k3tight-:\0\0\0\0\k4right-expressions: \h'|\n1u'\*(<:a\*(:> \h'|\n2u'\*(<:a\*(:> \h'|\n3u'\*(<:a\*(:> \h'|\n4u'\*(<:a\*(:> \h'|\n1u'\*(<:-a\*(:> \h'|\n4u'\*(<:-a\*(:> \h'|\n1u'\*(<:a+b\*(:> \h'|\n3u'\*(<:(a+b)\*(:> \h'|\n4u'\*(<:(a+b)\*(:> .Xe .Tx The various kinds of expressions that are distinguished here serve to define the syntax in such a way that no parentheses are needed where the meaning is sufficiently clear. .Pr multiple-expression 1 .Al single-expression\*(<:,\*(:> single-expression .Al single-expression\*(<:,\*(:> multiple-expression .Ex 3 \k1multiple-expressions: \h'|\n1u'\*(<:1, 'abc'\*(:> \h'|\n1u'\*(<:(1, 0), (0, 1), (-1, 0), (0, -1)\*(:> .Xe .Tx The value of a multiple-expression composed of single-expressions separated by commas is the compound whose fields are the values of the successive single-expressions. .Se 3 6.1.1 NUMERIC-CONSTANTS .Sy 3 .Pr numeric-constant 3 .Al exact-constant .Al approximate-constant .Pr exact-constant 3 .Al integral-part\0optional-fractional-part .Al integral-part \*(<:.\*(:> .Al fractional-part .Pr integral-part 3 .Al digit .Al integral-part\0digit .Pr digit 2 .Al \*(<:0\*(:> .Al \*(<:1\*(:> .Al \*(<:2\*(:> .Al \*(<:3\*(:> .Al \*(<:4\*(:> .Al \*(<:5\*(:> .Al \*(<:6\*(:> .Al \*(<:7\*(:> .Al \*(<:8\*(:> .Al \*(<:9\*(:> .Pr fractional-part 3 .Al \&\*(<:.\*(:> digit .Al fractional-part\0digit .Pr approximate-constant 2 .Sl exact-constant\0exponent-part .Pr exponent-part 2 .Sl \*(<:E\*(:> optional-plusminus\0integral-part .Pr plusminus 2 .Al \*(<:+\*(:> .Al \*(<:-\*(:> .Eo 5 exact-constants:\0\0\0\0\0\0\k2approximate-constants: \h'|\n1u'\*(<:666\*(:> \h'|\n2u'\*(<:2.99793E8\*(:> \h'|\n1u'\*(<:666.\*(:> \h'|\n2u'\*(<:2.99793E+8\*(:> \h'|\n1u'\*(<:3.14\*(:> \h'|\n2u'\*(<:1E-9\*(:> .Xe .Tx The value of an exact-constant is an exact number. For example, \*(<:1.25\*(:> stands for the exact number \*(<:5/4\*(:>. The value of an approximate-constant is an approximate number. The exponent-part gives the power of ten in floating-point notation. For example, \*(<:1.2345E2\*(:> and \*(<:~123.45\*(:> are (approximately) the same, because \*(<:123.45 = 1.2345*10**2\*(:>. .Se 2 6.1.2 TARGET-CONTENTS .Sy 2 .Pr target-content 2 .Sl tag .Tx The value of a target-content is the value last put in the target whose name is the given tag. .Se 2 6.1.3 TRIMMED-TEXTS .Xx integer .Sy 2 .Pr trimmed-text 2 .Al tight-expression \*(<:@\*(:> right-expression .Al tight-expression \*(<:|\*(:> right-expression .Ps .Ex 6 \k1trimmed-texts: \h'|\n1u'\*(<:t@p\*(:> \h'|\n1u'\*(<:t|1\*(:> \h'|\n1u'\*(<:t|q@p\*(:> \h'|\n1u'\*(<:t@p|(q-p+1)\*(:> .Xe .Tx The value of the tight-expression must be a text T, and that of the right-expression must be an integer N. .br If the sign between the expressions is \*(<:@\*(:>, then the value of the trimmed-text is that of T after removing the first N\(mi1 characters. For example, \*(<:'lamplight'@4 = 'plight'\*(:>. N must be at least 1 and at most one more than the length of T. .br If the sign between the expressions is \*(<:|\*(:>, then the value of the trimmed-text is the text consisting of the first N characters of T. For example, \*(<:'scarface'|5 = 'scarf'\*(:>. N must be at least 0 and at most equal to the length of T. .br Note that the tight-expression itself may be a trimmed-text again. For example, \*(<:'department'|6@3 = 'depart'@3 = 'part'\*(:>. .Se 3 6.1.4 TABLE-SELECTIONS .Xx key .Xx associate .Xx table entry .Sy 3 .Pr table-selection 3 .Sl tight-expression \*(<:[\*(:> expression \*(<:]\*(:> .Sx 2 table-selection: \*(<:t[i, j]\*(:> .Xe .Tx The value of the tight-expression must be a table T, and the value of the expression between the square brackets must be a key K of T. The value of the table-selection is then the associate of the table entry in T whose key is K. .Se 3 6.1.5 DISPLAYS .Xx integer .Xx character .Xx quote .Xx convert to a text .Xx ambiguity .Xx empty list .Xx empty table .Xx key .Xx associate .Sy 3 .Pr display 4 .Al text-display .Al list-display .Al table-display .Pr text-display 3 .Al \&\*(<:'\*(:> optional-text-body \*(<:'\*(:> .Al \*(<:"\*(:> optional-text-body \*(<:"\*(:> .Ps The text-displays \*(<:''\*(:> and \*(<:""\*(:> stand for the empty text. A text-body may be any sequence of printable characters (see section 1 under `Texts') and conversions (see below). However, in a text-display in the \*(<:'\*(:>\^...\^\*(<:'\*(:> style, any single quote \*(<:'\*(:> in the text must be written twice to give \*(<:''\*(:>. Otherwise, it will signal the end of the text-display. Similarly, in a text-display in the \*(<:"\*(:>\^...\^\*(<:"\*(:> style, any double quote \*(<:"\*(:> in the text must be written twice to give \*(<:""\*(:>. Finally, the back-quote \*(<:`\*(:> must be written twice too, giving \*(<:``\*(:>. Otherwise, it signals a conversion. .Pr conversion 2 .Sl \*(<:`\*(:> expression \*(<:`\*(:> .Ps The requirement that some signs be written twice does not hold \fIinside\fP a conversion. For example, \*(<:'`t['a']`'\*(:> is proper, whereas \*(<:'`t[''a'']`'\*(:> is not. .Eo 6 text-displays: \h'|\n1u'\*(<:''\*(:> \h'|\n1u'\*(<:'He said: "Don''t!"'\*(:> \h'|\n1u'\*(<:"He said: ""Don't!"""\*(:> \h'|\n1u'\*(<:'altitude is `a/1E3` km'\*(:> .Xe .Tx The value of a text-display is the text composed of the characters given between the enclosing text quotes. If the text-display contains conversions, the expressions of these conversions are evaluated first and converted to a text in the same way as for a write-command. For example, since .Di 1 \*(<:WRITE 239*4649\*(:> .Ed causes the text \*(<:1111111\*(:> to be written, the text-display .Di 1 \&\*(<:'239 times 4649 gives `239*4649`'\*(:> .Ed is equivalent to .Di 1 \&\*(<:'239 times 4649 gives 1111111'\*(:>. .Ed The quotes and conversion-signs that had to be written twice according to the above rules correspond to one character of the resulting text. For example, the number of characters in \*(<:'x''y""z'\*(:> is 6, because it consists of one \*(<:x\*(:>, \fIone\fP \*(<:'\*(:> character, one \*(<:y\*(:>, \fItwo\fP \*(<:"\*(:> characters, and finally one \*(<:z\*(:>. Another way to specify the same text is \*(<:"x'y""""z"\*(:>. .Pr list-display 2 .Sl \*(<:{\*(:> optional-list-body \*(<:}\*(:> .Pr list-body 5 .Al list-filler-series .Al single-expression \*(<:..\*(:> single-expression .Ps The ambiguity in, e.g., \*(<:{1...9}\*(:>, is resolved by parsing it as \*(<:{1. .. 9}\*(:>. .Pr list-filler-series 2 .Al list-filler .Al list-filler\*(<:;\*(:> list-filler-series .Pr list-filler 2 .Sl single-expression .Eo 6 list-displays: \h'|\n1u'\*(<:{}\*(:> \h'|\n1u'\*(<:{x1; x2; x3}\*(:> \h'|\n1u'\*(<:{1..n-1}\*(:> \h'|\n1u'\*(<:{'a'..'z'}\*(:> .Xe .Tx The value of \*(<:{}\*(:> is an empty list. (It may also be an empty table; see below.) .br The value of a list-display containing list-fillers is the list whose entries are the values of those list-fillers. If values occur multiply, they give rise to multiple entries in the list. .br For a list-display of the form \*(<:{\*(:>p\*(<:..\*(:>q\*(<:}\*(:>, p and q must both be integers, or both be characters (texts of length one). The resulting value is then the list of all integers or characters x such that p\ \(<= x\ \(<=\ q. For example, \*(<:{1..4} = {1; 2; 3; 4}\*(:> and \*(<:{'a'..'c'} = {'a'; 'b'; 'c'}\*(:>. .br If p\ >\ q, the list is empty, but this is only allowed if p and q are adjacent. If there is an intervening integer or character x (such that p\ >\ x\ >\ q), an error is reported. .Pr table-display 2 .Sl \*(<:{\*(:> optional-table-filler-series \*(<:}\*(:> .Pr table-filler-series 2 .Al table-filler .Al table-filler\*(<:;\*(:> table-filler-series .Pr table-filler 2 .Sl \*(<:[\*(:> expression \*(<:] :\*(:> single-expression .Eo 6 table-displays: \h'|\n1u'\*(<:{}\*(:> \h'|\n1u'\*(<:{[i, j]: 0}\*(:> \h'|\n1u'\*(<:{[0]: {}; [1]: {0}}\*(:> \h'|\n1u'\*(<:{[name]: (month, day, year)}\*(:> .Xe .Tx The table-display \*(<:{}\*(:> stands for an empty table. Otherwise, each table-filler gives a table entry with key K and associate A, where K is the value of the expression between square brackets, and A is the value of the single-expression following the colon. The result is then the table containing these table entries. .br If there are \fIdifferent\fP table entries with the same key, an error is reported. Multiple occurrences of the \fIsame\fP table entry, however, are allowed. The extra occurrences are then simply discarded. .Se 2 6.1.6 FORMULAS .Xx formula .Xx function .Xx ambiguity .Xx parentheses .Xx brackets .Xx priority .Xx user-defined-function .Xx yield-unit .Xx target .Xx scratch-pad copy .Xx local .Xx return-command .Xx predefined functions .Xx number .Xx denominator .Xx numerator .Xx text .Xx convert to a text .Xx text, list and table .Xx key .Xx character .Xx associate .Xx list entry .Xx integer .Sy 2 .Pr zeroadic-formula 2 .Sl zeroadic-function .Pr monadic-formula 2 .Sl monadic-function\0actual-operand .Pr dyadic-formula 2 .Al actual-operand\0dyadic-function\0actual-operand .Ps The parsing ambiguities introduced by these rules are resolved by priority rules, as follows: .in +\w'2.\ 'u .ti -\w'2.\ 'u 1.\ If there is no parsing ambiguity (as in \*(<:1 + sin x\*(:>), no parentheses are needed. .ti -\w'2.\ 'u 2.\ If the order makes no difference (as in \*(<:a*b*c\*(:>, \*(<:a*b/c\*(:> or \*(<:a^b^c\*(:>), no parentheses are needed. .ti -\w'2.\ 'u 3.\ The five arithmetic functions \*(<:**\*(:>, \*(<:*\*(:>, \*(<:/\*(:>, \*(<:+\*(:> and \*(<:-\*(:> have their traditional priority rules: .in +4 \*(<:**\*(:> comes before \*(<:*\*(:>, \*(<:/\*(:>, \*(<:+\*(:> and \*(<:-\*(:>; .br \*(<:*\*(:> and \*(<:/\*(:> come before \*(<:+\*(:> and \*(<:-\*(:>; .br combinations of \*(<:+\*(:> and \*(<:-\*(:> are computed from left to right. .in -4 Note, however, that \*(<:a**b**c\*(:>, \*(<:a/b*c\*(:> and \*(<:a/b/c\*(:> are wrong. .ti -\w'2.\ 'u 4.\ The function \*(<:#\*(:> has a high priority, higher than the five arithmetic functions, and the function \*(<:~\*(:> has a higher priority than all other functions. .ti -\w'2.\ 'u 5.\ All other functions, in particular \*(<:^\*(:>, \*(<:^^\*(:>, \*(<:<<\*(:>, \*(<:><\*(:>, \*(<:>>\*(:> and all tags (like \*(<:sin\*(:> or \*(<:floor\*(:>) have no established priority and may be used .in +4 .ti -\w'\(em\ 'u \(em\ having formulas as operands only if these operands are parenthesized (except as in, e.g., \*(<:exp -x\*(:>, because of point 1 above, or as in \*(<:~1>>20\*(:> because of point 4); .ti -\w'\(em\ 'u \(em\ in operands of other formulas only if these operands are parenthesized (except as above). .in -4 .in -\w'2.\ 'u .Bl 3 None of \*(<:a/b/c\*(:>, \*(<:a/b*c\*(:> and \*(<:sin x+y\*(:> is a correct formula. Each of these can be made correct by inserting parentheses, depending on the intention: either \*(<:(a/b)/c\*(:> or \*(<:a/(b/c)\*(:>, either \*(<:(a/b)*c\*(:> or \*(<:a/(b*c)\*(:>, and either \*(<:(sin x) + y\*(:> or \*(<:sin(x+y)\*(:>. Note that because of point 5 above \*(<:sin(x)+1\*(:> is just as wrong as \*(<:sin x + 1\*(:>, in spite of what other programming languages might lead you to expect. .br The function \*(<:#\*(:> has been given a high priority since expressions like \*(<:#t+1\*(:> are so common, that it would be a nuisance to have to parenthesize these, and more so since \*(<:#(t+1)\*(:> is meaningless anyway. The reason for the high priority of the function \*(<:~\*(:> is to make \*(<:~0\*(:>, for example, for all practical purposes behave as a constant. .Pr zeroadic-function 2 .Sl tag .Pr monadic-function 6 .Al \*(<:~\*(:> .Al \*(<:+\*(:> .Al \*(<:-\*(:> .Al \*(<:*/\*(:> .Al \*(<:/*\*(:> .Al \*(<:#\*(:> .Al tag .Pr dyadic-function 3 .Al \*(<:+\*(:> .Al \*(<:-\*(:> .Al \*(<:*\*(:> .Al \*(<:/\*(:> .Al \*(<:**\*(:> .Al \*(<:^\*(:> .Al \*(<:^^\*(:> .Al \*(<:<<\*(:> .Al \*(<:><\*(:> .Al \*(<:>>\*(:> .Al \*(<:#\*(:> .Al tag .Pr actual-operand 3 .Sl single-expression .Eo 3 zeroadic-formula:\0\0\0\k2monadic-formula:\0\0\0\k3dyadic-formula: \h'|\n1u'\*(<:pi\*(:> \h'|\n2u'\*(<:atan(y/x)\*(:> \h'|\n3u'\*(<:x atan y\*(:> .Xe .Us 7 Formulas with user-defined functions A formula whose function is defined by a yield-unit, is evaluated in the following steps: .in \w'2.\ 'u .ti 0 1.\ A copy is made of the current environment (the value of all targets), and all computations during the evaluation of the formula will take place in this ``scratch-pad copy''. .ti 0 2.\ Any local tags in the yield-unit that might clash with tags currently in use are systematically replaced by other tags that do not cause conflict. .ti 0 3.\ Each actual-operand is evaluated and put in the corresponding formal-operand, used as a (new) target. .ti 0 4.\ The command-suite of the unit, thus modified, is executed. .in 0 The evaluation of the formula is complete when the execution of this command-suite terminates because of the execution of a return-command; the value of the formula is the value returned. .Us 7 Formulas with predefined functions .de Qr .sp 1 .in 0 .ne 3 .. .de Qe .br .sp -1 .in 7m .. .Us 0 A. Functions on numbers .Qr \*(<:~x\*(:> .Qe returns an approximate number, as close as possible in arithmetic magnitude to \*(<:x\*(:>. .Qr \*(<:x+y\*(:> .Qe returns the sum of \*(<:x\*(:> and \*(<:y\*(:>. The result is exact if both operands are exact. .Qr \*(<:+x\*(:> .Qe returns the value of \*(<:x\*(:>. .Qr \*(<:x-y\*(:> .Qe returns the difference of \*(<:x\*(:> and \*(<:y\*(:>. The result is exact if both operands are exact. .Qr \*(<:-x\*(:> .Qe returns minus the value of \*(<:x\*(:>. The result is exact if the operand is exact. .Qr \*(<:x*y\*(:> .Qe returns the product of \*(<:x\*(:> and \*(<:y\*(:>. The result is exact if both operands are exact. .Qr \*(<:x/y\*(:> .Qe returns the quotient of \*(<:x\*(:> and \*(<:y\*(:>. The value of \*(<:y\*(:> must not be zero. The result is exact if both operands are exact. .Qr \*(<:x**y\*(:> .Qe returns \*(<:x\*(:> to the power \*(<:y\*(:>. The result is exact if \*(<:x\*(:> is exact and \*(<:y\*(:> is an integer. If \*(<:x\*(:> is negative, \*(<:y\*(:> must be an integer or an exact number with an odd denominator. If \*(<:x\*(:> is zero, \*(<:y\*(:> must not be negative. If \*(<:y\*(:> is zero, the result is one (exact or approximate). .Qr \*(<:n root x\*(:> .Qe returns the same as \*(<:x**(1/n)\*(:>. .Qr \*(<:root x\*(:> .Qe returns the same as \*(<:2 root x\*(:>, the square root of \*(<:x\*(:>. .Qr \*(<:abs x\*(:> .Qe returns the absolute value of \*(<:x\*(:>. The result is exact if the operand is exact. .Qr \*(<:sign x\*(:> .Qe returns \(mi1 if \*(<:x\*(:> is negative, 0 if \*(<:x\*(:> is zero, and 1 otherwise. .Qr \*(<:floor x\*(:> .Qe returns the largest integer not exceeding \*(<:x\*(:> in arithmetic magnitude. .Qr \*(<:ceiling x\*(:> .Qe returns the same as \*(<:- floor -x\*(:>. .Qr \*(<:n round x\*(:> .Qe returns the same as \*(<:(10**-n)*floor(x*10**n+.5)\*(:>. For example, \*(<:4 round pi = 3.1416\*(:>. The value of \*(<:n\*(:> must be an integer. It may be negative: \*(<:(-2) round 666 = 700\*(:>. .Qr \*(<:round x\*(:> .Qe returns the same as \*(<:0 round x\*(:>. .Qr \*(<:a mod n\*(:> .Qe returns the same as \*(<:a-n*floor(a/n)\*(:>, that is, the remainder after dividing \*(<:a\*(:> by \*(<:n\*(:>. (Both operands may be approximate, and \*(<:n\*(:> may be negative, but not zero.) .Qr \*(<:/*x\*(:> .Qe returns the ``denominator'' of \*(<:x\*(:>, that is, regarding \*(<:x\*(:> as the fraction \*(<:p/q\*(:>, the smallest positive integer \*(<:q\*(:> such that \*(<:q*x\*(:> is an integer. The value of \*(<:x\*(:> must be an exact number. .Qr \*(<:*/x\*(:> .Qe returns the corresponding ``numerator'' with the same sign as \*(<:x\*(:>, the same integer as \*(<:(/*x)*x\*(:>. So, if \*(<:x\*(:> is exact, \*(<:x = (*/x)/(/*x)\*(:>. .Qr \*(<:pi\*(:> .Qe returns approximately \*(<:3.1415926535\*(:>... .Qr \*(<:sin x\*(:> .Qe returns an approximate number by applying the sine function to \*(<:x\*(:>, with \*(<:x\*(:> in radians. .Qr \*(<:cos x\*(:> .Qe returns an approximate number by applying the cosine function to \*(<:x\*(:>, with \*(<:x\*(:> in radians. .Qr \*(<:tan x\*(:> .Qe returns the same as \*(<:(sin x) / (cos x)\*(:>. .Qr \*(<:x atan y\*(:> .Qe returns an approximate number \*(<:phi\*(:>, in the range from (about) \*(<:-pi\*(:> to \*(<:+pi\*(:>, such that \*(<:x\*(:> is approximated by \*(<:r * cos phi\*(:> and \*(<:y\*(:> by \*(<:r * sin phi\*(:>, where \*(<:r = root(x*x+y*y)\*(:>. The operands must not both be zero. .Qr \*(<:atan x\*(:> .Qe returns the same as \*(<:1 atan x\*(:>. .Qr \*(<:e\*(:> .Qe returns approximately \*(<:2.7182818284\*(:>... .Qr \*(<:exp x\*(:> .Qe returns approximately the same as \*(<:e**x\*(:>. .Qr \*(<:log x\*(:> .Qe returns an approximate number by applying the natural logarithm function (with base \*(<:e\*(:>) to \*(<:x\*(:>. The value of \*(<:x\*(:> must be positive. .Qr \*(<:b log x\*(:> .Qe returns the same as \*(<:(log x) / (log b)\*(:>, that is, the logarithm with base \*(<:b\*(:> of \*(<:x\*(:>. .Us 7 B. Functions on texts .Qr \*(<:t^u\*(:> .Qe returns the text consisting of \*(<:t\*(:> and \*(<:u\*(:> joined. For example, \*(<:'now'^'here' = 'nowhere'\*(:>. .Qr \*(<:t^^n\*(:> .Qe returns the text consisting of \*(<:n\*(:> copies of \*(<:t\*(:> joined together. For \pexample, \*(<:'Fi! '^^3 = 'Fi! Fi! Fi! '\*(:>. The value of \*(<:n\*(:> must be an integer and not negative. .Qr \*(<:x< .Qe converts \*(<:x\*(:> to a text and adds space characters to the right until the length is \*(<:n\*(:>. For example, \*(<:123<<6 = '123 '\*(:>. In no case is the text truncated; if \*(<:n\*(:> is too small, the resulting text is as long as necessary. The value of \*(<:n\*(:> must be an integer, but \*(<:x\*(:> may be of any type. See write-commands, section 5.1.2, for details about converting values to texts. .Qr \*(<:x> .Qe converts \*(<:x\*(:> to a text and adds space characters to the right and to the left, in turn, until the length is \*(<:n\*(:>. For example, \*(<:123><6 = ' 123 '\*(:>. In no case is the text truncated. The value of \*(<:n\*(:> must be an integer, but \*(<:x\*(:> may be of any type. .Qr \*(<:x>>n\*(:> .Qe converts \*(<:x\*(:> to a text and adds space characters to the left until the length is \*(<:n\*(:>. For example, \*(<:123>>6 = ' 123'\*(:>. In no case is the text truncated. The value of \*(<:n\*(:> must be an integer, but \*(<:x\*(:> may be of any type. .Bl 7 .Us 7 C. Functions on texts, lists and tables .Qr \*(<:keys t\*(:> .Qe requires a table as operand, and returns a list of all keys in the table. For example, \*(<:keys {[1]: 1; [4]: 2; [9]: 3} = {1; 4; 9}\*(:>. .Qr \*(<:#t\*(:> .Qe accepts texts, lists and tables. For a text operand, its length is returned, and for a list or table operand, the number of entries is returned (where duplicates in lists are counted). .Qr \*(<:e#t\*(:> .Qe accepts texts, lists and tables for the right operand. .br For a text operand, the first operand must be a character, and the number of times the character occurs in the text is returned. For example, \*(<:'i'#'mississippi' = 4\*(:>. .br For a list operand, the number of entries is returned that are equal to the first operand (which must be of the same type as the list entries.) .br For example, \*(<:3#{1; 3; 3; 4} = 2\*(:>. .br .?? For a table operand, the number of \fIassociates\fP is returned that are equal to the first operand (which must be of the same type as the associates in the table.) For example, \*(<:3#{[1]: 3; [2]: 4; [3]: 3} = 2\*(:>. .Qr \*(<:min t\*(:> .Qe accepts texts, lists and tables. For a text operand, its smallest (in the ASCII order) character is returned, for a list operand, its smallest entry is returned, and for a table operand, its smallest \fIassociate\fP .?? is returned. For example, \*(<:min 'uscule' = 'c'\*(:>, \*(<:min{1; 3; 3; 4} = 1\*(:>, and \*(<:min{[1]: 3; [2]: 4; [3]: 3} = 3\*(:>. The text, list or table must not be empty. .br To get the smallest \fIkey\fP of a table \*(<:t\*(:>, use \*(<:min keys t\*(:>. .Qr \*(<:e min t\*(:> .Qe accepts texts, lists and tables for the right operand. .br For a text operand, the first operand must be a character, and the smallest character in the text \fIexceeding\fP that character is returned. For example, \*(<:'i' min 'mississippi' = 'm'\*(:>. .br For a list operand, the smallest entry is returned exceeding the first operand (which must be of the same type as the list entries.) For example, \*(<:3 min {1; 3; 3; 4} = 4\*(:>. .br For a table operand, the smallest associate is returned exceeding the first operand (which must be of the same type as the associates in the table.) For example, \*(<:3 min {[1]: 3; [2]: 4; [3]: 3} = 4\*(:>. .br There must be a character, list entry or table associate exceeding the first operand. .Qr \*(<:max t\*(:> and .br \*(<:e max t\*(:> .Qe .Qe are like \*(<:min\*(:>, except that they return the largest element, and in the dyadic case the largest element that is less than the first operand. For example, \*(<:'m' max 'mississippi' = 'i'\*(:>. .Qr \*(<:n th'of t\*(:> .Qe requires an integer in \*(<:{1..#t}\*(:> for the left operand, and accepts texts, lists and tables for the right operand. It returns the \*(<:n\*(:>'th character, list entry or associate. .br In fact, \*(<:n th'of t\*(:>, for a text \*(<:t\*(:>, is written as easily \*(<:t@n|1\*(:>. For a table, it is the same as \*(<:t[n th'of (keys t)]\*(:>, which is something different from \*(<:t[n]\*(:>, unless, of course, \*(<:keys t = {1..#t}\*(:>. For a list, \*(<:1 th'of t\*(:> is \*(<:min t\*(:>. .Se 2 6.1.7 REFINED-EXPRESSIONS .Xx expression-refinement .Xx scratch-pad copy .Xx return-command .Sy 2 .Pr refined-expression 2 .Sl tag .Ps The tag of a refined-expression must occur as the tag of one expression-refinement in the unit in which it occurs. .Sx 3 \k1refined-expression: \*(<:stack'pointer\*(:> .Xe .Tx A refined-expression is evaluated in the following steps: .in \w'2.\ 'u .ti 0 1.\ A copy is made of the current environment (the value of all targets), and all computations during the evaluation of the expression will take place in this ``scratch-pad copy''. .ti 0 2.\ The command-suite of the corresponding expression-refinement is executed. .in 0 The evaluation of the refined-expression is complete when the execution of this command-suite terminates because of the execution of a return-command; the value of the refined-expression is the value returned. .Sa expression-refinements (4.4). .Se 4 6.2 TARGETS .Xx compound .Sy 4 .Pr target 4 .Al single-target .Al multiple-target .Pr single-target 3 .Al basic-target .Al \*(<:(\*(:> target \*(<:)\*(:> .Pr basic-target 4 .Al tag .Al trimmed-text-target .Al table-selection-target .Tx For the use of a tag as target, see below under IDENTIFIERS. For other kinds of targets, see below under the appropriate heading. .Pr multiple-target 1 .Al single-target\*(<:,\*(:> single-target .Al single-target\*(<:,\*(:> multiple-target .Ex 3 \k1multiple-targets: \h'|\n1u'\*(<:nn, t2\*(:> \h'|\n1u'\*(<:(x0, y0), (x1, y1), (x2, y2), (x3, y3)\*(:> .Xe .Tx If a value is put in a multiple-target, the value must be a compound with as many fields as there are single-targets separated by commas in the multiple-target. The successive fields are then put in the successive single-targets. If it makes a difference in what order the fields are put in the single-targets (as in \*(<:PUT 1, 2 IN x, x\*(:> where the final value of \*(<:x\*(:> might be either \*(<:1\*(:> or \*(<:2\*(:>), an error is reported {{but this is currently not checked}}. .br Note that the meaning of \*(<:PUT a, b IN b, a\*(:> is well defined (provided that \*(<:a\*(:> and \*(<:b\*(:> are defined and have values of the same type): first the value of the expression \*(<:a, b\*(:> is determined, and that value is next put in \*(<:b, a\*(:>. Note also that the meaning of \*(<:PUT t[i], t[j] IN t[j], t[i]\*(:> is well defined, even if \*(<:i\*(:> and \*(<:j\*(:> have the same value. For although in this case a value is put twice in the same target, that value is the same each time, so the order does not matter. .Se 2 6.2.1 IDENTIFIERS .Xx tag .Xx target .Xx location .Xx local .Sy 2 .Pr identifier 4 .Al single-identifier .Al multiple-identifier .Pr single-identifier 3 .Al tag .Al \*(<:(\*(:> identifier \*(<:)\*(:> .Pr multiple-identifier 1 .Al single-identifier\*(<:,\*(:> single-identifier .Al single-identifier\*(<:,\*(:> multiple-identifier .Eo 6 identifiers:\0\0\0\0\0\0\0\0\0\0\0\k2single-identifiers: \h'|\n1u'\*(<:a\*(:>\h'|\n2u'\*(<:a\*(:> \h'|\n1u'\*(<:(a)\*(:>\h'|\n2u'\*(<:(a)\*(:> \h'|\n1u'\*(<:(a, b, (c, d))\*(:>\h'|\n2u'\*(<:(a, b, (c, d))\*(:> \h'|\n1u'\*(<:a, b, (c, d)\*(:> .Xe .Tx All identifiers can be used as targets, but the converse is not true. For example, .Di 1 \*(<:FOR a[1] IN {1..3}: WRITE a\*(:> .Ed is wrong, because \*(<:a[1]\*(:>, although a target, is not an identifier. If something is put in a target that is a tag, and no location for that tag exists already, it is created first. If the location is created locally (the tag did not occur in an immediate command and was not listed in a share-heading), the location will cease to exist when the current unit is exited. For putting in multiple-identifiers, see multiple-targets in section 6.2. .Se 2 6.2.2 TRIMMED-TEXT-TARGETS .Sy 2 .Pr trimmed-text-target 3 .Al target \*(<:@\*(:> right-expression .Al target \*(<:|\*(:> right-expression .Ps\"(The \*(<:|\*(:> in the last line is not the BNF choice indicator, but should be takenliterally.) .Ex 6 \k1trimmed-text-targets: \h'|\n1u'\*(<:t@p\*(:> \h'|\n1u'\*(<:t|1\*(:> \h'|\n1u'\*(<:t|q@p\*(:> \h'|\n1u'\*(<:t@p|(q-p+1)\*(:> .Xe .Tx The target must hold a text T, and the value of the right-expression must be an integer N. .br If the sign used is \*(<:@\*(:>, then the trimmed-text-target indicates a location consisting of the positions of T starting with the N'th position. N must be at least 1 and at most one more than the length of T. For example, after .Di 2 \*(<:PUT 'computer' IN tt PUT 'ass' IN tt@5\*(:> .Ed \*(<:tt\*(:> will contain the text \*(<:'compass'\*(:>. .br If the sign used is \*(<:|\*(:>, then the trimmed-text-target indicates a location consisting of the first N characters of T. N must be at least 0 and at most equal to the length of T. For example, after .Di 2 \*(<:PUT 'computer' IN tt PUT 'ne' IN tt|4\*(:> .Ed \*(<:tt\*(:> will contain the text \*(<:'neuter'\*(:>. .Bl 1 Note that the target itself may be a trimmed-text-target again. For example, after .Di 2 \*(<:PUT 'computer' IN tt PUT 'm' IN tt@4|1\*(:> .Ed \*(<:tt\*(:> will contain the text \*(<:'commuter'\*(:>. .br Some useful special cases: \*(<:PUT '' IN t|1\*(:> removes the first character of the text in \*(<:t\*(:>; .br \*(<:PUT '.' IN t@(#t+1)\*(:> appends a period to the text in \*(<:t\*(:>. .Se 2 6.2.3 TABLE-SELECTION-TARGETS .Xx key .Xx associate .Xx table entry .Xx location .Xx type .Sy 2 .Pr table-selection-target 2 .Sl target \*(<:[\*(:> expression \*(<:]\*(:> .Sx 3 \k1table-selection-target: \*(<:t[i, j]\*(:> .Xe .Tx The target must contain a table. The value of the expression is a key K, to be used as selector. For each key in the table, there is a location for the corresponding associate. If K is an existing key of the table, the location for the table-selection-target is that of the associate corresponding to K. If a value A is then put in the table-selection-target, the original associate held in that location is superseded by A. If K is not an existing key and a value A is to be put in the table-selection-target, a new location is created, and the (original) table is made to contain a new table entry consisting of K and A. K must be of the same type as the other keys of the table, and A of the same type as the other associates. .Se 5 6.3 TESTS .Xx bound tags .Xx scratch-pad copy .Tx Tests do not return a value, but succeed or fail when tested. In \*B, the testing of a test cannot alter the values of targets that currently exist, nor can it create new targets that survive the test, with the exception of the temporary survival of bound tags as described under QUANTIFICATIONS (section 6.3.7) and REFINED-TESTS (section 6.3.3). .br If a test appears to alter an existing target, it effectively modifies a local, ``scratch-pad'' \fIcopy\fP of that target, and the change is invisible outside the test. .Sy 6 .Pr test 6 .Al tight-test .Al conjunction .Al disjunction .Al negation .Al quantification .Pr tight-test 6 .Al \*(<:(\*(:> test \*(<:)\*(:> .Al order-test .Al proposition .Al refined-test .Pr right-test 4 .Al tight-test .Al negation .Al quantification .Tx The various kinds of tests that are distinguished here serve to define the syntax in such a way that no parentheses are needed where the meaning is sufficiently clear. .Se 7 6.3.1 ORDER-TESTS .Xx order .Xx approximate .Xx exact .Xx equal .Xx number .Sy 7 .Pr order-test 3 .Al single-expression\0order-sign\0single-expression .Al order-test\0order-sign\0single-expression .Pr order-sign 7 .Al \*(<:<\*(:> .Al \*(<:<=\*(:> .Al \*(<:=\*(:> .Al \*(<:<>\*(:> .Al \*(<:>=\*(:> .Al \*(<:>\*(:> .Ps (The order-sign \*(<:<>\*(:> stands for ``not equals''.) .Ex 5 \k1order-tests: \h'|\n1u'\*(<:(i', j') > (i, j)\*(:> \&\h'|\n1u'\*(<:'0' <= d <= '9'\*(:> \h'|\n1u'\*(<:fa <= f(x) >= fb\*(:> .Xe The single-expressions are evaluated one by one, from left to right, and each adjacent pair is compared. As soon as a comparison does not comply with the given order-sign, the whole order-test fails and no further single-expressions are evaluated. The order-test succeeds if all comparisons comply with the specified order-signs. .br Note carefully that an approximate number is \fInever\fP equal to an exact number, so, for instance, if you want to compare an approximate number \*(<:a\*(:> for equality with an exact number \*(<:e\*(:>, you should write .Di 1 \*(<:IF a = ~e:\*(:>\ ... .Ed .br This also allows you to test if a number is exact or not: .Di 3 \*(<:SELECT: x = ~x: WRITE 'Approximate' ELSE: WRITE 'Exact'\*(:> .Ed .Se 2 6.3.2 PROPOSITIONS .Xx proposition .Xx user-defined predicate .Xx scratch-pad copy .Xx test-unit .Xx report-command .Xx succeed-command .Xx fail-command .Xx text, list or table .Sy 2 .Pr zeroadic-proposition 2 .Sl zeroadic-predicate .Pr monadic-proposition 2 .Sl monadic-predicate\0actual-operand .Pr dyadic-proposition 2 .Al actual-operand\0dyadic-predicate\0actual-operand .Pr zeroadic-predicate 2 .Sl tag .Pr monadic-predicate 2 .Sl tag .Pr dyadic-predicate 2 .Sl tag .Us 7 Propositions with user-defined predicates A proposition whose predicate is defined by a test-unit, is tested in the following steps: .in \w'2.\ 'u .ti 0 1.\ A copy is made of the current environment (the value of all targets), and all computations during the testing of the proposition will take place in this ``scratch-pad copy''. .ti 0 2.\ Any local tags in the test-unit that might clash with tags currently in use are systematically replaced by other tags that do not cause conflict. .ti 0 3.\ Each actual-operand is evaluated and put in the corresponding formal-operand, used as a (new) target. .ti 0 4.\ The command-suite of the unit, thus modified, is executed. .in 0 The testing of the proposition is complete when the execution of this command-suite terminates because of the execution of a report-, succeed- or fail-command; the proposition succeeds or fails accordingly. .Us 7 Propositions with predefined predicates .Qr \*(<:e in t\*(:> .Qe accepts texts, lists and tables for the right operand. It succeeds if \*(<:e#t > 0\*(:> succeeds, in other words, if the value \*(<:e\*(:> occurs in \*(<:t\*(:>. .Qr \*(<:e not'in t\*(:> .Qe is the same as \*(<:(NOT e in t)\*(:>. .Se 2 6.3.3 REFINED-TESTS .Xx scratch-pad copy .Xx report-command .Xx succeed-command .Xx fail-command .Xx bound tags .Sy 2 .Pr refined-test 2 .Sl tag .Sx 3 \k1refined-test: \*(<:special'case\*(:> .Xe .Tx A refined-test is tested in the following steps: .in \w'2.\ 'u .ti 0 1.\ A copy is made of the current environment (the value of all targets), and all computations during the testing of the test will take place in this ``scratch-pad copy''. .ti 0 2.\ The command-suite of the corresponding test-refinement is executed. .in 0 The testing of the refined-test is complete when the execution of this command-suite terminates because of the execution of a report-, succeed- or fail-command, and the refined-test succeeds or fails accordingly. .ne 3 .br Any bound tags set by a for-command or a quantification (see 6.3.7) at that time will temporarily survive for those parts that are reachable only by virtue of the outcome of the test. This is so that you can turn any test into a refined-test with the same effect. .br For example, in .Di 3 \*(<: IF divisible AND n > d**2: WRITE d \*(:>...\*(<: divisible: REPORT SOME d IN {2..n-1} HAS n mod d = 0\*(:>, .Ed the bound tag \*(<:d\*(:> is set to a divisor of \*(<:n\*(:> if the refined-test succeeds, and since the part \*(<:n > d**2\*(:> is only reached after success, \*(<:d\*(:> may be used there. The same is true for the write-command using \*(<:d\*(:>. The line after (indicated with three dots), however, can be reached if the divisibility test fails. So there \*(<:d\*(:> has ceased to exist. .Sa test-refinements (4.4). .Se 2 6.3.4 CONJUNCTIONS .Sy 2 .Pr conjunction 3 .Al tight-test \*(<:AND\*(:> right-test .Al tight-test \*(<:AND\*(:> conjunction .Ex 4 \k1conjunctions: \h'|\n1u'\*(<:a > 0 AND b > 0\*(:> \h'|\n1u'\*(<:i in keys t AND t[i] in keys u AND u[t[i]] <> 'dummy'\*(:> .Xe .Tx The tests of the conjunction, separated by \*(<:AND\*(:>, are tested one by one, from left to right. As soon as one of these tests fails, the whole conjunction fails and no further parts are tested. The conjunction succeeds if all its tests succeed. .Se 2 6.3.5 DISJUNCTIONS .Sy 2 .Pr disjunction 3 .Al tight-test \*(<:OR\*(:> right-test .Al tight-test \*(<:OR\*(:> disjunction .Ex 4 \k1disjunctions: \h'|\n1u'\*(<:a <= 0 OR b <= 0\*(:> \h'|\n1u'\*(<:n = 0 OR s[1] = s[n] OR t[1] = t[n]\*(:> .Xe .Tx The tests of the disjunction, separated by \*(<:OR\*(:>, are tested one by one, from left to right. As soon as one of these tests succeeds, the whole disjunction succeeds and no further parts are tested. The disjunction fails if all its tests fail. .Se 2 6.3.6 NEGATIONS .Sy 2 .Pr negation 2 .Sl \*(<:NOT\*(:> right-test .Sx 3 \k1negation: \*(<:NOT a subset b\*(:> .Xe .Tx A negation succeeds if its right-test fails, and fails if that test succeeds. .Se 3 6.3.7 QUANTIFICATIONS .Xx bound tags .Xx text, list or table .Xx character .Xx list entry .Xx associate .Sy 3 .Pr quantification 2 .Sl quantifier\0ranger \*(<:HAS\*(:> right-test .Pr quantifier 4 .Al \*(<:SOME\*(:> .Al \*(<:EACH\*(:> .Al \*(<:NO\*(:> .Pr ranger 3 .Al in-ranger .Al parsing-ranger .Pr parsing-ranger 3 .Sl multiple-identifier \*(<:PARSING\*(:> expression .Ps Note that the identifier of a parsing-ranger must be a multiple-identifier (like \*(<:p, q, r\*(:>): it may not be a single-identifier (like \*(<:pqr\*(:>). Moreover, each of the single-identifiers (like \*(<:p\*(:>) must be plain tags. The reason is that this determines the number of parts which the value of the expression must be split into (see below). .Bl 1 (For in-rangers, see for-commands, section 5.2.4.) .Ex 5 \k1quantifications: \h'|\n1u'\*(<:SOME p, q, r PARSING line HAS q in {'. '; '? '; '! '}\*(:> \h'|\n1u'\*(<:EACH i, j IN keys t HAS t[i, j] = t[j, i]\*(:> \h'|\n1u'\*(<:NO d IN {2..n-1} HAS n mod d = 0\*(:> .Xe .Tx The tags of the identifier of a quantifier may not be used as targets or target-contents outside such a quantifier. They are ``bound tags'', and lose their meaning outside the quantifier, except as described below. .Bl 2 The meaning of quantifications will first be described for the case of \*(<:SOME\*(:>\ ...\ \*(<:IN\*(:>\ ... .br The value of the expression must be a text, list or table. The items (characters, list entries or associates) of that value are assigned one by one to the identifier, and the right-test is tested each time. The quantification succeeds as soon as the right-test succeeds once. It fails only if the text, list or table is exhausted and the right-test has failed each time. .br If the quantification succeeds, the bound tags set at that moment will temporarily survive and may be used in those parts that are reachable only by virtue of the outcome of the test. .br For example, in .Di 3 \*(<: IF (SOME d IN {2..n-1} HAS n mod d = 0) AND n > d**2: WRITE d \*(:>\ ... .Ed the bound tag \*(<:d\*(:> is set to a divisor of \*(<:n\*(:> if the quantification succeeds, and since the part \*(<:n > d**2\*(:> is only reached after success, \*(<:d\*(:> may be used there. The same is true for the write-command using \*(<:d\*(:>. So, if \*(<:n\*(:> has the value \*(<:77\*(:>, \*(<:7\*(:> will be written, since the test \*(<:n mod d = 0\*(:> succeeds the first time when \*(<:d\*(:> is set to \*(<:7\*(:> (and \*(<:77 > 7**2\*(:>). The line after (indicated with three dots), however, can be reached if the divisibility test fails. So there \*(<:d\*(:> has ceased to exist and may not be used. .sp The meaning of a quantification \*(<:SOME id IN tlt HAS prop\*(:> can also be described as the meaning of the refined-test \*(<:test'if'some\*(:>, given a test-refinement .Di 4 \*(<:test'if'some: FOR id IN tlt: IF prop: SUCCEED FAIL\*(:> .Ed .Bl 3 The meaning of \*(<:EACH id IN tlt HAS prop\*(:> is the same as that of \*(<:NOT SOME id IN tlt HAS NOT prop\*(:>. In other words, an \*(<:EACH\*(:> quantification succeeds only if its right-test succeeds each time. .br The meaning of \*(<:NO id IN tlt HAS prop\*(:> is the same as that of \*(<:NOT SOME id IN tlt HAS prop\*(:>. In other words, a \*(<:NO\*(:> quantification succeeds only if its right-test fails each time. .br The rules for temporary survival are the same as for \*(<:SOME\*(:>. So an \*(<:EACH\*(:> or \*(<:NO\*(:> quantification will only have set its bound tags on failure. Thus, in the following, the bound tag \*(<:d\*(:> survives into the \*(<:ELSE\*(:>: .Di 4 \*(<:SELECT: NO d IN {2..n-1} HAS n mod d = 0: WRITE 'prime' ELSE: WRITE 'divisible by `d`'\*(:> .Ed .Bl 3 If \*(<:PARSING\*(:> is specified, all \fIparsings\fP of the value of the given expression are tried, instead of its items. The value of the expression must be a text. A ``parsing'' of a text is a way of splitting it in parts. The text is split in all possible ways in as many parts as there are tags in the multiple-identifier, and each split is put in that identifier, whereupon the right-test is tested. For example, .Di 1 \*(<:SOME p, q, r PARSING 'abracadabra' HAS (p = r AND #p > 3)\*(:> .Ed will succeed with \*(<:p\*(:> and \*(<:r\*(:> set to \*(<:'abra'\*(:> and \*(<:q\*(:> set to \*(<:'cad'\*(:>. If the test \*(<:#p > 3\*(:> is omitted, the quantification will succeed with the uninteresting result that \*(<:p\*(:> and \*(<:r\*(:> are set to \*(<:''\*(:> and \*(<:q\*(:> to \*(<:'abracadabra'\*(:>. .br To give another example, .Di 3 \*(<: PUT 'a man, a plan, a canal: panama!' IN palindrome WHILE SOME hd, x, tl PARSING palindrome HAS x'non'letter: PUT hd^tl IN palindrome WRITE palindrome / x'non'letter: REPORT #x = 1 AND x not'in {'a'..'z'}\*(:> .Ed will successively find and remove all non-letters from the text in \*(<:palindrome\*(:> finally leaving the text \*(<:'amanaplanacanalpanama'\*(:>. (This is not a recommended way, because it will be very slow. There are equally simple and much faster ways to achieve the same effect. The example is only chosen to illustrate the possibilities of \*(<:PARSING\*(:>.) Note that the test \*(<:#x = 1\*(:> here is essential. If it is omitted, the program will go into an endless loop ``removing'' empty texts \*(<:x\*(:> from \*(<:palindrome\*(:>. .br The meaning of \*(<:SOME p, q,\*(:>\ ...\ \*(<:PARSING whole HAS prop\*(:> may more precisely be described as follows. Let \*(<:parsings\*(:> stand for a list, containing \fIall\fP compounds with the same number of fields as the multiple-identifier \*(<:p, q,\*(:>\ ..., such that those fields (which are texts) joined together give the text \*(<:whole\*(:>. For example, in .Di 1 \*(<:SOME p, q, r PARSING 'abracadabra' HAS (p = r AND #p > 3)\*(:> .Ed the list \*(<:parsings\*(:> will begin with .Di 1 \*(<:{('', '', 'abracadabra'); ('', 'a', 'bracadabra');\*(:>\ ...\ , .Ed contain somewhere in the middle .Di 1 \&...\ \*(<:; ('abra', 'cad', 'abra');\*(:>\ ...\ , .Ed and end with .Di 1 \&...\ \*(<:; ('abracadabr', 'a', ''); ('abracadabra', '', '')}\*(:>. .Ed The effect of the quantification is then the same as that of .Di 1 \*(<:SOME p, q,\*(:>\ ...\ \*(<:IN parsings HAS prop\*(:>. .Ed The meaning of \*(<:EACH\*(:> or \*(<:NO\*(:> is accordingly defined. .Sa for-commands (5.2.4). .ps 10 .vs 12 .de PH\"Page Header .ie \\n+(cl<3 \{\ .po +\\n(TWu/3u .rt .ns \} .el \{\ .po \\n(POu .nr f1 \\n(.f\" current font .ft .nr f2 \\n(.f\" previous font .ft R .nr sp \\n(.s\"current point size .ps \\n(ms-1 'bp .CM \" Cut Mark 'ie o 'tl ''\\*(TL'\\*(Sn' 'el 'tl '\\*(Sn'\\*(TL'' .ft \\n(f2\" restore previous font .ft \\n(f1\" restore current font .ps \\n(sp\"restore point size 'sp 2 .mk 'ns 'EH\"Extra Header 'nr cl 0 1 \} 'na .. .ch PH .wh -(\n(HFu-1v) PH .de Fo\" Page footer .nr f1 \\n(.f\" current font .ft .nr f2 \\n(.f\" previous font .ft R .nr sp \\n(.s\"current point size .ps \\n(ms-1 .po \\n(POu .if \\n%>2 .tl ''%'' .po .ft \\n(f2\" restore previous font .ft \\n(f1\" restore current font .ps \\n(sp\"restore point size .. .de XX .br .ti 0 .. .ds Sn Index .nr cl 4 1 .ll \n(TWu/3u-2n .na .bp .Us 3 INDEX .mk .in 2n .XX actual-operand 6.1.6 .XX actual-parameter 5.1.16 .XX alternative-sequence 5.2.2 .XX alternative-suite 5.2.2 .XX ambiguity 6.1.5, 6.1.6 .XX approximate 6.3.1 .XX approximate-constant 6.1.1 .XX approximate number 1 .XX associate 1, 5.1.6, 5.2.4, 6.1.4, 6.1.5, 6.1.6, 6.2.3, 6.3.7 .XX basic-expression 6.1 .XX basic-target 6.2 .XX bound tags 5.1.13, 5.1.14, 5.1.15, 5.2.4, 6.3, 6.3.3, 6.3.7 .XX brackets 6.1.6 .XX character 1, 5.1.6, 5.2.4, 6.1.5, 6.1.6, 6.3.7 .XX check-command 5.1.1 .XX choose-command 5.1.6 .XX command 5 .XX command-refinement 4.4, 5.1.11, 5.1.17 .XX command-sequence 4.5 .XX command-suite 4.5 .XX comment 3 .XX compound 1, 6.1, 6.2 .XX conjunction 6.3.4 .XX control-command 5.2 .XX conversion 6.1.5 .XX convert to a text 5.1.2, 6.1.5, 6.1.6 .XX decrease-indentation 3 .XX delete-command 5.1.10 .XX denominator 6.1.6 .XX digit 6.1.1 .XX disjunction 6.3.5 .XX display 6.1.5 .XX draw-command 5.1.5 .XX dyadic 4.2, 4.3 .XX dyadic-formula 6.1.6 .XX dyadic-function 6.1.6 .XX dyadic-predicate 6.3.2 .XX dyadic-proposition 6.3.2 .XX else-alternative 5.2.2 .XX empty 2 .XX empty list 6.1.5 .XX empty table 6.1.5 .XX entry 1 .XX equal 6.3.1 .XX exact 6.3.1 .XX exact-constant 6.1.1 .XX exact number 1 .XX exponent-part 6.1.1 .XX expression 6.1 .XX expression-refinement 4.4, 4.5, 5.1.12, 6.1.7 .XX fail-command 4.5, 5.1.15, 6.3.2, 6.3.3 .XX field 1 .XX for-command 5.2.4 .XX formal-dyadic-formula 4.2 .XX formal-dyadic-proposition 4.3 .XX formal-formula 4.2 .XX formal-monadic-formula 4.2 .XX formal-monadic-proposition 4.3 .XX formal-operand 4.2 .XX formal-parameter 4.1 .XX formal-proposition 4.3 .XX formal-tail 4.1 .XX formal-trailer 4.1 .XX formal-user-defined-command 4.1 .XX formal-zeroadic-formula 4.2 .XX formal-zeroadic-proposition 4.3 .XX formula 4.2, 4.3, 6.1.6 .XX fractional-part 6.1.1 .XX function 4.2, 4.3, 6.1.6 .XX further-comment 3 .XX global 4.5, 5 .XX how-to-unit 4.1, 5.1.11, 5.1.16 .XX identifier 6.2.1 .XX if-command 5.2.1 .XX immediate command 5, 5.1.11 .XX in-ranger 5.2.4 .XX increase-indentation 3 .XX indentation 3 .XX insert-command 5.1.9 .XX integer 6.1.3, 6.1.5, 6.1.6 .XX integral-part 6.1.1 .XX interrupt key 5, 5.1.2 .XX key 1, 6.1.4, 6.1.5, 6.1.6, 6.2.3 .XX keyword 3, 4.1, 4.4, 5.1.16, 5.1.17 .XX list 1 .XX list-body 6.1.5 .XX list-display 6.1.5 .XX list entry 1, 5.1.6, 5.1.8, 5.1.9, 5.2.4, 6.1.6, 6.3.7 .XX list-filler 6.1.5 .XX list-filler-series 6.1.5 .XX local 4.5, 6.1.6, 6.2.1 .XX location 5.1.4, 5.1.10, 6.2.1, 6.2.3 .XX monadic 4.2, 4.3 .XX monadic-formula 6.1.6 .XX monadic-function 6.1.6 .XX monadic-predicate 6.3.2 .XX monadic-proposition 6.3.2 .XX multiple-expression 6.1 .XX multiple-identifier 6.2.1 .XX multiple-target 6.2 .XX negation 6.3.6 .XX new-line 3 .XX new-line-proper 3 .XX new-liners 5.1.2 .XX number 1, 5.1.5, 6.1.6, 6.3.1 .XX numerator 6.1.6 .XX numeric-constant 6.1.1 .XX optional-ANYTHING 2 .XX order 1, 6.3.1 .XX order-sign 6.3.1 .XX order-test 6.3.1 .XX overloading of functions and predicates 4.2, 4.3 .XX parentheses 6.1.6 .XX parsing-ranger 6.3.7 .XX permanent environment 4.5, 5.1.2, 5.1.11 .XX plusminus 6.1.1 .XX predefined functions 6.1.6 .XX predefined predicates 6.3.2 .XX predicate 4.2, 4.3 .XX priority 6.1.6 .XX proposition 4.3, 6.3.2 .XX put-command 5.1.4 .XX quantification 6.3.7 .XX quantifier 6.3.7 .XX quit-command 5.1.11, 5.1.16, 5.1.17 .XX quote 6.1.5 .XX random 5.1.5, 5.1.6, 5.1.7 .XX ranger 6.3.7 .XX read-command 5.1.3 .XX refined-command 5.1.17 .XX refined-expression 5.1.12, 6.1.7 .XX refined-test 5.1.13, 5.1.14, 5.1.15, 6.3.3 .XX refinement 4.4 .XX refinement-suite 4 .XX remove-command 5.1.8 .XX report-command 4.5, 5.1.13, 6.3.2, 6.3.3 .XX return-command 4.5, 5.1.12, 6.1.6, 6.1.7 .XX right-expression 6.1 .XX right-test 6.3 .XX scratch-pad copy 6.1, 6.1.6, 6.1.7, 6.3, 6.3.2, 6.3.3 .XX select-command 5.2.2 .XX set-random-command 5.1.7 .XX share-heading 4.5 .XX simple-command 5.1 .XX simple-expression 6.1 .XX single-alternative 5.2.2 .XX single-expression 6.1 .XX single-identifier 6.2.1 .XX single-target 6.2 .XX spaces 3 .XX succeed-command 4.5, 5.1.14, 6.3.2, 6.3.3 .XX table 1 .XX table-display 6.1.5 .XX table entry 1, 5.1.10, 6.1.4, 6.2.3 .XX table-filler 6.1.5 .XX table-filler-series 6.1.5 .XX table-selection 6.1.4 .XX table-selection-target 5.1.10, 6.2.3 .XX tag 3, 6.2.1 .XX target 4.5, 5.1.4, 5.2.4, 6.1.6, 6.2, 6.2.1 .XX target-content 6.1.2 .XX terminating-command 5.1, 5.2.3 .XX test 4.3, 6.3 .XX test-refinement 4.4, 4.5, 5.1.13, 5.1.14, 5.1.15 .XX test-unit 4.3, 4.5, 5.1.13, 5.1.14, 5.1.15, 6.3.2 .XX text 1, 6.1.6 .XX text, list and table 5.1.6, 5.2.4, 6.1.6, 6.3.2, 6.3.7 .XX text-display 6.1.5 .XX tight-expression 6.1 .XX tight-test 6.3 .XX trailer 5.1.16 .XX trimmed-text 6.1.3 .XX trimmed-text-target 6.2.2 .XX type 5.1.4, 6.2.3 .XX unit 4 .XX user-defined-command 4.1, 5.1.16 .XX user-defined-function 4.2, 5.1.12, 6.1.6 .XX user-defined-predicate 4.3, 5.1.13, 5.1.14, 5.1.15, 6.3.2 .XX while-command 5.2.3 .XX work-space 4, 4.5 .XX write-command 5.1.2 .XX yield-unit 4.2, 4.5, 5.1.12, 6.1.6 .XX zeroadic 4.2, 4.3 .XX zeroadic-formula 6.1.6 .XX zeroadic-function 6.1.6 .XX zeroadic-predicate 6.3.2 .XX zeroadic-proposition 6.3.2 .rm PH .wh -0 CM .bp