Previous | Next | Table of Contents | Index | Program List | Copyright

6.6 System Structures: Writing Simple Procedures

In this book you have been using calls to procedures provided by the standard input/output libraries and another package called Screen. In this section you will learn how to write procedures.

Writing Procedures

Procedures and functions are both subprograms, but they differ in two important ways. First, a procedure is called with a procedure call statement, as in

    Ada.Float_Text_IO.Put (Item => X, Fore => 3, Aft => 2, Exp => 0);
whereas a function is used in an expression, for example,
    Temp := UsefulFunctions.Minimum (Value1 => X, Value2 => Y) + 45;
A function returns a result so that the result can be used in an expression; a procedure does not return a result.

The second important difference is that a function is permitted to have parameters that are passed only into the function, whereas a procedure is allowed to have parameters of three kinds, or modes:

The determination of a particular parameter's mode is based on the direction of the data flow between the procedure and its calling programs. If the parameter is used to transmit data to the procedure, its mode should be IN; if the parameter receives data from the procedure, its mode should be OUT.

Mode IN parameters are similar to the parameters of a function and are used to transmit values that will not be changed by the procedure, only used by it. For example, the parameters to the various Put procedures provided by Ada.Text_IO are IN parameters, because the data and formatting values are transmitted from the caller to the procedure.

Mode OUT parameters are commonly used in input routines like the Get operations in Ada.Text_IO. It may seem strange that an input routine should have an OUT parameter, but the input routine receives a value from the terminal or a file and passes it out to the program that calls it. The caller receives the input value from the procedure.

Mode IN OUT parameters are used when a procedure will modify its parameters. An example follows.

Example 6.12

Here is a procedure specification for a procedure Order, which orders the values in the two variables whose names are supplied to it as actual parameters, placing the smaller of the two values in X and the larger in Y:

    PROCEDURE Order (X: IN OUT Float; Y: IN OUT Float);

A procedure call statement

    Order (X => Num1, Y => Num2);

is intended to order the values in the two floating-point variables Num1 and Num2. Suppose, for example, that Num1 is 3.0 and Num2 is -5.0. After the above call we want Num1 to be -5.0 and Num2 to be 3.0. Ordering pairs of values is a very common operation in programming, especially in sorting applications. Here is the body of procedure Order:

    PROCEDURE Order (X: IN OUT Float; Y: IN OUT Float) IS
    -- Pre: X and Y are assigned values
    -- Post: X has the smaller value and Y has the larger value
    
        Temp: Float;
    
    BEGIN
    
        IF X > Y THEN
        	-- interchange the values of X and Y
        	Temp := X;
        	X := Y;
        	Y := Temp;
        END IF;
    
    END Order;

The variable Temp is a local variable of the procedure, necessary to carry out the interchange. Temp is created when the procedure is called; it is destroyed when the procedure returns to its caller. X and Y must be IN OUT parameters because their values are changed by the procedure. The effect of calling procedure Order is shown in Program 6.9, which carries out a very simple sort of three numbers Num1, Num2, and Num3 by calling Order three times:

    Order (X => Num1, Y => Num2);
    Order (X => Num1, Y => Num3);
    Order (X => Num2, Y => Num3);

Because each statement contains a different association of actual parameters with the formal parameters X and Y, a different pair of variables is ordered each time the procedure is called. Figure 6.1 shows a structure chart for this program.

Program 6.9
A Very Simple Sorting Program

WITH Ada.Text_IO;
WITH Ada.Float_Text_IO;
PROCEDURE Sort_3_Numbers IS
------------------------------------------------------------------------
--| Reads three numbers and sorts them
--| so that they are in increasing order.
--| Author: Michael B. Feldman, The George Washington University
--| Last Modified: July 1995
------------------------------------------------------------------------

  Num1 : Float;            -- a list of three cells
  Num2 : Float;
  Num3 : Float;

  -- procedure specification
  PROCEDURE Order (X: IN OUT Float; Y: IN OUT Float);

  -- procedure body
  PROCEDURE Order (X: IN OUT Float; Y: IN OUT Float) IS
  -- Pre:  X and Y are assigned values.
  -- Post: X has the smaller value and Y has the larger value.

    Temp : Float;          -- copy of number originally in X

  BEGIN  -- Order

    IF X > Y THEN
      -- interchange the values of X and Y
      Temp := X;            -- Store old X in Temp
      X := Y;               -- Store old Y in X
      Y := Temp;            -- Store old X in Y
    END IF;

  END Order;

