Skip to main content

Software > Software Development > IBM REXX Family >

NetRexx

Technical detail

Expressions and Operators

Many clauses can include expressions. Expressions in NetRexx are a general mechanism for combining one or more data items in various ways to produce a result, usually different from the original data.

Expressions consist of one or more terms, such as literal strings, symbols, method calls, or sub-expressions, and zero or more operators that denote operations to be carried out on terms. Most operators act on two terms, and there will be at least one of these dyadic operators between every pair of terms.[1]  There are also prefix (monadic) operators, that act on the term that is immediately to the right of the operator. There may be one or more prefix operators to the left of any term, provided that adjacent prefix operators are different.

Evaluation of an expression is left to right, modified by parentheses and by operator precedence in the usual 'algebraic' manner. Expressions are wholly evaluated, except when an error occurs during evaluation.

As each term is used in an expression, it is evaluated as appropriate and its value (and the type of that value) are determined.

The result of any operation is also a value, which may be a character string, a data object of some other type, or (in special circumstances) a binary representation of a character or number. The type of the result is well-defined, and depends on the types of any terms involved in an operation and the operation carried out. Consequently, the result of evaluating any expression is a value which has a known type.

Note that the NetRexx language imposes no restriction on the maximum size of results, but there will usually be some practical limitation dependent upon the amount of storage and other resources available during execution.

Operators

The operators in NetRexx are constructed from one or more operator characters. Blanks (and comments) adjacent to operator characters have no effect on the operator, and so the operators constructed from more than one character may have embedded blanks and comments. In addition, blank characters, where they occur between tokens within expressions but are not adjacent to another operator, also act as an operator.

The operators may be subdivided into five groups: concatenation, arithmetic, comparative, logical, and type operators. The first four groups work with terms whose type is 'well-known' (that is, strings, or known types that can be be converted to strings without information loss). The operations in these groups are defined in terms of their operations on strings.

Concatenation

The concatenation operators are used to combine two strings to form one string by appending the second string to the right-hand end of the first string. The concatenation may occur with or without an intervening blank:

(blank)
Concatenate terms with one blank in between.
||
Concatenate without an intervening blank.
(abuttal)
Concatenate without an intervening blank.

Concatenation without a blank may be forced by using the || operator, but it is useful to remember that when two terms are adjacent and are not separated by an operator,[2]  they will be concatenated in the same way. This is the abuttal operation. For example, if the variable Total had the value '37.4', then Total'%' would evaluate to '37.4%'.

Values that are not strings are first converted to strings before concatenation.

Arithmetic

Character strings that are numbers may be combined using the arithmetic operators:

+
Add.
-
Subtract.
*
Multiply.
/
Divide.
%
Integer divide.
Divide and return the integer part of the result.
//
Remainder.
Divide and return the remainder (this is not modulo, as the result may be negative).
**
Power.
Raise a number to a whole number power.
Prefix -
Same as the subtraction: '0-number'.
Prefix +
Same as the addition: '0+number'.
The section on Numbers and Arithmetic describes numeric precision, the format of valid numbers, and the operation rules for arithmetic. Note that if an arithmetic result is shown in exponential notation, then it is likely that rounding has occurred.

In binary classes, the arithmetic operators will use binary arithmetic if both terms involved have values which are binary numbers. The section on Binary values and operations describes binary arithmetic.

Comparative

The comparative operators compare two terms and return the value '1' if the result of the comparison is true, or '0' otherwise. Two sets of operators are defined: the strict comparisons and the normal comparisons.

The strict comparative operators all have one of the characters defining the operator doubled. The '==', and '\==' operators test for strict equality or inequality between two strings. Two strings must be identical to be considered strictly equal. Similarly, the other strict comparative operators (such as '>>' or '<<') carry out a simple left-to-right character-by-character comparison, with no padding of either of the strings being compared. If one string is shorter than, and is a leading sub-string of, another then it is smaller (less than) the other. Strict comparison operations are case sensitive, and the exact collating order may depend on the character set used for the implementation.[3] 

