1. Explain all the differences between assignment
    compatibility and expression compatibility.
    Give examples.
    Two types are assignment compatible if a value of one type can be assigned into a variable of the other type. CARDINAL and INTEGER are assignment compatible (within the range of CARDINAL), but CARDINAL and REAL are not.
    Two types are expression compatible for a particular operator if that operator is defined with one operand of one type and another operand of the other type. Again, CARDINAL and INTEGER are expression compatible, but CARDINAL and REAL are not. More complex examples also exist, e.g., the compatibility rules for subranges.
  2. Explain all the differences between the built-in string concatenation operator (+) and the standard library function Strings.Concat().
    The builtin operator only works on string literals and constants. Strings.Concat(src1, src2: ARRAY OF CHAR; VAR dst: ARRAY OF CHAR) also works with string variables, concatenating src1 and src2 and storing the result in dst.
  3. Explain the advantages and disadvantages of FOR versus WHILE.
    Be specific (not just "one is more flexible").
    Any FOR loop can be rewritten as a WHILE loop, but the converse is not true. Any one of the following points is a valid answer: The loop counter in a FOR loop must proceed in order from the starting value to the ending value by the given increment; the increment cannot be changed during the course of the loop, and the loop cannot be exited prematurely. The FOR loop counter may not be threatened by code within the loop, and after the FOR loop concludes, the value of the loop control variable is undefined.
  4. The following module will not compile. What is wrong? How would you fix it?
    MODULE BuggyReadVector;
    	(* user inputs values to initialize a vector *)
    FROM SWholeIO IMPORT
    	ReadCard;
    VAR
    	myVector : ARRAY [1 .. 11] OF CARDINAL;
    	count, counter : CARDINAL;
    BEGIN
    	FOR count := 1 to 10
    		DO
    			counter := count;
    			ReadCard (count);
    			SkipLine;
    			myVector [counter] := count;
    		END;
    	myVector [counter + 1] := 11;
    END BuggyReadVector.
    

    The problem is that the FOR loop control variable (count) is threatened by the ReadCard(count) statement. If the desired semantics are to fill in the first 10 entries with user-supplied values, then the following code is one possible solution:
    MODULE FixedReadVector;
    	(* user inputs values to initialize a vector *)
    FROM SWholeIO IMPORT
    	ReadCard;
    VAR
    	myVector : ARRAY [1 .. 11] OF CARDINAL;
    	count : CARDINAL;
    BEGIN
    	FOR count := 1 TO 10
    		DO
    			ReadCard (myVector [count]);
    			SkipLine;
    		END;
    	myVector [11] := 11;
    END FixedReadVector.
    
  5. In the remainder of this exam, you will be writing up a library and test-suite for generating pseudorandom numbers: Your library should provide a Random() function, which returns a new random real between 0 and 1 each time it is invoked. There should also be a way to seed the random number generator. The default seed (if the user does not manually set it) should be 0.
    Section 7.8 (p.299) of the textbook contains a library implementation that almost completely satisfies the requirements. The lecture notes also have example code.
    1. Write a separate test suite (test harness, test framework) for your library -- a complete Modula-2 program module that imports from your library. This program should produce 1,000 random CARDINALS between 0 and 9,999 and save them into a file of the user's choosing. The numbers should be formatted ten per row, in columns: e.g.,
      	9472 3930 4876  239 1029   12 7349 1920    0 2382
      	3390 1528    3 5867 9999 8821 2002   77 1103  902
      	....
      Here's one possible implementation of the test suite:
      MODULE PseudoRandomTest;
      FROM STextIO IMPORT
        WriteString, WriteLn;
      FROM SWholeIO IMPORT
        WriteCard;
      FROM RedirStdIO IMPORT
        OpenOutput, CloseOutput;
      FROM PseudoRandom IMPORT
        Random;
      VAR
        row, col : CARDINAL;
      BEGIN
        WriteString ("This program will output 1,000 random numbers between ");
        WriteString ("0 and 9999 to a file of your choosing.");
        WriteLn;
        WriteString ("Please select a file in the popup window.");
        WriteLn;
      
        OpenOutput;
        FOR row := 1 TO 100
          DO
            FOR col := 1 TO 10
              DO
      	  WriteCard (TRUNC (10000.0 * Random()), 5);
              END;
            WriteLn;
          END;
        CloseOutput;
      
        WriteString ("All done!");
        WriteLn;
      END PseudoRandomTest.