#include <perms.h>
// Edinburgh IMP77 Compiler - Version 8.4
//
// 1 %begin
int main(int argc, char **argv) { /*%begin*/
_imp_initialise(argc, argv);
// 2 %realfn eval {evaluate sub-expression}
float EVAL(void) {
auto void PUSHOPD(float VAL);
auto void PUSHOP(int OP);
auto float POPOPD(void);
auto int POPOP(void);
auto float NEXTOPD(void);
auto int NEXTOP(void);
auto void OPERATE(void);
// 3 %routinespec pushopd(%real val)
// 4 %routinespec pushop(%integer op)
// 5 %realfnspec popopd
// 6 %integerfnspec popop
// 7 %realfnspec nextopd
// 8 %integerfnspec nextop
// 9 %routinespec operate
// 10 %constinteger plus=1,minus=2,times=3,divide=4,exp=5,assign=6,end=7,space=' '
// 11 %constintegerarray prec(plus:assign)=1,1,2,2,3,0
const int PREC[6] = {1, 1, 2, 2, 3, 0};
// 12 %realarray opds(0:4) {operand stack}
float OPDS[5];
// 13 %integerarray ops(0:3) {operator stack}
int OPS[4];
// 14 %ownrealarray vars('a':'z')=0(*)
static float VARS[26] = {[0 ... 25] = 0};
// 15 %ownintegerarray vara('a':'z')=0(*)
static int VARA[26] = {[0 ... 25] = 0};
// 16 %integer op,opdsp,opsp,var
int OP;
int OPDSP;
int OPSP;
int VAR;
// 17 opdsp=0 ; opsp=0 {init stack pointers}
OPDSP = 0;
OPSP = 0;
// 18 pushopd(nextopd) {first operand}
PUSHOPD(NEXTOPD());
// 19 %cycle {for each operator}
L_0001:;
// 20 op=nextop
OP = NEXTOP();
// 21 %if op=end %then %exit
if (OP != 7) goto L_0002;
goto L_0003;
L_0002:;
// 22 operate %while opsp>0 %and prec(ops(opsp))>=prec(op)
L_0004:;
if (OPSP <= 0) goto L_0005;
if (PREC[OPS[OPSP] - 1] < PREC[OP - 1]) goto L_0005;
OPERATE();
goto L_0004;
L_0005:;
// 23 %if op=assign %then %start
if (OP != 6) goto L_0006;
// 24 read symbol(var)
_imp_READSYMBOL(/*?*/ &VAR);
// 25 %unless 'a'<=var<='z' %or 'A'<=var<='Z' %then print symbol(var) %c
{
// Double-sided test on VAR (Part I)
int tmp;
if (97 > (tmp = VAR)) goto L_0007;
// Double-sided test on VAR (Part II)
if (tmp <= 122) goto L_0008;
}
L_0007:;
{
// Double-sided test on VAR (Part I)
int tmp;
if (65 > (tmp = VAR)) goto L_0009;
// Double-sided test on VAR (Part II)
if (tmp <= 90) goto L_0008;
}
L_0009:;
_imp_PRINTSYMBOL(VAR);
_imp_PRINTSTRING(_imp_str_literal(" variable"));
_imp_signal(15, 0, 0, "");
L_0008:;
// 26+ %and print string(" variable") %and %signal 15
// 27 %if 'A'<=var<='Z' %then var=var-'A'+'a'
{
// Double-sided test on VAR (Part I)
int tmp;
if (65 > (tmp = VAR)) goto L_000A;
// Double-sided test on VAR (Part II)
if (tmp > 90) goto L_000A;
}
VAR = VAR - 65 + 97;
L_000A:;
// 28 vars(var)=opds(opdsp)
VARS[VAR - 97] = OPDS[OPDSP];
// 29 vara(var)=1 {assigned}
VARA[VAR - 97] = 1;
// 30 %continue
goto L_000B;
// 31 %finish
L_0006:;
// 32 pushop(op)
PUSHOP(OP);
// 33 pushopd(nextopd)
PUSHOPD(NEXTOPD());
// 34 %repeat
L_000B:;
goto L_0001;
L_0003:;
// 35 operate %while opsp>0
L_000C:;
if (OPSP <= 0) goto L_000D;
OPERATE();
goto L_000C;
L_000D:;
// 36 %result=popopd
return POPOPD();
// 37 !
// 38 %routine pushopd(%real val)
void PUSHOPD(float VAL) {
// 39 opdsp=opdsp+1
OPDSP = OPDSP + 1;
// 40 opds(opdsp)=val
OPDS[OPDSP] = VAL;
// 41 %end
return;
} /* end of PUSHOPD */
// 42 !
// 43 %routine pushop(%integer op)
void PUSHOP(int OP) {
// 44 opsp=opsp+1
OPSP = OPSP + 1;
// 45 ops(opsp)=op
OPS[OPSP] = OP;
// 46 %end
return;
} /* end of PUSHOP */
// 47 !
// 48 %realfn popopd
float POPOPD(void) {
// 49 %real val
float VAL;
// 50 val=opds(opdsp)
VAL = OPDS[OPDSP];
// 51 opdsp=opdsp-1
OPDSP = OPDSP - 1;
// 52 %result=val
return VAL;
// 53 %end
} /* end of POPOPD */
// 54 !
// 55 %integerfn popop
int POPOP(void) {
// 56 %integer op
int OP;
// 57 op=ops(opsp)
OP = OPS[OPSP];
// 58 opsp=opsp-1
OPSP = OPSP - 1;
// 59 %result=op
return OP;
// 60 %end
} /* end of POPOP */
// 61 !
// 62 %realfn nextopd
float NEXTOPD(void) {
// 63 %integer var
int VAR;
// 64 %real opd
float OPD;
// 65 skip symbol %while next symbol=space %or next symbol=nl
L_000E:;
if (_imp_NEXTSYMBOL() == 32) goto L_000F;
if (_imp_NEXTSYMBOL() != 10) goto L_0010;
L_000F:;
_imp_SKIPSYMBOL();
goto L_000E;
L_0010:;
// 66 %if '0'<=next symbol<='9' %or next symbol='-' %or next symbol='.' %c
{
// Double-sided test on _imp_NEXTSYMBOL() (Part I)
int tmp;
if (48 > (tmp = _imp_NEXTSYMBOL())) goto L_0011;
// Double-sided test on _imp_NEXTSYMBOL() (Part II)
if (tmp <= 57) goto L_0012;
}
L_0011:;
if (_imp_NEXTSYMBOL() == 45) goto L_0012;
if (_imp_NEXTSYMBOL() != 46) goto L_0013;
L_0012:;
_imp_READ(/*?*/ &OPD);
return OPD;
L_0013:;
// 67+ %then read(opd) %and %result=opd
// 68 %if next symbol='(' %then skip symbol %and %result=eval
if (_imp_NEXTSYMBOL() != 40) goto L_0014;
_imp_SKIPSYMBOL();
return EVAL();
L_0014:;
// 69 %if 'a'<=next symbol<='z' %or 'A'<=next symbol<='Z' %then %start
{
// Double-sided test on _imp_NEXTSYMBOL() (Part I)
int tmp;
if (97 > (tmp = _imp_NEXTSYMBOL())) goto L_0015;
// Double-sided test on _imp_NEXTSYMBOL() (Part II)
if (tmp <= 122) goto L_0016;
}
L_0015:;
{
// Double-sided test on _imp_NEXTSYMBOL() (Part I)
int tmp;
if (65 > (tmp = _imp_NEXTSYMBOL())) goto L_0017;
// Double-sided test on _imp_NEXTSYMBOL() (Part II)
if (tmp > 90) goto L_0017;
}
L_0016:;
// 70 read symbol(var)
_imp_READSYMBOL(/*?*/ &VAR);
// 71 %if 'A'<=var<='Z' %then var=var-'A'+'a'
{
// Double-sided test on VAR (Part I)
int tmp;
if (65 > (tmp = VAR)) goto L_0018;
// Double-sided test on VAR (Part II)
if (tmp > 90) goto L_0018;
}
VAR = VAR - 65 + 97;
L_0018:;
// 72 %if vara(var)=0 %then print symbol(var) %and %c
if (VARA[VAR - 97] != 0) goto L_0019;
_imp_PRINTSYMBOL(VAR);
_imp_PRINTSTRING(_imp_str_literal(" unassigned"));
_imp_signal(15, 0, 0, "");
L_0019:;
// 73+ print string(" unassigned") %and %signal 15
// 74 %result=vars(var)
return VARS[VAR - 97];
// 75 %finish
L_0017:;
// 76 read symbol(var)
_imp_READSYMBOL(/*?*/ &VAR);
// 77 print symbol(var)
_imp_PRINTSYMBOL(VAR);
// 78 print string(" operand")
_imp_PRINTSTRING(_imp_str_literal(" operand"));
// 79 %signal 15
_imp_signal(15, 0, 0, "");
// 80 %end
_imp_signal(8, 4, 0, "result missing");
} /* end of NEXTOPD */
// 81 !
// 82 %integerfn nextop
int NEXTOP(void) {
// 83 %integer sym
int SYM;
// 84 skip symbol %while next symbol=space
L_001A:;
if (_imp_NEXTSYMBOL() != 32) goto L_001B;
_imp_SKIPSYMBOL();
goto L_001A;
L_001B:;
// 85 read symbol(sym)
_imp_READSYMBOL(/*?*/ &SYM);
// 86 %if sym='+' %then %result=plus
if (SYM != 43) goto L_001C;
return 1;
L_001C:;
// 87 %if sym='-' %then %result=minus
if (SYM != 45) goto L_001D;
return 2;
L_001D:;
// 88 %if sym='*' %then %result=times
if (SYM != 42) goto L_001E;
return 3;
L_001E:;
// 89 %if sym='/' %then %result=divide
if (SYM != 47) goto L_001F;
return 4;
L_001F:;
// 90 %if sym='^' %then %result=exp
if (SYM != 94) goto L_0020;
return 5;
L_0020:;
// 91 %if sym=':' %then %result=assign
if (SYM != 58) goto L_0021;
return 6;
L_0021:;
// 92 %if sym=')' %or sym=nl %then %result=end
if (SYM == 41) goto L_0022;
if (SYM != 10) goto L_0023;
L_0022:;
return 7;
L_0023:;
// 93 print symbol(sym)
_imp_PRINTSYMBOL(SYM);
// 94 print string(" operator")
_imp_PRINTSTRING(_imp_str_literal(" operator"));
// 95 %signal 15
_imp_signal(15, 0, 0, "");
// 96 %end
_imp_signal(8, 4, 0, "result missing");
} /* end of NEXTOP */
// 97 !
// 98 %routine operate
void OPERATE(void) {
// 99 %real opd1,opd2
float OPD1;
float OPD2;
// 100 %switch opn(plus:exp)
int OPN_index;
int OPN_line;
char *OPN_file;
static const void *OPN[5] = {&&case_OPN_1, &&case_OPN_2, &&case_OPN_3, &&case_OPN_4, &&case_OPN_5};
// 101 opd2=popopd
OPD2 = POPOPD();
// 102 opd1=popopd
OPD1 = POPOPD();
// 103 ->opn(popop)
OPN_line = __LINE__;
OPN_file = __FILE__;
OPN_index = POPOP();
goto case_OPN_dispatch;
// 104 opn(plus):pushopd(opd1+opd2) ; %return
case_OPN_1:;
PUSHOPD(OPD1 + OPD2);
return;
// 105 opn(minus):pushopd(opd1-opd2) ; %return
case_OPN_2:;
PUSHOPD(OPD1 - OPD2);
return;
// 106 opn(times):pushopd(opd1*opd2) ; %return
case_OPN_3:;
PUSHOPD(OPD1 * OPD2);
return;
// 107 opn(divide):%if opd2=0 %then print string("divide by zero") %and %signal 15
case_OPN_4:;
if (OPD2 != 0) goto L_0025;
_imp_PRINTSTRING(_imp_str_literal("divide by zero"));
_imp_signal(15, 0, 0, "");
L_0025:;
// 108 pushopd(opd1/opd2) ; %return
PUSHOPD((double)(OPD1 / OPD2));
return;
// 109 opn(exp):pushopd(opd1^int(opd2))
case_OPN_5:;
PUSHOPD(_imp_REXP(OPD1, _imp_INT(OPD2)));
// 110 %end
return;
case_OPN_dispatch:
if (OPN_index < 1 || OPN_index > 5)
_imp_signalf(6, 3, OPN_index, "->OPN(%d) out of bounds at %s line %d", OPN_index, OPN_file, OPN_line);
goto *OPN[OPN_index - 1];
} /* end of OPERATE */
// 111 !
// 112 %end {of eval}
_imp_signal(8, 4, 0, "result missing");
} /* end of EVAL */
// 113 %real val
float VAL;
// 114
// 115 %on %event 9,15 %start {to trap everything}
if (!_imp_on_event(9, 15)) goto L_0026;
// 116 {*} %stop %if Event_Event = 9
if (_imp_EVENT().EVENT != 9) goto L_0027;
_imp_stop(0);
L_0027:;
// 117 print string("?
_imp_PRINTSTRING(_imp_str_literal("?\n"));
// 118+ ")
// 119 ->again ; %finish
goto U_1000;
L_0026:;
// 120
// 121 select input(0); select output(0)
_imp_SELECTINPUT(0);
_imp_SELECTOUTPUT(0);
// 122 prompt("eval:")
_imp_PROMPT(_imp_str_literal_size(15, "eval:"));
// 123 again:val=eval
U_1000:;
VAL = EVAL();
// 124 %if val=int(val) %then write(int(val),0) { imp77 perms missing} {%else print(val,0,4)}
if (VAL != _imp_INT(VAL)) goto L_0028;
_imp_WRITE(_imp_INT(VAL), 0);
L_0028:;
// 125 newline
_imp_NEWLINE();
// 126 ->again
goto U_1000;
// 127
// 128 %endofprogram
end_0:;
}