(*global code, tab, btab*)
var ir: order; (*instruction buffer*)
pc: integer; (*program counter*)
ps: (run,fin,caschk,divchk,inxchk,stkchk,linchk,lngchk,redchk);
t: integer; (*top stack index*)
b: integer; (*base index*)
lncnt, ocnt, blkcnt, chrcnt: integer; (*counters*)
fld: array [1..4] of integer; (*default field widths*)
display: array [1..lmax] of integer;
s: array [1..stacksize] of (*blockmark: *)
record case types of (* s[b+0] = fct result *)
ints: (i: integer); (* s[b+1] = return adr *)
reals: (r: real); (* s[b+2] = static link *)
bools: (b: boolean); (* s[b+3] = dynamic link*)
chars: (c: char) (* s[b+4] = table index *)
s[1].i := 0; s[2].i := 0; s[3].i := -1; s[4].i := btab[1].last;
t := btab[2].vsize - 1; pc := tab[s[4].i].adr;
lncnt := 0; ocnt := 0; chrcnt := 0;
fld[1] := 10; fld[2] := 22; fld[3] := 10; fld[4] := 1;
repeat ir := code[pc]; pc := pc+1; ocnt := ocnt + 1;
0: begin (*load address*) t := t+1;
if t > stacksize then ps := stkchk
else s[t].i := display[ir.x] + ir.y
1: begin (*load value*) t := t+1;
if t > stacksize then ps := stkchk
else s[t] := s[display[ir.x] + ir.y]
2: begin (*load indirect*) t := t+1;
if t > stacksize then ps := stkchk
else s[t] := s[s[display[ir.x] + ir.y].i]
3: begin (*update display*)
h1 := ir.y; h2 := ir.x; h3 := b;
repeat display[h1] := h3; h1 := h1-1; h3 := s[h3+2].i
0: s[t].i := abs(s[t].i);
1: s[t].r := abs(s[t].r);
2: s[t].i := sqr(s[t].i);
3: s[t].r := sqr(s[t].r);
4: s[t].b := odd(s[t].i);
if (s[t].i < 0) or (s[t].i > 127) then ps := inxchk
else s[t].c := chr(s[t].i)
6: s[t].i := ord(s[t].c) ;
7: s[t].c := succ(s[t].c);
8: s[t].c := pred(s[t].c);
9: s[t].i := round(s[t].r);
10: s[t].i := trunc(s[t].r);
11: s[t].r := sin(s[t].r);
12: s[t].r := cos(s[t].r);
13: s[t].r := exp(s[t].r);
14: s[t].r := ln(s[t].r);
15: s[t].r := sqrt(s[t].r);
16: s[t].r := arctan(s[t].r);
if t > stacksize then ps := stkchk else s[t].b := eof(input)
if t > stacksize then ps := stkchk else s[t].b := eoln(input)
9: s[t].i := s[t].i + ir.y; (*offset*)
11: begin (*conditional jump*)
if not s[t].b then pc := ir.y; t := t-1
12: begin (*switch*) h1 := s[t].i; t := t-1;
repeat if code[h2].f <> 13 then
begin h3 := 1; ps := caschk
begin h3 := 1; pc := code[h2+1].y
14: begin (*for1up*) h1 := s[t-1].i;
if h1 <= s[t].i then s[s[t-2].i].i := h1 else
begin t := t-3; pc := ir.y
15: begin (*for2up*) h2 := s[t-2].i; h1 := s[h2].i + 1;
begin s[h2].i := h1; pc := ir.y end
16: begin (*for1down*) h1 := s[t-1].i;
if h1 >= s[t].i then s[s[t-2].i].i := h1 else
begin pc := ir.y; t := t-3
17: begin (*for2down*) h2 := s[t-2].i; h1 := s[h2].i - 1;
begin s[h2].i := h1; pc := ir.y end
18: begin (*mark stack*) h1 := btab[tab[ir.y].ref].vsize;
if t+h1 > stacksize then ps := stkchk else
begin t := t+5; s[t-1].i := h1-1; s[t].i := ir.y
19: begin (*call*) h1 := t - ir.y; (*h1 points to base*)
h2 := s[h1+4].i; (*h2 points to tab*)
h3 := tab[h2].lev; display[h3+1] := h1;
s[h1+1].i := pc; s[h1+2].i := display[h3]; s[h1+3].i := b;
for h3 := t+1 to h4 do s[h3].i := 0;
b := h1; t := h4; pc := tab[h2].adr
20: begin (*index1*) h1 := ir.y; (*h1 points to atab*)
h2 := atab[h1].low; h3 := s[t].i;
if h3 < h2 then ps := inxchk else
if h3 > atab[h1].high then ps := inxchk else
begin t := t-1; s[t].i := s[t].i + (h3-h2)
21: begin (*index*) h1 := ir.y; (*h1 points to atab*)
h2 := atab[h1].low; h3 := s[t].i;
if h3 < h2 then ps := inxchk else
if h3 > atab[h1].high then ps := inxchk else
begin t := t-1; s[t].i := s[t].i + (h3-h2)*atab[h1].elsize
22: begin (*load block*) h1 := s[t].i; t := t-1;
h2 := ir.y + t; if h2 > stacksize then ps := stkchk else
begin t := t+1; s[t] := s[h1]; h1 := h1+1
23: begin (*copy block*) h1 := s[t-1].i;
h2 := s[t].i; h3 := h1 + ir.y;
begin s[h1] := s[h2]; h1 := h1+1; h2 := h2+1
24: begin (*literal*) t := t+1;
if t > stacksize then ps := stkchk else s[t].i := ir.y
25: begin (*load real*) t := t+1;
if t > stacksize then ps := stkchk else s[t].r := rconst[ir.y]
64,65: begin t := t + 1; if t > stacksize then ps := stkchk
else s[t].c := chr(ir.y) end;
26: begin (*float*) h1 := t - ir.y; s[h1].r := s[h1].i
if eof(input) then ps := redchk else
28: begin (*write string*)
h1 := s[t].i; 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
chrcnt := chrcnt + fld[ir.y];
if chrcnt > lineleng then ps := lngchk else
1: write(s[t].i: fld[1]);
2: write(s[t].r: fld[2]);
3: write(s[t].b: fld[3]);
chrcnt := chrcnt + s[t].i;
if chrcnt > lineleng then ps := lngchk else
1: write(s[t-1].i: s[t].i);
2: write(s[t-1].r: s[t].i);
3: write(s[t-1].b: s[t].i);
4: write(s[t-1].c: s[t].i);
32: begin (*exit procedure*)
t := b-1; pc := s[b+1].i; b := s[b+3].i
33: begin (*exit function*)
t := b; pc := s[b+1].i; b := s[b+3].i
35: s[t].b := not s[t].b;
37: begin chrcnt := chrcnt + s[t-1].i;
if chrcnt > lineleng then ps := lngchk else
write(s[t-2].r: s[t-1].i: s[t].i);
38: begin (*store*) s[s[t-1].i] := s[t]; t := t-2
39: begin t := t-1; s[t].b := s[t].r = s[t+1].r
40: begin t := t-1; s[t].b := s[t].r <> s[t+1].r
41: begin t := t-1; s[t].b := s[t].r < s[t+1].r
42: begin t := t-1; s[t].b := s[t].r <= s[t+1].r
43: begin t := t-1; s[t].b := s[t].r > s[t+1].r
44: begin t := t-1; s[t].b := s[t].r >= s[t+1].r
45: begin t := t-1; s[t].b := s[t].i = s[t+1].i
46: begin t := t-1; s[t].b := s[t].i <> s[t+1].i
47: begin t := t-1; s[t].b := s[t].i < s[t+1].i
48: begin t := t-1; s[t].b := s[t].i <= s[t+1].i
49: begin t := t-1; s[t].b := s[t].i > s[t+1].i
50: begin t := t-1; s[t].b := s[t].i >= s[t+1].i
51: begin t := t-1; s[t].b := s[t].b or s[t+1].b
52: begin t := t-1; s[t].i := s[t].i + s[t+1].i
53: begin t := t-1; s[t].i := s[t].i - s[t+1].i
54: begin t := t-1; s[t].r := s[t].r + s[t+1].r;
55: begin t := t-1; s[t].r := s[t].r - s[t+1].r;
56: begin t := t-1; s[t].b := s[t].b and s[t+1].b
57: begin t := t-1; s[t].i := s[t].i * s[t+1].i
if s[t+1].i = 0 then ps := divchk else
s[t].i := s[t].i div s[t+1].i
if s[t+1].i = 0 then ps := divchk else
s[t].i := s[t].i mod s[t+1].i
60: begin t := t-1; s[t].r := s[t].r * s[t+1].r;
if s[t+1].r = 0.0 then ps := divchk else s[t].r := s[t].r / s[t+1].r;
62: if eof(input) then ps := redchk else readln;
63: begin writeln; lncnt := lncnt + 1; chrcnt := 0;
if lncnt > linelimit then ps := linchk
write('0halt at', pc:5, ' because of ');
caschk: writeln('undefined case');
divchk: writeln('division by 0');
inxchk: writeln('invalid index');
stkchk: writeln('storage overflow');
linchk: writeln('too much output');
lngchk: writeln('line too long');
redchk: writeln('reading past end of file');
h1 := b; blkcnt := 10; (*post mortem dump*)
repeat writeln; blkcnt := blkcnt - 1;
if blkcnt = 0 then h1 := 0; h2 := s[h1+4].i;
writeln(' ', tab[h2].name, ' called at', s[h1+1].i: 5);
h2 := btab[tab[h2].ref].last;
begin if obj = variable then
begin write(' ', name, ' = ');
if normal then h3 := h1+adr else h3 := s[h1+adr].i;
writeln; writeln(ocnt, ' steps')