home *** CD-ROM | disk | FTP | other *** search
-
- {$K1} {$K2} {$K4} {$K7} {$K12} {$K13} {$K14} { symbol table space reduction }
-
- module cpsinterpreter;
-
-
- {$I global.inc }
-
- var
- cc: external integer; {character counter}
- lc: external integer; {program location counter}
- ll: external integer; {length of current line}
- ch: external char;
- errs: external set of er;
- errpos: external integer;
- progname:external alfa;
- skipflag: external boolean;
- constbegsys, typebegsys, blockbegsys, facbegsys, statbegsys: external symset;
- key:external array
- [1.. nkw] of alfa;
- ksy:external array
- [1.. nkw] of symbol;
- sps:external array
- [char] of symbol; {special aymbols}
- t, a, b, sx, c1, c2: external integer; {indices to tables}
- stantyps: external typset;
- display:external array
- [0.. lmax] of integer;
- tab: external array
- [0.. tmax] of {identifier table}
- packed record
- name: alfa;
- link: index;
- obj: object;
- typ: types;
- ref: index;
- normal: boolean;
- lev: 0.. lmax;
- adr: integer;
- end;
- atab: external array
- [1.. amax] of {array-table}
- packed record
- inxtyp, eltyp: types;
- elref, low, high, elsize, size: index;
- end;
- btab: external array
- [1..bmax] of {block-table}
- packed record
- last, lastpar, psize, vsize: index
- end;
- stab: external packed array
- [0.. smax] of char; {string table}
- code: external array
- [0.. cmax] of order; { interpreter declarations }
- ir: order; {instruction buffer}
- ps: {processor status}
- (run, fin, divchk, inxchk, stkchk, linchk, lngchk, redchk,
- deadlock);
- lncnt, {number of lines}
- chrcnt: integer; {number of characters in lines}
- h1, h2, h3, h4: integer; {local variables}
- s: array
- [1.. stmax] of integer; {the stack}
-
- {process table-one entry for each process}
- ptab: array
- [ptype] of record
- t, b, {top, bottom of stack}
- pc, {program counter}
- stacksize: integer; {stack limit}
- display: array
- [1.. lmax] of integer;
- suspend: integer; {0 or index of semaphore}
- active: boolean {procedure active flag}
- end;
- npr, {number of concurrent processes}
- curpr: ptype; {current process executing}
- stepcount: integer; {number of steps before switch}
- seed: real; {random seed}
- pflag: boolean; {concurrent call flag }
-
-
- function ran: real;
-
- { random number generator. output : 0 < ran < 1 .
- bowles,k. microcomputer problem solving using pascal, p. 257 }
-
- const
- mult = 27.182813;
- incr = 31.415917;
-
- begin
- seed := seed * mult + incr;
- seed := seed - trunc(seed);
- ran := seed;
- end {ran};
-
- {functions to convert integers to booleans and converesely}
-
- function itob(i: integer): boolean;
-
- begin
- if i = tru
- then
- itob := true
- else
- itob := false
- end {itob};
-
-
- function btoi(b: boolean): integer;
-
- begin
- if b
- then
- btoi := tru
- else
- btoi := fals
- end {btoi};
-
-
- procedure initialize;
-
- var cpf : ptype;
-
- begin
- s[1] := 0;
- s[2] := 0;
- s[3] := - 1;
- s[4] := btab[1].last;
- with ptab[0] do
- begin
- b := 0;
- suspend := 0;
- display[1] := 0;
- t := btab[2].vsize - 1;
- pc := tab[s[4]].adr;
- active := true;
- stacksize := stmax - pmax * stkincr
- end;
- for cpf := 1 to pmax do
- with ptab[cpf] do
- begin
- active := false;
- display[1] := 0;
- pc := 0;
- suspend := 0;
- b := ptab[cpf - 1].stacksize + 1;
- stacksize := b + stkincr - 1;
- t := b - 1
- end;
- npr := 0;
- curpr := 0;
- pflag := false;
- seed := 1.23456789; { seed for random number generator }
- stepcount := 0;
- ps := run;
- lncnt := 0;
- chrcnt := 0;
- end {initialize};
-
- { because of limitations of procedure length in pascal/mt the case statement of
- the interpreter has been split into four procedures.
- }
-
- procedure exec1;
- var hx : integer;
- begin
- with ptab[curpr] do
- case ir.f of
- 0:
- begin {load address}
- t := t + 1;
- if t > stacksize
- then
- ps := stkchk
- else
- s[t] := display[ir.x] + ir.y
- end;
- 1:
- begin {load value}
- t := t + 1;
- if t > stacksize
- then
- ps := stkchk
- else
- s[t] := s[display[ir.x] + ir.y]
- end;
- 2:
- begin {load indirect}
- t := t + 1;
- if t > stacksize
- then
- ps := stkchk
- else
- s[t] := s[s[display[ir.x] + ir.y]]
- end;
- 3:
- begin {update display}
- h1 := ir.y;
- h2 := ir.x;
- h3 := b;
- repeat
- display[h1] := h3;
- h1 := h1 - 1;
- h3 := s[h3 + 2]
- until h1 = h2
- end;
- 4: {cobegin}
- pflag := true;
- 5: {coend}
- begin
- pflag := false;
- ptab[0].active := false
- end;
- 6:
- begin {wait}
- h1 := s[t];
- t := t - 1;
- if s[h1] > 0
- then
- s[h1] := s[h1] - 1
- else
- begin
- suspend := h1;
- stepcount := 0
- end
- end;
- 7:
- begin {signal}
- h1 := s[t];
- t := t - 1;
- h2 := pmax + 1;
- h3 := trunc(ran * h2);
- while (h2 >= 0) and (ptab[h3].suspend <> h1) do
- begin
- h3 := (h3 + 1) mod (pmax + 1);
- h2 := h2 - 1
- end;
- if h2 < 0
- then
- s[h1] := s[h1] + 1
- else
- ptab[h3].suspend := 0
- end;
- 8:
- case ir.y of
- 17:
- begin
- t := t + 1;
- if t > stacksize
- then
- ps := stkchk
- else
- s[t] := btoi(eof(input))
- end;
- 18:
- begin
- t := t + 1;
- if t > stacksize
- then
- ps := stkchk
- else
- s[t] := btoi(eoln(input))
- end;
- end;
- 10:
- pc := ir.y; {jump}
- 11:
- begin {conditional jump}
- if s[t] = fals then
- pc := ir.y;
- t := t - 1
- end;
- 14:
- begin {for1up}
- h1 := s[t - 1];
- if h1 <= s[t]
- then
- s[s[t - 2]] := h1
- else
- begin
- t := t - 3;
- pc := ir.y
- end
- end;
- end;
- end {exec1};
-
- procedure exec2;
- var hx :integer;
-
- begin
- with ptab[curpr] do
- case ir.f of
- 15:
- begin {for2up}
- h2 := s[t - 2];
- h1 := s[h2] + 1;
- if h1 <= s[t]
- then
- begin
- s[h2] := h1;
- pc := ir.y
- end
- else
- t := t - 3;
- end;
- 18:
- begin
- h1 := btab[tab[ir.y].ref].vsize;
- if t + h1 > stacksize
- then
- ps := stkchk
- else
- begin
- t := t + 5;
- s[t - 1] := h1 - 1;
- s[t] := ir.y
- end;
- end;
- 19:
- begin
- active := true;
- h1 := t - ir.y;
- h2 := s[h1 + 4]; {h2 points to tab}
- h3 := tab[h2].lev;
- display[h3 + 1] := h1;
- h4 := s[h1 + 3] + h1;
- s[h1 + 1] := pc;
- s[h1 + 2] := display[h3];
- if pflag
- then
- s[h1 + 3] := ptab[0].b
- else
- s[h1 + 3] := b;
- for hx := t + 1 to h4 do
- s[hx] := 0;
- b := h1;
- t := h4;
- pc := tab[h2].adr
- end;
- 21:
- begin {index}
- h1 := ir.y; {h1 points to atab}
- h2 := atab[h1].low;
- h3 := s[t];
- if h3 < h2
- then
- ps := inxchk
- else
- if h3 > atab[h1].high
- then
- ps := inxchk
- else
- begin
- t := t - 1;
- s[t] := s[t] + (h3 - h2) * atab[h1].
- elsize
- end
- end;
- 22:
- begin {load block}
- h1 := s[t];
- t := t - 1;
- h2 := ir.y + t;
- if h2 > stacksize
- then
- ps := stkchk
- else
- while t < h2 do
- begin
- t := t + 1;
- s[t] := s[h1];
- h1 := h1 + 1
- end
- end;
- 23:
- begin {copy block}
- h1 := s[t - 1];
- h2 := s[t];
- h3 := h1 + ir.y;
- while h1 < h3 do
- begin
- s[h1] := s[h2];
- h1 := h1 + 1;
- h2 := h2 + 1
- end;
- t := t - 2
- end;
- end;
- end {exec1};
-
-
-
- procedure exec4;
- var hx :integer;
-
- begin
- with ptab[curpr] do
- case ir.f of
- 38:
- begin {store}
- s[s[t - 1]] := s[t];
- t := t - 2
- end;
- 45:
- begin
- t := t - 1;
- s[t] := btoi(s[t] = s[t+ 1])
- end;
- 46:
- begin
- t := t - 1;
- s[t] := btoi(s[t] <> s[t + 1])
- end;
- 47:
- begin
- t := t - 1;
- s[t] := btoi(s[t] < s[t + 1])
- end;
- 48:
- begin
- t := t - 1;
- s[t] := btoi(s[t] <= s[t + 1])
- end;
- 49:
- begin
- t := t - 1;
- s[t] := btoi(s[t] > s[t + 1])
- end;
- 50:
- begin
- t := t - 1;
- s[t] := btoi(s[t] >= s[t + 1])
- end;
- 51:
- begin
- t := t - 1;
- s[t] := btoi(itob(s[t]) or itob(s[t + 1]))
- end;
- 52:
- begin
- t := t - 1;
- s[t] := s[t] + s[t + 1]
- end;
- 53:
- begin
- t := t - 1;
- s[t] := s[t] - s[t + 1]
- end;
- 56:
- begin
- t := t - 1;
- s[t] := btoi(itob(s[t]) and itob(s[t + 1]))
- end;
- 57:
- begin
- t := t - 1;
- s[t] := s[t] * s[t + 1]
- end;
- 58:
- begin
- t := t - 1;
- if s[t + 1] = 0
- then
- ps := divchk
- else
- s[t] := s[t] div s[t + 1]
- end;
- 59:
- begin
- t := t - 1;
- if s[t + 1] = 0
- then
- ps := divchk
- else
- s[t] := s[t] mod s[t + 1]
- end;
- 62:
- if eof(input)
- then
- ps := redchk
- else
- readln;
- 63:
- begin
- writeln;
- lncnt := lncnt + 1;
- chrcnt := 0;
- if lncnt > linelimit then
- ps := linchk
- end
- end;
- end {exec1};
-
-
-
- procedure exec3;
-
- begin
- with ptab[curpr] do
- case ir.f of
- 24:
- begin {literal}
- t := t + 1;
- if t > stacksize
- then
- ps := stkchk
- else
- s[t] := ir.y
- end;
- 27:
- begin {read}
- if eof(input)
- then
- ps := redchk
- else
- case ir.y of
- 1:
- read(s[s[t]]);
- 3:
- begin
- read(ch);
- s[s[t]] := ord(ch)
- end;
- end;
- t := t - 1
- end;
- 28:
- begin {write string}
- h1 := s[t];
- h2 := ir.y;
- t := t - 1;
- chrcnt := chrcnt + h1;
- if chrcnt > lineleng then
- ps := lngchk;
- repeat
- write(stab[h2]);
- h1 := h1 - 1;
- h2 := h2 + 1
- until h1 = 0
- end;
- 29:
- begin {write1}
- if ir.y = 3
- then
- h1 := 1
- else
- h1 := 10;
- chrcnt := chrcnt + h1;
- if chrcnt > lineleng
- then
- ps := lngchk
- else
- case ir.y of
- 1:
- write(s[t]);
- 2:
- write(itob(s[t]));
- 3:
- if (s[t] < charl) or (s[t] > charh)
- then
- ps := inxchk
- else
- write(chr(s[t]))
- end;
- t := t - 1
- end;
- 31:
- ps := fin;
- 32:
- begin
- t := b - 1;
- pc := s[b + 1];
- if pc <> 0
- then
- b := s[b + 3]
- else
- begin
- npr := npr - 1;
- active := false;
- stepcount := 0;
- ptab[0].active := (npr = 0)
- end
- end;
- 33:
- begin {exit function}
- t := b;
- pc := s[b + 1];
- b := s[b + 3]
- end;
- 34:
- s[t] := s[s[t]];
- 35:
- s[t] := btoi(not (itob(s[t])));
- 36:
- s[t] := - s[t];
- end {case};
- end {exec3};
-
-
- procedure interpret;
- var hx:integer;
- label
- 97, 98;
-
-
- procedure chooseproc;
-
- {from a random starting point search for a process that is active and
- not suspended. d aborts the interpreter if a deadlock occurs.}
-
- var
- d: integer;
-
- begin
- d := pmax + 1;
- curpr := (curpr + trunc(ran * pmax)) mod (pmax + 1);
- while ((not ptab[curpr].active) or (ptab[curpr].suspend <>
- 0)) and (d >= 0) do
- begin
- d := d - 1;
- curpr := (curpr + 1) mod (pmax + 1)
- end;
- if d < 0
- then
- begin
- ps := deadlock;
- writeln('deadlock');
- readln;
- end
- else
- stepcount := trunc(ran * stepmax);
- end {chooseproc};
-
-
- begin {interpret}
- initialize;
- repeat
- if ptab[0].active
- then
- curpr := 0
- else
- if stepcount = 0
- then
- chooseproc
- else
- stepcount := stepcount - 1;
- with ptab[curpr] do
- begin
- ir := code[pc];
- pc := pc + 1
- end;
- if pflag then
- begin
- if ir.f = 18 {markstack} then
- npr := npr + 1;
- curpr := npr
- end;
- with ptab[curpr] do
- begin
- if ir.f < 15
- then
- exec1
- else if ir.f < 24
- then exec2
- else if ir.f < 37
- then exec3
- else exec4;
- end;
- until ps <> run;
- 98: writeln;
- if ps <> fin
- then
- begin
- with ptab[curpr] do
- write(' halt at', pc: 3, ' in process', curpr: 4,
- ' because of ');
- case ps of
- deadlock:
- writeln('deadlock');
- divchk:
- writeln('division by 0');
- inxchk:
- writeln('invalid index');
- stkchk:
- writeln('storage overflow');
- linchk:
- writeln('too much output');
- lngchk:
- writeln('linr too long');
- redchk:
- writeln('reading past end of file');
- end;
- writeln('process active suspend pc');
- for hx := 0 to pmax do
- with ptab[hx] do
- writeln(hx: 4,' ':4,active:6,' ',suspend:4,' ':4,pc);
- writeln;
- writeln('global variables');
- for hx := btab[1].last + 1 to tmax do
- with tab[hx] do
- if lev <> 1
- then
- goto 97
- else
- if obj = variable
- then
- if typ in stantyps
- then
- case typ of
- ints:
- writeln(name, ' = ', s[adr]);
- bools:
- writeln(name, ' = ', itob(s[adr]));
- chars:
- writeln(name, ' = ', chr(s[adr] { mod
- 64}));
- end;
- end;
- 97: writeln
- end {interpret};
- modend.
-