perm filename IOV1.2[EAL,HE] blob
sn#701197 filedate 1983-03-24 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00010 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 {$NOMAIN Individual statement interpreters }
C00005 00003 procedure doProg (* ** ** *) external
C00006 00004 procedure doBlock external
C00008 00005 procedure doCoblock external
C00010 00006 procedure doEnd external
C00014 00007 procedure doFor external
C00016 00008 procedure doIf external
C00017 00009 procedure doWhile external
C00018 00010 procedure doUntil external
C00019 ENDMK
C⊗;
{$NOMAIN Individual statement interpreters }
%include ialhdr.pas;
{ Externally defined routines: }
(* From ALLOC *)
procedure relNode(n: nodep); external;
procedure relEentry(n: enventryp); external;
function newEheader: envheaderp; external;
function newEnvironment: environp; external;
(* From IAUX1A *)
function pop: nodep; external;
function gtVarn (n: nodep): enventryp; external;
function getPdb: pdbp; external;
procedure freePdb(p: pdbp); external;
function getEvent: eventp; external;
procedure freeEvent(e: eventp); external;
procedure makeVar(e: enventryp; vari: varidefp; tbits: integer);external;
function enterEntry (var i,j: integer; var env: environp;
envhdr: envheaderp; v: varidefp): enventryp; external;
procedure killStack; external;
(* From IAUX1B *)
procedure sleep(whenV: integer); external;
(* From IAUX2A *)
procedure killEnv; external;
(* From IAUX2B *)
function cmonCheck: boolean; external;
(* Display-related Routines *)
procedure ppLine; external;
procedure ppOutNow; external;
procedure ppChar(ch: ascii); external;
procedure pp5(ch: c5str; length: integer); external;
procedure pp10(ch: cstring; length: integer); external;
procedure pp10L(ch: cstring; length: integer); external;
procedure pp20(ch: c20str; length: integer); external;
procedure pp20L(ch: c20str; length: integer); external;
procedure ppInt(i: integer); external;
procedure ppReal(r: real); external;
procedure ppStrng(length: integer; s: strngp); external;
procedure doProg; (* ** ** *) external;
procedure doProg;
begin
(* *** stuff to reset affixments *** *)
speedfactor↑.s := 2.0; (* initialize speed_factor *)
curInt↑.spc := curInt↑.spc↑.pcode;
curInt↑.mode := 0;
end;
procedure doBlock; external;
procedure doBlock;
var i,j: integer; v: varidefp;
envhdr: envheaderp; e: enventryp; envir: environp;
begin
with curInt↑ do
begin
if spc↑.variables <> nil then
with spc↑ do
begin
envhdr := newEheader;
envhdr↑.parent := env;
env := envhdr;
envhdr↑.block := spc;
envhdr↑.varcnt := 0;
envhdr↑.procp := false;
envir := newEnvironment; (* always need at least one environment record *)
envir↑.next := nil;
envhdr↑.env[0] := envir;
for j := 1 to 4 do envhdr↑.env[j] := nil;
for j := 0 to 9 do envir↑.vals[j] := nil;
i := 0;
j := -1;
v := variables;
while v <> nil do
begin
if v↑.vtype < dimensiontype then
begin
e := enterEntry(i,j,envir,envhdr,v);
makeVar(e,v,v↑.tbits); (* make variable environment entry *)
end
else (* if v↑.vtype = freevartype then - need to do it for macros too *)
begin
relEentry(enterEntry(i,j,envir,envhdr,v)); (* space past env entry *)
envir↑.vals[j] := nil;
end;
v := v↑.next
end;
for i := j+1 to 9 do envir↑.vals[i] := nil;
end;
mode := 0;
spc := spc↑.bcode;
end;
end;
procedure doCoblock; external;
procedure doCoblock;
var e: eventp;
procedure sched(n: nodep);
var p: pdbp;
begin
if n↑.next <> nil then sched(n↑.next); (* maintain lexical order *)
if n↑.cstmnt↑.stype <> commenttype then
begin (* we don't want to schedule comments (yet) *)
p := getPdb; (* get a pdb for this thread *)
with p↑ do
begin
next := activeInts; (* add us to list of active interpreters *)
activeInts := p;
status := runqueue;
spc := n↑.cstmnt;
sdef := spc;
evt := e; (* event to signal when we go away *)
end;
end;
end;
begin
with curInt↑ do
case mode of
1: begin (* schedule the parallel threads for execution *)
mode := 2;
if spc↑.threads <> nil then
begin
e := getEvent; (* event to use for signalling when all threads are done *)
e↑.count := -spc↑.nthreads;
e↑.waitlist := curInt;
sched(spc↑.threads); (* schedule all the threads *)
curInt↑.status := joinwait;
curInt := nil;
resched := true; (* start up first of them *)
end;
end;
2: begin (* all threads are done - continue with main *)
mode := 0;
spc := spc↑.next;
end;
end;
end;
procedure doEnd; external;
procedure doEnd;
var spcp: statementp; e: eventp; b: boolean;
begin
b := true;
with curInt↑ do
begin
spcp := spc↑.bparent;
case spcp↑.stype of
progtype: begin
running := false; (* all done running *)
mode := 0;
end;
blocktype: begin
if spcp↑.variables <> nil then (* any variables? *)
b := cmonCheck; (* any cmons now running? *)
if b then
begin (* no - we can clean things up *)
if spcp↑.variables <> nil then killEnv;
spcp := spcp↑.next;
mode := 0;
end
else sleep(30); (* give cmons time to finish *)
end;
coblocktype: begin
if evt = nil then
begin
running := false; (* break to debugger *)
(* *** if not iSingleThreadMode then complain??? *** *)
end
else
begin
b := false;
e := evt;
killStack; (* flush stack *)
freePdb(curInt);
if e↑.count = -1 then
begin (* this was last thread *)
curInt := e↑.waitlist; (* return to main *)
curInt↑.status := nowrunning;
freeEvent(e);
if activeInts <> nil then
if curInt↑.priority < activeInts↑.priority then
resched := true;
end
else
begin (* other threads still executing *)
e↑.count := e↑.count + 1;
curInt := nil; (* swap in someone else *)
resched := true;
end;
end;
end;
cmtype: begin (* terminate or resched this cmon *);
cm↑.running := false;
killStack;
b := false;
spc := spcp; (* set us up for next time *)
mode := 0;
if not cm↑.enabled then
begin (* we're done, swap us out *)
curInt↑.status := nullqueue;
curInt := nil; (* swap in someone else *)
resched := true;
end;
end;
fortype: begin
if sp↑.ntype <> forvalnode then (* gack! stack error *)
begin
pp20L('Can''t find FOR node ',20); pp20('- stack error!!! ',16);
ppLine;
(* could try to recover, but.... *)
end;
sp↑.fvar↑.s := sp↑.fvar↑.s + sp↑.fstep; (* next for value *)
mode := 2; (* do for check *)
end;
untiltype: mode := 2;
whiletype: mode := 0;
movetype, (* for error handler *)
iftype,
casetype: begin
spcp := spcp↑.next;
mode := 0;
end;
otherwise {do nothing};
end;
if b then spc := spcp;
end;
end;
procedure doFor; external;
procedure doFor;
var ev: enventryp; fnode, res: nodep;
begin
with curInt↑ do
case mode of
1: begin (* stack contains: forvar subscripts, initial, step & final values *)
ev := gtVarn(spc↑.forvar); (* access variable *)
res := pop; (* get initial value *)
ev↑.s := res↑.s; (* store it away *)
relNode(res); (* release node *)
fnode := sp; (* get step value *)
fnode↑.ntype := forvalnode;
fnode↑.fstep := fnode↑.s; (* copy step value - note s & step fields may overlap *)
fnode↑.fvar := ev; (* copy environment entry *)
mode := 2;
end;
2: begin
fnode := sp;
if (fnode↑.fvar↑.s - fnode↑.next↑.s) * fnode↑.fstep <= 0.0 (* (cur-fin)*step *)
then spc:= spc↑.fbody (* go interpret for body *)
else begin
spc := spc↑.next; (* move on to next statement *);
res := fnode↑.next;
sp := res↑.next; (* pop for nodes off of stack *)
relNode(fnode); (* and release them *)
relNode(res);
end;
mode := 0;
end;
end;
end;
procedure doIf; external;
procedure doIf;
var res: nodep; s: statementp;
begin
with curInt↑ do
begin
res := pop; (* pop value off of stack *)
s := spc;
if res↑.s = 0.0 then spc := s↑.els else spc := s↑.thn;
if spc = nil then spc := s↑.next; (* if nil clause just go on to next stmnt *)
relNode(res);
mode := 0;
end;
end;
procedure doWhile; external;
procedure doWhile;
var res: nodep;
begin
with curInt↑ do
begin
res := pop; (* pop value off of stack *)
if res↑.s = 0.0 then spc := spc↑.next (* if false move on to next stmnt *)
else if spc↑.body <> nil then spc := spc↑.body;
relNode(res);
mode := 0;
end;
end;
procedure doUntil; external;
procedure doUntil;
var res: nodep;
begin
with curInt↑ do
case mode of
1: begin
if spc↑.body <> nil then begin spc := spc↑.body; mode := 0 end
else mode := 2;
end;
2: begin
epc := spc↑.exprs; (* need to evaluate until condition *)
mode := 3;
end;
3: begin
res := pop; (* pop value off of stack *)
if (res↑.s <> 0.0) then
begin
spc := spc↑.next; (* if true move on to next stmnt *)
mode := 0;
end
else mode := 1; (* if still false repeat body *)
relNode(res);
end;
end;
end;