Chapter 11

[*]Ex 11.1
   PROGRAM ex11 1 CONTEXT VOID
   USE standard
   BEGIN
      []CHAR digits =
            "0123456789abcdef"[@0];

      PROC itostr = (INT n,r#adix#)STRING:
      IF n<r
      THEN digits[n]
      ELSE itostr(n%r,r)+digits[n%*r]
      FI;

      print(("Table of numbers 0--15",
             newline,newline,
             "Dec. Hex. Binary",newline));

      FOR i FROM 0 TO 15
      DO
         STRING bin = itostr(i,2),
                dec = itostr(i,10),
                hex = digits[i];
                #only one digit#
         print(((4-UPB dec)*blank,
                dec,3*blank,hex,
                4*blank,(4-UPB bin)*"0",
                bin,newline))
      OD
   END
   FINISH
[*]Ex 11.2

(a)

9410 =5×161+14×160
=5e16

(b)

1310 =1×23+×22+0×21+1×20
=11012

(c)

1111 10012 = f916  

(d)

3e116 = 3×162 + e×161 +1×160  
  = 3×256 + 14×16 + 1  
  = 768 + 224 + 1  
  = 99310  

(e)
2c16 = 0010 11002.
(f)

101012 = 1×24 +1×22 +1×20  
  = 16 + 4 + 1  
  = 2110  

[*]Ex 11.3

(a)
10112
(b)
e316
(c)
568

[*]Ex 11.4

(a)
16r 0101 0101
(b)
16r 99bb ddff
(c)
16r 6745 2301
(d)
FALSE
[*]Ex 11.5

(a)
16r 558
(b)
16r 17

[*]Ex 11.6
   PROC transpose=(REF[,]INT m)VOID:
   IF   1 UPB m - 1 LWB m
               =
        2 UPB m - 2 LWB m
   THEN #m is square#
      REF[,]INT mm=m[@1,@1]; #a precaution#

      FOR i TO 1 UPB mm - 1
      DO
         REF[]INT mr=mm[i,i+1:],
                  mc=mm[i+1:,i];
         []INT temp=mr;
         mr:=mc;  mc:=temp
      OD
   FI

[*]Ex 11.7
Use a cast: REF REAL(xx):=120.5
[*]Ex 11.8
   REF REF[]CHAR rrq;
   []CHAR m = "ABCDEFGHIJ";
   rrq:=LOC REF[]CHAR:=LOC[10]CHAR:=m[@1];
[*]Ex 11.9

   REF FLEX[]INT rfi;
   rfi:=FLEX[1:0]INT:=(3,-2,4)

[*]Ex 11.10
f has the mode REF STRING and ss has the mode REF REF STRING.
[*]Ex 11.11
The multiple of mode STRING whose value is "Joan of Arc".
[*]Ex 11.12
f[3:4]=s[7:8]. The modes are both STRING.
[*]Ex 11.13
Here are three possible answers:
   REF STRING(ff) IS ss
   ff IS REF STRING(ss)
   REF STRING(ff) IS REF STRING(ss)
You could also use ISNT, :=: or :/=:.

[*]Ex 11.14

(a)
A name of mode REF REF FILE.
(b)
TRUE        BOOL.
(c)
A name of mode REF FILE.
(d)
FALSE        BOOL.
[*]Ex 11.15

(a)
REF FILE
(b)
REF REF FILE

[*]Ex 11.16
REF REF QUEUE(tail):=
        LOC QUEUE:=(("Barbara",3),nilq)
[*]Ex 11.17
tail:=next OF tail
[*]Ex 11.18
No.

[*]Ex 11.19
   PROC add fan=(REF REF REF QUEUE
                    head,tail,
                 REF FAN fan)VOID:
      tail:=next OF (REF REF QUEUE
             (head IS nilq|head|tail):=
                HEAP QUEUE:=(fan,nilq))
[*]Ex 11.20
   PROGRAM ex11 20 CONTEXT VOID
   USE standard
   BEGIN
      MODE FAN = STRUCT(STRING name,
                        INT ticket),
         QUEUE = STRUCT(FAN fan,
                        REF QUEUE next);

      REF QUEUE nilq = NIL;

      PROC add fan=(REF REF REF QUEUE
                        head,tail,
                    REF FAN fan)VOID:
         tail:=next OF
                (REF REF QUEUE
                  (head IS nilq|head|tail)
                     :=HEAP QUEUE
                     :=(fan,nilq);

      REF REF QUEUE head,tail;
      head:=tail:=LOC REF QUEUE:=nilq;

      FOR q TO 1000
      DO
         add fan(head,tail,
                 LOC FAN:=(IF ODD q
                           THEN "Iain"
                           ELSE "Fiona"
                           FI,
                           q))
      OD
   END
   FINISH
The generator LOC FAN is used because add fan requires a parameter of mode REF FAN. The scope of the generated name is from the declarations of head and tail to the end of the program because there are no identity declarations in the FOR loop clause (therefore it is not a range).

[*]Ex 11.21
Because marker has mode REF REF QUEUE, it is made to refer to each REF QUEUE name in the linked-list. The condition
   next OF marker ISNT nilq
ensures that marker is not currently referring to the last REF QUEUE in the list. The loop will terminate when marker refers to the last REF QUEUE in the list or the number of the ticket of the fan to be inserted in the queue does not exceed the number of the ticket of the fan referred to by marker.


If the operator AND had been used, both operands would have been elaborated before the operator; in which case, if the left operand had yielded FALSE, elaboration of the right operand would have caused the run-time error "Selection from NIL".

[*]Ex 11.22
This can best be done by writing a program. Here is a possible solution:-
   PROGRAM ex11 22 CONTEXT VOID
   USE standard
   BEGIN
      MODE FAN = STRUCT(STRING name,
                        INT ticket),
         QUEUE = STRUCT(FAN fan,
                        REF QUEUE next);
      REF QUEUE nilq = NIL;

      PROC insert fan = . . .
      . . .
      PROC print queue = . . .
      . . .
      REF REF QUEUE head,tail;
      head:=tail:=LOC REF QUEUE:=nilq;
      INT max ticket = 1000;
      INT tickets issued:=0;
      [max ticket]BOOL ticket issued;

      FOR i
      FROM LWB ticket issued
      TO UPB ticket issued
      DO FALSE OD;

      WHILE tickets issued < max ticket
      DO
         INT i=random int(max ticket);
         IF REF BOOL ti=ticket issued[i];
            NOT ti
         THEN
            ti:=TRUE;
            insert fan(head,tail,HEAP FAN:=
                       ((ODD i
                        |"Iain"
                        |"Fiona"
                        ),i));
            tickets issued+:=1
         FI
      OD #fans added to the queue#;

      print queue(head)
   END FINISH
Instead of sending the output to stand out, it would be better to direct it to an output book so that the results could be examined at leisure. Alternatively, command line redirection could be used. The use of ticket issued ensures that unique ticket numbers are added to the queue since insert fan does not cater explicitly for duplicate ticket numbers.
[*]Ex 11.23
The procedure has to find the fan concerned and must keep track of the reference to that fan.
   PROC delete fan=(REF REF QUEUE q,
                    INT t#icket#
                   )UNION(REF FAN,BOOL):
   IF   q IS nilq
   THEN FALSE #empty queue#
   ELIF next OF q IS nilq
   THEN #last fan in the queue#
      IF   ticket OF q = t
      THEN REF FAN rf = q;
         q:=nilq;  #delete last fan#
         rf
      ELSE FALSE
      FI
   ELIF ticket OF next OF q < t
   THEN delete fan(next OF q,t)
   ELIF ticket OF next OF q > t
   THEN #not found# FALSE
   ELSE REF FAN rf = next OF q;
      next OF q:=next OF next OF q;
      rf
   FI #delete fan#;
In the assignment, the mode of next OF q is REF REF QUEUE, so the mode of next OF next OF q must be REF QUEUE. Look at the required dereferencing to see what is assigned to next OF q.

[*]Ex 11.24

   PROGRAM ex11 24 CONTEXT VOID
   USE standard
   BEGIN
      MODE
      LETTER=STRUCT(CHAR c,INT o),
      TREE=STRUCT(REF LETTER l,
                  REF TREE left,right);

      REF TREE leaf=NIL;
      REF TREE root:=leaf;

      PROC get letter=(REF FILE f)
                        REF LETTER:
      IF   CHAR ch;  get(f,ch);
           ch>="A" & ch<="Z"
                  OR
           ch>="a" & ch<="z"
      THEN HEAP LETTER:=(ch,1)
      ELSE get letter(f) #skip non-letters#
      FI #get letter#;

      PROC add letter=
            (REF REF TREE root,
             REF LETTER let)VOID:
      IF   root IS leaf
      THEN root:=HEAP TREE:=(let,leaf,leaf)
      ELIF c OF l OF root > c OF let
      THEN add letter(left OF root,let)
      ELIF c OF l OF root < c OF let
      THEN add letter(right OF root,let)
      ELSE o OF l OF root+:=1
      FI #add letter#;

      FILE inf, arg;
      STRING in bk;

      INT max row=13;
      [max row,81]CHAR out page;
      INT row:=max row, col:=0;

      FOR i TO max row
      DO
         out page[i,:80]:=80*blank;
         out page[i,81]:=lf
      OD #initialise out page#;

      INT num letters:=0;

      PROC put letter=(REF LETTER let)VOID:
      BEGIN
         IF   row=max row
         THEN col+:=1;  row:=1
         ELSE row+:=1
         FI;
         FILE f;
         establish(f,
                   "",
                   mem channel,
                   1,1,20);
         put(f,(c OF let,
                fixed(o OF let/
                        num letters*100,
                      -7,2),blank*12));
         out page[row,(col-1)*20+1:col*20]
           :=file buffer(f);
         close(f)
      END #put letter#;

      PROC print tree=
            (REF REF TREE root)VOID:
      IF   root ISNT leaf
      THEN
         print tree(left OF root);
         IF o OF l OF root > 0
         THEN put letter(l OF root)
         FI;
         print tree(right OF root)
      FI #print tree#;

      IF open(arg,"",arg channel)/=0
      THEN
         put(stand error,
             ("Cannot access arguments",
              newline));
         stop
      ELIF
         on logical file end(arg,
          (REF FILE f)BOOL:
           (put(stand error,
             ("Usage: tt in-book",
              newline)); stop; SKIP));
         get(arg,(LOC STRING,
                  LOC CHAR,
                  in bk));
         open(inf,
              in bk,
              stand in channel)/=0
      THEN
         put(stand error,
             ("Cannot open book ",in bk,
              newline));
         stop
      ELSE
         on logical file end(inf,
          (REF FILE f)BOOL:
           (
            print tree(root);
            print((
               "Frequency of occurrence ",
               "of letters in the book ",
               idf(f),newline,
               newline,out page,newline,
               "Total letters read: ",
               whole(num letters,0),
               newline));
            stop;  SKIP
           ))
      FI;

      FOR i TO 26 #letters in the alphabet#
      DO
         add letter(
            root,
            HEAP LETTER:=
             (REPR(ABS("A")-1+i),0));
         add letter(
            root,
            HEAP LETTER:=
             (REPR(ABS("a")-1+i),0))
      OD #all letters are now in the tree#;

      DO
         add letter(root,get letter(inf));
         num letters+:=1
      OD
   END
   FINISH
Sian Mountbatten 2012-01-19