char op = '?';
LineInfo li = new LineInfo(0, 0);
try {
if (rec > MAX_RECURSION)
throw new PlcException("stack overflow", "Aborted due to too many recursive non-tail calls.");
try {
while (ip < code.length) {
opc[0]++;
if (opc[0] == MAX_INSTRUCTION_COUNT)
throw new PlcException("ran too long", "Aborted due to running too many instructions in " +
"one update");
if (executionStack.size() > MAX_STACK_SIZE)
throw new PlcException("stack too big", "Aborted due to too many values pushed onto stack" +
".");
op = code[ip];
li = lis[ip];
switch (op) {
case '+':
executionStack.push(true);
break;
case '-':
executionStack.push(false);
break;
case 'A':
executionStack.push(a);
break;
case 'B':
executionStack.push(b);
break;
case 'C':
executionStack.push(c);
break;
case '<':
case '>':
case 'e': {
int mul = 1;
int add = 0;
switch (code[ip]) {
case '<':
add = -1;
break;
case '>':
add = +1;
break;
case 'e':
mul = 0;
break;
default:
break;
}
switch (code[++ip]) {
case 'p':
case 'P':
pshift = mul * pshift + add;
break;
case 't':
case 'T':
tshift = mul * tshift + add;
break;
case 'l':
case 'L':
lshift = mul * lshift + add;
break;
default:
break;
}
}
break;
case 'S':
case 'L': {
boolean[] table = null;
int shift = 0;
switch (code[++ip]) {
case 'p':
shift = pshift;
case 'P':
table = pt;
break;
case 't':
shift = tshift;
case 'T':
table = tt;
break;
case 'l':
shift = lshift;
case 'L':
table = lt;
break;
default:
break;
}
if(table == null)
break;
int add = decodeAddress(code[++ip], shift);
if (op == 'S')
table[add] = executionStack.pop();
else
executionStack.push(table[add]);
}
break;
case 'd':
executionStack.push(executionStack.peek());
break;
case 'p':
executionStack.pop();
break;
case 'v':
try {
int level = parseNumber(code[++ip]);
executionStack.push(executionStack.get(executionStack.size() - 1 - level));
} catch (ArrayIndexOutOfBoundsException e) {
throw new PlcException("bad stack pos", "Attempted to call peek on too small a " +
"stack.");
}
break;
case 'x':
boolean x = executionStack.pop();
boolean y = executionStack.pop();
executionStack.push(x);
executionStack.push(y);
break;
default:
break;
case '!':
executionStack.push(!executionStack.pop());
break;
// Using the short-circuiting versions would cause it to sometimes pop one less
// value than it should.
case '^':
executionStack.push(executionStack.pop() ^ executionStack.pop());
break;
case '&':
executionStack.push(executionStack.pop() & executionStack.pop());
break;
case '|':
executionStack.push(executionStack.pop() | executionStack.pop());
break;
case '=':
executionStack.push(executionStack.pop() == executionStack.pop());
break;
case '.':
boolean ta = parseTableChar(code[++ip]);
boolean tb = parseTableChar(code[++ip]);
boolean tc = parseTableChar(code[++ip]);
boolean td = parseTableChar(code[++ip]);
boolean e = executionStack.pop();
boolean f = executionStack.pop();
if (!e && !f) {
executionStack.push(ta);
} else if (!e && f) {
executionStack.push(tb);
} else if (e && !f) {
executionStack.push(tc);
} else {
executionStack.push(td);
}
break;
case 'c':
case 't':
int n = parseNumber(code[++ip]) * 10 + parseNumber(code[++ip]);
int nArgs = parseNumber(code[++ip]);
boolean[] arg = new boolean[nArgs];
if (n < 0 || n >= funs.length)
throw new PlcException("func not found", "Attempted to call nonexistent function " +
"#" + n);
if (op == 'c') {
for (int i = nArgs - 1; i >= 0; i--) {
arg[i] = executionStack.pop();
}
Boolean v = executeFunction(n, pt, tt, funs, a, b, c, arg, opc, rec + 1);
if (v != null) {
executionStack.push(v);
}
break;
} else {
fno = n;
args = arg;
tailcalls++;
continue outer;
}
case '[':
if (!executionStack.pop()) {
ip = jt[ip];
}
break;
case ']':
if (executionStack.pop()) {
ip = jt[ip];
}
break;
case 's':
return null;
case 'r':
return executionStack.pop();
}
ip++;
}
} catch (EmptyStackException e) {
throw new PlcException("empty stack", "Popped while stack was empty.");
} catch (StackOverflowError e) {
throw new PlcException("stack overflow", "Java stack overflow.");
}
} catch (PlcException e) {
throw new PlcException(e.getMessage(), errmsg(e.detailedMessage, fno, op, li, pt, tt, lt, pshift,
tshift, lshift, executionStack,
tailcalls));
}
return null;
}