package jvm.engine;
import jvm.classfile.method.Method;
import jvm.exception.ReadClassException;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class ExecutorEngine {
private Stack<StackFrame> stack = new Stack<>();
public void execute(Method main) throws ReadClassException {
StackFrame mainFrame = StackFrame.create(main);
stack.push(mainFrame);
while (!stack.isEmpty()) {
StackFrame top = stack.peek();
ExecutionResult result = top.execute();
if (result.isExitCurrentFrame()) {
stack.pop();
} else if (result.isPauseAndRunNewFrame()) {
Method next = result.getNextMethod();
StackFrame newFrame = StackFrame.create(next);
setupFunctionCallParams(top, newFrame);
stack.push(newFrame);
}
}
}
private void setupFunctionCallParams(StackFrame currentFrame, StackFrame nextFrame) {
List<JavaObject> local = createLocalVariableTable(currentFrame, nextFrame.getMethod());
nextFrame.setLocalVariableTable(local);
nextFrame.setCallerFrame(currentFrame);
}
private List<JavaObject> createLocalVariableTable(StackFrame top, Method next) {
int paramCount = next.getParamCount();
Stack<JavaObject> params = new Stack<>();
for (int i = 0; i < paramCount; ++i) {
JavaObject param = top.getOperandStack().pop();
params.push(param);
}
if (!next.getAccessFlag().isStatic()) {
JavaObject param = top.getOperandStack().pop();
params.push(param);
}
List<JavaObject> local = new ArrayList<>();
while (!params.isEmpty()) {
local.add(params.pop());
}
return local;
}
}