Home Up Intro Contents Chapter 1 2 3 4 5 6 7 8 9 10 Design Assert Timing EBNF Report Pas Last Changed: July 12th, 1997
This is a conversion from Oberon text to HTML, and from German to English. The converter software is still under development, and some features or information may be missing in this converted version. HTML hypertext facilities are not yet active in this document. To exploit the interactive facilities, use Oberon System 3 and the source of this text, available for download using binary ftp as Oberon System 3 archive. The converter from German to English is still under development as well. A previous version is also available for Oberon V4. To access this and other additional material use ftp.
For the convenience of our students, most of this information and the related material is available in German as well.

Introduction to Oberon

The Oberon Programming Language

G. Sawitzki <gs@statlab.uni-heidelberg.de>



06 Control Structures

Like in most programming languages, the actual program is described as a sequence of instructions in Oberon. We already met these instruction sequences in the body section of a module, as well as in procedure declarations. The examples we have seen up to now were strictly sequential: the statements were executed in exactly the order in which they are given.

Only few problems can be solved in a strictly sequential way. Among others, for a problem to allow a strictly sequential solution, there must be an algorithm which leads to the required solution in a fixed (a priori given) number of steps. Even elementary problems, like for example writing a decimal expression for a rational number, do not fall into this class. We need a possibility of controlling an algorithm in a way which might dependent on intermediate results. Thus besides the linear sequential structure in which a program is written down, we will have another structure, or a group of structures, called control structures.

In Oberon there are two elementary control structures: the IF statement and the LOOP statement. The IF statement only executes a statement sequence if a controlling logical expression is true. The LOOP statement repeatedly executes a series of instructions.

The formal syntax of the elementary control structure in Oberon is:
Elementary IF Statement:
  IF expression THEN
    statement sequence
  END

LOOP Statement:
  LOOP
    statement sequence
  END


The interpretation of the IF statement is immediate. Expression can be any expression which evaluates to one of the logical values, TRUE or FALSE. The meaning corresponds to what the English-language formulation suggest. The statement sequence in the IF statement is executed if the expression evalutates as TRUE. If the expression yields FALSE, the statement sequence is not executed.
Example
  IF ( i MOD 3) = 0 THEN
    Texts.WriteString(W,"i is divisible by 3.")
  END;

The interpretation of the LOOP statement is more delicate. The statement sequence in the LOOP statement is executed repeatedly. This is a rather exceptional situation. The operating system is one of these rare exceptions. In principle it reduces to a LOOP statement of the following form:
LOOP
  ... (* identify next command *)
  ... (* execute command *)
END

In most cases however a statement sequence should not repeat indefinitely for all times, but only until some controlled condition is satisfied: there must be a way to terminate a LOOP statement. This leads to a set of specializations which we will discuss later in this section.

All control structures can be used exactly the same way as individual statements can. In formal definitions of the language they are but special cases of the general class of statements. If it is necessary to point out their more complex internal structure out, they are called structured statements. Languages with structured statements are called structured programming languages.

Both elementary control structures come with various versions. These versions could be expressed logically as statement sequences using the elementary control structures. Because they are used very frequently, they are defined as language constituents. We look at the IF statement first, and return to the LOOP statement later.

The IF statement may have an alternative. Example:
  IF ( i MOD 3) = 0 THEN
    Texts.WriteString(W,"i is divisible by 3.")
  ELSE
    Texts.WriteString(W,"i is not divisible by 3.")
  END;

IF statements can form a "cascade". Cascades can be used with or without alternative. Example:
  IF length >= 1000 THEN
    Texts.WriteReal(W,length/1000,6);
    Texts.WriteString(W,"km.")
  ELSEIF length >= 1 THEN
    Texts.WriteReaFixl(W,length,6,2);
    Texts.WriteString(W,"m.")
  ELSE
    Texts.WriteRealFix(W,length*100,6,2);
    Texts.WriteString(W,"cm.")
  END;

The complete syntax is
IF Statement:
  IF expression THEN
    statement sequence
   {ELSIF expression THEN
    statement sequence}
  [ELSE
statement sequence]
  END

