/* Java implementation of a unified-stack abstract machine sestoft@dina.kvl.dk * 2001-02-05 In a real stack machine, the stack is an array (not a list as in the SML model), and there is a special register called the stack pointer sp which is updated as the stack grows and shrinks. Accessing a variable x stored n deep into the stack can be done in constant time by address arithmetic relative to the stack pointer: just access the element stack[sp-n]. The interpreter seval below is a simple bytecode machine: each instruction is a single integer (representable in a byte). Instructions with arguments, such as CST and VAR, simply take their arguments from the next integer in the instruction stream. This is a Java program but might be written in C instead; it does not rely on object-orientation or garbage collection. */ class Machine { final static int CST = 0, VAR = 1, ADD = 2, SUB = 3, MUL = 4, POP = 5, SWAP = 6; public static void main(String[] args) { final int[] rpn1 = { CST, 17, VAR, 0, VAR, 1, ADD, SWAP, POP }; System.out.println(seval(rpn1)); final int[] rpn2 = { CST, 17, CST, 22, CST, 100, VAR, 1, MUL, SWAP, POP, VAR, 1, ADD, SWAP, POP }; System.out.println(seval(rpn2)); } static int seval(int[] code) { int[] stack = new int[1000]; // evaluation and env stack int sp = -1; // pointer to current stack top int pc = 0; // program counter int instr; // current instruction while (pc < code.length) switch (instr = code[pc++]) { case CST: stack[sp+1] = code[pc++]; sp++; break; case VAR: stack[sp+1] = stack[sp-code[pc++]]; sp++; break; case ADD: stack[sp-1] = stack[sp-1] + stack[sp]; sp--; break; case SUB: stack[sp-1] = stack[sp-1] - stack[sp]; sp--; break; case MUL: stack[sp-1] = stack[sp-1] * stack[sp]; sp--; break; case POP: sp--; break; case SWAP: { int tmp = stack[sp]; stack[sp] = stack[sp-1]; stack[sp-1] = tmp; break; } default: throw new RuntimeException("Illegal instruction " + instr + " at address " + (pc-1)); } return stack[sp]; } }