1. A block is a sequence of declarations followed by a block body. It is a component of program modules, implementation modules, local modules, and procedure declarations. In Modula-2, blocks have names.
2. A procedure block includes a parameter list and the module blocks seen thus far does not.
3. A module may have a body if it is a program, implementation, or local module or, though a program module that neither has nor imports a module block body will not do anything. A definition module, however, must not have a body.
4. Scope is the portion of a program where an identifier is visible.
5. A procedure's parameters and local variables are in its scope, but its own name is in the surrounding scope and visible inside the procedure by inheritance.
6. A procedure's name might not be visible inside itself if the name is cut off by it's reuse as a parameter or local variable.
7. The term local means that the entity is in the scope of the module or procedure defining it. Global on the other hand means that the entity is defined externally to a procedure and inherited by it.
8. Using too many global variables can result in difficulty keeping track of them. Failure to keep track of global variables may result in writing code that modifies the value of a variable that is important to the correct functioning of some other part of the program.
9. An assignment to the z in the innermost procedure has no effect on the ones of the same name that are external to the procedure‹at either level. If the assignment is made inside another procedure declared at the same level as the outermost z, its value is affected unless the said procedure has a z of its own. If the assignment takes place in a third-level nested procedure without a z of its own, the one altered is that in the immediately surrounding procedure (the second one nested).
10. Visibility is the ability for an entity to be used in a statement in some portion of a program.
11. A side effect is the modification, by a procedure, of some variable global to it. Normally this is done by using a variable parameter or by assignment on return from a function procedure.
12. Side effects are good when the intent of the side effect is to manipulate the global variable. It is bad when it changes a global variable that it is not intended to change. That is, all such changes should be planned and documented.
13. It is common to use names such as "count" or "counter" as loop control variables. As long as the same name is used in a different scope, this isn't a problem.
14. Visibility of entities declared in procedures is inherited hierarchically and automatically inward with increasing levels, but visibility of entities declared in modules must be explicitly and manually controlled using IMPORT and EXPORT.
15. The outermost level is referred to as the main (program) module. In other words, the outermost scope is local to the main program.
16. Two items with the same name can be imported into the same scope as long as one of them is imported qualified.
17. If the item being exported has the same name as another entity in that scope, it has to EXPORTed as QUALIFIED.
18. An item that is EXPORTed does not need a reference to the module it was exported from. An item EXPORTed as QUALIFIED needs to be qualified with the module name. For example, consider the following modules:
MODULE Outer; MODULE Inner1; EXPORT QUALIFIED item1 VAR item1 : CARDINAL; END Inner1; MODULE Inner2; EXPORT item2; VAR item2 : CARDINAL; END Inner2; END Outer;
When item1 from Inner1 is to be used, it needs to be referenced because the name item1 is used in the MODULE Outer, thus it will be called as: Inner1.item1, whereas item2 can be used as is because of the manner of its export.
19. Program modules cannot have an EXPORT list, because they are at the outermost scope level. They have nowhere to EXPORT the variables to, as the (abstract) scope of library modules surrounding them cannot be manipulated except by adding another exporting library module.
20. A standard identifier is a built-in identifier of a pre-defined constant, variable, procedure, type, or module. It may be re-used in the program. A reserved word is a special word or symbol used as part of the framework or punctuation of a module. It cannot be used other than for its intended purposes.
21. A dynamic module is a module that resides in a procedure. It only exists when the procedure is invoked.
22. If a standard identifier name is cut off by its use in a procedure, it will still be available in an enclosed dynamic module.
23. A Fibonacci sequence is a sequence in which after the first two numbers, all subsequent numbers in the sequence are generated by adding the previous two.
24. A type that is exported from a definition module, but whose details are hidden in the implementation module is called an opaque type. Types whose details are visible (normal types) are called transparent types.
25. The type of a procedure is the form or pattern of all its parameter types and/or return types taken together. The presence of this facility allows for procedure variables.
26.
(a) TYPE writeTofile : PROCEDURE (VAR ChanId; ARRAY OF CHAR; FlagSet; VAR OpenResults); (b) TYPE writeToStd : PROCEDURE (ARRAY OF CHAR); (c) TYPE writeRealtoChan : PROCEDURE (IOChan.ChanId, REAL; INTEGER; CARDINAL); (d) TYPE AltAppend : PROCEDURE (ARRAY OF CHAR; VAR ARRAY OF CHAR); (d) TYPE NatLog : PROCEDURE (LONGREAL) : LONGREAL;
27. One should use a LOOP structure a loop structure when (a) there must be more than one exit point from a loop, (b) the natural exit point is in the middle of the sequence, or (c) when one must exit from a deeply nested loop or selection structure.
28. EXIT and RETURN are unconditional transfers of control.
29. HALT and RETURN (in the outermost block) will terminate a program.
30. A program could terminate if an exception is raised.
31. A termination event can be detected in a FINALLY clause.
32. One can detect if the program is in an exceptional execution state by using EXCEPTIONS.IsExceptionalExecution.
33. An exception is a violation of the run-time meaning of a program that when detected automatically alters the normal flow of control in the procedure or module body where it occurs, immediately transferring control to an exception handler for that procedure or module body, if one exists.
34. An exception is trapped by an exception handler or EXCEPT clause that may be attached to any block.
35. The first strategy is to let the control run off the end of the handler with the exception still raised. The second is to issue a RETURN command and clear the exception. This returns the state to normal execution and control passes back out to the caller of the procedure in which the exception occurred. Third, one can use a RETRY command which is similar to the RETURN except instead of giving control out to the caller of the procedure, it gives control to the beginning of the same procedure that initially raised the exception.
36. To declare and detect user-defined exceptions, one must define the exception type (usually an enumeration) and register it as the source of the exception with EXCEPTIONS. Procedures such as IsMyException and MyException should be defined to detect and discriminate one's own exceptions, which can be raised with RAISE, then handled in an EXCEPT clause.
37. When any exception is raised, a variable of type ExceptionSource must be passed, which only the module defining and raising the exception has access to.
38. Every block may contain one exception handler, and a FINALLY clause one more.
39. The body of a module may have two, one for itself and one for its FINALLY clause.
40. Note: _ is used to denote spaces
_ _ _ _ _ 1_ _ _ _ _ 2_ _ _ _ _ 3_ _ _ _ _ 4
_ _ _ _ _ 7 _ _ _ _ _2_ _ _ _ _ 3_ _ _ _ _4
41. Point1: inner1C, inner1D.
Point2: inner2E, inner2F, inner3H.
Point3: inner3G, inner3H.
Point4: outA, outB, Inner2.inner2E, Inner2.inner3H.
Note: Not all problems are shown. Most problems are left up to students as labs.
(* Created June 21 1999 Chapter 10 Question 42 This program shows what happens when a procedure changes a variable global to it. This program should fill in the database at once. *) MODULE BadGlobal; FROM STextIO IMPORT WriteString, WriteLn, ReadString, ReadChar, SkipLine; FROM SWholeIO IMPORT WriteCard, ReadCard; FROM SRealIO IMPORT ReadReal, WriteFixed; CONST start = 1; end = 3; TYPE StudentRec = RECORD test : ARRAY [1..5] OF REAL; name : ARRAY [0..20] OF CHAR; final : REAL; END; StuRecType = ARRAY [start..end] OF StudentRec; VAR count, option : CARDINAL; avg : REAL; Student : StuRecType; full : BOOLEAN; PROCEDURE Menu (VAR option : CARDINAL); (* displays and gets menu option *) BEGIN WriteString ("1. Populate Database"); WriteLn; WriteString ("2. Display Final Grades"); WriteLn; WriteString ("3. Exit"); WriteLn; WriteLn; WriteString ("Enter an option: "); ReadCard (option); SkipLine; WriteLn; END Menu; (* bad procedure count is a global variable *) PROCEDURE Fill(VAR student : StudentRec); (* populate student database one student at a time *) BEGIN WITH student DO WriteString ("Enter the student's name: "); ReadString (name); SkipLine; count := 1; (* enter the 5 grades *) WHILE count <= 5 DO WriteString ("Enter grade for test"); WriteCard (count, 0); WriteString (": "); ReadReal (test[count]); SkipLine; WriteLn; INC (count); END; END; END Fill; PROCEDURE Display (VAR student : StuRecType); (* displays the students and their final grade *) VAR countout, countin : CARDINAL; BEGIN WriteString ("---Grades---"); WriteLn; FOR countout := start TO end DO WITH student[countout] DO WriteString (name); WriteLn; final := 0.0; FOR countin := 1 TO 5 DO final := final + test[countin]; END; (* end FOR *) final := final / 50.0 * 100.0; WriteString ("Final Grade:"); WriteFixed (final, 2, 0); WriteString (" %"); WriteLn; WriteLn; END; (* end WITH *) END; (* end FOR *) END Display; BEGIN WriteString ("This program will fill a database with data consisting "); WriteLn; WriteString ("of the student's name and 5 test scores."); WriteLn; REPEAT Menu (option); IF option = 1 THEN count := start; (* do x students continuous no stopping *) WHILE count <= end DO Fill(Student[count]); INC (count); END; ELSIF option = 2 THEN Display (Student); END; UNTIL option = 3; END BadGlobal.
(* Created June.21.1999 Chapter 10 Question 43 This program demonstrates bad variable parameter use *) MODULE BadVarUse; FROM STextIO IMPORT WriteString, WriteLn, ReadString, ReadChar, SkipLine; FROM SWholeIO IMPORT WriteCard, ReadCard; FROM SRealIO IMPORT ReadReal, WriteFixed; FROM SIOResult IMPORT ReadResult, ReadResults; CONST start = 1; end = 3; TYPE StudentRec = RECORD test : ARRAY [1..5] OF REAL; name : ARRAY [0..20] OF CHAR; final : REAL; END; StuRecType = ARRAY [start..end] OF StudentRec; VAR count, option : CARDINAL; avg : REAL; Student : StuRecType; full : BOOLEAN; PROCEDURE Menu (VAR option : CARDINAL); (* displays and gets menu option *) BEGIN WriteString ("1. Populate Database"); WriteLn; WriteString ("2. Display Final Grades"); WriteLn; WriteString ("3. Display Final Grades Curved"); WriteLn; WriteString ("4. Exit"); WriteLn; WriteLn; WriteString ("Enter an option: "); ReadCard (option); SkipLine; WriteLn; END Menu; PROCEDURE Fill(VAR student : StudentRec); (* populate student database one student at a time *) VAR count : CARDINAL; BEGIN WITH student DO WriteString ("Enter the student's name: "); ReadString (name); SkipLine; count := 1; final := 0.0; FOR count := 1 TO 5 DO WriteString ("Enter grade for test"); WriteCard (count, 0); WriteString (": "); ReadReal (test[count]); SkipLine; WriteLn; (* calculate the final grade as grades are coming in *) final := final + test[count]; END; final := final / 50.0 * 100.0; END; END Fill; PROCEDURE Display (VAR student : StuRecType); (* displays the students and their final grade *) VAR countout, countin : CARDINAL; BEGIN WriteString ("---Grades---"); WriteLn; FOR countout := start TO end DO WITH student[countout] DO WriteString (name); WriteLn; WriteString ("Final Grade:"); WriteFixed (final, 2, 0); WriteString (" %"); WriteLn; WriteLn; END; END; END Display; (* bad procedure it is only suppose to show the "curved" mark, not change the actual *) PROCEDURE Curve (VAR student : StuRecType); (* displays the grades curved--somewhat at least gives the option of how much % each student gets. *) VAR countout, countin : CARDINAL; rate : REAL; BEGIN WriteString ("By how much % do you want to give them? "); ReadReal (rate); SkipLine; WriteLn; WriteString ("--Curved Grades--"); WriteLn; FOR countout := start TO end DO WITH student[countout] DO WriteString (name); WriteLn; final := final + rate; WriteString ("Curved Grade:"); WriteFixed (final, 2, 0); WriteString (" %"); WriteLn; WriteLn; END; END; END Curve; BEGIN WriteString ("This program will fill a database with data consisting "); WriteLn; WriteString ("of the student's name and 5 test scores."); WriteLn; REPEAT Menu (option); IF option = 1 THEN count := start; (* do "end" continuous *) WHILE count <= end DO Fill(Student[count]); INC (count); END; ELSIF option = 2 THEN Display (Student); ELSIF option = 3 THEN Curve (Student); END; UNTIL option = 4; END BadVarUse.