Expressions Every expression evaluates to a string. There are no numeric expressions, but arithmetic may be performed on those strings which happen to represent numbers in decimal. From here on, references to "numbers" or "numeric" values will mean strings of the following format: [+|-] [nnnnn][.][nnnn] [E [+|-] nnn] That is, an optional sign followed by a string of digits, possibly including a decimal point, followed by an optional exponent. The exponent consists of a letter `E' (or `e'), an optional sign, and a sequence of digits. No spaces are allowed within a number, but trailing or leading spaces are allowed, and spaces may occur between the leading sign and the first digit. There is no number which contains no digits before the exponent (if any), and "." is not a number. Whenever REXX constructs a number (such as the result of an arithmetic operation), it is formatted according to the following rules: - a zero result is always expressed as the single digit "0". - it is rounded up or down if necessary, so that the specified number of significant figures is not exceeded. The number of significant figures is usually 9, but can be changed with the NUMERIC DIGITS instruction. - If the number is negative, it is preceded by a minus sign, otherwise there is no sign. A number never contains spaces. - If the magnitude of the number is less than 1 (and if exponential notation is not used) then a single zero digit precedes the decimal point. - An exponential form of the number - e.g. 1.234E+65 - will be used if the number of digits otherwise required before or after the decimal point exceeds NUMERIC DIGITS or twice that value, respectively. - If NUMERIC FORM SCIENTIFIC is in effect (the default) and the number is expressed in exponential form, then the mantissa has precisely one digit before the decimal point (if any), which is non-zero. The exponent consists of the letter E followed by a plus or minus sign, and then the exponent (with no spaces or leading zeros). - If NUMERIC FORM ENGINEERING is in effect and the number is expressed in exponential form then the exponent is a multiple of three. Up to three digits appear before the decimal point in the mantissa, but otherwise the form is similar to the `scientific' form described above. See the NUMERIC command for some more information. An expression consists of one or more constants or variables which may be combined with the use of operators and functions, as described below. Spaces are allowed within expressions, as long as they do not split up variable names or other integral items. String Constants: These are enclosed in quotes. Either single or double quotes may be used, but the terminating quote must be the same as the initial quote. A string may contain any characters, but to enclose a quote of the same kind as the delimeters, the quote is typed twice. A string containing no characters is a null string. Example: "that's right" has value that's right '"I''m here," I said.' has value "I'm here," I said. "" is the null string. Hex Constants: A hex constant contains a sequence of hex digits grouped in pairs. The first group may have just one digit, in which case a `0' is added to the left. The groups are optionally separated by spaces. Each group (pair) of hex digits is translated into the character it represents in ASCII. The list is enclosed in quotes and immediately after the terminating quote is an `X' (or `x'). The `X' must not form part of a longer word. Example: "41 4243 44 "x has value ABCD Binary Constants: A binary constant is like a hex constant, but has `B' instead of `X' and contains binary digits ("0" or "1"). The digits are arranged in nybbles - that is, groups of 4, which may optionally be separated by spaces. The first nybble may have less than 4 digits, in which case it is extended on the left with zeros. If an odd number of nybbles is present, a zero nybble is added on the left. Each pair of nybbles is then translated into an ASCII character. Example: '10 0011 00100001'b has value CA NOTE: the sequence of binary or hex digits must not contain leading or trailing blanks. Symbols: A symbol contains any number of letters, numbers, dots and the characters @#$!?_ and is always translated to upper case before use. A constant symbol is one which starts with a number or a dot, and when it is found in an expression, the characters of the symbol itself are used. In addition, a single plus or minus sign is allowed in a constant symbol if it is part of (the exponent of) a number as defined above. Any non-constant symbol may be assigned a value by the statement symbol = expression A simple symbol is one which does not contain any dots and does not start with a digit. When it is used in an expression it names a variable, and if it has been assigned a value then that value is used, otherwise the symbol itself is used (after translating to upper case). A stem is a symbol which ends with a dot, but does not contain any other dots and does not start with a digit or dot. It can be used in an expression or assigned to (see below). A compound symbol is a symbol which consists of a stem followed by a tail. The tail consists of a non-empty sequence of `qualifiers' separated by dots. Each qualifier is ordinarily a simple symbol, a constant symbol, or null (that is, it contains no characters), but as a LOCAL extension, some additional qualifiers are allowed. The following can be used as qualifiers: 1. a simple symbol, which is substituted by its value before being used in the compound variable name 2. a constant symbol, which is uppercased before being used in the compound symbol 3. a null qualifier (as in `a..b') 4. a string constant 5. a parenthesised expression. The stem and all qualifiers (1) and (2) above are uppercased before use, but the value of a symbol in (1) or of a string constant or expression in (4) or (5) is not uppercased. After the name of a compound symbol has been found, if it has a value then that value is used, otherwise the name of the symbol is used (with no uppercasing). If a stem is assigned a value (as in `foo.=7'), then every possible compound symbol is given that value (so, for example, foo.bar now has value 7). If a stem is used in an expression, its value will be the last value assigned to the stem, if any (and otherwise its value will be the stem's name in uppercase). So, for example, foo. now has value 7. Examples: If foo has been assigned the value 5 but no other names have been assigned values, then: foo is a simple symbol with a value foobar is a simple symbol without a value and foo.5 foo.Foo FOO.'5' foo.(foo*3-10) all represent the same compound symbol (which has no value, so the string "FOO.5" will be used). However, foo.'bar' foo.'BAR' represent different compound symbols, each of which has no value (so the strings "FOO.bar" and "FOO.BAR" will be used respectively). LOCAL: Note that qualifiers (4) and (5) above are local extensions. Literals: A literal is another name for a constant symbol, or a non-constant symbol without a value. BUG: There is an upper limit on the length of variable names. If at any time during the interpretation of a variable name the interpreter's copy of the name is likely to exceed about 250 characters, there will be an error. Operators: Each operator described below will be given a priority. Operators are applied, from left to right, in order of their priority, 1 being carried out last. Thus, in "3+4*5/2" the operations carried out are, in order: 4*5=20 (priority 8) 20/2=10 (priority 8) 3+10=13 (priority 7) Unary operators: + 11 (+a is similar to 0+a) - 11 (arithmetical negation) ^ or \ 11 (boolean negation) Binary operators: **10 (exponentiation) * 8 (multiplication) / 8 (division) % 8 (integer division) // 8 (remainder from integer division) + 7 (addition) - 7 (subtraction) || 6 (concatenation) = 5 (equality) == 5 (strong equality) <> or >< or ^= or \= 5 (not equality) ^== \== 5 (strong nequality) < 5 <= or ^> or \> 5 (the usual relations) > 5 >= or ^< or \< 5 >> 5 (strong greater-than) << 5 (strong less-than) >>= or ^<< or \<< 5 (strong greater-or-equal) <<= or ^>> or \>> 5 (strong less-or-equal) & 3 (boolean and) | 2 (boolean or) && 2 (boolean xor) NOTE: The character `\' and the character `^' both mean `not' and are interchangeable. The preferred `not' character is `\'. In addition to these binary operations, there are two concatenation operators. Firstly, if two values are placed next to each other with no space in between (clearly they must be differentiable for this to make sense), they are concatenated, with priority 6. Secondly, if two values are placed next to each other with at least one space between, they are concatenated with a space between, with priority 6. For example, 1"+"1"="1+1 has value 1+1=2 1 "+" 1 "="1+1 has value 1 + 1 =2 NOTE: There are a small number of cases where the space operator does not give the intended result. Example: 1 -2 4 -7 does not equal 1 -2 4 -7 but it equals -1 -3 because spaces are allowed within expressions, and so this expression is interpreted as meaning 1-2 4-7 Parentheses are used in order to circumvent the usual priorities of operators, so that, for example, (1+2)*3 is 9, whereas 1+2*3 is 7. A function call consists of a function name (which is a symbol) followed immediately by a left parenthesis, a list of expressions separated by commas, and a right parenthesis. Arguments may be omitted simply by putting no expression between one comma (or parenthesis) and the next. As with simple symbols, the function name is translated to upper case unless it is a string constant. Note that a function name must not end with a dot unless it is quoted, because in that case it would be interpreted as a compound symbol containing a parenthesised expression. Also note that there must be no space between the function name and the opening parenthesis, because otherwise the space will be treated as a concatenation operator (see above). When a function is called, it must return a result, otherwise an error will be raised. Examples: time('c') uname('-a') format(x,,,,4) See the section on function or subroutine invocation for more details. Arithmetic Operators: The operand(s) must be numeric values. If they are not, then an error results. The usual arithmetic rules apply. See the "NUMERIC" command. The y operand the exponentiation operator in "x ** y" must be an integer, otherwise an error results. The exponentiation operator works effectively by multiplying x by itself y times, and taking the reciprocal if y<0. (It uses an O(log y) method). The integer division operator % is defined so that x%y is the integer part of x/y (obtained by rounding towards zero), and x = y*(x%y) + (x//y) For example, 10 % 0.3 = 33 and 10 // 0.3 = 0.1 An integer is a whole number which lies within the range of the machine (-2**31 to 2**31-1). A whole number is any number with no non-zero fractional part which would not be written in exponential notation when formatted. The maximum exponent is about 999999999. An overflow or underflow will occur if the limit is exceeded. BUG: You might find that the maximum number boundary is a little `fuzzy' but if you keep below 1E999999990 you should be alright! BUG: Whole numbers must be less than 1999999999. Boolean logic: Several of the above operators operate on boolean values or create boolean values. The following rules apply: 1. The result of a binary relation or of the \ (or ^) operator is always 1 for true, 0 or false. 2. A boolean value is represented by any number (attempts to use other strings will result in an error). False is represented by zero, and any other number represents true. LOCAL: In `real' REXX a boolean value may only be represented by 0 or 1. 3. \x has the obvious meaning consistent with the above (i.e. 1 if x=0, and 0 otherwise). 4. x & y is 0 if y is false but has the same value as x when y is true. 5. x | y is 1 if y is true but has the same value as x when y is false. 6. x && y has value x if y is false, and \x otherwise. Binary relations: (note that the symbol '\' means `not' and may be placed before any of the relations to negate its value, e.g. \=, \>> etc. Thus, for instance, \> and <= have the same meaning, as do \>> and <<=, etc. The character `^` is a synonym for '\' - so ^== is the same as \==). The operators ==, \==, <<, >>, <<=, >>= compare their two operands character by character and thus have the normal meaning of string equality, greater, less, etc. All other operators depend on whether or not both operands are numeric. If they are, then they are subtracted and the result compared with zero. Otherwise, leading and trailing spaces are stripped and the operations are compared as strings usually are, with the shorter string being padded on the right with spaces before the comparison. Hence: "0.10" \== "1e-1" (strict string comparison) "0.10" = "1e-1" (numeric comparison) " hello" \== "hello " (strict comparison respects spaces) " hello" = "hello " (weak comparison strips spaces) "abc " >> "abc" (strict comparison respects spaces) "61626300"x < "616263"x (the latter is padded with a space) "61626364"x > "616263"x (ordinary string comparison) "2.5" > "10abc" (string comparison) "2.5" < "10" (numeric comparison) "2.5" >> "10 (strict string comparison) In this implementation, character comparisons are unsigned, that is to say "ff"x is greater than "00"x, etc.