#include #include using namespace std; int trace = 0; #define TRACE if (trace) #define SIZESTACK 4096 int TOS=-1; int STACK[SIZESTACK]={0}; string allout = ""; string OPname(int opcode); void PUSH(int value);//PUT VALUE ON STACK //STACK SIZE INCREASES 1 void POP(int &value);//GET VALUE FROM STACK //STACK IS REDUCED BY ONE void LOAD(int sp);//LOAD FROM STACK ADDRESS (STACK[TOS] IS OFFSET, SP IS BASE) //STACK SIZE IS UNCHANGED void SAVE(int sp);//STORE BUT LEAVE VALUE ON STACK (STACK[TOS] IS OFFSET, STACK[TOS-1] HAS VALUE) //STACK SHRINKS BY ONE void STORE(int sp);//STORE AND REMOVE FROM STACK (STACK[TOS] IS OFFSET, STACK[TOS-1] HAS VALUE) //STACK SHRINKS BY TWO void CALL(int);//CALL FUNCTION params, FID must be on stack (pass nummparams) bool TRUE();//RETURNS TRUE IS TOP OF STACK IS NOT ZERO//STACK IS REDUCED BY ONE void ADD();//POPS TWO ITEMS AND REPLACES WITH SUM void SUB();//POPS TWO ITEMS AND REPLACES WITH DIFFERENCE void MUL();//POPS TWO ITEMS AND REPLACES WITH PRODUCT void DIV();//POPS TWO ITEMS AND REPLACES WITH QUOTIENT void EQU();//POPS TWO ITEMS AND REPLACES WITH ONE IF EQUAL ELSE ZERO void NEQ();//POPS TWO ITEMS AND REPLACES WITH ONE IF NOTEQUAL ELSE ZERO void LES();//POPS TWO ITEMS(B, A) AND REPLACES WITH ONE IF A < B ELSE ZERO void GTR();//POPS TWO ITEMS(B, A) AND REPLACES WITH ONE IF A > B ELSE ZERO void LEQ();//POPS TWO ITEMS(B, A) AND REPLACES WITH ONE IF A <= B ELSE ZERO void GEQ(); //POPS TWO ITEMS(B, A) AND REPLACES WITH ONE IF A >= B ELSE ZERO //ALTERNATES SAME AS ABOVE void PLUS(){ADD();} //POPS TWO ITEMS AND REPLACES WITH SUM void MINUS(){SUB();} //POPS TWO ITEMS AND REPLACES WITH DIFFERENCE void MULT(){MUL();} //POPS TWO ITEMS AND REPLACES WITH PRODUCT void EQ(){EQU();} //POPS TWO ITEMS AND REPLACES WITH ONE IF EQUAL ELSE ZERO void NE(){NEQ();} //POPS TWO ITEMS AND REPLACES WITH ONE IF NOTEQUAL ELSE ZERO void LT(){LES();} //POPS TWO ITEMS(B, A) AND REPLACES WITH ONE IF A < B ELSE ZERO void LESS(){LES();} //POPS TWO ITEMS(B, A) AND REPLACES WITH ONE IF A < B ELSE ZERO void GT(){GTR();} //POPS TWO ITEMS(B, A) AND REPLACES WITH ONE IF A > B ELSE ZERO void MORE(){GTR();} //POPS TWO ITEMS(B, A) AND REPLACES WITH ONE IF A > B ELSE ZERO void LE(){LEQ();} //POPS TWO ITEMS(B, A) AND REPLACES WITH ONE IF A <= B ELSE ZERO void GE(){GEQ();} //POPS TWO ITEMS(B, A) AND REPLACES WITH ONE IF A >= B ELSE ZERO void FCALL(int fid, int numparms);//CALL FUNCTION BY NUMBER, REQUIRES PARM COUNT #define BRANCHTRUE(LABEL) if (TRUE()) goto LABEL; #define BRANCHZERO(LABEL) if (!TRUE()) goto LABEL; #define BRANCH(LABEL) goto LABEL; #define JUMP(LABEL) goto LABEL; #define GOTO(LABEL) goto LABEL; #define END goto RET;//RETURN FROM PROCEDURE #define RETURN goto RETV; //RETURN FROM FUNCTION (RETURN VALUE MUST BE ON STACK) #define JUMPTABLE switch (fid){ #define FID(fid, label) case (fid): BRANCH( label ); #define ENDTABLE default: exit(1); } #define SWAP REVERSE2(); #define START SP=TOS+1; goto MAIN; } int main(int argc, char ** argv){ trace = (argc > 1); STACKMACHINE(0,0); return 0; } void REVERSE2(){//REVERSE TOP 2 ITEMS ON STACK //STACK SIZE REMAINS UNCHANGED int t = STACK[TOS]; STACK[TOS] = STACK[TOS-1]; STACK[TOS-1] = STACK[TOS]; } void LOAD(int sp){//LOAD FROM STACK ADDRESS //STACK SIZE REMAINS UNCHANGED TRACE cout << " LOAD: " << sp << " OFFSET:" << STACK[TOS] ; STACK[TOS]=STACK[sp+STACK[TOS]]; TRACE cout << " FETCHED: "<< STACK[TOS] << " TOS: " << TOS << endl; } void STORE(int sp){//STORE AND REMOVE FROM STACK //STACK SIZE SHRINKS 2 STACK[sp+STACK[TOS-1]] = STACK[TOS]; TRACE cout << " STORE: " << sp+STACK[TOS-1] << " ASSIGNED: "<< STACK[TOS]; TOS-=2; TRACE cout << " TOS: " << TOS << endl; } void SAVE(int sp){//STORE BUT LEAVE VALUE ON STACK //STACK SHRINKS BY 1 STACK[sp+STACK[TOS]] = STACK[TOS-1]; TRACE cout << " SAVE: " << sp+STACK[TOS] << " ASSIGNED: "<< STACK[TOS-1]; TOS--; TRACE cout << " TOS: " << TOS << endl; } #define OPCODE_PLUS 1 #define OPCODE_MINUS 2 #define OPCODE_MULT 3 #define OPCODE_DIV 4 #define OPCODE_EQ 5 #define OPCODE_NE 6 #define OPCODE_LT 7 #define OPCODE_LE 8 #define OPCODE_GT 9 #define OPCODE_GE 10 void OP(int opcode); void ADD(){ OP(OPCODE_PLUS); } void SUB(){ OP(OPCODE_MINUS); } void MUL(){ OP(OPCODE_MULT); } void DIV(){ OP(OPCODE_DIV); } void EQU(){ OP(OPCODE_EQ); } void NEQ(){ OP(OPCODE_NE); } void LES(){ OP(OPCODE_LT); } void GTR(){ OP(OPCODE_GT); } void LEQ(){ OP(OPCODE_LE); } void GEQ(){ OP(OPCODE_GE); } void PUSH(int value){ TOS++; STACK[TOS]=value; TRACE cout << " PUSH: "<< STACK[TOS] << " TOS: " << TOS << endl; } void POP(int & value){ value = STACK[TOS]; TOS--; TRACE cout << " POP: "<< STACK[TOS+1] << " TOS: " << TOS << endl; } bool TRUE(){ TOS--; TRACE cout << " COND: "<< STACK[TOS+1] << " TOS: " << TOS << endl; return STACK[TOS+1] != 0; } void OP(int opcode){ TRACE cout << " OP: " << opcode << OPname(opcode) << endl; int left, right; right = STACK[TOS--]; left = STACK[TOS]; switch (opcode) { case (OPCODE_PLUS) : STACK[TOS]=(left+right); break; case (OPCODE_MINUS) : STACK[TOS]=(left-right); break; case (OPCODE_MULT) : STACK[TOS]=(left*right); break; case (OPCODE_DIV) : STACK[TOS]=(left/right); break; case (OPCODE_EQ) : if (left == right) STACK[TOS]=(1); else STACK[TOS]= (0); break; case (OPCODE_NE) : if (left != right) STACK[TOS]=(1); else STACK[TOS]= (0); break; case (OPCODE_LT) : if (left < right) STACK[TOS]=(1); else STACK[TOS]= (0); break; case (OPCODE_LE) : if (left <= right) STACK[TOS]=(1); else STACK[TOS]= (0); break; case (OPCODE_GT) : if (left > right) STACK[TOS]=(1); else STACK[TOS]= (0); break; case (OPCODE_GE) : if (left >= right) STACK[TOS]=(1); else STACK[TOS]= (0); break; default: cout << "bad opcode" << endl; exit(1); } TRACE cout << " OP: " << opcode << OPname(opcode) << " result: "<< STACK[TOS] << " TOS:" << TOS << endl; } string OPname(int opcode){ switch (opcode) { case (OPCODE_PLUS) : return "PLUS"; case (OPCODE_MINUS) : return "MINUS"; case (OPCODE_MULT) : return "MULT"; case (OPCODE_DIV) : return "DIV"; case (OPCODE_EQ) : return "EQ"; case (OPCODE_NE) : return "NE"; case (OPCODE_LT) : return "LT"; case (OPCODE_LE) : return "LE"; case (OPCODE_GT) : return "GT"; case (OPCODE_GE) : return "GE"; default: return "bad opcode"; } } void STACKMACHINE (int fid, int SP); void CALL(int numparms){ int fid; int SP; fid = STACK[TOS--]; SP = TOS-numparms+1; TRACE cout << " CALL: " << fid << " ParamCnt: " << numparms << " SP: " << SP << endl; STACKMACHINE (fid, SP); if (SP == TOS)//returned a value { TRACE cout << " RETURN: value:" << STACK[TOS] ; TRACE cout << " TOS: " << TOS << endl; } else//void return { TRACE cout << " RETURN TOS: " << TOS << endl; } } #define push(val) PUSH(val); #define load(val) LOAD(val); #define store(val) STORE(val); #define save(val) SAVE(val); #define add ADD(); #define sub SUB(); #define mult MUL(); #define div DIV(); #define eq EQU(); #define lt LES(); #define gt GTR(); #define ne NEQ(); #define nlt GEQ(); #define ngt LEQ(); #define jumptable JUMPTABLE #define entry(num,label) FID(num, label); #define endtable ENDTABLE; #define call(cnt) CALL(cnt); #define ret RETURN; #define end END; #define jump(label) BRANCH(label) #define brz(label) BRANCHZERO(label) #define brnz(label) BRANCHTRUE(label) #define start START; void STACKMACHINE (int fid, int SP) { goto CALLSWITCH; EXIT: exit(STACK[TOS]); RET: TOS=SP-1; return; RETV: TOS++; STACK[TOS]=SP; SAVE(0); TOS=SP; return; INPUT: { int value; cout << "(waiting for input)" ; cin >> value; TOS++; STACK[TOS]=value; goto RETV; } OUTPUT: { int value; POP(value); cout << "(output)" << value << endl; TRACE { stringstream ss; ss << value << endl; allout = allout + ss.str(); cout << "all output: " << endl << allout << endl; } goto RET; } /* YOUR GENERATED CODE GOES HERE */