Core library reprogramming #5
@ -1,7 +1,6 @@
|
||||
package me.topchetoeu.jscript.engine.frame;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import me.topchetoeu.jscript.Location;
|
||||
import me.topchetoeu.jscript.engine.Context;
|
||||
@ -25,8 +24,8 @@ public class CodeFrame {
|
||||
public final int tryStart, catchStart, finallyStart, end;
|
||||
public int state;
|
||||
public Object retVal;
|
||||
public Object err;
|
||||
public int jumpPtr;
|
||||
public EngineException err;
|
||||
|
||||
public TryCtx(int tryStart, int tryN, int catchN, int finallyN) {
|
||||
hasCatch = catchN >= 0;
|
||||
@ -46,7 +45,7 @@ public class CodeFrame {
|
||||
public final LocalScope scope;
|
||||
public final Object thisArg;
|
||||
public final Object[] args;
|
||||
public final List<TryCtx> tryStack = new ArrayList<>();
|
||||
public final Stack<TryCtx> tryStack = new Stack<>();
|
||||
public final CodeFunction function;
|
||||
|
||||
public Object[] stack = new Object[32];
|
||||
@ -94,9 +93,11 @@ public class CodeFrame {
|
||||
stack[stackPtr++] = Values.normalize(ctx, val);
|
||||
}
|
||||
|
||||
// TODO: THIS SYSTEM IS SEVERLY BROKEN
|
||||
// MUST FIX!!!!!
|
||||
|
||||
private void setCause(Context ctx, Object err, Object cause) throws InterruptedException {
|
||||
if (err instanceof ObjectValue) {
|
||||
Values.setMember(ctx, err, ctx.env.symbol("Symbol.cause"), cause);
|
||||
}
|
||||
}
|
||||
private Object nextNoTry(Context ctx) throws InterruptedException {
|
||||
if (Thread.currentThread().isInterrupted()) throw new InterruptedException();
|
||||
if (codePtr < 0 || codePtr >= function.body.length) return null;
|
||||
@ -115,195 +116,114 @@ public class CodeFrame {
|
||||
}
|
||||
}
|
||||
|
||||
private void setCause(Context ctx, Object err, Object cause) throws InterruptedException {
|
||||
if (err instanceof ObjectValue) {
|
||||
Values.setMember(ctx, err, ctx.env.symbol("Symbol.cause"), cause);
|
||||
}
|
||||
}
|
||||
// private void propagateErr(Context ctx, Object err) {
|
||||
// while (!tryStack.isEmpty()) {
|
||||
// var tmp = tryStack.get(tryStack.size() - 1);
|
||||
public Object next(Context ctx, Object value, Object returnValue, Object error) throws InterruptedException {
|
||||
if (value != Runners.NO_RETURN) push(ctx, value);
|
||||
|
||||
// if (tmp.state == TryCtx.STATE_TRY || tmp.state == TryCtx.STATE_CATCH) {
|
||||
// tmp.jumpPtr = tmp.end;
|
||||
|
||||
// if (tmp.state == TryCtx.STATE_TRY && tmp.hasCatch) {
|
||||
// tmp.state = TryCtx.STATE_CATCH;
|
||||
// scope.catchVars.add(new ValueVariable(false, err));
|
||||
// codePtr = tmp.catchStart;
|
||||
// return;
|
||||
// }
|
||||
// else if (tmp.hasFinally) {
|
||||
// tmp.state = TryCtx.STATE_FINALLY_THREW;
|
||||
// tmp.err = new EngineException(err);
|
||||
// codePtr = tmp.finallyStart;
|
||||
// return;
|
||||
// }
|
||||
// else if (tmp.state == TryCtx.STATE_CATCH) scope.catchVars.remove(scope.catchVars.size() - 1);
|
||||
// }
|
||||
|
||||
// tryStack.remove(tryStack.size() - 1);
|
||||
// }
|
||||
// throw new EngineException(err);
|
||||
// }
|
||||
// private void propagateRet(Context ctx, Object val) {
|
||||
// while (!tryStack.isEmpty()) {
|
||||
// var tmp = tryStack.get(tryStack.size() - 1);
|
||||
|
||||
// if (tmp.state == TryCtx.STATE_TRY || tmp.state == TryCtx.STATE_CATCH) {
|
||||
// tmp.jumpPtr = tmp.end;
|
||||
|
||||
// if (tmp.hasFinally) {
|
||||
// tmp.state = TryCtx.STATE_FINALLY_RETURNED;
|
||||
// tmp.err = new EngineException(err);
|
||||
// codePtr = tmp.finallyStart;
|
||||
// return;
|
||||
// }
|
||||
// else if (tmp.state == TryCtx.STATE_CATCH) scope.catchVars.remove(scope.catchVars.size() - 1);
|
||||
// }
|
||||
|
||||
// tryStack.remove(tryStack.size() - 1);
|
||||
// }
|
||||
// return val;
|
||||
// }
|
||||
|
||||
public Object next(Context ctx, Object prevValue, Object prevReturn, Object prevError) throws InterruptedException {
|
||||
TryCtx tryCtx = null;
|
||||
if (prevError != Runners.NO_RETURN) prevReturn = Runners.NO_RETURN;
|
||||
|
||||
while (!tryStack.isEmpty()) {
|
||||
var tmp = tryStack.get(tryStack.size() - 1);
|
||||
var remove = false;
|
||||
|
||||
if (prevError != Runners.NO_RETURN) {
|
||||
remove = true;
|
||||
if (tmp.state == TryCtx.STATE_TRY) {
|
||||
tmp.jumpPtr = tmp.end;
|
||||
|
||||
if (tmp.hasCatch) {
|
||||
tmp.state = TryCtx.STATE_CATCH;
|
||||
scope.catchVars.add(new ValueVariable(false, prevError));
|
||||
prevError = Runners.NO_RETURN;
|
||||
codePtr = tmp.catchStart;
|
||||
remove = false;
|
||||
}
|
||||
else if (tmp.hasFinally) {
|
||||
tmp.state = TryCtx.STATE_FINALLY_THREW;
|
||||
tmp.err = new EngineException(prevError);
|
||||
prevError = Runners.NO_RETURN;
|
||||
codePtr = tmp.finallyStart;
|
||||
remove = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (prevReturn != Runners.NO_RETURN) {
|
||||
remove = true;
|
||||
if (tmp.hasFinally && tmp.state <= TryCtx.STATE_CATCH) {
|
||||
tmp.state = TryCtx.STATE_FINALLY_RETURNED;
|
||||
tmp.retVal = prevReturn;
|
||||
prevReturn = Runners.NO_RETURN;
|
||||
codePtr = tmp.finallyStart;
|
||||
remove = false;
|
||||
}
|
||||
}
|
||||
else if (tmp.state == TryCtx.STATE_TRY) {
|
||||
if (codePtr < tmp.tryStart || codePtr >= tmp.catchStart) {
|
||||
if (jumpFlag) tmp.jumpPtr = codePtr;
|
||||
else tmp.jumpPtr = tmp.end;
|
||||
|
||||
if (tmp.hasFinally) {
|
||||
tmp.state = TryCtx.STATE_FINALLY_JUMPED;
|
||||
codePtr = tmp.finallyStart;
|
||||
}
|
||||
else codePtr = tmp.jumpPtr;
|
||||
remove = !tmp.hasFinally;
|
||||
}
|
||||
}
|
||||
else if (tmp.state == TryCtx.STATE_CATCH) {
|
||||
if (codePtr < tmp.catchStart || codePtr >= tmp.finallyStart) {
|
||||
if (jumpFlag) tmp.jumpPtr = codePtr;
|
||||
else tmp.jumpPtr = tmp.end;
|
||||
scope.catchVars.remove(scope.catchVars.size() - 1);
|
||||
|
||||
if (tmp.hasFinally) {
|
||||
tmp.state = TryCtx.STATE_FINALLY_JUMPED;
|
||||
codePtr = tmp.finallyStart;
|
||||
}
|
||||
else codePtr = tmp.jumpPtr;
|
||||
remove = !tmp.hasFinally;
|
||||
}
|
||||
}
|
||||
else if (codePtr < tmp.finallyStart || codePtr >= tmp.end) {
|
||||
if (!jumpFlag) {
|
||||
if (tmp.state == TryCtx.STATE_FINALLY_THREW) throw tmp.err;
|
||||
else if (tmp.state == TryCtx.STATE_FINALLY_RETURNED) return tmp.retVal;
|
||||
else if (tmp.state == TryCtx.STATE_FINALLY_JUMPED) codePtr = tmp.jumpPtr;
|
||||
}
|
||||
else codePtr = tmp.jumpPtr;
|
||||
remove = true;
|
||||
if (returnValue == Runners.NO_RETURN && error == Runners.NO_RETURN) {
|
||||
try { returnValue = nextNoTry(ctx); }
|
||||
catch (EngineException e) { error = e.value; }
|
||||
}
|
||||
|
||||
if (remove) tryStack.remove(tryStack.size() - 1);
|
||||
else {
|
||||
tryCtx = tmp;
|
||||
while (!tryStack.empty()) {
|
||||
var tryCtx = tryStack.peek();
|
||||
var newState = -1;
|
||||
|
||||
switch (tryCtx.state) {
|
||||
case TryCtx.STATE_TRY:
|
||||
if (error != Runners.NO_RETURN) {
|
||||
if (tryCtx.hasCatch) {
|
||||
tryCtx.err = error;
|
||||
newState = TryCtx.STATE_CATCH;
|
||||
}
|
||||
else if (tryCtx.hasFinally) {
|
||||
tryCtx.err = error;
|
||||
newState = TryCtx.STATE_FINALLY_THREW;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (prevError != Runners.NO_RETURN) throw new EngineException(prevError);
|
||||
if (prevReturn != Runners.NO_RETURN) return prevReturn;
|
||||
if (prevValue != Runners.NO_RETURN) push(ctx, prevValue);
|
||||
|
||||
if (tryCtx == null) return nextNoTry(ctx);
|
||||
else if (tryCtx.state == TryCtx.STATE_TRY) {
|
||||
try {
|
||||
var res = nextNoTry(ctx);
|
||||
if (res != Runners.NO_RETURN && tryCtx.hasFinally) {
|
||||
tryCtx.retVal = res;
|
||||
tryCtx.state = TryCtx.STATE_FINALLY_RETURNED;
|
||||
}
|
||||
|
||||
else return res;
|
||||
}
|
||||
catch (EngineException e) {
|
||||
throw e;
|
||||
// propagateErr(ctx, e.value);
|
||||
}
|
||||
|
||||
codePtr = tryCtx.finallyStart;
|
||||
return Runners.NO_RETURN;
|
||||
}
|
||||
else if (tryCtx.state == TryCtx.STATE_CATCH) {
|
||||
try {
|
||||
var res = nextNoTry(ctx);
|
||||
if (res != Runners.NO_RETURN && tryCtx.hasFinally) {
|
||||
tryCtx.retVal = res;
|
||||
tryCtx.state = TryCtx.STATE_FINALLY_RETURNED;
|
||||
}
|
||||
else return res;
|
||||
}
|
||||
catch (EngineException e) {
|
||||
setCause(ctx, e.value, tryCtx.err);
|
||||
else if (returnValue != Runners.NO_RETURN) {
|
||||
if (tryCtx.hasFinally) {
|
||||
tryCtx.err = e;
|
||||
tryCtx.state = TryCtx.STATE_FINALLY_THREW;
|
||||
tryCtx.retVal = error;
|
||||
newState = TryCtx.STATE_FINALLY_RETURNED;
|
||||
}
|
||||
else throw e;
|
||||
break;
|
||||
}
|
||||
else if (codePtr >= tryCtx.tryStart && codePtr < tryCtx.catchStart) return Runners.NO_RETURN;
|
||||
|
||||
if (tryCtx.hasFinally) {
|
||||
if (jumpFlag) tryCtx.jumpPtr = codePtr;
|
||||
else tryCtx.jumpPtr = tryCtx.end;
|
||||
newState = TryCtx.STATE_FINALLY_JUMPED;
|
||||
}
|
||||
else codePtr = tryCtx.end;
|
||||
break;
|
||||
case TryCtx.STATE_CATCH:
|
||||
if (error != Runners.NO_RETURN) {
|
||||
if (tryCtx.hasFinally) {
|
||||
tryCtx.err = error;
|
||||
newState = TryCtx.STATE_FINALLY_THREW;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (returnValue != Runners.NO_RETURN) {
|
||||
if (tryCtx.hasFinally) {
|
||||
tryCtx.retVal = error;
|
||||
newState = TryCtx.STATE_FINALLY_RETURNED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (codePtr >= tryCtx.catchStart && codePtr < tryCtx.finallyStart) return Runners.NO_RETURN;
|
||||
|
||||
if (tryCtx.hasFinally) {
|
||||
if (jumpFlag) tryCtx.jumpPtr = codePtr;
|
||||
else tryCtx.jumpPtr = tryCtx.end;
|
||||
newState = TryCtx.STATE_FINALLY_JUMPED;
|
||||
}
|
||||
else codePtr = tryCtx.end;
|
||||
break;
|
||||
case TryCtx.STATE_FINALLY_THREW:
|
||||
if (error != Runners.NO_RETURN) setCause(ctx, error, tryCtx.err);
|
||||
else if (codePtr < tryCtx.finallyStart || codePtr >= tryCtx.end) error = tryCtx.err;
|
||||
else return Runners.NO_RETURN;
|
||||
break;
|
||||
case TryCtx.STATE_FINALLY_RETURNED:
|
||||
if (returnValue == Runners.NO_RETURN) {
|
||||
if (codePtr < tryCtx.finallyStart || codePtr >= tryCtx.end) returnValue = tryCtx.retVal;
|
||||
else return Runners.NO_RETURN;
|
||||
}
|
||||
break;
|
||||
case TryCtx.STATE_FINALLY_JUMPED:
|
||||
if (codePtr < tryCtx.finallyStart || codePtr >= tryCtx.end) {
|
||||
if (!jumpFlag) codePtr = tryCtx.jumpPtr;
|
||||
else codePtr = tryCtx.end;
|
||||
}
|
||||
else return Runners.NO_RETURN;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tryCtx.state == TryCtx.STATE_CATCH) scope.catchVars.remove(scope.catchVars.size() - 1);
|
||||
|
||||
if (newState == -1) {
|
||||
tryStack.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
tryCtx.state = newState;
|
||||
switch (newState) {
|
||||
case TryCtx.STATE_CATCH:
|
||||
scope.catchVars.add(new ValueVariable(false, tryCtx.err));
|
||||
codePtr = tryCtx.catchStart;
|
||||
break;
|
||||
default:
|
||||
codePtr = tryCtx.finallyStart;
|
||||
}
|
||||
|
||||
return Runners.NO_RETURN;
|
||||
}
|
||||
else if (tryCtx.state == TryCtx.STATE_FINALLY_THREW) {
|
||||
try {
|
||||
return nextNoTry(ctx);
|
||||
}
|
||||
catch (EngineException e) {
|
||||
setCause(ctx, e.value, tryCtx.err);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
else return nextNoTry(ctx);
|
||||
|
||||
if (error != Runners.NO_RETURN) throw new EngineException(error);
|
||||
if (returnValue != Runners.NO_RETURN) return returnValue;
|
||||
return Runners.NO_RETURN;
|
||||
}
|
||||
|
||||
public Object run(Context ctx) throws InterruptedException {
|
||||
|
Loading…
Reference in New Issue
Block a user