Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6613 leency 1
2
3
4
5
<p>The Programming Language Oberon</p><p>Revision 22.9.2011</p><p>Niklaus Wirth</p>
6

Make it as simple as possible, but not simpler.

(A. Einstein)
7

Table of Contents

8
9

1. Introduction

10

2. Syntax

11

3. Vocabulary

12

4. Declarations and scope rules

13

5. Constant declarations

14

6. Type declarations

15

7. Variable declarations

16

8. Expressions

17

9. Statements

18

10. Procedure declarations

19

11. Modules

20

Appendix: The Syntax of Oberon

21
<p>1. Introduction</p>
22

Oberon is a general-purpose programming language that evolved from Modula-2. Its principal new feature is the concept of type extension. It permits the construction of new data types on the basis of existing ones and to relate them.

23

This report is not intended as a programmer's tutorial. It is intentionally kept concise. Its function is to serve as a reference for programmers, implementors, and manual writers. What remains unsaid is mostly left so intentionally, either because it is derivable from stated rules of the language, or because it would unnecessarily restrict the freedom of implementors.

24

This document describes the language defined in 1988/90 as revised in 2007/11.

25
26
<p>2. Syntax</p>
27

A language is an infinite set of sentences, namely the sentences well formed according to its syntax. In Oberon, these sentences are called compilation units. Each unit is a finite sequence of symbols from a finite vocabulary. The vocabulary of Oberon consists of identifiers, numbers, strings, operators, delimiters, and comments. They are called lexical symbols and are composed of sequences of characters. (Note the distinction between symbols and characters.)

28

To describe the syntax, an extended Backus-Naur Formalism called EBNF is used. Brackets [ and ] denote optionality of the enclosed sentential form, and braces { and } denote its repetition (possibly 0 times). Syntactic entities (non-terminal symbols) are denoted by English words expressing their intuitive meaning. Symbols of the language vocabulary (terminal symbols) are denoted by strings enclosed in quote marks or by words in capital letters.

29
30
<p>3. Vocabulary</p>
31

The following lexical rules must be observed when composing symbols. Blanks and line breaks must not occur within symbols (except in comments, and blanks in strings). They are ignored unless they are essential to separate two consecutive symbols. Capital and lower-case letters are considered as being distinct.

32

Identifiers are sequences of letters and digits. The first character must be a letter.

33
34

ident = letter {letter | digit}.

35
36

Examples:

37
38

x scan Oberon GetSymbol firstLetter

39
40

Numbers are (unsigned) integers or real numbers. Integers are sequences of digits and may be followed by a suffix letter. If no suffix is specified, the representation is decimal. The suffix H indicates hexadecimal representation.

41

A real number always contains a decimal point. Optionally it may also contain a decimal scale factor. The letter E is pronounced as "times ten to the power of". A real number is of type REAL, unless it contains a scale factor with the letter D, in which case it is of type LONGREAL.

42
43

number = integer | real.

44

integer = digit {digit} | digit {hexDigit} "H".

45

real = digit {digit} "." {digit} [ScaleFactor].

46

ScaleFactor = ("E" | "D") ["+" | "-"] digit {digit}.

47

hexDigit = digit | "A" | "B" | "C" | "D" | "E" | "F".

48

digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9".

49
50

Examples:

51
52

1987

53

100H = 256

54

12.3

55

4.567E8 = 456700000

56
57

