Chapter 7 - Overall Program Construction
We have pretty well covered the topic of how to put all the parts together to build up a program. In this chapter we will go over the whole process in order to clear up any loose ends and have the entire process in one place. There is nothing magic about the way the various pieces fit together but the rules must be followed in order to build a usable program.
Load and display the program named OVERPROG.MOD for the first look at the overall structure of the Modula-2 program. It would be well for you to keep in mind that there is a major category that we have not even hinted at yet, the issue of modules. They will be covered in Part III of this tutorial, and although they are very important, you can begin writing meaningful programs before you even hear what modules are or how they are used.
The program on display contains several levels of nested procedures as an illustration for you. The main program has lines 1 through 35 as its declaration part, and lines 37 through 42 as its statement part. Since the procedure definitions actually define the procedures called for by the main program, they correctly belong in the declaration part of the program. Only two of the procedures are actually callable by the main program, "Proc1", and "Proc2". The procedure "Proc1" is a simple procedure, but "Proc2" has additional procedures in its declaration part.
Procedure "Proc2" contains a declaration part in lines 12 through 29, and a statement part in lines 30 through 35. Its declaration part contains two procedures, "Proc3" and "Proc4". The nesting is carried one step farther in "Proc4" which contains the procedure "Proc5" in its declaration part. Procedures can be nested to whatever level desired according to the definition of Modula-2.
Who can call who?
It is important for you to clearly understand which procedure can call which other procedures. A procedure can call any procedure on the same level as itself provided that both have the same parentage, or any procedure that is included in its own declaration part at the level of its own declaration part. For example, the main program can only call "Proc1", and "Proc2". The others are nested within "Proc2" and are not available to the main program. Likewise the statement part of "Proc2" can call "Proc1", because it is on the same level, and "Proc3" and "Proc4", because they are within its declaration part. The procedure "Proc5" can only be called by "Proc4", because no other procedure is at its level. Note that if another triple nesting were included in "Proc1", its third level procedure could not be called by "Proc5" because they would not have the same parentage.
Nested procedures can be very useful when you wish to use a procedure that you don't want any other part of the program to be able to access or even see. A private procedure can therefore be written with no concern that the name may clash with some other part of the program and cause undesirable effects.
The important thing to gain from this program is that nesting is possible and can be very useful, and the definition of a procedure is the same as that of the main program. This means that procedures can be nested within procedures in any way that aids in designing the program.
Compile and run this program and see if you understand the output from it.
Where do we place constants, types, and variables?
Load MOREPROG.MOD, for examples of where you can put the other definitions in the declaration part of the program and the procedures. This is a repeat of the last program with CONST, TYPE, and VAR declarations added in every place where it is legal to put them. This is done as an example to you of where they can be put, so no explanation of details will be given. Some time spent studying this program should aid you in understanding even better the overall program construction problem.
What about order of declarations?
Load the program LASTPROG.MOD for an example of how the various fields can be ordered in the declaration part of the program. Notice that there are 2 procedures, two CONST's, two TYPE's, and two VAR's defined, but they are defined in a seemingly random order. The order is random and was done only to illustrate to you that the order doesn't matter as long as everything is defined before it is used.
In only one case does the order matter. The compiler is very picky about where the IMPORT list goes because the Modula-2 language definition requires it to be first. In addition, the EXPORT list must immediately follow the IMPORT list. We will cover both of these in detail later, for now simply remember that the order of all declarations can come in random order as long as they follow the IMPORT/EXPORT lists and come before the statement part of the program.
Next: Chapter 8. Input/Output