Chapter 3
EXPRESSIONS
expression
= value-expression
| reference-expression
| designational-expression
value-expression
= arithmetic-expression
| Boolean-expression
| character-expression
reference-expression
= object-expression
| text-expression
The primary constituents of programs describing algorithmic processes are
expressions. Constituents of these expressions, except for certain delimiters,
are constants, variables, function designators, labels, class and attribute
identifiers, switch designators and elementary operators. Since the syntactic
definition of both variables and function designators (see below) contain
expressions, the definition of expressions and their constituents is
necessarily recursive.
A value expression is a rule for obtaining a value.
An object expression is a rule for obtaining an object reference.
A text expression is a rule for obtaining an identification of a text variable
(and thereby a text reference).
A designational expression is a rule for obtaining a reference to a program
point.
Any value expression or reference expression has an associated type, which
is textually defined.
Variables
variable
= simple-variable-1
| subscripted-variable
simple-variable-1
= identifier-1
subscripted-variable
= array-identifier-1 "(" subscript-list ")"
array-identifier-1
= identifier-1
subscript-list
= subscript-expression { , subscript-expression }
subscript-expression
= arithmetic-expression
A variable local to a block instance is a memory device whose "contents" are
either a value or a reference, according to the type of the variable. The
contents of a variable may be changed by an appropriate assignment operation,
see 4.1. A reference is a piece of information which identifies a value,
called the "referenced" value. The distinction between a reference and the
referenced value is determined by context.
Variables are of two kinds, corresponding to the values being represented,
namely value type variables and reference type variables.
A value type variable has a value which is the contents of the variable. A
reference type variable is said to have a value which is the one referenced by
the contents of the variable.
The value of an array identifier is the ordered set of values of the
corresponding array of subscripted variables.
Examples
delta
a17
q(7,2)
x(sin(n*pi/2),q(3,n,4))
Simple variables
A simple-variable-1 is any variable which is not a subscripted variable. The corresponding values are described in chapter 2. Note: Certain syntax classes (such as simple-variable-1) are marked with a "-1". The corresponding program terms may contain a remote identifier (see 5.5.6). Value type variables have values of integer type, real type, Boolean or character. An object reference variable has an object as its value (or the value none). Text variables are described below.Text variables
A text variable is conceptually an instance of a composite structure with four constituent components (attributes):
ref (TEXTOBJ) OBJ;
integer START, LENGTH, POS;
Let X be a text variable. Then X.OBJ, X.START, X.LENGTH and X.POS denote the
components of X, respectively. These four components are not directly
accessible to the user. Instead, certain properties of a text variable are
represented by procedures accessible through the dot notation. These procedures
are described in chapter 8.
The components OBJ, START and LENGTH constitute the text reference part of the
variable. They identify the frame referenced (see 2.5.1). POS is used for
accessing the individual characters of the frame referenced (see 9.2).
The components of a text variable always satisfy one of the following two sets
of conditions:
1) OBJ =/= none
START >= 1
LENGTH >= 1
START + LENGTH <= OBJ.SIZE + 1
1 <= POS <= LENGTH + 1
2) OBJ == none
START = 1
LENGTH = 0
POS = 1
The latter alternative defines the contents of a variable which references no
frame. Note that this alternative thereby defines the special text reference
notext.
Array elements
Subscripted variables designate values which are components of multi- dimensional arrays. Each arithmetic expression of the subscript list occupies one subscript position of the subscripted variable and is called a subscript. The complete list of subscripts is enclosed by the subscript parentheses ( ) . The array component referred to by a subscripted variable is specified by the actual value of its subscripts. Each subscript position acts like a variable of type integer and the evaluation of the subscript is understood to be equivalent to an assignment to this fictitious variable. The value of the subscripted variable is defined only if the actual integer value of each subscript expression is within the associated subscript bounds of the array. A subscript expression value outside its associated bounds causes a run time error.Function designators
function-designator
= procedure-identifier-1 [ actual-parameter-part ]
procedure-identifier-1
= identifier-1
actual-parameter-part
= "(" actual-parameter { , actual-parameter } ")"
actual-parameter
= expression
| array-identifier-1
| switch-identifier
| procedure-identifier-1
A function designator defines a value which results through the application of
a given set of rules defined by a procedure declaration (see 5.4) to a fixed
set of actual parameters. The rules governing specification of actual
parameters are given in 4.6.
Note: Not every procedure declaration defines rules for determining the
value of a function designator (cf. 5.4.1).
Examples
sin(a-b)
j(v+s,n)
r
ss(s-5, !Temperature; T, !Pressure; P)
compile ("( := )", !Stack; q)
Remote identifiers
identifier-1
= identifier
| remote-identifier
remote-identifier
= simple-object-expression . attribute-identifier
| text-primary . attribute-identifier
attribute-identifier
= identifier
Let X be a simple object expression qualified by the class C, and let A be an
appropriate attribute identifier. Then the remote identifier "X.A", if valid,
is an attribute identification whose object is the value X and whose
qualification is C (cf. 5.5.6).
The remote identifier X.A is valid if the following conditions are satisfied:
- The value X is different from none.
- The object referenced by X has no class attribute declared at any prefix level equal or outer to that of C.
Condition 2 is an ad hoc rule intended to simplify the language and its implementations. A remote identifier of the form
text-primary.attribute-identifier
identifies an attribute of the text variable identified by evaluating the text
primary, provided that the attribute identifier is one of the procedure
identifiers defined in chapter 8.
Note: Even if the text primary references notext, the attribute access
is legal (in contrast to object expressions).
Example
Let P1 and P2 be variables declared and initialized as in example 2 of 4.1.4. Then the value of the expressionP1.plus (P2)is a new "point" object which represents the vector sum of P1 and P2. The value of the expressionP1 qua polar.plus (P2)is a new "polar" object representing the same vector sum.
Boolean expressions
Boolean-expression
= simple-Boolean-expression
| if-clause simple-Boolean-expression else Boolean-expression
simple-Boolean-expression
= Boolean-tertiary { or else Boolean-tertiary }
Boolean-tertiary
= equivalence { and then equivalence }
equivalence
= implication { eqv implication }
implication
= Boolean-term { imp Boolean-term }
Boolean-term
= Boolean-factor { or Boolean-factor }
Boolean-factor
= Boolean-secondary { and Boolean-secondary }
Boolean-secondary
= [ not ] Boolean-primary
Boolean-primary
= logical-value
| variable
| function-designator
| relation
| "(" Boolean-expression ")"
A Boolean expression is of type Boolean. It is a rule for computing a
logical value. Except for the operators and then and or else (see 3.4)
the semantics are entirely analogous to those given for arithmetic expressions.
Variables and function designators entered as Boolean primaries must be of type
Boolean.
Examples
x = -2
Y>v or z<q
a+b> -5 and z-d>q**2
p and not q or x<>y
t.more and then t.getchar
x == none or else x.a>0
if k<1 then s>w else h<=c
if if if a then b else c
then d else f
then g else h<k
Relations
relation
= arithmetic-relation
| character-relation
| text-value-relation
| object-relation
| object-reference-relation
| text-reference-relation
value-relational-operator
= < | <= | = | >= | > | <>
reference-comparator
= == | =/=
The value relational operators have the conventional meaning. Their specific
interpretation is described below in connection to the respective types. The
reference comparators have the same priority level as the relational operators.
Arithmetic relations
arithmetic-relation
= simple-arithmetic-expression
value-relational-operator simple-arithmetic-expression
The relational operators <, <=, =, >=, > and <> have their conventional meaning
(less than, less than or equal to, equal to, greater than or equal to, greater
than, not equal to). Arithmetic relations assume the value true whenever the
corresponding relation is satisfied for the expressions involved, otherwise
false. If the two constituent expressions are of different arithmetic types
conversion to the type with maximum value range is assumed. Consequently
overflow cannot occur during the evaluation.
Character relations
character-relation
= simple-character-expression
value-relational-operator simple-character-expression
Character values may be compared for equality and inequality and ranked with
respect to the collating sequence. Let X and Y be simple character expressions,
and let rel be any value relational operator. Then the relation "X rel Y" has
the same Boolean value as the relation "rank(X) rel rank(Y)".
Note: Because of variations in collating sequences the value of a character
relation (and by implication that of a text relation, see below) is
implementation-defined. Implementation-independent comparison of
character values is obtained by using the procedure "isorank".
Text value relations
text-value-relation
= simple-text-expression
value-relational-operator simple-text-expression
Two text values are equal if they are both empty, or if they are both instances
of the same character sequence, otherwise they are unequal.
A text value T ranks lower than a text value U if and only if they are unequal
and one of the following conditions is fulfilled:
- T is empty.
- U is equal to T followed by one or more characters.
- When comparing T and U from left to right the first non-matching character in T ranks lower than the corresponding character in U.
Object relations
object-relation
= simple-object-expression is class-identifier
| simple-object-expression in class-identifier
The operators is and in may be used to test the class membership of an
object.
The relation "X is C" has the value true if X refers to an object belonging
to the class C, otherwise the value is false.
The relation "X in C" has the value true if X refers to an object belonging
to a class C or a class inner to C, otherwise the value is false.
Object reference relations
object-reference-relation
= simple-object-expression
reference-comparator simple-object-expression
The reference comparators == and =/= may be used for the comparison of
references (as distinct from the corresponding referenced values). Two object
references X and Y are said to be "identical" if they refer to the same object
or if they both are none. In that event the relation "X==Y" has the value
true, otherwise the value is false.
The value of the relation "X=/=Y" is the negation of that of "X==Y".
Text reference relations
text-reference-relation
= simple-text-expression
reference-comparator simple-text-expression
Let T and U be text variables. The relation "T==U" is equivalent to
T.OBJ == U.OBJ and T.START = U.START and T.LENGTH = U.LENGTH
Note: The POS components are ignored. Also observe that the relations
"T=/=U" and "T=U" may both have the value true. (T and U reference
different text frames which contain the same text value.)
The following relations are all true (cf. 2.5)
T = notext eqv T == notext
"" == notext
"ABC" =/= "ABC" (different occurrences)
Example
class C; begin text T; T:- "ABC" end;
The relation "new C.T == new C.T" is true here.
The logical operators
The meaning of the logical operators not, and, or, imp, and eqv is given by the following function table:
b1 false false true true
b2 false true false true
---------------------------------------------------------
not b1 true true false false
b1 and b2 false false false true
b1 or b2 false true true true
b1 imp b2 true true false true
b1 eqv b2 true false false true
----------------------------------------------------------
The operation "b1 and then b2" denotes "conditional and". If the value of
b1 is false the operation yields the result false, otherwise it yields the
result of evaluating b2.
The operation "b1 or else b2" denotes "conditional or". If the value of b1
is true the operator yields the result true, otherwise it yields the result
of evaluating b2.
Note: The value of "b1 and then b2" is given by textual substitution of
the Boolean expression "(if b1 then b2 else false)". Similarly,
the operation "b1 or else b2" is defined by substitution of "(if b1
then true else b2)". These definitions imply that the evaluation
of the second operand is suppressed when the evaluation result is
already evident from the value of the first operand alone.
Precedence of Boolean operators
The sequence of operations within one expression is generally from left to right, with the following additional rules. According to the syntax given in 3.2 the following rules of precedence hold:
first: non-Boolean expressions
second: < <= = >= > <> == =/= is in
third: not
fourth: and
fifth: or
sixth: imp
seventh: eqv
eighth: and then
nineth: or else
The use of parentheses is interpreted in the sense given in 3.5.2.
Arithmetic expressions
arithmetic-expression
= simple-arithmetic-expression
| if-clause simple-arithmetic-expression
else arithmetic-expression
simple-arithmetic-expression
= [ + | - ] term { ( + | - ) term }
term
= factor { ( * | / | // ) factor }
factor
= primary { ** primary }
primary
= unsigned-number
| variable
| function-designator
| "(" arithmetic-expression ")"
An arithmetic expression is a rule for computing a numerical value. In the case
of simple arithmetic expressions this value is obtained by executing the
indicated arithmetic operations on the actual numerical values of the primaries
of the expression, as explained in detail in 3.5.1 below. The value of a
primary is obvious in the case of numbers. For variables it is the current
value (assigned last in the dynamic sense), and for function designators it is
the value arising from the computing rules defining the procedure when applied
to the current values of the procedure parameters given in the expression.
Finally, for arithmetic expressions enclosed by parentheses the value must
through a recursive analysis be expressed in terms of the values of primaries
of the other three kinds.
In the more general arithmetic expressions, which include if-clauses, one out
of several simple arithmetic expressions is selected on the basis of the actual
values of the Boolean expressions (see 3.2). This selection is made as follows:
The Boolean expressions of the if-clauses are evaluated one by one in sequence
from left to right until one having the value true is found. The value of the
arithmetic expression is then the value of the first arithmetic expression
following this Boolean (the longest arithmetic expression found in this
position is understood). If none of the Boolean expressions has the value
true, then the value of the arithmetic expression is the value of the
expression following the final else.
In evaluating an arithmetic expression, all primaries within that expression
are evaluated with the following exceptions:
- Primaries that occur within any expression governed by an if-clause but not selected by it.
- Primaries that occur within a Boolean expression
- after the operator or else when the evaluation of a preceding Boolean tertiary results in false, or
- after the operator and then when the evaluation of a preceding equivalence results in false.
- Primaries that occur after a function designator, and the evaluation of the function terminates with a goto-statement. In this case the evaluation of the arithmetic expression is abandoned.
Primaries: 7.394_604&-8
sum
w(i + 2,8)
cos( y + z*3.141_592_653_589_793_324&&0 )
( a - 3/y + vu**8)
Factors: omega
sum ** cos( y + z*3 )
7.394&-8 ** w(i + 2,8) ** ( a - 3/y + vu ** 8 )
Terms: u
omega * sum ** cos(y + z*3)/7.394&-8 ** (a - 3/y + vu**8)
Simple arithmetic expression:
u - yu + omega*sum**cos(y+z*3)/7.394&-8 **(a-3/y+vu**8)
Arithmetic expressions:
w*u - q(s+cu)**2
if q>0 then s+3*q//a else 2*s+3*q
if a<0 then u+v else if a*b>17 then u/v
else if k >= y then v/u else 0
0.57&12 * a( n*(n-1)//2 ,0 )
( a*arctan(y)+z ) ** (7+Q)
if q then n-1 else n
Operators and types
Apart from the Boolean expressions of if-clauses, the constituents of arithmetic expressions must be of arithmetic types. The meaning of the basic operators and the types of the expressions to which they lead are given by the following rules, where "i" and "j" are of integer type, "r" of real type, and "x" is any arithmetic type:- The operators +, -, and * have their conventional meaning.
- The operator / denotes real division. Any operand of integer type is converted before the operation. Division by zero constitutes an error.
- The operator // denotes integer division. It is valid only for integer
type operands (no implicit conversion). The meaning of "i//j" is defined
by:
integer procedure DIV(i, j); integer i, j; if j=0 then error("..." !div by zero;) else begin integer m, n; m:= 0; n:= abs(i); for n:= n - abs(j) while n>=0 do m:= m + 1; DIV:= if i<0 eqv j>0 then -m else m end DIV; - The operator ** denotes exponentiation. The value and type of the
operation depends upon the types of the operands as follows:
x**r: <type of r> procedure EXPR(x,r);
x; r; if x<0 or (x=0 and r<=0.0) then error("..." !EXPR undefined;); else EXPR := if x>0 then exp(r*ln(x)) else 0.0; i**j: integer procedure EXPI(i,j); integer i,j; if j<0 or i=0 and j=0 then error("..." !EXPI undefined;) else begin integer k,result; result:= 1; for k:= 1 step 1 until j do result:= result*i; EXPI:= result end EXPI r**i: <type of r> procedure EXPN(r, i); r; integer i; if i=0 and r=0.0 then error("..." !EXPN undefined;) else begin result; integer n; result:= 1.0; for n:= abs(i) step -1 until 1 do result := result*r; EXPN:= if i<0 then 1.0/result else result end EXPN;
Note: The result of evaluating an arithmetic expression can never be of type short integer. Conversion from short integer to integer is always exact. Conversion from an integer type to a real type is exact within an implementation-defined range which includes zero. Conversion from real to long real is exact within an implementation-defined range which includes zero. The type of the operation (and by repeated application also the type of the arithmetic expression) is a consequence of the type conversion rule as follows:If one operand is of type long real the other is converted to long real, else if one operand is of type real the other is converted to real, else short integer operands are converted to integer.
SI I R LR
SI I I R LR SI: short integer
I I I R LR I: integer
R R R R LR R: real
LR LR LR LR LR LR: long real
The rule also determines the type of a conditional expression, i.e. an
arithmetic expression of the form
"if B then SAE else AE":Note: The type of a conditional expression is independent of the actual value of the Boolean expression, i.e. it is completely determined by the program text.The expression is of type long real if either SAE or AE is long real. Otherwise, if either SAE or AE is of type real, the type of the expression is real, else the type is integer.
Precedence of arithmetic operators
The sequence of operations within one expression is generally from left to right, with the following additional rules: According to the syntax given in 3.3.1 the following rules of precedence hold:
first: **
second: * / //
third: + -
The expression between a left parentheses and the matching right parenthesis is
evaluated by itself and this value is used in subsequent calculations.
Consequently the desired order of execution of operations within an expression
can always be arranged by appropriate positioning of parentheses.
Note: The order of evaluation of the primaries is not influenced by the
use of parenthesis.
Arithmetics of real quantities
Numbers and variables of real type must be interpreted in the sense of numerical analysis, i.e. as entities defined inherently with only a finite accuracy. Similarly, the possibility of the occurrence of a finite deviation from the mathematically defined result in any arithmetic expression is explicitly understood. No exact arithmetic will be specified, however, and it is indeed understood that, different implementations may evaluate arithmetic expressions differently. The control of the possible consequences of such differences must be carried out by the methods of numerical analysis. This control must be considered a part of the process to be described, and is therefore expressed in terms of the language itself.Character expressions
character-expression
= simple-character-expression
| if-clause simple-character-expression
else character-expression
simple-character-expression
= character-constant
| variable
| function-designator
| "(" character-expression ")"
A character expression is of type character. It is a rule for obtaining a
character value (see 2.1.3). Apart from possible if-clauses, all constituents
of a character expression must be of type character.
Text expressions
text-expression
= simple-text-expression
| if-clause simple-text-expression else text-expression
simple-text-expression
= text-primary { & text-primary }
text-primary
= notext
| string
| variable
| function-designator
| "(" text-expression ")"
A text expression is of type text. It is a rule for obtaining an
identification of a text variable. Apart from possible if-clauses, all
constituents of a text expression must be of type text.
Each textual occurrence of a non-empty string corresponds to a unique constant
main text frame. A given occurrence always references that same frame, while
different occurrences of the same non-empty string always reference different
text frames.
The empty string ("") is textually equivalent to notext.
Text concatenation
The operator & permits text concatenation. The simple text expression "TP1 & TP2 & ... & TPn", where TPi is a text primary (1<=i<=n), references a new alterable main frame whose contents is formed by concatenating copies of the frames referenced by TP1, TP2, ... , TPn (in that order). The expression is equivalent to CONCATENATE_n(T1,T2,...,Tn) defined by
text procedure CONCATENATE_ _n(T1,T2,...,Tn); text T1,T2,...,Tn;
begin text temp;
CONCATENATE_ _n :- temp :- blanks(T1.length+T2.length+ ... +Tn.length);
temp.sub(1,t1.length) := T1;
temp.sub(1+T1.length,T2.length) := T2;
...
temp.sub(1+T1.length+T2.length+... ,Tn.length) := Tn;
end;
Note: It follows that the text primary constituents of a simple text
expression are evaluated in strict lexical order. The evaluation
of Ti may influence the result of evaluating Tj, if i<j (due to
the specified "by reference" transmission of parameters to the
procedures CONCATENATE_n).Observe further that it follows from the syntax (cfr. 3.1.5) that . is evaluated before &, thus the two expressions "T1 & T2.sub(1,2) & T3.main" and "T1 & (T2.sub(1,2)) & (T3.main)" are equivalent.
Text expression evaluation
The result of evaluating- notext, or an empty string, identifies an anonymous text variable whose contents are defined by (2) of 3.1.2.
- a non-empty string identifies an anonymous text variable which references a constant text frame whose value is the internal representation of the external character sequence. This frame is always a main frame. The POS component of the anonymous variable equals 1.
- a text variable identifies the variable itself.
- a text function designator identifies an anonymous text variable which contains a copy of the final contents of the text variable associated with the procedure identifier during the execution of the procedure in question.
- a text expression enclosed by parentheses identifies an anonymous text variable which contains a copy of (the contents of) the text variable identified when evaluating the same expression without parentheses.
- a conditional text expression identifies an anonymous text variable which contains a copy of (the contents of) the text variable identified by the branch which was selected for evaluation.
Object expressions
object-expression
= simple-object-expression
| if-clause simple-object-expression else object-expression
simple-object-expression
= none
| variable
| function-designator
| object-generator
| local-object
| qualified-object
| "(" object-expression ")"
object-generator
= new class-identifier [ actual-parameter-part ]
local-object
= this class-identifier
qualified-object
= simple-object-expression qua class-identifier
An object expression is of type ref(qualification). It is a rule for
obtaining a reference to an object. The value of the expression is the
referenced object or none. Apart from a possible if-clause all constituents
must be of object reference type.
Qualification
The qualification of an object expression is defined by the following rules:- The expression none is qualified by a fictitious class which is inner to all declared classes.
- A variable or function designator is qualified as stated in the declaration (or specification, see below) of the variable or array or procedure in question.
- An object generator, local object or qualified object is qualified by the class of the identifier following the symbol new, this or qua respectively.
- A conditional object expression is qualified by the innermost class which includes the qualifications of both alternatives. If there is no such class, the expression is illegal.
- Any formal parameter of object reference type is qualified according to its specification regardless of the qualification of the corresponding actual parameter.
- The qualification of a function designator whose procedure identifier is that of a virtual quantity depends on the access level (see 5.5.5). The qualification is that of the matching declaration, if any, occurring at the innermost prefix level equal or outer to the access level, or, if no such match exists, it is that of the virtual specification.
Object generator
The value of an object generator is the object generated as the result of its evaluation. See 4.7.Local objects
A local object "this C" is valid provided that the expression is used within- the class body of C or that of any subclass of C, or
- a connection block whose block qualification is C or a subclass of C (see 4.8).
Instantaneous qualification
Let X represent any simple reference expression, and let C and D be class identifiers such that D is the qualification of X. The qualified object "X qua C" is then a legal object expression, provided that C is outer to or equal to D or is a subclass of D. Otherwise, since C and D belong to disjoint prefix sequences, the expression is illegal. If the value of X is none or is an object belonging to a class outer to C, the evaluation of X qua C constitutes a run-time error. Otherwise, the value of X qua C is that of X. Instantaneous qualification restricts or extends the visibility of attributes of a concatenated class object accessible through inspection or remote accessing (cf. 3.1.5 and 4.8).Designational expressions
designational-expression
= simple-designational-expression
| if-clause simple-designational-expression
else designational-expression
simple-designational-expression
= label
| switch-designator
| "(" designational-expression ")"
switch-designator
= switch-identifier "(" subscript-expression ")"
switch-identifier
= identifier
label
= identifier
A designational expression is a rule for obtaining a reference to a program
point. The principle of the evaluation is entirely analogous to that of
arithmetic expressions. In the general case the Boolean expressions of the
if-clauses select a simple designational expression. If this is a label the
desired result is already found. A switch designator refers to the
corresponding switch declaration and by the actual numerical value of its
subscript expression selects one of the designational expressions listed in the
switch declaration by counting these from left to right. Since the expression
thus selected may again be a switch designator this evaluation is obviously a
recursive process.
The evaluation of the subscript expression is analogous to that of subscripted
variables. The value of a switch designator is defined only if the subscript
expression assumes one of the values 1, 2, ... , n, where n is the number of
entries in the switch list. A value outside this range causes a run time
error.
Note: It is a consequence of the syntax that class attributes which are labels or switches cannot be accessed by the dot notation.