BEGIN  -- Sort_3_Numbers

  Ada.Text_IO.Put
    (Item => "Enter 3 float numbers to be sorted, one per line.");
  Ada.Text_IO.New_Line;
  Ada.Float_Text_IO.Get(Item => Num1);
  Ada.Float_Text_IO.Get(Item => Num2);
  Ada.Float_Text_IO.Get(Item => Num3);

  -- Sort the numbers
  Order (X => Num1, Y => Num2);      -- Order the data in Num1 and Num2
  Order (X => Num1, Y => Num3);      -- Order the data in Num1 and Num3
  Order (X => Num2, Y => Num3);      -- Order the data in Num2 and Num3

  -- Display the results.
  Ada.Text_IO.Put(Item => "The three numbers in order are: ");
  Ada.Float_Text_IO.Put(Item => Num1, Fore => 5, Aft => 2, Exp => 0);
  Ada.Float_Text_IO.Put(Item => Num2, Fore => 5, Aft => 2, Exp => 0);
  Ada.Float_Text_IO.Put(Item => Num3, Fore => 5, Aft => 2, Exp => 0);
  Ada.Text_IO.New_Line;

END Sort_3_Numbers;
Sample Run
Enter 3 float numbers to be sorted, one per line.
23.7
-99.4
1.78
The three numbers in order are:   -99.40    1.78   23.70

Figure 6.1.
Structure Chart for Simple Sort Program

Figure 6.1

To show the importance of the choice of parameter mode for procedure Order, Fig. 6.2 gives a compilation listing for a modification of the procedure, with the parameter modes changed from IN OUT to IN. Notice that the Ada compiler has marked as errors the lines in which attempts are made to change the IN parameters.

Figure 6.2
Procedure Order with Compilation Errors

NYU GNAT Compiler Version 2.06 (C) Copyright NYU, 1992,1993,1994,1995

Compiling: order.adb  last modified at 95-07-25 21:02.21 GMT.

     1.   PROCEDURE Order (X: IN Float; Y: IN Float) IS
     2.   -- Pre:  X and Y are assigned values.
     3.   -- Post: X has the smaller value and Y has the larger value.
     4. 
     5.     Temp : Float;          -- copy of number originally in X   
     6. 
     7.   BEGIN  -- Order   
     8. 
     9.     IF X > Y THEN
    10.       -- interchange the values of X and Y   
    11.       Temp := X;            -- Store old X in Temp   
    12.       X := Y;               -- Store old Y in X   
              |
        >>> assignment to "IN" mode parameter not allowed

    13.       Y := Temp;            -- Store old X in Y   
              |
        >>> assignment to "IN" mode parameter not allowed

    14.     END IF;
    15. 
    16.   END Order;

Executing a Procedure with Parameters

Figure 6.3 shows the data areas for the main program and procedure Order immediately after the execution of the procedure call statement

    Order(X => Num1, Y => Num2);      -- Order the data in Num1 and Num2

This diagram shows the data values read into Num1, Num2, and Num3. It also shows that the local variable Temp is considered undefined immediately after the procedure is called.

Figure 6.3 also shows the parameter correspondence specified by the actual parameter list above. The double-headed arrows symbolize the connection between formal parameters X and Y and main program variables Num1 and Num2, respectively. Whenever X is referenced in the procedure, the data in variable Num1 are actually manipulated.

Figure 6.3
Parameter Correspondence for Order (Num1, Num2)

Figure 6.3

The execution of the procedure is traced in Table 6.1. The actual parameter represented by each formal parameter is shown in parentheses at the top of the table. Because the value of Num1 is less than that of Num2, the true alternative is skipped and the variable values are unchanged.

Table 6.1
Trace of Procedure Execution for Order (Num1, Num2)

Statement in Order  X (Num1)  Y (Num3)	Temp	Effect
			8.0	10.0	?
IF X > Y THEN					8.0 > 10.0 is false; do nothing

The parameter correspondence specified by the procedure call statement

    Order (X => Num1, X => Num3);

is pictured in Fig. 6.4. This time parameter X corresponds to variable Num1 and parameter Y corresponds to variable Num3. This means that whenever formal parameter Y is referenced in the procedure, the data in main program variable Num3 are actually manipulated.

Figure 6.4 Parameter Correspondence for Order (Num1, Num3)

Figure 6.4

This second execution of the procedure is traced in Table 6.2. The actual parameter represented by each formal parameter is shown in parentheses at the top of the table. The procedure execution switches the values stored in main program variables Num1 and Num3, as desired.