For the special case that a list of cases needs to be handled which one could write as list of integral or CHAR values, there is a special CASE statement. The "cases" in this CASE statement must be constant expressions, i.e. their values must be determined at compiling time. While for in an IF statement the expressions are evaluated in the given order, for a CASE statement the evaluation and the analysis of the decision takes place only once at entrance of the CASE statement.

CASE Statement:
  CASE expression OF
    case
    {
| case }
  [ELSE
statement sequence]
  END
where
Case:
  Case list : statement sequence
Case List:
  Case label {, Case label}
Case Label:
  Case expression [.. Case expression]

Example:
  CASE ch OF
    "A".."Z":  Texts.WriteString(W,"letter (upper case)")
  |  "a".."z":  Texts.WriteString(W,""letter (lower case)")
  |  "0".."9":  Texts.WriteString(W,"digit")
  |  ".", ",", ":", "?", "!":  Texts.WriteString(W,"mark")
  ELSE  Texts.WriteString(W,"something else")
  END

The LOOP statement is only left by an EXIT statement in the statement sequence. The statement EXIT leaves the containing LOOP statement. Processing is continued with the next statement following the LOOP statement.

Example:
LOOP
  ... (* any statement sequence, for example a calculation with I *)
  IF I>IMAX OR I<IMIN THEN EXIT;
  ... (* any statement sequence, for example a calculation with I *)
END

In principle the inner core of Oberon is just one LOOP statement. A simplified picture is:
LOOP
  ... identify (* next command *)
  IF... (* command = System.Quit *) THEN EXIT END;
  ... (* otherwise: execute command *)
END

The LOOP construct is inherently dangerous: the programmer has to guarantee that the LOOP construct will leave correctly. The LOOP is left by EXIT. But execution is not continued after the EXIT statement, but after the end of the appropriate LOOP statement: Non-local knowledge of the program structure is necessary in order to be able to interpret the control flow. Even harmless looking LOOP construct can be insidious. Example:

LOOP
IF X=1 THEN EXIT
  ELSIF X MOD 2 = 0 THEN X:=X DIV 2 ELSE X: = TO X*3+1 END;
END;

Try to find out whether this program fragment will leave for an arbitrary integral value of X. Do not be disappointed, if you did not find the solution by next morning.

For the LOOP statement there are these variants:
REPEAT Statement:
  REPEAT
     statement sequence
  UNTIL expression ;

The statement sequence in the REPEAT statement is executed and repeated until the expression yields TRUE.

WHILE Statement:
  WHILE expression
  DO
    statement sequence
  END

The REPEAT statement sequence is at least executed once. After execution of the statement sequence the expression is checked, and the repear statement sequence is repeated unless the expression yields TRUE. For a WHILE statement the expression is evaluated first. Only if the expression has the value TRUE the statement sequence is executed and repeated, until the expression is FALSE. If the expression yields FALSE at start, the statement sequence is not executed at all.



Exercises:

Let i,k be integer variables and k=0. What is the meaning of

  k:=0;
  WHILE i > 0 DO i := i DIV 2; k := k + 1 END

Give a LOOP statement, which is equivalent to this WHILE statement.

What is the meaning of this REPEAT statement?
  k:=0;  REPEAT i := i DIV 2; k := k + 1 UNTIL i<=0
(Hint: Discuss the cases i>0, i=0, i<0 one by one).




An additional loop construction, used commonly in other languages, is

FOR Statement:
  FOR name :=expression TO expression [BY constant expression] DO
    statement sequence
  END


The statement

  FOR v := beg TO end BY step DO statements END

is equivalent to
temp := end; v := beg;
IF step > 0 THEN
  WHILE v <= temp DO statements; v := v + step END
ELSE
  WHILE v >= temp DO statements; v := v + step END
END

The FOR statement is used when a statement sequence is to be executed for a successive set of values of some variable. Name must be a variable of integer type. Its value is set on that of the first expression and with each turn it is changed by the the increment const expression, as long as the second expression is not exceeded. The constant expression must have the same type as the variable. It may not have the value 0. If no increment is given, then the increment 1 is taken.



Exercises:

Which output is produced by the following FOR statements:
a)  FOR I:= 1 TO 10 DO Texts.WriteInt(W,I,20) END
b)  FOR I:= 8 TO 8 DO Texts.WriteInt(W,I,20) END
c)  FOR I:= 10 TO 0 DO Texts.WriteInt(W,I,20) END
d)  FOR I:= 5 TO 0 BY -1 DO Texts.WriteInt(W,I,20) END
e)  FOR I:= 5 TO 0 BY -2 DO Texts.WriteInt(W,I,20) END
f)  FOR I:= 5 TO 10 BY -5 DO Texts.WriteInt(W,I,20) END



