// -*- mode: Java; c-basic-offset: 3; tab-width: 8; indent-tabs-mode: nil -*-
// Copyright (C) 2008 Andreas Krey, Ulm, Germany <a.krey@gmx.de>
package gloop;
public class Runner {
private String [] strings;
private byte [] code;
private int entry;
private static final Object nullval = new Object () {
public String toString () { return "nullval"; }
};
public Runner (String [] str, byte [] a, int e) {
strings = str;
code = a;
entry = e;
}
private static class Frame {
public Frame stat;
public Frame dyn;
public int base; // Number of saved stack cells
public Object [] data;
public int pc;
}
private static class Fun {
public Frame ctx;
public int start;
public int nargs;
}
public void run () {
Object [] stack = new Object [100]; /// XXX Need some measure...
int sp = 0;
int pc = entry;
Object acc = null;
Frame tmp = null;
int param = 0;
Frame fp = new Frame ();
fp.base = 0;
fp.data = new Object [100];
fp.pc = -1;
while (true) {
int c = code [pc ++] & 255;
if (c >= 240) {
param = (param << 4) | (c & 15);
continue;
}
String op = Code.getCode (c);
for (int i = 0; i < sp; i ++) {
System.out.print (" " + stack [i]);
}
System.out.println (" * " + acc);
if (param != 0) {
System.out.println (" [" + (pc - 1) + "] op=" + op +
" (" + param + ")");
} else {
System.out.println (" [" + (pc - 1) + "] op=" + op);
}
if (op == "nop") {
} else if (op == "up") {
for (tmp = fp; param > 0; param --) {
tmp = tmp.stat;
}
} else if (op == "lstore") {
fp.data [param + fp.base] = acc;
param = 0;
} else if (op == "store") {
tmp.data [param + tmp.base] = acc;
param = 0;
} else if (op == "lload") {
acc = fp.data [param + fp.base];
param = 0;
} else if (op == "load") {
acc = tmp.data [param + tmp.base];
param = 0;
} else if (op == "print") {
System.out.println ("PRINT: " + acc);
} else if (op == "strval") {
acc = strings [param];
param = 0;
} else if (op == "numval") {
acc = new Integer (param);
param = 0;
} else if (op == "nullval") {
acc = nullval;
} else if (op == "fun") {
Fun f = new Fun ();
f.ctx = fp;
f.start = ((Integer)acc).intValue ();
f.nargs = param;
param = 0;
acc = f;
} else if (op == "push") {
stack [sp ++ ] = acc;
} else if (op == "swap") {
Object h = acc;
acc = stack [sp - 1];
stack [sp - 1] = h;
} else if (op == "mult") {
acc = new Integer (((Integer)acc).intValue () *
((Integer)stack [-- sp]).intValue ());
} else if (op == "call") {
Fun a = (Fun)acc;
Frame f = new Frame ();
if (a.nargs != param) {
throw new IllegalArgumentException ("mismatching arg count");
}
f.data = new Object [100];
f.pc = pc;
f.base = sp - param; // We take the params from the stack!
f.dyn = fp;
f.stat = a.ctx;
for (int i = 0; i < sp; i ++) {
System.out.println ("COPY " + stack [i]);
f.data [i] = stack [i];
}
pc = a.start;
sp = 0;
param = 0;
fp = f;
} else if (op == "ret") {
pc = fp.pc;
sp = 0;
for (int i = 0; i < fp.base; i ++) {
stack [sp ++] = fp.data [i];
}
fp = fp.dyn;
} else if (op == "stop") {
break;
} else {
throw new IllegalArgumentException ("unknown op " + op +
" (" + c + ")");
}
}
}
}