Chapter 11
Keywords: pame

#
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