Modula-2 (на английском языке) (1161147), страница 5
Текст из файла (страница 5)
Examples:
The following procedure takes no parameters and does not return a value.
PROCEDURE Error;
BEGIN
WriteString('ERROR');
END Error;
The following procedure takes the parameter x and returns a REAL value.
PROCEDURE tan(x : REAL) : REAL;
BEGIN
RETURN sin(x) / cos(x);
END tan;
FORWARD
The FORWARD modifier is not allowed in DEFINITION modules and it signals that the procedure header is a forward declaration of the full procedure declaration which follows later in the source code. This keyword exists in the language to support single pass compilers.
PROCEDURE add(a, b : CARDINAL) : CARDINAL; FORWARD;
... (* other code *)
PROCEDURE add(a, b : CARDINAL) : CARDINAL;
BEGIN
RETURN a + b;
END add;
The Stony Brook compiler is a two pass compiler and therefore never requires the use of the FORWARD keyword.
Formal Parameters
The parameters of a procedure are variables that are declared in the procedure header. These variables are referred to as the formal parameters. The formal parameters can be referred to in the body of the procedure.
When you call a procedure you must supply a variable or expression for each of the formal parameters. These are called the actual parameters.
See the section Function calls in the Expressions chapter of this book and the section Procedure calls in the Statements chapter of this book for more information on calling procedures and actual parameters.
There are two classes of formal parameters: value parameters and variable parameters. A formal parameter is a value parameter unless the VAR keyword precedes it in the procedure declaration.
Value parameters
Value parameters act as if they are local variables that are assigned an initial value when the procedure is called. The initial value is the value of the actual parameter.
Because the relationship between the actual parameter and the formal parameter is an assignment, the type of the actual parameter must be assignable to the type of the formal parameter.
The actual parameter associated with a value parameter can be either a variable or an expression. If it is a variable, assignments to the formal parameter inside the procedure have no effect on the value of the actual variable.
Variable parameters
The actual parameter associated with a variable parameter must be a variable whose type is identical to that of the formal parameter. The formal parameter refers to the same variable as the actual, so assignments to the formal parameter also change the value of the variable that is passed as an actual parameter.
You use variable parameters when you want the procedure to alter the value of the actual parameter passed to it, for example, to return a new value.
You should also use variable parameters for array and record types, whenever possible because they can be more efficient. When you pass a value parameter, it must be copied, and copying of large arrays and records can be time consuming.
Example:
PROCEDURE Next(a : CHAR; VAR b : CHAR);
BEGIN
INC(a);
b := a;
END Next;
VAR
X, Y : CHAR;
BEGIN
X := 'A';
Y := 'Z';
Next(X, Y);
END
After the call to Next, X will have the value 'A' and Y will have the value 'B'. X is unchanged even though the associated formal parameter is changed, since it is a value parameter. Y is changed by the procedure since it is associated with b, a variable parameter.
Open array parameters
You can pass array types as parameters to a procedure by declaring a formal parameter with the type name of an array type. This method, however, is inflexible, since the actual parameter must be exactly the same type as the formal, including the same index type and bounds.
To pass arrays of varying sizes to a procedure, you can declare the formal parameter like this:
ARRAY OF {ARRAY OF} ElementType
Open array parameters can have any number of dimensions, for now just consider an open array parameter with a single dimension. The rules for multi dimension open array parameters logically extend from the single dimension rules.
When the formal parameter is declared this way, you can pass any single dimensional array having the same ElementType, regardless of the index type or range.
Inside the procedure, array formals are indexed by cardinals from 0 to the number of elements in the actual array minus 1, regardless of the type and range of the index of the actual parameter.
You can use the standard procedure HIGH to get the upper bound of the array formal. It returns a CARDINAL value, which is the number of elements in the actual parameter minus one.
Example:
PROCEDURE WriteStr(s : ARRAY OF CHAR);
VAR
i : CARDINAL;
BEGIN
FOR i := 0 TO HIGH(s) DO
Write(s[i]);
END;
END WriteStr;
You can pass any single dimensional array of characters to this procedure. For example:
VAR
message : ARRAY [1..10] OF CHAR;
In this case, the formal parameter will be indexed from 0 to 9, even though the actual was indexed from 1 to 10.
Let us now consider two dimensional open array parameters.
If a formal parameter is a two dimensional array of type REAL then you can pass any two dimensional array of type REAL to this parameter. The rules regarding the range of array subscripts are the same as for one dimensional open array parameters.
You can use the standard procedure HIGH to get the upper bound of each dimension of the array formal. It returns a CARDINAL value, which is the number of elements in specified dimension of the actual parameter minus one.
Example:
PROCEDURE MatrixAdd(VAR c : ARRAY OF ARRAY OF REAL;
a, b : ARRAY OF ARRAY OF REAL);
VAR
i, j : CARDINAL;
BEGIN
IF (HIGH© = HIGH(a)) AND (HIGH(c) = HIGH(b)) AND
(HIGH(c[0]) = HIGH(a[0])) AND (HIGH(c[0]) = HIGH(b[0]))
THEN
FOR i := 0 TO HIGH(c) DO
FOR j := 0 TO HIGH(c[0]) DO
c[i, j] := a[i, j] + b[i, j];
END;
END;
ELSE
FatalError('Bozo');
END;
END MatrixAdd;
The rules we have just discussed for one a two dimensional open array parameters are extended for arrays of any dimension. For more information on the HIGH function see the standard procedure chanter of this document.
Function Procedures
Procedures that return a value are called function procedures. Function procedures can be called inside an expression, and the value returned is substituted for the call.
You declare a function procedure by including the ReturnType in the procedure declaration.
The type returned by a function procedure can be any type.
Inside a function procedure, there must be at least one RETURN statement. The RETURN statement takes the following form:
RETURN expression
The expression must be assignable to the type declared as the return type of the procedure. The RETURN statement terminates the execution of the procedure, returning the value of the expression as the value of the function.
Local Variables
Any declarations included in the body of a procedure are local to the procedure. The names are not defined outside the procedure body.
Variables declared in a procedure body are known as local variables. Space is allocated for these variables only when the procedure is executed.
Each time the procedure is executed, the values of the local variables are undefined. Local variables do not retain their values from one call of the procedure to the next.
Modula-2 procedures can be called recursively. The procedure can be called from its own body, or by other procedures called from its body.
Each recursive call of a procedure allocates a new set of local variables. Changes to a variable in one invocation of the procedure have no effect on the values in other invocations.
Standard procedures
The Modula-2 language includes a set of standard procedures that are built into the compiler and therefore are always available without importing them.
This chapter lists the standard procedures, their uses, allowed parameter types, and the type returned, if any.
ABS
PROCEDURE ABS(X : type) : type;
The absolute value function. X can be any signed integer type, REAL, LONGREAL, COMPLEX or LONGCOMPLEX. The result is the same type as the parameter.
The absolute value of a positive number is itself, and the absolute value of a negative number is the negative of the number.
The absolute value of a complex number is its magnitude. (Remember magnitude is defined as SQRT(real2 + imaginary2))
CAP
PROCEDURE CAP(ch : AnyCharType) : AnyCharType;
Converts ch to uppercase. Characters other than lowercase letters in are left unchanged by this function.
For operating systems that support many languages this function returns correct results for the language the operating system has been setup to use.
CHR
PROCEDURE CHR(val : type) : CHAR;
Converts a numeric value to a value of type CHAR. The value can be any signed or unsigned integer type. The result is the character whose ordinal value is val.
If assignment checking is on, val is checked for a value in the range of type CHAR.
DEC
PROCEDURE DEC(VAR v : type);
PROCEDURE DEC(VAR v : type; amount : CARDINAL);
Decreases the value of variable v by one or by a specified amount. If an amount is not passed a value of one is assumed for amount. The variable can be of any signed or unsigned integer type, any character type, any boolean type or any enumeration type. The amount must be assignable to CARDINAL.
DISPOSE
PROCEDURE DISPOSE(VAR P : PointerType {;tag : tagtype});
Releases the storage allocated to a pointer by the NEW standard procedure or the ALLOCATE procedure.
The optional tag expressions are the tags of variant parts in a record that is being disposed. Each tag expression must be a compile-time constant. The values of the tags must be identical to those given when the object was allocated.
When you dispose of dynamic arrays you do not supply the array HIGH bounds to DISPOSE as you did with NEW. The compiler will fetch these values automatically for you from the dynamic array data.
A call to DISPOSE is translated to a call to DEALLOCATE. In order to use DISPOSE, you must define the procedure DEALLOCATE. Usually, you import DEALLOCATE from the ISO module Storage. You can, however, define the procedure yourself.
EXCL
PROCEDURE EXCL(SetVar : SetType; Element : ElementType);
Excludes an element from a SET or PACKEDSET variable. SetVar must be a variable of a set type and Element must be an expression resulting in a value of the element type of the set. The specified element is removed from the value of the set variable.
FLOAT
PROCEDURE FLOAT(num : AnyIntegerType) : REAL;
Converts the integer number num to REAL. num can be any signed or unsigned integer type.
LENGTH
PROCEDURE LENGTH(str : ARRAY OF AnyCharacterType) : CARDINAL;
Returns the length in characters of the passed string. The string passed to length can be an ANSI or Unicode string.
LFLOAT
PROCEDURE FLOAT(num : AnyIntegerType) : LONGREAL;
Converts the integer number num to LONGREAL. num can be any signed or unsigned integer type.
HALT
PROCEDURE HALT;
PROCEDURE HALT(status : CARDINAL);
Halts the execution of a program. Use the second form to return a status to the operating system. This is useful to inform the program that executed the current program about the success or lack thereof of the execution. If no status is given, 0 is the default value is returned.
HIGH
PROCEDURE HIGH(ArrayVar : ArrayType) : CARDINAL;
Returns the upper bound of an open array parameter variable.