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 os methods. This is equivalent to
(os m method) (o, Bindings)
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)
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.
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.
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 es argument type. The outcome is the exception e paired with the argument x.
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.
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 |