Previous Table of Contents Next


For a READONLY or VALUE parameter, the actual can be any expression assignable to the type of the formal (except that the prohibition against assigning local procedures is relaxed). For a VAR parameter, the actual must be a writable designator whose type is the same as that of the formal, or, in case of a VAR array parameter, assignable to that of the formal (see section 11.7.3).

A VAR formal is bound to the variable designated by the corresponding actual; that is, it is aliased. A VALUE formal is bound to a variable with an unused location and initialized to the value of the corresponding actual. A READONLY formal is treated as a VAR formal if the actual is a designator and the type of the actual is the same as the type of the formal (or an array type that is assignable to the type of the formal); otherwise, it is treated as a VALUE formal.

Implementations are allowed to forbid VAR or READONLY parameters of packed types.

To execute the call, the procedure P and its arguments are evaluated, the formal parameters are bound, and the body of the procedure is executed. The order of evaluation of P and its actual arguments is undefined. It is a checked runtime error to call an undefined or NIL procedure.

It is a checked runtime error for a procedure to raise an exception not included in its raises set (if an implementation maps this runtime error into an exception, the exception is implicitly included in all RAISES clauses) or for a function procedure to fail to return a result.

A procedure call is a statement only if the procedure is proper. To call a function procedure and discard its result, use EVAL.

A procedure call can also have the form

   o.m(Bindings)

where o is an object and m names one of o’s methods. This is equivalent to

   (o’s m method) (o, Bindings)

11.5.3. EVAL

An EVAL statement has the form

   EVAL e

where e is an expression. The effect is to evaluate e and ignore the result, as in:

   EVAL Thread.Fork(p)

11.5.4. Block Statements

A block statement has the form

   Decls BEGIN S END

where Decls is a sequence of declarations and S is a statement. The block introduces the constants, types, variables, and procedures declared in Decls and then executes S. The scope of the declared names is the block.

11.5.5. Sequential Composition

A statement of the form

   S1; S2

executes S1 and then if the outcome is normal, executes S2. If the outcome of S1 is an exception, S2 is ignored.

Some programmers use the semicolon as a statement terminator, some as a statement separator. Similarly, some use the vertical bar in case statements as a case initiator, some as a separator. Modula-3 allows both styles. This chapter uses both operators as separators.

11.5.6. RAISE

A RAISE statement without an argument has the form

   RAISE e

where e is an exception that takes no argument. The outcome of the statement is the exception e. A RAISE statement with an argument has the form

   RAISE e(x)

where e is an exception that takes an argument and x is an expression assignable to e’s argument type. The outcome is the exception e paired with the argument x.

11.5.7. TRY-EXCEPT

A TRY-EXCEPT statement has the form

   TRY
       Body
   EXCEPT
       id1 (v1) => Handler1
   | ...
   | idn (vn) => Handlern
   ELSE Handler0
   END

where Body and each Handler are statements, each id names an exception, and each vi is an identifier. The ELSE Handler0 and each (vi) are optional. It is a static error for an exception to be named more than once in the list of ids.

The statement executes Body. If the outcome is normal, the except clause is ignored. If Body raises any listed exception idi, then Handleri is executed. If Body raises any other exception and ELSE Handler0 is present, then it is executed. In either case, the outcome of the TRY statement is the outcome of the selected handler. If Body raises an unlisted exception and ELSE Handler0 is absent, then the outcome of the TRY statement is the exception raised by Body.

Each (vi) declares a variable whose type is the argument type of the exception idi and whose scope is Handleri. When an exception idi paired with an argument x is handled, vi is initialized to x before Handleri is executed. It is a static error to include (vi) if exception idi does not take an argument.

If (vi) is absent, then idi can be a list of exceptions separated by commas, as shorthand for a list in which the rest of the handler is repeated for each exception:

   id1, ..., idn => Handler

is shorthand for

   id1 => Handler | ... | idn => Handler

It is a checked runtime error to raise an exception outside the dynamic scope of a handler for that exception. A TRY EXCEPT ELSE counts as a handler for all exceptions.

11.5.8. TRY-FINALLY

A statement of the form

   TRY S1 FINALLY S2 END

executes statement S1 and then statement S2. If the outcome of S1 is normal, the TRY statement is equivalent to S1; S2. If the outcome of S1 is an exception and the outcome of S2 is normal, the exception from S1 is re-raised after S2 is executed. If both outcomes are exceptions, the outcome of the TRY is the exception from S2.


Previous Table of Contents Next