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