Previous: The Operator, Up: Subroutine Declaration



6.1.6.4 Subroutine Parameter List Declaration

     parameter; ...; parameter

Each parameter can start with a prefix (see below) describing how the parameters are passed, followed by a comma seperated list of one or more parameter_identifiers and an optional parameter_type.

     procedure DoIt (var x, y, z: OneType; a, b: AnotherType; var q);

To understand parameter passing, first some definitions.

actual parameter
the parameter passed in to the routine.
formal parameter
the parameter as used inside the procedure.
by value
the value of the actual parameter is copied on to the stack.
by reference
the address of the actual parameter is copied on to the stack.
L-value
(left hand of a := statement) something that can be assigned to (not a constant, or const or protected variable or other immutable item).
R-value
(right hand of a := statement) anything you can get the value of (could be a constant, an expression, a variable (whether const or protected or not) or just about anything.
addressable
something you can get the address of (not a field of a packed structure or a variable with `attribute (register)' (GPC extension)).
aliasing
accessing memory via two different names (e.g. a global variable passed by reference to a procedure can be accessed either as the global variable or the formal paramater). Generally this is very bad practice.

Technical note: Parameters are not always passed on the stack, they may also be passed in registers, especially on RISC machines.

The prefix defines how a variable is passed on the stack and how you can access the formal_parameter inside the procedure. The prefix can be one of:

nothing
          procedure DoIt (x: SomeType);
     

Technical: The actual parameter is passed by value or reference, but if passed by reference, it is then copied to a local copy on the stack. Aliasing has no effect on x.

What it means: you can modify x inside the routine, but your changes will not affect the actual parameter (and vice versa). The actual parameter can be a constant or other immutable object, or a protected or const variable.

protected
          procedure DoIt (protected x: SomeType);
     

Technical: The actual parameter is passed by value or reference, but if passed by reference, it is then copied to a local copy on the stack. Aliasing has no effect on x. protected is a Extended Pascal extension.

What it means: if you modify the actual parameter, this will not affect x inside the routine. The actual parameter can be a constant or other immutable object, or a protected or const variable. You are forbidden from modifying x inside the routine.

var
          procedure DoIt (var x: SomeType);
     

Technical: The actual parameter is passed by reference. Aliasing will definitely change x.

What it means: modifications to x inside the routine will change the actual parameter passed in. The actual parameter must be an addressable L-value (ie, it must be something you can take the address of and assign to).

A parameter of this kind is called variable parameter and internally corresponds to an L-value pointer (to the specified type identifier if any). This declaration is necessary if the parameter is to be modified within the routine and to hold its value still after return.

const
          procedure DoIt (const x: SomeType);
     

Technical: The actual parameter is passed by value or reference. The compiler will make a copy of the actual parameter to have something it can address if the actual parameter is not addressable. You are forbidden from modifying x inside the routine, and therefore you cannot modify the actual parameter. Aliasing may or may not change x. const is a Borland Pascal extension.

What it means: You can pass any R-value. You cannot modify x inside the routine. If you change the actual parameter while inside the routine, x will have an undefined value.

protected var
          procedure DoIt (protected var x: SomeType);
     

Technical: The actual parameter is passed by reference. The compiler will never make a copy of the actual parameter. You are forbidden from modifying x inside the routine, and therefore you cannot modify the actual parameter. Aliasing will definitely change x.

What it means: You can pass anything addressable. You cannot modify x inside the routine. If you change the actual parameter while inside the routine, x will change as well.

In GPC, the protected var mode guarantees that the parameter is always passed by reference, making it the correct choice for calling C routines with const pointer parameters.

If you omit the formal parameter type specification, then any type may be passed to that parameter. Generally this is a bad idea, but occasionally it can be useful, especially for low level code.

As an Extended Pascal extension, you can also declare procedural parameters directly:

     procedure parameter_identifier

or:

     function parameter_identifier: parameter_identifier_result_type

Example for parameter lists:

     program ParameterDemo;
     
     procedure Foo (var Bar; var Baz: Integer; const Fred: Integer);
     
       procedure Glork1 (function Foo: Integer; procedure Bar (Baz: Integer));
       begin
         Bar (Foo)
       end;
     
     begin
       Baz := Integer (Bar) + Fred
     end;
     
     var
       a, b, c: Integer;
     
     begin
       Foo (a, b, c)
     end.

See also

Data Types, var, const, protected