Table 6.2 Trace of Procedure Execution for Order (Num1, Num3)

Statement in Order  X (Num1)  Y (Num3)	Temp	Effect
			8.0	6.0	?
IF X > Y THEN					8.0 > 6.0 is true
  Temp := X;				8.0	save old Num1 in Temp;
  X := Y;		6.0			save old Num3 in Num1;
  Y := Temp;			8.0		save Temp in Num3.

The Procedure Data Area

Each time a procedure call statement is executed, an area of memory is allocated for storage of that procedure's data. Included in the procedure data area are storage cells for any local variables or constants that may be declared in the procedure. The procedure data area is always erased when the procedure terminates, and it is recreated (with all values undefined) when the procedure is called again.

Memory cells are allocated in the procedure data area for each formal parameter. These cells are used in different ways for parameters of the three modes:

We note that these rules apply to parameters of scalar type, which are the only kind we have studied so far. Beginning in Chapter 8, you will see that parameter-passing behavior may differ somewhat for parameters of structured type. Also, parameters are passed to a function's data area, just as they are to a procedure's; recall, though, that function parameters in Ada can have mode IN parameters only; mode OUT and IN OUT parameters are not permitted.

Syntax Rules for Parameter Lists

This section presents the syntax rules for procedure declarations and procedure call statements with parameters. The displays that follow summarize these rules.

SYNTAX DISPLAY
Procedure Specification (Procedure with Parameters)

Form:
PROCEDURE pname (formal-parameters);

Example:
PROCEDURE Highlight (Ch : IN Character);

Interpretation:
The procedure pname is declared. The formal parameters are enclosed in parentheses.

SYNTAX DISPLAY
Procedure Body (Procedure with Parameters)

Form:
PROCEDURE pname (formal-parameters) IS
    local declaration-section
BEGIN
    statement sequence
END pname;

Example:
PROCEDURE Highlight (Ch : IN Character) IS

    Border  CONSTANT Character := '*';

BEGIN

    Ada.Text_IO.Put (Item => Border);
    Ada.Text_IO.Put (Item => Ch);  
    Ada.Text_IO.Put (Item => Border);

END Highlight;

Interpretation:
The procedure pname is declared. The formal parameters are enclosed in parentheses. Any identifiers that are declared in the declaration-section are defined only during the execution of the procedure.

The statement sequence describes the data manipulation to be performed by the procedure. The formal parameter names are used in place of the actual parameter names in this description.

SYNTAX DISPLAY
Procedure Call Statement (Procedure with Parameters)

Form:
pname (actual-parameters)

Example:
Highlight (Ch => 'A')

Interpretation:
The actual-parameters are enclosed in parentheses; each actual parameter is preceded by the name of the corresponding formal parameter. When procedure pname is called into execution, each actual parameter is associated with the corresponding formal parameter.

The formal parameter list determines the form of any actual parameter list that may be used to call the procedure. This form is determined during the translation of the program when the compiler processes the procedure declaration.

Later, when a procedure call statement is reached, the compiler checks the actual parameter list for consistency with the formal parameter list. An actual parameter list may be a list of expressions, variables, or constants separated by commas. The actual parameter list must satisfy the rules shown below.

Rules for Parameter List Correspondence

  1. The correspondence between actual and formal parameters is determined by their position in their respective parameter lists unless named association is used. These lists must be of the same size. The names of corresponding actual and formal parameters may be, and often are, different.
  2. The type of each actual parameter must be compatible with the type of the corresponding formal parameter, that is, either of the same type or of a related subtype.
  3. For mode OUT and IN OUT parameters, an actual parameter must be a variable. For mode IN parameters, an actual parameter may be a variable, constant, or expression.

PROGRAM STYLE
Named Association in Actual Parameter Lists

In this book, named association is used to associate each formal parameter with an actual parameter (the two are separated by =>). This naming is optional in Ada; if it is used, the order of the actual parameters does not, strictly speaking, have to match the order of the formal parameters. It is good practice to use named association and also to list the actual parameters in an order corresponding to the order of the formal parameters. In this way, no confusion arises for the reader of the program as to which actual parameter matches which formal parameter.


[1] In Ada 83 it was not permitted to use the value of an OUT parameter inside the procedure (e.g., it could not appear on the right side of an assignment statement). This restriction is eliminated in Ada 95.


Previous | Next | Table of Contents | Index | Program List | Copyright

Copyright © 1996 by Addison-Wesley Publishing Company, Inc.