The FOR statement makes some iteration constructs simpler. It should however be used only in trivial situations. In critical situations its meaning is not always obvious. E.g. what is the meaning of the following ( formally admissible) statement:
...
FOR I:= I-11 TO I+1 DO ... END



Exercises:

1.) Calculate and tabulate n! for n=0... 10.

2.) Calculate and tabulate n! as far as n! can be represented as number of the type INTEGER resp. LONGINT.


3.) Tabulate n for k=1,2... the value of min {: n! > = 2k} as far as possible.

4.) A linear congruence generator is a pseudo-random number generator which generates numbers following the rule
     x - > (ax + b) MOD m.
a)  Write a program that generates pseudo-random numbers for constants of a, b, m and write n of the generated numbers. Try different constants. How do you select an initial value?
b)  If necessary, check and modify your program in such a way that it works correctly for all a, x, b, m: MAX(LONGINT)>=a, x>0, MAX(LONGINT) > =b>=0.
Generate 1000 pseudo-random numbers each with the following generators:
  (Lewis, Goodman, Miller ) a=75=16807, b=0, m=231-1
  (Payne, Rebung, Bogyo)  a=630360016, b=0, m=231-1
  (UNIX rand)      a=1103515245, b=12345, m=231
  [Literature: B.D. Ripley, Computer Generation of Random Variables: A Tutorial. International Statistical Review 51 (1983) 301-319;
see also Reiser&Wirth, Ch.2]

5.) Take the time to generate 10, 100, 1000, 10000, 100000 random numbers. Use the program fragment Test2 in ItO/ItOTime06.Mod. Which measurements are below time measurement resolution? How reliable are the measured values?



The pre-defined procedure HALT allows to break all current control structures and of leaving a process. HALT is called as HALT(status), where status is a value which is returned to the global environment. In a sense, HALT is an ultimate exit. Oberon modules are resident,s even after a HALT abort. The module remains loaded, and on all exported variables can be accessed even after the abort. The handling of HALT is implementation dependent. Usually the control is transferred to the Oberon module, and Oberon would open a window with a diagnostic message.

Control statements play different roles in different stages of program development. Besides control statements directing the intended program flow, there may be implementation dependent additional control statements to support error handling. The most important of these is the ASSERT statement. It called as ASSERT(condition,status). The meaning is equivalent to
  IF condition THEN HALT(status) END;
In contrast to the IF construct, the implementation is controlled by the compiler. Usually there is a compiler option which permits to swich off or on any code generation for ASSERTs. With the appropriate option set on, ASSERT statements are generated and the appropriate checks are executed. Without this option set to off, no ASSERT code is generated. Since the ASSERT statements are administered by the compiler it offer a possibility for code analysis and diagnostics. The use of ASSERTs and further checks is discussed in a special chapter.

Different compilers offer specific possibilities for diagnostics and program checkin. These options are documented in the respective compiler documents.



Exercises:

Which control and test options are offered by your compiler? For system 3 you find more information in

  Compiler.Tool




Introduction to the Oberon programming language. ItO/Ch06.Text
gs (c) G. Sawitzki, StatLab Heidelberg
<http://statlab.uni-heidelberg.de/projects/oberon/intro/>

Home Up Intro Contents Chapter 1 2 3 4 5 6 7 8 9 10 Design Assert Timing EBNF Report Pas