For all the other comparative operators, if both the terms involved are numeric,[4]  a numeric comparison (in which leading zeros are ignored, etc.) is effected; otherwise, both terms are treated as character strings. For this character string comparison, leading and trailing blanks are ignored, and then the shorter string is padded with blanks on the right. The character comparison operation takes place from left to right, and is not case sensitive (that is, 'Yes' compares equal to 'yes'). As for strict comparisons, the exact collating order may depend on the character set used for the implementation.

The comparative operators return true ('1') if the terms are:

Normal comparative operators:

=
Equal (numerically or when padded, etc.).
\=
Not equal (inverse of =).
>
Greater than.
<
Less than.
><, <>
Greater than or less than (same as 'Not equal').
>=, \<
Greater than or equal to, not less than.
<=, \>
Less than or equal to, not greater than.

 

Strict comparative operators:

==
Strictly equal (identical).
\==
Strictly not equal (inverse of ==).
>>
Strictly greater than.
<<
Strictly less than.
>>=, \<<
Strictly greater than or equal to, strictly not less than.
<<=, \>>
Strictly less than or equal to, strictly not greater than.

The equal and not equal operators ('=', '==', '\=', and '\==') may be used to compare two objects which are not strings for equality, if the implementation allows them to be compared (usually they will need to be of the same type). The strict operators test whether the two objects are in fact the same object,[5]  and the normal operators may provide a more relaxed comparison, if available to the implementation.[6] 

In binary classes, all the comparative operators will use binary arithmetic to effect the comparison if both terms involved have values which are binary numbers. In this case, there is no distinction between the strict and the normal comparative operators. The section on Binary values and operations describes the binary arithmetic used for comparisons.

Logical (Boolean)

A character string is taken to have the value 'false' if it is '0', and 'true' if it is '1'. The logical operators take one or two such values (values other than '0' or '1' are not allowed) and return '0' or '1' as appropriate:

&
And.
Returns 1 if both terms are true.
|
Inclusive or.
Returns 1 if either term is true.
&&
Exclusive or.
Returns 1 if either (but not both) is true.
Prefix \
Logical not.
Negates; 1 becomes 0 and vice versa.

In binary classes, the logical operators will act on all bits in the values if both terms involved have values which are boolean or integers. The section on Binary values and operations describes this in more detail.

Type

Several of the operators already described can be used to carry out operations related to types. Specifically:

  • Any of the concatenation operators may be used for type concatenation, which concatenates a type to a value. All three operators (blank, '||', and abuttal) have the same effect, which is to convert the value to the type specified (if the conversion is not possible, an error is reported or an exception is signalled). The type must be on the left-hand side of the operator.
    Examples:
      String "abc"
    int (a+1)
    long 1
    Exception e
    InputStream myfile
  • The 'less than or equal' and the 'greater than or equal' operators ('<=' and '>=') may be used with a type on either side of the operator, or on both sides. In this case, they test whether a value or type is a subclass of, or is the same as, a type, or vice versa.
    Examples:
      if i<=Object then say 'I is an Object'
    if String>=i then say 'I is a String'
    if String<=Object then say 'String is an Object'
The precedence of these operators is not affected by their being used with types as operands.

Numbers

The arithmetic operators above require that both terms involved be numbers; similarly some of the comparative operators carry out a numeric comparison if both terms are numbers.

Numbers are introduced and defined in detail in the section on Numbers and arithmetic. In summary, numbers are character strings consisting of one or more decimal digits optionally prefixed by a plus or minus sign, and optionally including a single period ('.') which then represents a decimal point. A number may also have a power of ten suffixed in conventional exponential notation: an 'E' (uppercase or lowercase) followed by a plus or minus sign then followed by one or more decimal digits defining the power of ten.

Numbers may have leading blanks (before and/or after the sign, if any) and may have trailing blanks. Blanks may not be embedded among the digits of a number or in the exponential part.

Examples:

  '12'
'-17.9'
'127.0650'
'73e+128'
' + 7.9E-5 '
'00E+000'

