ExpressProcImpl.mesa
Created July 11, 1984 12:57:43 pm PDT
Last edited by Eric Nickell, July 19, 1984 3:47:23 pm PDT
DIRECTORY
ExpressProc,
ExpressTree,
PrincOps,
PrincOpsUtils,
RTSD,
VM
;
ExpressProcImpl: CEDAR MONITOR
IMPORTS ExpressTree, PrincOpsUtils, VM
EXPORTS ExpressProc
~ {
OPEN ExpressProc, ET: ExpressTree, PrincOps, RTSD; --PrincOps & RTSD only used for machine code
Public Procedures
NoProcedureAvailable: PUBLIC ERROR ~ CODE;
IllegalToken: PUBLIC ERROR ~ CODE;
GetProc: PUBLIC ENTRY PROC
[fcn: XTree, oldProc: ANYPROCNIL]
RETURNS [proc: ANYPROC] ~ TRUSTED {
code: Code;
ops: OpsList;            --List of opcodes to do work of proc
codePos, frameSize: CARDINAL;
length: CARDINAL ← SizeNeeded[fcn];
procBase: ProcBase;
FreeProcedureUnderLock[oldProc];     --Free procedure if given
[proc, procBase] ← FindProcedure[length];   --Can raise !NoProcedureAvailable
codePos ← PullArgsOffStack[procBase];    --Set ups code to take args off stack
Generate the code into a list
[code, frameSize] ← ParseTreeToCode[fcn, procTemp];
ops ← Cat[code.init, code.exec];
codePos ← AppendOpsToProc[procBase, codePos, ops];
AppendReturn[procBase, codePos];
SetFrameSize[proc, frameSize];
};
FreeProcedure: PUBLIC ENTRY PROC [proc: ANYPROC] ~ {
FreeProcedureUnderLock[proc];
};
Tokens
TokenInfo: TYPE ~ REF TokenInfoRec;
TokenInfoRec: TYPE ~ RECORD [
type: ATOM,
code: LIST OF PrincOps.op,
size: CARDINAL
];
SizeNeeded: PROC [x: XTree] RETURNS [size: CARDINAL ← 11] ~ {
Given an expression, tell how many bytes will be needed for the procedure which implements them
AddSize: ET.EnumerateProc ~ TRUSTED {
token: Token;
WITH narrowX: x SELECT FROM
constant => token ← $Constant;
fcn => token ← $Proc;
id => token ← narrowX.op;
unX => token ← narrowX.op;
binX => token ← narrowX.op;
trinX => token ← narrowX.op;
ENDCASE => ERROR;
size ← size + GetTokenInfo[token].size;
};
[] ← ET.EnumDescendants[x, AddSize];
};
GetTokenInfo: PROC [token: Token] RETURNS [tokenInfo: TokenInfo] ~ {
FOR tokens: LIST OF TokenInfo ← definedTokens, tokens.rest WHILE tokens#NIL DO
IF tokens.first.type = token THEN RETURN [tokens.first];
ENDLOOP;
ERROR IllegalToken[];
};
AddToken: PROC [token: Token, code: LIST OF PrincOps.op] RETURNS [] ~ {
size: CARDINAL ← 0;
tokenInfo: TokenInfo;
See how much space this takes
FOR ops: LIST OF PrincOps.op ← code, ops.rest WHILE ops#NIL DO
size ← size+1;
ENDLOOP;
tokenInfo ← NEW[TokenInfoRec ← [token, code, size]];
definedTokens ← CONS[tokenInfo, definedTokens];
};
InitTokens: PROC ~ {
AddToken[$Name, LIST[PrincOps]];
AddToken[$Add, LIST[zMISC, aFADD]];       --Floating Arithmetic
AddToken[$Subtract, LIST[zMISC, aFSUB]];
AddToken[$Multiply, LIST[zMISC, aFMUL]];
AddToken[$Divide, LIST[zMISC, aFDIV]];
AddToken[$Id1, LIST[zLLDB, arg1]];
AddToken[$Id2, LIST[zLLDB, arg2]];
AddToken[$Id3, LIST[zLLDB, arg3]];
AddToken[$Id4, LIST[zLLDB, arg4]];
AddToken[$Id5, LIST[zLLDB, arg5]];
AddToken[$Negate, LIST[zLINI, zXOR]];       --Flip the sign bit
AddToken[$Constant, LIST[zLIW, 0, 0, zLIW, 0, 0, zSLDB, 0, zLLDB, 0]]; --Handled manually
AddToken[$If, LIST[zSLDB, temp1, zSLDB, temp2, zLI1, zAND, zLI1, zJEQ4, zLLDB, temp1, zJ3, zLLDB, temp2]];
AddToken[$Proc, LIST[zLIW, 0, 0, zSFC]];      --Handled manually
AddToken[$max, LIST[zSLDB, temp1, zSLDB, temp2, zLLDB, temp2, zLLDB, temp2, zLLDB, temp1, zMISC, aFCOMP, zLI0, zJGEB, 6, zPOP, zPOP, zLLDB, temp1]];
AddToken[$min, LIST[zSLDB, temp1, zSLDB, temp2, zLLDB, temp2, zLLDB, temp2, zLLDB, temp1, zMISC, aFCOMP, zLI0, zJLEB, 6, zPOP, zPOP, zLLDB, temp1]];
REMEMBER: When a BOOLEAN is on the stack in this interpreter, only the least significant bit matters!!! Bit set is TRUE.
AddToken[$GT, LIST[zMISC, aFCOMP, zINC, zLIN1, zSHIFT]];
AddToken[$LT, LIST[zMISC, aFCOMP, zLIN1, zSHIFT]];
AddToken[$EQ, LIST[zMISC, aFCOMP, zINC]];
AddToken[$GE, LIST[zMISC, aFCOMP, zLIN1, zSHIFT, zINC]];
AddToken[$LE, LIST[zMISC, aFCOMP, zNEG, zLIN1, zSHIFT, zINC]];
AddToken[$NE, LIST[zMISC, aFCOMP]];
AddToken[$not, LIST[zINC]];
AddToken[$or, LIST[zOR]];
AddToken[$and, LIST[zAND]];
AddToken[$xor, LIST[zXOR]];
};
Converting Parse Trees to Code
OpsList: TYPE ~ LIST OF PrincOps.op;
Code: TYPE ~ RECORD [
init: OpsList,
exec: OpsList
];
ParseTreeToCode: PROC [x: XTree, temp: CARDINAL] RETURNS [code: Code, nextTemp: CARDINAL] ~ TRUSTED {
nextTemp ← temp;
WITH narX: x SELECT FROM
id => RETURN [[NIL, GetCode[narX.op]], nextTemp];
constant => RETURN [[NIL, GetCodeForReal[narX.value]], nextTemp];
unX => {
c1: Code;
[c1, nextTemp] ← ParseTreeToCode[narX.exp1, nextTemp];
RETURN [[c1.init, Cat[c1.exec, GetCode[narX.op]]], nextTemp];
};
binX => {
c1, c2: Code;
[c1, nextTemp] ← ParseTreeToCode[narX.exp1, nextTemp];
[c2, nextTemp] ← ParseTreeToCode[narX.exp2, nextTemp];
RETURN [[Cat[c1.init, c2.init], Cat[c1.exec, c2.exec, GetCode[narX.op]]], nextTemp];
};
trinX => {
Maybe change this later to handle if-then-else better
c1, c2, c3: Code;
[c1, nextTemp] ← ParseTreeToCode[narX.exp1, nextTemp];
[c2, nextTemp] ← ParseTreeToCode[narX.exp2, nextTemp];
[c3, nextTemp] ← ParseTreeToCode[narX.exp3, nextTemp];
RETURN [[Cat[c1.init, c2.init, c3.init], Cat[c1.exec, c2.exec, c3.exec, GetCode[narX.op]]], nextTemp];
};
fcn => {
c1: Code;
cInit, cExec: OpsList ← NIL;
FOR args: LIST OF XTree ← narX.args, args.rest UNTIL args=NIL DO
[c1, nextTemp] ← ParseTreeToCode[args.first, nextTemp];
cInit ← Cat[cInit, c1.init];
cExec ← Cat[cExec, c1.exec];
ENDLOOP;
RETURN [ [Cat[cInit, cExec, GetCodeForCall[narX.proc, nextTemp]], GetCodeForRetrieve[nextTemp] ], nextTemp+2];
};
ENDCASE => ERROR;
};
GetCodeForReal: PROC [r: REAL] RETURNS [OpsList] ~ {
RETURN [LIST[
zLIW,
HiB[LoW[r]],
LoB[LoW[r]],
zLIW,
HiB[HiW[r]],
LoB[HiW[r]]
]];
};
GetCode: PROC [token: Token] RETURNS [OpsList] ~ {
RETURN [GetTokenInfo[token].code];
};
GetCodeForCall: PROC [proc: ANYPROC, temp: CARDINAL] RETURNS [OpsList] ~ {
RETURN [LIST[
zLIW,    --Push the link to the procedure
HiB[proc],
LoB[proc],
zKFCB,   --check for assignment of nested procs out of scope
sProcCheck,
zSFC,    --If we still exist, call the procedure
zSLDB,   --Save the result
LoB[temp]
]];
};
GetCodeForRetrieve: PROC [temp: CARDINAL] RETURNS [OpsList] ~ {
RETURN [LIST[
zLLDB,
LoB[temp]
]];
};
Cat: PROC [c1, c2, c3, c4: OpsList ← NIL] RETURNS [c: OpsList ← NIL] ~ {
cTail: OpsList ← NIL;
listList: LIST OF OpsList ← LIST[c1, c2, c3, c4];
FOR lists: LIST OF OpsList ← listList, lists.rest UNTIL lists=NIL DO
FOR ops: OpsList ← lists.first, ops.rest UNTIL ops=NIL DO
IF c=NIL
THEN cTail ← c ← CONS[ops.first, NIL]
ELSE cTail ← cTail.rest ← CONS[ops.first, NIL];
ENDLOOP;
ENDLOOP;
};
Procedure-twiddling
ProcBase: TYPE ~ LONG POINTER;
ProcInfo: TYPE ~ REF ProcInfoRec;
ProcInfoRec: TYPE ~ RECORD [
proc: ANYPROC,
inUse: BOOLEANFALSE,
size: CARDINAL
];
ProcList: TYPE ~ LIST OF ProcInfo;
FindProcedure: UNSAFE PROC [length: CARDINAL] RETURNS [proc: ANYPROC, procBase: ProcBase] ~ UNCHECKED {
FOR procs: ProcList ← procList, procs.rest WHILE procs#NIL DO
IF ~procs.first.inUse AND length<procs.first.size THEN {
procs.first.inUse ← TRUE;
RETURN [procs.first.proc, BaseOfProc[procs.first.proc]];
};
ENDLOOP;
ERROR NoProcedureAvailable[];
};
FreeProcedureUnderLock: PROC [proc: ANYPROC] ~ {
Procedure assumes the caller has already got a lock on the monitor
IF proc=NIL THEN RETURN;
FOR procs: ProcList ← procList, procs.rest WHILE procs#NIL DO
IF procs.first.proc=proc THEN {procs.first.inUse ← FALSE; RETURN};
ENDLOOP;
};
BaseOfProc: UNSAFE PROC [proc: ANYPROC] RETURNS [procBase: ProcBase] ~ UNCHECKED {
gf: PrincOps.GlobalFrameHandle ← PrincOpsUtils.GlobalFrame[proc];
codeBase: LONG POINTER TO PrincOps.CSegPrefix ← LOOPHOLE[PrincOpsUtils.Codebase[gf]];
offset: PrincOps.BytePC ← codeBase^.entry[PrincOpsUtils.GlobalFrameAndEntryPoint[proc].ep].initialpc;
procBase ← LOOPHOLE[codeBase + offset];
};
SetFrameSize: UNSAFE PROC [proc: ANYPROC, size: CARDINAL] ~ UNCHECKED {
fsi: FrameSizeIndex ← PrincOpsUtils.MakeFsi[size];
gf: PrincOps.GlobalFrameHandle ← PrincOpsUtils.GlobalFrame[proc];
codeBase: LONG POINTER TO PrincOps.CSegPrefix ← LOOPHOLE[PrincOpsUtils.Codebase[gf]];
where: LONG POINTER TO PrincOps.EntryInfo ← @(codeBase^.entry[PrincOpsUtils.GlobalFrameAndEntryPoint[proc].ep].info);
page: VM.PageNumber ← VM.PageNumberForAddress[where];
VM.MakeReadWrite[[page, 1]];
where^.framesize ← fsi;
VM.MakeReadOnly[[page, 1]];
};
PullArgsOffStack: UNSAFE PROC [procBase: ProcBase] RETURNS [codePos: CARDINAL ← 0] ~ UNCHECKED {
codePos ← AppendOpsToProc[procBase, codePos, LIST[zSLDB, arg5, zSLDB, arg4, zSLDB, arg3, zSLDB, arg2, zSLDB, arg1]];     --Kluge for now pull 5 REALs off stack
};
AppendFcn: UNSAFE PROC [procBase: ProcBase, oldCodePos: CARDINAL, token: Token] RETURNS [codePos: CARDINAL] ~ UNCHECKED {
code: LIST OF PrincOps.op ← GetTokenInfo[token].code;
codePos ← AppendOpsToProc[procBase, oldCodePos, code];
};
AppendPushConstant: UNSAFE PROC [procBase: ProcBase, oldCodePos: CARDINAL, constant: REAL] RETURNS [codePos: CARDINAL] ~ UNCHECKED {
opList: LIST OF PrincOps.op ← LIST[
zLIW,
HiB[LoW[constant]],
LoB[LoW[constant]],
zLIW,
HiB[HiW[constant]],
LoB[HiW[constant]]
];
codePos ← AppendOpsToProc[procBase, oldCodePos, opList];
};
AppendProcCall: UNSAFE PROC [procBase: ProcBase, oldCodePos: CARDINAL, proc: ANYPROC] RETURNS [codePos: CARDINAL] ~ UNCHECKED {
opList: LIST OF PrincOps.op ← LIST[
zLIW,    --Push the link to the procedure
HiB[proc],
LoB[proc],
zKFCB,   --check for assignment of nested procs out of scope
sProcCheck,
zSFC    --If we still exist, call the procedure
];
codePos ← AppendOpsToProc[procBase, oldCodePos, opList];
};
AppendReturn: UNSAFE PROC [procBase: ProcBase, oldCodePos: CARDINAL] ~ UNCHECKED {
[] ← AppendOpsToProc[procBase, oldCodePos, LIST[zRET]];
};
AppendOpsToProc: UNSAFE PROC [procBase: ProcBase, oldCodePos: CARDINAL, opList: LIST OF PrincOps.op] RETURNS [codePos: CARDINAL] ~ UNCHECKED {
WhichByte: TYPE ~ {even, odd};
codePos ← oldCodePos;
Go through the ops given, placing them in the code at the current location pointer
FOR ops: LIST OF PrincOps.op ← opList, ops.rest WHILE ops#NIL DO
offset: CARDINAL ← codePos/2;
which: WhichByte ← IF offset*2=codePos THEN even ELSE odd;
code: LONG POINTER TO PrincOps.InstWord ← LOOPHOLE[procBase+offset];
page: VM.PageNumber ← VM.PageNumberForAddress[code];
VM.MakeReadWrite[[page, 1]];
SELECT which FROM
even => code^.evenbyte ← LOOPHOLE[ops.first];
odd => code^.oddbyte ← LOOPHOLE[ops.first];
ENDCASE;
VM.MakeReadOnly[[page, 1]];
codePos ← codePos + 1;
ENDLOOP;
};
RegisterP: PROC [proc: ANYPROC, size: CARDINAL] ~ {
procInfo: ProcInfo ← NEW[ProcInfoRec ← [proc: proc, inUse: FALSE, size: size]];
procList ← CONS[procInfo, procList];
};
InitProcs: PROC ~ {
RegisterP[P1000, 1000]; RegisterP[P1001, 1000]; RegisterP[P602, 600]; RegisterP[P603, 600]; RegisterP[P604, 600];
RegisterP[P605, 600]; RegisterP[P606, 600]; RegisterP[P607, 600]; RegisterP[P608, 600]; RegisterP[P609, 600];
RegisterP[P410, 400]; RegisterP[P411, 400]; RegisterP[P412, 400]; RegisterP[P413, 400]; RegisterP[P414, 400];
RegisterP[P415, 400]; RegisterP[P416, 400]; RegisterP[P417, 400]; RegisterP[P418, 400]; RegisterP[P419, 400];
RegisterP[P220, 200]; RegisterP[P221, 200]; RegisterP[P222, 200]; RegisterP[P223, 200]; RegisterP[P224, 200];
RegisterP[P225, 200]; RegisterP[P226, 200]; RegisterP[P227, 200]; RegisterP[P228, 200]; RegisterP[P229, 200];
RegisterP[P130, 100]; RegisterP[P131, 100]; RegisterP[P132, 100]; RegisterP[P133, 100]; RegisterP[P134, 100];
RegisterP[P135, 100]; RegisterP[P136, 100]; RegisterP[P137, 100]; RegisterP[P138, 100]; RegisterP[P139, 100];
RegisterP[Pf40, 50]; RegisterP[Pf41, 50]; RegisterP[Pf42, 50]; RegisterP[Pf43, 50]; RegisterP[Pf44, 50];
RegisterP[Pf45, 50]; RegisterP[Pf46, 50]; RegisterP[Pf47, 50]; RegisterP[Pf48, 50]; RegisterP[Pf49, 50];
};
LoW: PROC [r: REAL] RETURNS [UNSPECIFIED] ~ {
card: LONG CARDINALLOOPHOLE[r];
cardinal: CARDINAL ← card - 10000H*(card/10000H);
RETURN[LOOPHOLE[cardinal]];
};
HiW: PROC [r: REAL] RETURNS [UNSPECIFIED] ~ {
card: LONG CARDINALLOOPHOLE[r];
cardinal: CARDINAL ← card/10000H;
RETURN[LOOPHOLE[cardinal]];
};
LoB: PROC [u: UNSPECIFIED] RETURNS [PrincOps.op] ~ {
card: CARDINALLOOPHOLE[u];
RETURN[LOOPHOLE[card - 100H*(card/100H)]];
};
HiB: PROC [u: UNSPECIFIED] RETURNS [PrincOps.op] ~ {
card: CARDINALLOOPHOLE[u];
RETURN[LOOPHOLE[card/100H]];
};
Recyclable Procedures
Some frame location definitions
arg1: PrincOps.op = 4;
arg2: PrincOps.op = 6;
arg3: PrincOps.op = 8;
arg4: PrincOps.op = 10;
arg5: PrincOps.op = 12;
temp1: PrincOps.op = 14;
temp2: PrincOps.op = 16;
procTemp: PrincOps.op = 18;
MC25: PROC ~ TRUSTED MACHINE CODE {
zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP; zNOOP;
};
MC50: PROC ~ INLINE {MC25[]; MC25[]};
MC100: PROC ~ INLINE {MC25[]; MC25[]; MC25[]; MC25[]};
MC200: PROC ~ INLINE {MC25[]; MC25[]; MC25[]; MC25[]; MC25[]; MC25[]; MC25[]; MC25[]};
MC400: PROC ~ INLINE {MC200[]; MC200[]};
MC600: PROC ~ INLINE {MC200[]; MC200[]; MC200[]};
MC1000: PROC ~ INLINE {MC200[]; MC200[]; MC200[]; MC200[]; MC200[]};
P1000: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC1000};
P1001: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC1000};
P602: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P603: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P604: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P605: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P606: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P607: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P608: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P609: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC600};
P410: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P411: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P412: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P413: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P414: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P415: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P416: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P417: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P418: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P419: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC400};
P220: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P221: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P222: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P223: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P224: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P225: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P226: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P227: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P228: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P229: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC200};
P130: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P131: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P132: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P133: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P134: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P135: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P136: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P137: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P138: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
P139: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC100};
Pf40: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf41: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf42: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf43: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf44: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf45: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf46: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf47: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf48: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Pf49: PROC [a,b,c,d,e: REAL] RETURNS [z: REAL] ~ TRUSTED {MC50};
Initialization
definedTokens: LIST OF TokenInfo ← NIL;
procList: ProcList ← NIL;
InitTokens[];
InitProcs[];
}.