home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol162 / interpre.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1984-04-29  |  13.1 KB  |  726 lines

  1.  
  2. {$K1} {$K2} {$K4} {$K7} {$K12} {$K13} {$K14} { symbol table space reduction }
  3.  
  4. module cpsinterpreter;
  5.  
  6.  
  7. {$I global.inc }
  8.  
  9. var
  10.    cc:    external integer;    {character counter}
  11.    lc: external integer;    {program location counter}
  12.    ll:    external integer;    {length of current line}
  13.    ch: external char;
  14.    errs: external set of er;
  15.    errpos: external  integer;
  16.    progname:external  alfa;
  17.    skipflag: external boolean;
  18.    constbegsys, typebegsys, blockbegsys, facbegsys, statbegsys: external symset;
  19.    key:external  array
  20.       [1.. nkw] of alfa;
  21.    ksy:external  array
  22.       [1.. nkw] of symbol;
  23.    sps:external  array
  24.       [char]    of symbol;             {special aymbols}
  25.    t, a, b, sx, c1, c2: external integer;    {indices to tables}
  26.    stantyps: external  typset;
  27.    display:external  array
  28.       [0.. lmax] of integer;
  29.    tab: external array
  30.       [0.. tmax] of             {identifier table}
  31.    packed record
  32.           name: alfa;
  33.           link: index;
  34.           obj: object;
  35.           typ: types;
  36.           ref: index;
  37.           normal: boolean;
  38.           lev: 0.. lmax;
  39.           adr: integer;
  40.        end;
  41.    atab: external  array
  42.       [1.. amax] of         {array-table}
  43.    packed record
  44.           inxtyp, eltyp: types;
  45.           elref, low, high,    elsize,    size: index;
  46.        end;
  47.    btab: external array
  48.       [1..bmax] of         {block-table}
  49.    packed record
  50.           last, lastpar, psize, vsize: index
  51.        end;
  52.    stab: external packed array
  53.       [0.. smax] of char;        {string table}
  54.    code: external array
  55.       [0.. cmax] of order;        { interpreter    declarations }
  56.    ir:    order;                {instruction buffer}
  57.    ps:                    {processor status}
  58.       (run, fin, divchk, inxchk, stkchk, linchk, lngchk, redchk,
  59.     deadlock);
  60.    lncnt,                {number of lines}
  61.    chrcnt: integer;            {number of characters    in lines}
  62.    h1,    h2, h3,    h4: integer;        {local variables}
  63.    s: array
  64.       [1.. stmax] of    integer;    {the stack}
  65.  
  66. {process table-one entry for each process}
  67.    ptab:  array
  68.       [ptype] of record
  69.                t, b,     {top, bottom of stack}
  70.                pc,     {program counter}
  71.                stacksize: integer;    {stack limit}
  72.                display:    array
  73.               [1..    lmax] of integer;
  74.                suspend:    integer;    {0 or    index of semaphore}
  75.                active: boolean         {procedure active flag}
  76.             end;
  77.    npr,             {number of concurrent    processes}
  78.    curpr: ptype;        {current process executing}
  79.    stepcount:  integer;        {number of steps before switch}
  80.    seed: real;            {random seed}
  81.    pflag: boolean;        {concurrent call flag    }
  82.  
  83.  
  84. function ran: real;
  85.  
  86. { random number generator. output : 0 < ran < 1 .
  87.   bowles,k. microcomputer problem solving using pascal, p. 257 }
  88.  
  89.    const
  90.       mult = 27.182813;
  91.       incr = 31.415917; 
  92.  
  93.    begin
  94.       seed := seed * mult + incr;
  95.       seed := seed - trunc(seed);
  96.       ran := seed;
  97.    end    {ran};
  98.  
  99. {functions to    convert    integers to booleans and converesely}
  100.  
  101. function itob(i: integer): boolean;
  102.  
  103.    begin
  104.       if i = tru
  105.       then
  106.       itob := true
  107.       else
  108.       itob := false
  109.    end    {itob};
  110.  
  111.  
  112. function btoi(b: boolean): integer;
  113.  
  114.    begin
  115.       if b
  116.       then
  117.       btoi := tru
  118.       else
  119.       btoi := fals
  120.    end    {btoi};
  121.  
  122.  
  123. procedure initialize;
  124.  
  125. var cpf : ptype;
  126.  
  127.    begin
  128.       s[1] := 0;
  129.       s[2] := 0;
  130.       s[3] := - 1;
  131.       s[4] := btab[1].last;
  132.       with ptab[0] do
  133.       begin
  134.          b := 0;
  135.          suspend :=    0;
  136.          display[1] := 0;
  137.          t := btab[2].vsize - 1;
  138.          pc    := tab[s[4]].adr;
  139.          active := true;
  140.          stacksize := stmax    - pmax * stkincr
  141.       end;
  142.       for cpf   := 1 to pmax do
  143.       with ptab[cpf] do
  144.          begin
  145.         active := false;
  146.         display[1] :=    0;
  147.         pc := 0;
  148.         suspend    := 0;
  149.         b := ptab[cpf - 1].stacksize + 1;
  150.         stacksize := b + stkincr - 1;
  151.         t := b - 1
  152.          end;
  153.       npr := 0;
  154.       curpr :=    0;
  155.       pflag :=    false;
  156.       seed := 1.23456789; { seed for random number generator }
  157.       stepcount := 0;
  158.       ps := run;
  159.       lncnt :=    0;
  160.       chrcnt := 0;
  161.    end    {initialize};
  162.  
  163. { because of limitations of procedure length in pascal/mt the case statement of
  164.   the interpreter has been split into four procedures.
  165. }
  166.  
  167. procedure exec1;  
  168. var hx : integer;
  169.    begin
  170.       with ptab[curpr] do
  171.       case ir.f of
  172.          0:
  173.         begin {load address}
  174.            t :=    t + 1;
  175.            if t    > stacksize
  176.            then
  177.               ps := stkchk
  178.            else
  179.               s[t] :=    display[ir.x]    + ir.y
  180.         end;
  181.          1:
  182.         begin {load value}
  183.            t :=    t + 1;
  184.            if t    > stacksize
  185.            then
  186.               ps := stkchk
  187.            else
  188.               s[t] :=    s[display[ir.x] + ir.y]
  189.         end;
  190.          2:
  191.         begin {load indirect}
  192.            t :=    t + 1;
  193.            if t    > stacksize
  194.            then
  195.               ps := stkchk
  196.            else
  197.               s[t] :=    s[s[display[ir.x] +    ir.y]]
  198.         end;
  199.          3:
  200.         begin {update display}
  201.            h1 := ir.y;
  202.            h2 := ir.x;
  203.            h3 := b;
  204.            repeat
  205.               display[h1] := h3;
  206.               h1 := h1 - 1;
  207.               h3 := s[h3 + 2]
  208.            until h1 = h2
  209.         end;
  210.          4:    {cobegin}
  211.         pflag := true;
  212.          5:    {coend}
  213.         begin
  214.            pflag := false;
  215.            ptab[0].active := false
  216.         end;
  217.          6:
  218.         begin {wait}
  219.            h1 := s[t];
  220.            t :=    t - 1;
  221.            if s[h1] >    0
  222.            then
  223.               s[h1] := s[h1] - 1
  224.            else
  225.               begin
  226.              suspend := h1;
  227.              stepcount := 0
  228.               end
  229.         end;
  230.          7:
  231.         begin {signal}
  232.            h1 := s[t];
  233.            t :=    t - 1;
  234.            h2 := pmax +    1;
  235.            h3 := trunc(ran * h2);
  236.            while (h2 >=    0) and (ptab[h3].suspend <> h1) do
  237.               begin
  238.              h3 := (h3 + 1)    mod (pmax + 1);
  239.              h2 := h2 - 1
  240.               end;
  241.            if h2 < 0
  242.            then
  243.               s[h1] := s[h1] + 1
  244.            else
  245.               ptab[h3].suspend := 0
  246.         end;
  247.          8:
  248.         case ir.y of
  249.            17:
  250.               begin
  251.              t := t    + 1;
  252.              if t >    stacksize
  253.              then
  254.                 ps := stkchk
  255.              else
  256.                 s[t] := btoi(eof(input))
  257.               end;
  258.            18:
  259.               begin
  260.              t := t    + 1;
  261.              if t >    stacksize
  262.              then
  263.                 ps := stkchk
  264.              else
  265.                 s[t] := btoi(eoln(input))
  266.               end;
  267.         end;
  268.          10:
  269.         pc := ir.y;    {jump}
  270.          11:
  271.         begin {conditional jump}
  272.            if s[t] = fals then
  273.               pc := ir.y;
  274.            t :=    t - 1
  275.         end;
  276.          14:
  277.         begin {for1up}
  278.            h1 := s[t -    1];
  279.            if h1 <= s[t]
  280.            then
  281.               s[s[t -    2]] := h1
  282.            else
  283.               begin
  284.              t := t    - 3;
  285.              pc := ir.y
  286.               end
  287.         end;
  288.       end;
  289.    end    {exec1};
  290.  
  291. procedure exec2;
  292. var hx :integer;
  293.  
  294.    begin
  295.       with ptab[curpr] do
  296.       case ir.f of
  297.          15:
  298.         begin {for2up}
  299.            h2 := s[t -    2];
  300.            h1 := s[h2] + 1;
  301.            if h1 <= s[t]
  302.            then
  303.               begin
  304.              s[h2] := h1;
  305.              pc := ir.y
  306.               end
  307.            else
  308.               t    := t - 3;
  309.         end;
  310.          18:
  311.         begin
  312.            h1 := btab[tab[ir.y].ref].vsize;
  313.            if t    + h1 > stacksize
  314.            then
  315.               ps := stkchk
  316.            else
  317.               begin
  318.              t := t    + 5;
  319.              s[t -    1] := h1 - 1;
  320.              s[t]    := ir.y
  321.               end;
  322.         end;
  323.          19:
  324.         begin
  325.            active := true;
  326.            h1 := t - ir.y;
  327.            h2 := s[h1 + 4];    {h2 points to    tab}
  328.            h3 := tab[h2].lev;
  329.            display[h3 + 1] :=    h1;
  330.            h4 := s[h1 + 3] + h1;
  331.            s[h1 + 1] := pc;
  332.            s[h1 + 2] := display[h3];
  333.            if pflag
  334.            then
  335.               s[h1 + 3] := ptab[0].b
  336.            else
  337.               s[h1 + 3] := b;
  338.            for hx := t + 1 to h4 do
  339.               s[hx] := 0;
  340.            b :=    h1;
  341.            t :=    h4;
  342.            pc := tab[h2].adr
  343.         end;
  344.          21:
  345.         begin {index}
  346.            h1 := ir.y;    {h1 points to    atab}
  347.            h2 := atab[h1].low;
  348.            h3 := s[t];
  349.            if h3 < h2
  350.            then
  351.               ps := inxchk
  352.            else
  353.               if h3 > atab[h1].high
  354.               then
  355.              ps := inxchk
  356.               else
  357.              begin
  358.                 t := t - 1;
  359.                 s[t] := s[t] + (h3 - h2) * atab[h1].
  360.                    elsize
  361.              end
  362.         end;
  363.          22:
  364.         begin {load block}
  365.            h1 := s[t];
  366.            t :=    t - 1;
  367.            h2 := ir.y +    t;
  368.            if h2 > stacksize
  369.            then
  370.               ps := stkchk
  371.            else
  372.               while t <    h2 do
  373.              begin
  374.                 t := t + 1;
  375.                 s[t] := s[h1];
  376.                 h1 := h1 + 1
  377.              end
  378.         end;
  379.          23:
  380.         begin {copy block}
  381.            h1 := s[t -    1];
  382.            h2 := s[t];
  383.            h3 := h1 + ir.y;
  384.            while h1 < h3 do
  385.               begin
  386.              s[h1] := s[h2];
  387.              h1 := h1 + 1;
  388.              h2 := h2 + 1
  389.               end;
  390.            t :=    t - 2
  391.         end;
  392.       end;
  393.    end    {exec1};
  394.  
  395.  
  396.  
  397. procedure exec4;
  398. var hx :integer;
  399.  
  400.    begin
  401.       with ptab[curpr] do
  402.       case ir.f of
  403.          38:
  404.         begin {store}
  405.            s[s[t - 1]] := s[t];
  406.            t :=    t - 2
  407.         end;
  408.          45:
  409.         begin
  410.            t :=    t - 1;
  411.            s[t] := btoi(s[t] = s[t+ 1])
  412.         end;
  413.          46:
  414.         begin
  415.            t :=    t - 1;
  416.            s[t] := btoi(s[t] <> s[t + 1])
  417.         end;
  418.          47:
  419.         begin
  420.            t :=    t - 1;
  421.            s[t] := btoi(s[t] < s[t    + 1])
  422.         end;
  423.          48:
  424.         begin
  425.            t :=    t - 1;
  426.            s[t] := btoi(s[t] <= s[t + 1])
  427.         end;
  428.          49:
  429.         begin
  430.            t :=    t - 1;
  431.            s[t] := btoi(s[t] > s[t    + 1])
  432.         end;
  433.          50:
  434.          begin
  435.            t :=    t - 1;
  436.            s[t] := btoi(s[t] >= s[t + 1])
  437.         end;
  438.          51:
  439.         begin
  440.            t :=    t - 1;
  441.            s[t] := btoi(itob(s[t]) or itob(s[t + 1]))
  442.         end;
  443.          52:
  444.         begin
  445.            t :=    t - 1;
  446.            s[t] := s[t] + s[t + 1]
  447.         end;
  448.          53:
  449.         begin
  450.            t :=    t - 1;
  451.            s[t] := s[t] - s[t + 1]
  452.         end;
  453.          56:
  454.         begin
  455.            t :=    t - 1;
  456.            s[t] := btoi(itob(s[t]) and itob(s[t + 1]))
  457.         end;
  458.          57:
  459.         begin
  460.            t :=    t - 1;
  461.            s[t] := s[t] * s[t + 1]
  462.         end;
  463.          58:
  464.         begin
  465.            t :=    t - 1;
  466.            if s[t + 1] = 0
  467.            then
  468.               ps := divchk
  469.            else
  470.               s[t] :=    s[t] div s[t    + 1]
  471.         end;
  472.          59:
  473.         begin
  474.            t :=    t - 1;
  475.            if s[t + 1] = 0
  476.            then
  477.               ps := divchk
  478.            else
  479.               s[t] :=    s[t] mod s[t    + 1]
  480.         end;
  481.          62:
  482.         if eof(input)
  483.         then
  484.            ps := redchk
  485.         else
  486.            readln;
  487.          63:
  488.         begin
  489.            writeln;
  490.            lncnt := lncnt + 1;
  491.            chrcnt := 0;
  492.            if lncnt > linelimit    then
  493.               ps := linchk
  494.         end
  495.       end;
  496.    end    {exec1};
  497.  
  498.  
  499.  
  500. procedure exec3;
  501.  
  502.    begin
  503.       with ptab[curpr] do
  504.       case ir.f of
  505.          24:
  506.         begin {literal}
  507.            t :=    t + 1;
  508.            if t    > stacksize
  509.            then
  510.               ps := stkchk
  511.            else
  512.               s[t] :=    ir.y
  513.         end;
  514.          27:
  515.         begin {read}
  516.            if eof(input)
  517.            then
  518.               ps := redchk
  519.            else
  520.               case ir.y    of
  521.              1:
  522.                 read(s[s[t]]);
  523.              3:
  524.                 begin
  525.                    read(ch);
  526.                    s[s[t]] := ord(ch)
  527.                 end;
  528.               end;
  529.            t :=    t - 1
  530.         end;
  531.          28:
  532.         begin {write string}
  533.            h1 := s[t];
  534.            h2 := ir.y;
  535.            t :=    t - 1;
  536.            chrcnt := chrcnt + h1;
  537.            if chrcnt > lineleng    then
  538.               ps := lngchk;
  539.            repeat
  540.               write(stab[h2]);
  541.               h1 := h1 - 1;
  542.               h2 := h2 + 1
  543.            until h1 = 0
  544.         end;
  545.          29:
  546.         begin {write1}
  547.            if ir.y = 3
  548.            then
  549.               h1 := 1
  550.            else
  551.               h1 := 10;
  552.            chrcnt := chrcnt + h1;
  553.            if chrcnt > lineleng
  554.            then
  555.               ps := lngchk
  556.            else
  557.               case ir.y    of
  558.              1:
  559.                 write(s[t]);
  560.              2:
  561.                 write(itob(s[t]));
  562.              3:
  563.                 if (s[t] < charl)    or (s[t] > charh)
  564.                 then
  565.                    ps := inxchk
  566.                 else
  567.                    write(chr(s[t]))
  568.               end;
  569.            t :=    t - 1
  570.         end;
  571.          31:
  572.         ps := fin;
  573.          32:
  574.         begin
  575.            t :=    b - 1;
  576.            pc := s[b +    1];
  577.            if pc <> 0
  578.            then
  579.               b    := s[b    + 3]
  580.            else
  581.               begin
  582.              npr :=    npr - 1;
  583.              active    := false;
  584.              stepcount := 0;
  585.              ptab[0].active := (npr = 0)
  586.               end
  587.         end;
  588.          33:
  589.         begin {exit function}
  590.            t :=    b;
  591.            pc := s[b +    1];
  592.            b :=    s[b + 3]
  593.         end;
  594.          34:
  595.         s[t] := s[s[t]];
  596.          35:
  597.         s[t] := btoi(not (itob(s[t])));
  598.          36:
  599.         s[t] := - s[t];
  600.       end {case};
  601.    end    {exec3};
  602.  
  603.  
  604. procedure interpret;
  605. var hx:integer;
  606.    label
  607.       97, 98;
  608.  
  609.  
  610.    procedure chooseproc;
  611.  
  612. {from    a random starting point    search for a process that is active and
  613. not suspended.    d aborts the interpreter if a deadlock occurs.}
  614.  
  615.       var
  616.       d: integer;
  617.  
  618.       begin
  619.       d := pmax + 1;
  620.       curpr    := (curpr + trunc(ran *    pmax)) mod (pmax + 1);
  621.       while    ((not ptab[curpr].active) or (ptab[curpr].suspend <>
  622.          0)) and (d    >= 0) do
  623.          begin
  624.         d := d - 1;
  625.         curpr := (curpr    + 1) mod (pmax + 1)
  626.          end;
  627.       if d < 0
  628.       then
  629.          begin
  630.         ps := deadlock;
  631.         writeln('deadlock');
  632.         readln;
  633.          end
  634.       else
  635.          stepcount := trunc(ran * stepmax);
  636.       end {chooseproc};
  637.  
  638.  
  639.    begin {interpret}
  640.       initialize;
  641.       repeat
  642.       if ptab[0].active
  643.       then
  644.          curpr := 0
  645.       else
  646.          if    stepcount = 0
  647.          then
  648.         chooseproc
  649.          else
  650.         stepcount := stepcount - 1;
  651.       with ptab[curpr] do
  652.          begin
  653.         ir := code[pc];
  654.         pc := pc + 1
  655.          end;
  656.       if pflag then
  657.          begin
  658.         if ir.f    = 18 {markstack} then
  659.            npr := npr +    1;
  660.         curpr := npr
  661.          end;
  662.       with ptab[curpr] do
  663.       begin 
  664.          if    ir.f < 15
  665.          then
  666.         exec1
  667.          else if ir.f < 24 
  668.          then exec2
  669.          else if ir.f < 37
  670.          then exec3
  671.          else exec4;
  672.     end;    
  673.       until ps    <> run;
  674.   98: writeln;
  675.       if ps <>    fin
  676.       then
  677.       begin
  678.          with ptab[curpr]    do
  679.         write('    halt at', pc: 3, ' in process',    curpr: 4,
  680.            ' because of    ');
  681.          case ps of
  682.         deadlock:
  683.            writeln('deadlock');
  684.         divchk:
  685.            writeln('division by    0');
  686.         inxchk:
  687.            writeln('invalid index');
  688.         stkchk:
  689.            writeln('storage overflow');
  690.         linchk:
  691.            writeln('too    much output');
  692.         lngchk:
  693.            writeln('linr too long');
  694.         redchk:
  695.            writeln('reading past end of    file');
  696.          end;
  697.          writeln('process active suspend pc');
  698.          for hx := 0 to pmax do
  699.         with ptab[hx]    do
  700.            writeln(hx: 4,' ':4,active:6,' ',suspend:4,' ':4,pc);
  701.          writeln;
  702.          writeln('global variables');
  703.          for hx := btab[1].last +    1 to tmax do
  704.         with tab[hx] do
  705.            if lev <> 1
  706.            then
  707.               goto 97
  708.            else
  709.               if obj = variable
  710.               then
  711.              if typ    in stantyps
  712.              then
  713.                 case typ of
  714.                    ints:
  715.                   writeln(name,    ' = ', s[adr]);
  716.                    bools:
  717.                   writeln(name,    ' = ', itob(s[adr]));
  718.                    chars:
  719.                   writeln(name,    ' = ', chr(s[adr] { mod
  720.                   64}));
  721.                 end;
  722.       end;
  723.   97: writeln
  724.    end    {interpret};
  725. modend.
  726.