/* A unified-stack abstract machine for imperative programs sestoft@dina.kvl.dk * 2001-03-21, 2002-03-19 To execute a program file using this abstract machine, do: java Machine ... or java Machinetrace ... */ import java.io.*; import java.util.*; class Machine { public static void main(String[] args) throws FileNotFoundException, IOException { if (args.length == 0) System.out.println("Usage: java Machine ...\n"); else execute(args, false); } // These numeric instruction codes must agree with Machine.sml: final static int CST = 0, ADD = 1, SUB = 2, MUL = 3, DIV = 4, MOD = 5, EQ = 6, LT = 7, NOT = 8, DUP = 9, SWAP = 10, LDI = 11, STI = 12, GETBP = 13, GETSP = 14, INCSP = 15, GOTO = 16, IFZERO = 17, IFNZRO = 18, CALL = 19, TCALL = 20, RET = 21, PRINTI = 22, PRINTC = 23, STOP = 24; // Read code from file and execute it final static int STACKSIZE = 1000; static void execute(String[] args, boolean trace) throws FileNotFoundException, IOException { int[] p = readfile(args[0]); // Read the program from file int[] s = new int[STACKSIZE]; // The evaluation stack int sp = execcode(p, s, 1, -1, trace); // Allocate global variables for (int i=1; i=0; i--) s[sp-i-pop] = s[sp-i]; sp = sp - pop; pc = p[pc]; } break; case RET: { int res = s[sp]; sp = sp-p[pc]; bp = s[--sp]; pc = s[--sp]; s[sp] = res; } break; case PRINTI: System.out.print(s[sp] + " "); break; case PRINTC: System.out.print((char)(s[sp])); break; case STOP: return sp; default: throw new RuntimeException("Illegal instruction " + p[pc-1] + " at address " + (pc-1)); } } } // Print the stack machine instruction at p[pc] static String insname(int[] p, int pc) { switch (p[pc]) { case CST: return "CST " + p[pc+1]; case ADD: return "ADD"; case SUB: return "SUB"; case MUL: return "MUL"; case DIV: return "DIV"; case MOD: return "MOD"; case EQ: return "EQ"; case LT: return "LT"; case NOT: return "NOT"; case DUP: return "DUP"; case SWAP: return "SWAP"; case LDI: return "LDI"; case STI: return "STI"; case GETBP: return "GETBP"; case GETSP: return "GETSP"; case INCSP: return "INCSP " + p[pc+1]; case GOTO: return "GOTO " + p[pc+1]; case IFZERO: return "IFZERO " + p[pc+1]; case IFNZRO: return "IFNZRO " + p[pc+1]; case CALL: return "CALL " + p[pc+1] + " " + p[pc+2]; case TCALL: return "TCALL " + p[pc+1] + " " + p[pc+2] + " " + p[pc+3]; case RET: return "RET " + p[pc+1]; case PRINTI: return "PRINTI"; case PRINTC: return "PRINTC"; case STOP: return "STOP"; default: return ""; } } // Print current stack and current instruction static void printsppc(int[] s, int bp, int sp, int[] p, int pc) { System.out.print("{ "); for (int i=sp; i>=0; i--) System.out.print(s[i] + " "); System.out.print("}"); System.out.println("[" + pc + ": " + insname(p, pc) + "]"); } // Read instructions from a file public static int[] readfile(String filename) throws FileNotFoundException, IOException { ArrayList /* of String */ rawprogram = new ArrayList(); Reader inp = new FileReader(filename); StreamTokenizer tstream = new StreamTokenizer(inp); tstream.parseNumbers(); tstream.nextToken(); while (tstream.ttype == StreamTokenizer.TT_NUMBER) { rawprogram.add(new Integer((int)tstream.nval)); tstream.nextToken(); } inp.close(); final int programsize = rawprogram.size(); int[] program = new int[programsize]; for (int i=0; i ...\n"); else Machine.execute(args, true); } }