Strings are sequences of characters enclosed in quote marks ("). A string cannot contain the delimiting quote mark. Alternatively, a single-character string may be specified by the ordinal number of the character in hexadecimal notation followed by an "X". The number of characters in a string is called the length of the string.

58
59

string = """ {character} """ | digit {hexdigit} "X" .

60
61

Examples:

62
63

"OBERON" "Don't worry!" 22X

64
65

Operators and delimiters are the special characters, character pairs, or reserved words listed below. These reserved words consist exclusively of capital letters and cannot be used in the role of identifiers.

66
67

+ := ARRAY IMPORT THEN

68

- ^ BEGIN IN TO

69

* = BY IS TRUE

70

/ # CASE MOD TYPE

71

~ < CONST MODULE UNTIL

72

& > DIV NIL VAR

73

. <= DO OF WHILE

74

, >= ELSE OR

75

; .. ELSIF POINTER

76

| : END PROCEDURE

77

( ) FALSE RECORD

78

[ ] FOR REPEAT

79

{ } IF RETURN

80
81

Comments may be inserted between any two symbols in a program. They are arbitrary character sequences opened by the bracket (* and closed by *). Comments do not affect the meaning of a program. They may be nested.

82
83
<p>4. Declarations and scope rules</p>
84

Every identifier occurring in a program must be introduced by a declaration, unless it is a predefined identifier. Declarations also serve to specify certain permanent properties of an object, such as whether it is a constant, a type, a variable, or a procedure.

85

The identifier is then used to refer to the associated object. This is possible in those parts of a program only which are within the scope of the declaration. No identifier may denote more than one object within a given scope. The scope extends textually from the point of the declaration to the end of the block (procedure or module) to which the declaration belongs and hence to which the object is local. The scope rule has the following amendments:

86

1. If a type T is defined as POINTER TO T1 (see 6.4), the identifier T1 can be declared textually following the declaration of T, but it must lie within the same scope.

87

2. Field identifiers of a record declaration (see 6.3) are valid in field designators only.

88

In its declaration, an identifier in the global scope may be followed by an export mark (*) to indicate that it be exported from its declaring module. In this case, the identifier may be used in other modules, if they import the declaring module. The identifier is then prefixed by the identifier designating its module (see Ch. 11). The prefix and the identifier are separated by a period and together are called a qualified identifier.

89
90

qualident = [ident "."] ident.

91

identdef = ident ["*"].

92
93

The following identifiers are predefined; their meaning is defined in section 6.1 (types) or 10.2 (procedures):

94
95

ABS ASR ASSERT BOOLEAN CHAR

96

CHR COPY DEC EXCL FLOOR

97

FLT INC INCL INTEGER LEN

98

LSL LONG LONGREAL NEW ODD

99

ORD PACK REAL ROR SET

100

SHORT UNPK

101
102
<p>5. Constant declarations</p>
103

A constant declaration associates an identifier with a constant value.

104
105

ConstantDeclaration = identdef "=" ConstExpression.

106

ConstExpression = expression.

107
108

A constant expression can be evaluated by a mere textual scan without actually executing the program. Its operands are constants (see Ch. 8). Examples of constant declarations are:

109
110

N = 100

111

limit = 2*N - 1

112

all = {0 .. WordSize-1}

113

name = "Oberon"

114
115
<p>6. Type declarations</p>
116

A data type determines the set of values which variables of that type may assume, and the operators that are applicable. A type declaration is used to associate an identifier with a type. The types define the structure of variables of this type and, by implication, the operators that are applicable to components. There are two different structures, namely arrays and records, with different component selectors.

117
118

TypeDeclaration = identdef "=" StrucType.

119

StrucType = ArrayType | RecordType | PointerType | ProcedureType.

120

type = qualident | StrucType.

121
122

Examples:

123
124

Table = ARRAY N OF REAL

125

Tree = POINTER TO Node

126

Node = RECORD

127

key: INTEGER;

128

left, right: Tree

129

END

130

CenterNode = RECORD (Node)

131

name: ARRAY 32 OF CHAR;

132

subnode: Tree

133

END

134

Function = PROCEDURE (x: INTEGER): INTEGER

135
<p>6.1. Basic types</p>
136

The following basic types are denoted by predeclared identifiers. The associated operators are defined in 8.2, and the predeclared function procedures in 10.2. The values of a given basic type are the following:

137
138

BOOLEAN the truth values TRUE and FALSE

139

CHAR the characters of a standard character set

140

INTEGER the integers

141

REAL real numbers

142

LONGREAL real numbers

143

SET the sets of integers between 0 and 31

144
145

The type LONGREAL is intended to represent real numbers with a higher number of digits than REAL. However, the two types may be identical.

146
147
<p>6.2. Array types</p>
148

An array is a structure consisting of a fixed number of elements which are all of the same type, called the element type. The number of elements of an array is called its length. The elements of the array are designated by indices, which are integers between 0 and the length minus 1.

149
150

ArrayType = ARRAY length {"," length} OF type.

151

length = ConstExpression.

152
153

A declaration of the form

154
155

ARRAY N0, N1, ... , Nk OF T

156

is understood as an abbreviation of the declaration
157

ARRAY N0 OF

158

ARRAY N1 OF

159

...

160

ARRAY Nk OF T

161
162

Examples of array types:

163
164

ARRAY N OF INTEGER

165

ARRAY 10, 20 OF REAL

166
167
<p>6.3. Record types</p>
168

A record type is a structure consisting of a fixed number of elements of possibly different types. The record type declaration specifies for each element, called field, its type and an identifier which denotes the field. The scope of these field identifiers is the record definition itself, but they are also visible within field designators (see 8.1) referring to elements of record variables.

169
170

RecordType = RECORD ["(" BaseType ")"] [FieldListSequence] END.

171

BaseType = qualident.

172

FieldListSequence = FieldList {";" FieldList}.

173

FieldList = IdentList ":" type.

174

IdentList = identdef {"," identdef}.

175
176

If a record type is exported, field identifiers that are to be visible outside the declaring module must be marked. They are called public fields; unmarked fields are called private fields.

177

Record types are extensible, i.e. a record type can be defined as an extension of another record type. In the examples above, CenterNode (directly) extends Node, which is the (direct) base type of CenterNode. More specifically, CenterNode extends Node with the fields name and subnode.

178

Definition: A type T extends a type T0, if it equals T0, or if it directly extends an extension of T0. Conversely, a type T0 is a base type of T, if it equals T, or if it is the direct base type of a base type of T.

179

Examples of record types:

180
181

RECORD day, month, year: INTEGER

182

END

183

RECORD

184

name, firstname: ARRAY 32 OF CHAR;

185

age: INTEGER;

186

salary: REAL

187

END

188
189
<p>6.4. Pointer types</p>
190

Variables of a pointer type P assume as values pointers to variables of some type T. It must be a record type. The pointer type P is said to be bound to T, and T is the pointer base type of P. Pointer types inherit the extension relation of their base types, if there is any. If a type T is an extension of T0 and P is a pointer type bound to T, then P is also an extension of P0, the pointer type bound to T0.

191
192

PointerType = POINTER TO type.

193
194

If p is a variable of type P = POINTER TO T, then a call of the predefined procedure NEW(p) has the following effect (see 10.2): A variable of type T is allocated in free storage, and a pointer to it is assigned to p. This pointer p is of type P and the referenced variable p^ is of type T. Failure of allocation results in p obtaining the value NIL. Any pointer variable may be assigned the value NIL, which points to no variable at all.

195
196
<p>6.5. Procedure types</p>
197

Variables of a procedure type T have a procedure (or NIL) as value. If a procedure P is assigned to a procedure variable of type T, the (types of the) formal parameters of P must be the same as those indicated in the formal parameters of T. The same holds for the result type in the case of a function procedure (see 10.1). P must not be declared local to another procedure, and neither can it be a standard procedure.

198
199

ProcedureType = PROCEDURE [FormalParameters].

200
201
202
<p>7. Variable declarations</p>
203

Variable declarations serve to introduce variables and associate them with identifiers that must be unique within the given scope. They also serve to associate fixed data types with the variables.

204
205

VariableDeclaration = IdentList ":" type.

206
207

Variables whose identifiers appear in the same list are all of the same type. Examples of variable declarations (refer to examples in Ch. 6):

208
209

i, j, k: INTEGER

210

x, y: REAL

211

p, q: BOOLEAN

212

s: SET

213

f: Function

214

a: ARRAY 100 OF REAL

215

w: ARRAY 16 OF

216

RECORD

217

ch: CHAR;

218

count: INTEGER

219

END

220

t: Tree

221
222
<p>8. Expressions</p>
223

Expressions are constructs denoting rules of computation whereby constants and current values of variables are combined to derive other values by the application of operators and function procedures. Expressions consist of operands and operators. Parentheses may be used to express specific associations of operators and operands.

224
<p>8.1. Operands</p>
225

With the exception of sets and literal constants, i.e. numbers and strings, operands are denoted by designators. A designator consists of an identifier referring to the constant, variable, or procedure to be designated. This identifier may possibly be qualified by module identifiers (see Ch. 4 and 11), and it may be followed by selectors, if the designated object is an element of a structure.

226

If A designates an array, then A[E] denotes that element of A whose index is the current value of the expression E. The type of E must be of type INTEGER. A designator of the form A[E1, E2, ..., En] stands for A[E1][E2] ... [En]. If p designates a pointer variable, p^ denotes the variable which is referenced by p. If r designates a record, then r.f denotes the field f of r. If p designates a pointer, p.f denotes the field f of the record p^, i.e. the dot implies dereferencing and p.f stands for p^.f.

227

The typeguard v(T0) asserts that v is of type T0, i.e. it aborts program execution, if it is not of type T0. The guard is applicable, if

228

1. T0 is an extension of the declared type T of v, and if

229

2. v is a variable parameter of record type, or v is a pointer.

230
231

designator = qualident {selector}.

232

selector = "." ident | "[" ExpList "]" | "^" | "(" qualident ")".

233

ExpList = expression {"," expression}.

234
235

If the designated object is a variable, then the designator refers to the variable's current value. If the object is a procedure, a designator without parameter list refers to that procedure. If it is followed by a (possibly empty) parameter list, the designator implies an activation of the procedure and stands for the value resulting from its execution. The (types of the) actual parameters must correspond to the formal parameters as specified in the procedure's declaration (see Ch. 10).

236

Examples of designators (see examples in Ch. 7):

237
238

i (INTEGER)

239

a[i] (REAL)

240

w[3].ch (CHAR)

241

t.key (INTEGER)

242

t.left.right (Tree)

243

t(CenterNode).subnode (Tree)

244
245
<p>8.2. Operators</p>
246

The syntax of expressions distinguishes between four classes of operators with different precedences (binding strengths). The operator ~ has the highest precedence, followed by multiplication operators, addition operators, and relations. Operators of the same precedence associate from left to right. For example, x-y-z stands for (x-y)-z.

247
248

expression = SimpleExpression [relation SimpleExpression].

249

relation = "=" | "#" | "<" | "<=" | ">" | ">=" | IN | IS.

250

SimpleExpression = ["+"|"-"] term {AddOperator term}.

251

AddOperator = "+" | "-" | OR.

252

term = factor {MulOperator factor}.

253

MulOperator = "*" | "/" | DIV | MOD | "&" .

254

factor = number | string | NIL | TRUE | FALSE |

255

set | designator [ActualParameters] | "(" expression ")" | "~" factor.

256

set = "{" [element {"," element}] "}".

257

element = expression [".." expression].

258

ActualParameters = "(" [ExpList] ")" .

259
260

The available operators are listed in the following tables. In some instances, several different operations are designated by the same operator symbol. In these cases, the actual operation is identified by the type of the operands.

261
<p><emphasis>8.2.1. Logical operators</emphasis></p>
262

symbol result

263
264

OR logical disjunction

265

& logical conjunction

266

~ negation

267
268

These operators apply to BOOLEAN operands and yield a BOOLEAN result.

269
270

p OR q stands for "if p then TRUE, else q"

271

p & q stands for "if p then q, else FALSE"

272

~ p stands for "not p"

273
274
<p><emphasis>8.2.2. Arithmetic operators</emphasis></p>
275

symbol result

276
277

+ sum

278

- difference

279

* product

280

/ quotient

281

DIV integer quotient

282

MOD modulus

283
284

The operators +, -, *, and / apply to operands of numeric types. Both operands must be of the same type, which is also the type of the result. When used as unary operators, - denotes sign inversion and + denotes the identity operation.

285

The operators DIV and MOD apply to integer operands only. Let q = x DIV y, and r = x MOD y. Then quotient q and remainder r are defined by the equation

286
287

x = q*y + r 0 <= r < y

288
289
<p><emphasis>8.2.3. Set operators</emphasis></p>
290

symbol result

291
292

+ union

293

- difference

294

* intersection

295

/ symmetric set difference

296
297

When used with a single operand of type SET, the minus sign denotes the set complement.

298
299
<p><emphasis>8.2.4. Relations</emphasis></p>
300

symbol relation

301
302

= equal

303

# unequal

304

< less

305

<= less or equal

306

> greater

307

>= greater or equal

308

IN set membership

309

IS type test

310
311

Relations are Boolean. The ordering relations <, <=, >, >= apply to the numeric types, CHAR, and character arrays. The relations = and # also apply to the types BOOLEAN and SET, and to pointer and procedure types. The relations <= and >= denote inclusion when applied to sets.

312

x IN s stands for "x is an element of s". x must be of type INTEGER, and s of type SET.

313

v IS T stands for "v is of type T" and is called a type test. It is applicable, if

314

1. T is an extension of the declared type T0 of v, and if

315

2. v is a variable parameter of record type or v is a pointer.

316

Assuming, for instance, that T is an extension of T0 and that v is a designator declared of type T0, then the test v IS T determines whether the actually designated variable is (not only a T0, but also) a T. The value of NIL IS T is undefined.

317

Examples of expressions (refer to examples in Ch. 7):

318
319

1987 (INTEGER)

320

i DIV 3 (INTEGER)

321

~p OR q (BOOLEAN)

322

(i+j) * (i-j) (INTEGER)

323

s - {8, 9, 13} (SET)

324

a[i+j] * a[i-j] (REAL)

325

(0<=i) & (i<100) (BOOLEAN)

326

t.key = 0 (BOOLEAN)

327

k IN {i .. j-1} (BOOLEAN)

328

t IS CenterNode (BOOLEAN)

329
330
331
332
<p>9. Statements</p>
333

Statements denote actions. There are elementary and structured statements. Elementary statements are not composed of any parts that are themselves statements. They are the assignment and the procedure call. Structured statements are composed of parts that are themselves statements. They are used to express sequencing and conditional, selective, and repetitive execution. A statement may also be empty, in which case it denotes no action. The empty statement is included in order to relax punctuation rules in statement sequences.

334
335

statement = [assignment | ProcedureCall | IfStatement | CaseStatement |

336

WhileStatement | RepeatStatement | ForStatement].

337
<p>9.1. Assignments</p>
338

The assignment serves to replace the current value of a variable by a new value specified by an expression. The assignment operator is written as ":=" and pronounced as becomes.

339
340

assignment = designator ":=" expression.

341
342

If a value parameter is structured (of array or record type), no assignment to it or to its elements are permitted. Neither may assignments be made to imported variables.

343

The type of the expression must be the same as that of the designator. The following exceptions hold:

344

1. The constant NIL can be assigned to variables of any pointer or procedure type.

345

2. Strings can be assigned to any array of characters, provided the number of characters in the string is not greater than that of the array. If it is less, a null character (0X) is appended. Singlecharacter strings can also be assigned to variables of type CHAR.

346

3. In the case of records, the type of the source must be an extension of the type of the destination. Examples of assignments (see examples in Ch. 7):

347
348

i := 0

349

p := i = j

350

x := FLT(i + 1)

351

k := (i + j) DIV 2

352

f := log2

353

s := {2, 3, 5, 7, 11, 13}

354

a[i] := (x+y) * (x-y)

355

t.key := i

356

w[i+1].ch := "A"

357
358
<p>9.2. Procedure calls</p>
359

A procedure call serves to activate a procedure. The procedure call may contain a list of actual parameters which are substituted in place of their corresponding formal parameters defined in the procedure declaration (see Ch. 10). The correspondence is established by the positions of the parameters in the lists of actual and formal parameters respectively. There exist two kinds of parameters: variable and value parameters.

360

In the case of variable parameters, the actual parameter must be a designator denoting a variable. If it designates an element of a structured variable, the selector is evaluated when the formal/actual parameter substitution takes place, i.e. before the execution of the procedure. If the parameter is a value parameter, the corresponding actual parameter must be an expression. This expression is evaluated prior to the procedure activation, and the resulting value is assigned to the formal parameter which now constitutes a local variable (see also 10.1.).

361
362

ProcedureCall = designator [ActualParameters].

363
364

Examples of procedure calls:

365
366

ReadInt(i) (see Ch. 10)

367

WriteInt(2*j + 1, 6)

368

INC(w[k].count)

369
370
<p>9.3. Statement sequences</p>
371

Statement sequences denote the sequence of actions specified by the component statements which are separated by semicolons.

372
373

StatementSequence = statement {";" statement}.

374
375
<p>9.4. If statements</p>
376

IfStatement = IF expression THEN StatementSequence

377

{ELSIF expression THEN StatementSequence}

378

[ELSE StatementSequence]

379

END.

380
381

If statements specify the conditional execution of guarded statements. The Boolean expression preceding a statement is called its guard. The guards are evaluated in sequence of occurrence, until one evaluates to TRUE, whereafter its associated statement sequence is executed. If no guard is satisfied, the statement sequence following the symbol ELSE is executed, if there is one.

382

Example:

383
384

IF (ch >= "A") & (ch <= "Z") THEN ReadIdentifier

385

ELSIF (ch >= "0") & (ch <= "9") THEN ReadNumber

386

ELSIF ch = 22X THEN ReadString

387

END

388
389
<p>9.5. Case statements</p>
390

Case statements specify the selection and execution of a statement sequence according to the value of an expression. First the case expression is evaluated, then the statement sequence is executed whose case label list contains the obtained value. The case expression must be of type INTEGER or CHAR, and all labels must be integers or single-character strings, respectively.

391
392

CaseStatement = CASE expression OF case {"|" case} END.

393

case = [CaseLabelList ":" StatementSequence].

394

CaseLabelList = LabelRange {"," LabelRange}.

395

LabelRange = label [".." label].

396

label = integer | string | ident.

397
398

Example:

399
400

CASE k OF

401

0: x := x + y

402

| 1: x := x - y

403

| 2: x := x * y

404

| 3: x := x / y

405

END

406
407
<p>9.6. While statements</p>
408

While statements specify repetition. If any of the Boolean expressions (guards) yields TRUE, the corresponding statement sequence is executed. The expression evaluation and the statement execution are repeated until none of the Boolean expressions yields TRUE.

409
410

WhileStatement = WHILE expression DO StatementSequence

411

{ELSIF expression DO StatementSequence} END.

412
413

Examples:

414
415

WHILE j > 0 DO

416

j := j DIV 2; i := i+1

417

END

418

WHILE (t # NIL) & (t.key # i) DO

419

t := t.left

420

END

421

WHILE m > n DO m := m - n

422

ELSIF n > m DO n := n - m

423

END

424
425
<p>9.7. Repeat Statements</p>
426

A repeat statement specifies the repeated execution of a statement sequence until a condition is satisfied. The statement sequence is executed at least once.

427
428

RepeatStatement = REPEAT StatementSequence UNTIL expression.

429
430
<p>9.8. For statements</p>
431

A for statement specifies the repeated execution of a statement sequence for a given number of times, while a progression of values is assigned to an integer variable called the control variable of the for statement.

432
433

ForStatement =

434

FOR ident ":=" expression TO expression [BY ConstExpression] DO

435

StatementSequence END .

436
437

The for statement

438
439

FOR v := beg TO end BY inc DO S END

440
441
is, if inc > 0, equivalent to
442
443

v := beg; lim := end;

444

WHILE v <= lim DO S; v := v + inc END

445
446
and if inc < 0 it is equivalent to
447
448

v := beg; lim := end;

449

WHILE v >= lim DO S; v := v + inc END

450
451

The types of v, beg and end must be INTEGER, and inc must be an integer (constant expression). If the step is not specified, it is assumed to be 1.

452
453
454
<p>10. Procedure declarations</p>
455

Procedure declarations consist of a procedure heading and a procedure body. The heading specifies the procedure identifier, the formal parameters, and the result type (if any). The body contains declarations and statements. The procedure identifier is repeated at the end of the procedure declaration.

456

There are two kinds of procedures, namely proper procedures and function procedures. The latter are activated by a function designator as a constituent of an expression, and yield a result that is an operand in the expression. Proper procedures are activated by a procedure call. A function procedure is distinguished in the declaration by indication of the type of its result following the parameter list. Its body must end with a RETURN clause which defines the result of the function procedure.

457

All constants, variables, types, and procedures declared within a procedure body are local to the procedure. The values of local variables are undefined upon entry to the procedure. Since procedures may be declared as local objects too, procedure declarations may be nested.

458

In addition to its formal parameters and locally declared objects, the objects declared in the environment of the procedure are also visible in the procedure (with the exception of variables and of those objects that have the same name as an object declared locally).

459

The use of the procedure identifier in a call within its declaration implies recursive activation of the procedure.

460
461

ProcedureDeclaration = ProcedureHeading ";" ProcedureBody ident.

462

ProcedureHeading = PROCEDURE identdef [FormalParameters].

463

ProcedureBody = DeclarationSequence [BEGIN StatementSequence]

464

[RETURN expression] END.

465

DeclarationSequence = [CONST {ConstantDeclaration ";"}]

466

[TYPE {TypeDeclaration ";"}] [VAR {VariableDeclaration ";"}]

467

{ProcedureDeclaration ";"}.

468
<p>10.1. Formal parameters</p>
469

Formal parameters are identifiers which denote actual parameters specified in the procedure call. The correspondence between formal and actual parameters is established when the procedure is called. There are two kinds of parameters, namely value and variable parameters. A variable parameter corresponds to an actual parameter that is a variable, and it stands for that variable. A value parameter corresponds to an actual parameter that is an expression, and it stands for its value, which cannot be changed by assignment. However, if a value parameter is of a scalar type, it represents a local variable to which the value of the actual expression is initially assigned.

470

The kind of a parameter is indicated in the formal parameter list: Variable parameters are denoted by the symbol VAR and value parameters by the absence of a prefix.

471

A function procedure without parameters must have an empty parameter list. It must be called by a function designator whose actual parameter list is empty too.

472

Formal parameters are local to the procedure, i.e. their scope is the program text which constitutes the procedure declaration.

473
474

FormalParameters = "(" [FPSection {";" FPSection}] ")" [":" qualident].

475

FPSection = [VAR] ident {"," ident} ":" FormalType.

476

FormalType = {ARRAY OF} qualident.

477
478

The type of each formal parameter is specified in the parameter list. For variable parameters, it must be identical to the corresponding actual parameter's type, except in the case of a record, where it must be a base type of the corresponding actual parameter's type.

479

If the formal parameter's type is specified as

480
481

ARRAY OF T

482
483
the parameter is said to be an open array, and the corresponding actual parameter may be of arbitrary length.
484

If a formal parameter specifies a procedure type, then the corresponding actual parameter must be either a procedure declared globally, or a variable (or parameter) of that procedure type. It cannot be a predefined procedure. The result type of a procedure can be neither a record nor an array.

485

Examples of procedure declarations:

486
487

PROCEDURE ReadInt(VAR x: INTEGER);

488

VAR i : INTEGER; ch: CHAR;

489

BEGIN i := 0; Read(ch);

490

WHILE ("0" <= ch) & (ch <= "9") DO

491

i := 10*i + (ORD(ch)-ORD("0")); Read(ch)

492

END ;

493

x := i

494

END ReadInt

495
496

PROCEDURE WriteInt(x: INTEGER); (* 0 <= x < 10^5 *)

497

VAR i: INTEGER;

498

buf: ARRAY 5 OF INTEGER;

499

BEGIN i := 0;

500

REPEAT buf[i] := x MOD 10; x := x DIV 10; INC(i) UNTIL x = 0;

501

REPEAT DEC(i); Write(CHR(buf[i] + ORD("0"))) UNTIL i = 0

502

END WriteInt

503
504

PROCEDURE log2(x: INTEGER): INTEGER;

505

VAR y: INTEGER; (*assume x>0*)

506

BEGIN y := 0;

507

WHILE x > 1 DO x := x DIV 2; INC(y) END ;

508

RETURN y

509

END log2

510
511
<p>10.2. Predefined procedures</p>
512

The following table lists the predefined procedures. Some are generic procedures, i.e. they apply to several types of operands. v stands for a variable, x and n for expressions, and T for a type.

513
514

Function procedures:

515
516

Name Argument type Result type Function

517
518

ABS(x) numeric type type of x absolute value

519

ODD(x) INTEGER BOOLEAN x MOD 2 = 1

520

LEN(v) v: array INTEGER the length of v

521

LSL(x, n) x, n: INTEGER type of x logical shift left, x * 2n

522

ASR(x, n) x, n: INTEGER type of x signed shift right, x DIV 2n

523

ROR(x, n) x. n: INTEGER type of x x rotated right by n bits

524
525

Type conversion functions:

526
527

Name Argument type Result type Function

528
529

FLOOR(x) REAL, LONGREAL INTEGER largest integer <= x

530

FLT(x) INTEGER REAL identity

531

ORD(x) CHAR, BOOLEAN, SET INTEGER ordinal number of x

532

CHR(x) INTEGER CHAR character with ordinal number x

533

LONG(x) REAL LONGREAL x

534

SHORT(x) LONGREAL REAL x

535
536

Proper procedures:

537
538

Name Argument types Function

539
540

INC(v) INTEGER v := v + 1

541

INC(v, n) INTEGER v := v + n

542

DEC(v) INTEGER v := v - 1

543

DEC(v, n) INTEGER v := v - n

544

INCL(v, x) v: SET; x: INTEGER v := v + {x}

545

EXCL(v, x) v: SET; x: INTEGER v := v - {x}

546

COPY(x, v) x: character array, string v := x

547

v: character array

548

NEW(v) pointer type allocate v^

549

ASSERT(b) BOOLEAN abort, if ~b

550

ASSERT(b, n) BOOLEAN, INTEGER

551

PACK(x, y) REAL; INTEGER pack x and y into x

552

UNPK(x, y) REAL; INTEGER unpack x into x and y

553
554

Procedures INC and DEC may have an explicit increment or decrement. It must be a constant. Also for INCL and EXCL, x must be a constant. The second parameter n of ASSERT is a value transmitted to the system as an abort parameter.

555

The parameter y of PACK represents the exponent of x. PACK(x, y) is equivalent to x := x * 2y. UNPK is the reverse operation of PACK. The resulting x is normalized, i.e. 1.0 <= x < 2.0.

556
557
558
<p>11. Modules</p>
559

A module is a collection of declarations of constants, types, variables, and procedures, and a sequence of statements for the purpose of assigning initial values to the variables. A module typically constitutes a text that is compilable as a unit.

560
561

module = MODULE ident ";" [ImportList ";"] DeclarationSequence

562

[BEGIN StatementSequence] END ident "." .

563

ImportList = IMPORT import {"," import} ";" .

564

Import = ident [":=" ident].

565
566

The import list specifies the modules of which the module is a client. If an identifier x is exported from a module M, and if M is listed in a module's import list, then x is referred to as M.x. If the form "M := M1" is used in the import list, an exported object x declared within M1 is referenced in the importing module as M.x .

567

Identifiers that are to be visible in client modules, i.e. which are to be exported, must be marked by an asterisk (export mark) in their declaration. Variables cannot be exported, with the exception of those of scalar types in read-only mode.

568

The statement sequence following the symbol BEGIN is executed when the module is added to a system (loaded). Individual (parameterless) procedures can thereafter be activated from the system, and these procedures serve as commands.

569

Example:

570
571

MODULE Out; (*exported procedures: Write, WriteInt, WriteLn*)

572

IMPORT Texts, Oberon;

573

VAR W: Texts.Writer;

574
575

PROCEDURE Write*(ch: CHAR);

576

BEGIN Texts.Write(W, ch)

577

END ;

578
579

PROCEDURE WriteInt*(x, n: INTEGER);

580

VAR i: INTEGER; a: ARRAY 16 OF CHAR;

581

BEGIN i := 0;

582

IF x < 0 THEN Texts.Write(W, "-"); x := -x END ;

583

REPEAT a[i] := CHR(x MOD 10 + ORD("0")); x := x DIV 10; INC(i) UNTIL x = 0;

584

REPEAT Texts.Write(W, " "); DEC(n) UNTIL n <= i;

585

REPEAT DEC(i); Texts.Write(W, a[i]) UNTIL i = 0

586

END WriteInt;

587
588

PROCEDURE WriteLn*;

589

BEGIN Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)

590

END WriteLn;

591
592

BEGIN Texts.OpenWriter(W)

593

END Out.

594
<p>11.1 The Module SYSTEM</p>
595

The optional module SYSTEM contains definitions that are necessary to program low-level operations referring directly to resources particular to a given computer and/or implementation. These include for example facilities for accessing devices that are controlled by the computer, and perhaps facilities to break the data type compatibility rules otherwise imposed by the language definition. It is strongly recommended to restrict their use to specific low-level modules, as such modules are inherently non-portable and not "type-safe". However, they are easily recognized due to the identifier SYSTEM appearing in their import lists. The subsequent definitions are generally applicable. However, individual implementations may include in their module SYSTEM additional definitions that are particular to the specific, underlying computer. In the following, v stands for a variable, x, a, and n for expressions.

596
597

Function procedures:

598
599

Name Argument types Result type Function

600
601

ADR(v) any INTEGER address of variable v

602

SIZE(T) any type INTEGER size in bytes

603

BIT(a, n) a, n: INTEGER BOOLEAN bit n of mem[a]

604
605

Proper procedures:

606
607

Name Argument types Function

608
609

GET(a, v) a: INTEGER; v: any basic type v := mem[a]

610

PUT(a, x) a: INTEGER; x: any basic type mem[a] := x

611
612
613
<p>Appendix</p><p>The Syntax of Oberon</p>
614

letter = "A" | "B" | … | "Z" | "a" | "b" | … | "z".

615

digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9".

616

hexDigit = digit | "A" | "B" | "C" | "D" | "E" | "F".

617

ident = letter {letter | digit}.

618

qualident = [ident "."] ident.

619

identdef = ident ["*"].

620

integer = digit {digit} | digit {hexDigit} "H".

621

real = digit {digit} "." {digit} [ScaleFactor].

622

ScaleFactor = ("E" | "D") ["+" | "-"] digit {digit}.

623

number = integer | real.

624

string = """ {character} """ | digit {hexDigit} "X".

625

ConstantDeclaration = identdef "=" ConstExpression.

626

ConstExpression = expression.

627

TypeDeclaration = identdef "=" StrucType.

628

StrucType = ArrayType | RecordType | PointerType | ProcedureType.

629

type = qualident | StrucType.

630

ArrayType = ARRAY length {"," length} OF type.

631

length = ConstExpression.

632

RecordType = RECORD ["(" BaseType ")"] [FieldListSequence] END.

633

BaseType = qualident.

634

FieldListSequence = FieldList {";" FieldList}.

635

FieldList = IdentList ":" type.

636

IdentList = identdef {"," identdef}.

637

PointerType = POINTER TO type.

638

ProcedureType = PROCEDURE [FormalParameters].

639

VariableDeclaration = IdentList ":" type.

640

expression = SimpleExpression [relation SimpleExpression].

641

relation = "=" | "#" | "<" | "<=" | ">" | ">=" | IN | IS.

642

SimpleExpression = ["+" | "-"] term {AddOperator term}.

643

AddOperator = "+" | "-" | OR.

644

term = factor {MulOperator factor}.

645

MulOperator = "*" | "/" | DIV | MOD | "&".

646

factor = number | string | NIL | TRUE | FALSE |

647

set | designator [ActualParameters] | "(" expression ")" | "~" factor.

648

designator = qualident {selector}.

649

selector = "." ident | "[" ExpList "]" | "^" | "(" qualident ")".

650

set = "{" [element {"," element}] "}".

651

element = expression [".." expression].

652

ExpList = expression {"," expression}.

653

ActualParameters = "(" [ExpList] ")" .

654

statement = [assignment | ProcedureCall | IfStatement | CaseStatement |

655

WhileStatement | RepeatStatement | ForStatement].

656

assignment = designator ":=" expression.

657

ProcedureCall = designator [ActualParameters].

658

StatementSequence = statement {";" statement}.

659

IfStatement = IF expression THEN StatementSequence

660

{ELSIF expression THEN StatementSequence}

661

[ELSE StatementSequence] END.

662

CaseStatement = CASE expression OF case {"|" case} END.

663

case = [CaseLabelList ":" StatementSequence].

664

CaseLabelList = LabelRange {"," LabelRange}.

665

LabelRange = label [".." label].

666

label = integer | string | ident.

667

WhileStatement = WHILE expression DO StatementSequence

668

{ELSIF expression DO StatementSequence} END.

669

RepeatStatement = REPEAT StatementSequence UNTIL expression.

670

ForStatement = FOR ident ":=" expression TO expression [BY ConstExpression]

671

DO StatementSequence END.

672

ProcedureDeclaration = ProcedureHeading ";" ProcedureBody ident.

673

ProcedureHeading = PROCEDURE identdef [FormalParameters].

674

ProcedureBody = DeclarationSequence [BEGIN StatementSequence]

675

[RETURN expression] END.

676

DeclarationSequence = [CONST {ConstDeclaration ";"}]

677

[TYPE {TypeDeclaration ";"}]

678

[VAR {VariableDeclaration ";"}]

679

{ProcedureDeclaration ";"}.

680

FormalParameters = "(" [FPSection {";" FPSection}] ")" [":" qualident].

681

FPSection = [VAR] ident {"," ident} ":" FormalType.

682

FormalType = {ARRAY OF} qualident.

683

module = MODULE ident ";" [ImportList] DeclarationSequence

684

[BEGIN StatementSequence] END ident "." .

685

ImportList = IMPORT import {"," import} ";".

686

import = ident [":=" ident].

687
688
689
690
691