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:

  1. The value X is different from none.
  2. The object referenced by X has no class attribute declared at any prefix level equal or outer to that of C.

Note: Condition 1 corresponds to a check which causes an error if the value of X is none.
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 expression

                P1.plus (P2)

is a new "point" object which represents the vector sum of P1 and P2. The value of the expression

                P1 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:

  1. T is empty.
  2. U is equal to T followed by one or more characters.
  3. 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 are always evaluated in strict lexical order.

Examples:

     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:

It is understood that the finite deviations of using the exponentiation operator may be different from those of using the procedures EXPR and EXPN.

If the operands of an arithmetic operator are of different types, or both short integer, an appropriate type conversion function is understood to be automatically invoked, except as explicitly noted above, before the operation is evaluated 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.

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:

                     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":

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.

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.

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

For further information on the text concept, see chapter 8.

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:

  1. The expression none is qualified by a fictitious class which is inner to all declared classes.
  2. 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.
  3. An object generator, local object or qualified object is qualified by the class of the identifier following the symbol new, this or qua respectively.
  4. 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.
  5. Any formal parameter of object reference type is qualified according to its specification regardless of the qualification of the corresponding actual parameter.
  6. 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

  1. the class body of C or that of any subclass of C, or
  2. a connection block whose block qualification is C or a subclass of C (see 4.8).

The value of a local object in a given context is the object which is, or is connected by, the smallest textually enclosing block instance in which the local object is valid. If there is no such block the local object is illegal (in the given context). For an instance of a procedure or a class body, "textually enclosing" means containing its declaration.

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.