Note that the sequence -17.9 (without quotes) in an expression is not simply a number. It is a minus operator (which may be prefix minus if there is no term to the left of it) followed by a positive number. The result of the operation will be a number.

A whole number in NetRexx is a number that has a zero (or no) decimal part.

Implementation minimum: All implementations must support 9-digit arithmetic. In unavoidable cases this may be limited to integers only, and in this case the divide operator ('/') must not be supported. If exponents are supported in an implementation, then they must be supported for exponents whose absolute value is at least as large as the largest number that can be expressed as an exact integer in default precision, i.e., 999999999.

Parentheses and operator precedence

Expression evaluation is from left to right; this is modified by parentheses and by operator precedence:

  • When parentheses are encountered, other than those that identify method calls, the entire sub-expression delimited by the parentheses is evaluated immediately when the term is required.
  • When the sequence
      term1 operator1 term2 operator2 term3
    is encountered, and operator2 has a higher precedence than operator1, then the operation (term2 operator2 term3) is evaluated first. The same rule is applied repeatedly as necessary.
    Note, however, that individual terms are evaluated from left to right in the expression (that is, as soon as they are encountered). It is only the order of operations that is affected by the precedence rules.

For example, '*' (multiply) has a higher precedence than '+' (add), so 3+2*5 will evaluate to 13 (rather than the 25 that would result if strict left to right evaluation occurred). To force the addition to be performed before the multiplication the expression would be written (3+2)*5, where the first three tokens have been formed into a sub-expression by the addition of parentheses.

The order of precedence of the operators is (highest at the top):

Prefix operators

+ - \

Power operator

**

Multiplication and division

* / % //

Addition and subtraction

+ -

Concatenation

(blank) || (abuttal)

Comparative operators

= == > < <= >= << \>> etc.

And

&

Or, exclusive or

| &&

If, for example, the symbol a is a variable whose value is '3', and day is a variable with the value 'Monday', then:

  a+5              =>  '8'
a-4*2 => '-5'
a/2 => '1.5'
a%2 => '1'
0.5**2 => '0.25'
(a+1)>7 => '0' /* that is, False */
' '='' => '1' /* that is, True */
' '=='' => '0' /* that is, False */
' '\=='' => '1' /* that is, True */
(a+1)*3=12 => '1' /* that is, True */
'077'>'11' => '1' /* that is, True */
'077'>>'11' => '0' /* that is, False */
'abc'>>'ab' => '1' /* that is, True */
'If it is' day => 'If it is Monday'
day.substr(2,3) => 'ond'
'!'day'!' => '!Monday!'

Note: The NetRexx order of precedence usually causes no difficulty, as it is the same as in conventional algebra and other computer languages. There are two differences from some common notations; the prefix minus operator always has a higher priority than the power operator, and power operators (like other operators) are evaluated left-to-right. Thus

  -3**2      =>  9    /* not -9  */
-(2+1)**2 => 9 /* not -9 */
2**2**3 => 64 /* not 256 */

These rules were found to match the expectations of the majority of users when the Rexx language was first designed, and NetRexx follows the same rules.

Footnotes:

[1]  One operator, direct concatenation, is implied if two terms abut.

[2]  This can occur when the terms are syntactically distinct (such as a literal string and a symbol).

[3]  For example, in an ASCII or Unicode environment, the digits 0-9 are lower than the alphabetics, and lowercase alphabetics are higher than uppercase alphabetics. In an EBCDIC environment, lowercase alphabetics precede uppercase, but the digits are higher than all the alphabetics.

[4]  That is, if they can be compared numerically without error.

[5]  Note that two distinct objects compared in this way may contain values (properties) that are identical, yet they will not compare equal as they are not the same object.

[6]  In the reference implementation, the equals method is used for normal comparisons. Where not provided by a type, this is implemented by the Object class as a strict comparison.

 

 

PreviousTable of contents Next
We're here to help
Easy ways to get the answers you need.
E-mail us

or call us at
877-426-3774
Priority code:
104CBW67