TranslatedFunction* Code::functionByName(const string& name) const { FunctionMap::const_iterator it = _functionById.find(name); if (it == _functionById.end()) { return 0; } return functionById((*it).second); }
void BytecodeInterpreter::processCall(uint16_t functionId) { auto fun = (BytecodeFunction *)functionById(functionId); StackFrame frame = { fun, 0, (uint32_t)variableStack.size(), (uint32_t)operandStack.size() - fun->parametersNumber() }; callStack.push_back(frame); ctxOffset[functionId].push_back(frame.v_offset); // move arguments to variable stack auto it = std::prev(operandStack.end(), frame.function->parametersNumber()); std::move(it, operandStack.end(), std::back_inserter(variableStack)); operandStack.erase(it, operandStack.end()); // allocate space for locals variableStack.resize(variableStack.size() + frame.function->localsNumber()); }
Status* InterpreterCodeImpl::execute(std::vector<Var*>& vars) { ByteStack stack; typedef std::map<uint16_t, ByteStorage> VarMap; VarMap var_map; for (std::vector<Var*>::iterator it = vars.begin(); it != vars.end(); ++it) { if ((*it)->name() == "#__INTERPRETER_TRACING__#") { m_trace = true; } } BytecodeFunction* function = (BytecodeFunction*) functionById(0); Bytecode* bytecode = function->bytecode(); for (size_t bci = 0; bci < bytecode->length();) { Instruction insn = BC_INVALID; size_t length = 1; // size of the BC_INVALID decodeInsn(bytecode, bci, insn, length); switch (insn) { case BC_INVALID: return new Status("BC_INVALID", bci); break; case BC_DLOAD: stack.pushTyped(bytecode->getDouble(bci + 1)); break; case BC_ILOAD: stack.pushTyped(bytecode->getInt64(bci + 1)); break; case BC_SLOAD: stack.pushTyped(bytecode->getUInt16(bci + 1)); break; case BC_DLOAD0: stack.pushTyped(double(0)); break; case BC_ILOAD0: stack.pushTyped(int64_t(0)); break; case BC_SLOAD0: stack.pushTyped(uint16_t(0)); break; case BC_DLOAD1: stack.pushTyped(double(1)); break; case BC_ILOAD1: stack.pushTyped(int64_t(1)); break; case BC_DADD: stack.pushDouble(stack.popDouble() + stack.popDouble()); break; case BC_IADD: stack.pushInt64(stack.popInt64() + stack.popInt64()); break; case BC_DSUB: stack.pushDouble(stack.popDouble() - stack.popDouble()); break; case BC_ISUB: stack.pushInt64(stack.popInt64() - stack.popInt64()); break; case BC_DMUL: stack.pushDouble(stack.popDouble() * stack.popDouble()); break; case BC_IMUL: stack.pushInt64(stack.popInt64() * stack.popInt64()); break; case BC_DDIV: stack.pushDouble(stack.popDouble() / stack.popDouble()); break; case BC_IDIV: stack.pushInt64(stack.popInt64() / stack.popInt64()); break; case BC_IMOD: stack.pushInt64(stack.popInt64() % stack.popInt64()); break; case BC_DNEG: stack.pushDouble(-stack.popDouble()); break; case BC_INEG: stack.pushInt64(-stack.popInt64()); break; case BC_IPRINT: std::cout << stack.popInt64(); break; case BC_DPRINT: std::cout << stack.popDouble(); break; case BC_SPRINT: std::cout << constantById(stack.popUInt16()); break; case BC_POP: stack.pop(); break; case BC_LOADDVAR0: stack.pushDouble(var_map[0].getDouble()); break; case BC_LOADDVAR1: stack.pushDouble(var_map[1].getDouble()); break; case BC_LOADDVAR2: stack.pushDouble(var_map[2].getDouble()); break; case BC_LOADDVAR3: stack.pushDouble(var_map[3].getDouble()); break; case BC_LOADIVAR0: stack.pushInt64(var_map[0].getInt64()); break; case BC_LOADIVAR1: stack.pushInt64(var_map[1].getInt64()); break; case BC_LOADIVAR2: stack.pushInt64(var_map[2].getInt64()); break; case BC_LOADIVAR3: stack.pushInt64(var_map[3].getInt64()); break; case BC_LOADSVAR0: stack.pushUInt16(var_map[0].getUInt16()); break; case BC_LOADSVAR1: stack.pushUInt16(var_map[1].getUInt16()); break; case BC_LOADSVAR2: stack.pushUInt16(var_map[2].getUInt16()); break; case BC_LOADSVAR3: stack.pushUInt16(var_map[3].getUInt16()); break; case BC_STOREDVAR0: var_map[0].setDouble(stack.popDouble()); break; case BC_STOREIVAR0: var_map[0].setInt64(stack.popInt64()); break; case BC_STORESVAR0: var_map[0].setUInt16(stack.popUInt16()); break; case BC_LOADDVAR: stack.pushDouble(var_map[bytecode->getUInt16(bci + 1)].getDouble()); break; case BC_LOADIVAR: stack.pushInt64(var_map[bytecode->getUInt16(bci + 1)].getInt64()); break; case BC_LOADSVAR: stack.pushUInt16(var_map[bytecode->getUInt16(bci + 1)].getUInt16()); break; case BC_STOREDVAR: var_map[bytecode->getUInt16(bci + 1)].setDouble(stack.popDouble()); break; case BC_STOREIVAR: var_map[bytecode->getUInt16(bci + 1)].setInt64(stack.popInt64()); break; case BC_STORESVAR: // out << name << " @" << getUInt16(bci + 1); var_map[bytecode->getUInt16(bci + 1)].setUInt16(stack.popUInt16()); break; // case BC_LOADCTXDVAR: // case BC_STORECTXDVAR: // case BC_LOADCTXIVAR: // case BC_STORECTXIVAR: // case BC_LOADCTXSVAR: // case BC_STORECTXSVAR: //// out << name << " @" << getUInt16(bci + 1) //// << ":" << getUInt16(bci + 3); // break; case BC_IFICMPNE: if (stack.popInt64() != stack.popInt64()) { bci += bytecode->getInt16(bci + 1) + 1; continue; } break; case BC_IFICMPE: if (stack.popInt64() == stack.popInt64()) { bci += bytecode->getInt16(bci + 1) + 1; continue; } break; case BC_IFICMPG: if (stack.popInt64() > stack.popInt64()) { bci += bytecode->getInt16(bci + 1) + 1; continue; } break; case BC_IFICMPGE: if (stack.popInt64() >= stack.popInt64()) { bci += bytecode->getInt16(bci + 1) + 1; continue; } break; case BC_IFICMPL: if (stack.popInt64() < stack.popInt64()) { bci += bytecode->getInt16(bci + 1) + 1; continue; } break; case BC_IFICMPLE: if (stack.popInt64() <= stack.popInt64()) { bci += bytecode->getInt16(bci + 1) + 1; continue; } break; case BC_JA: bci += bytecode->getInt16(bci + 1) + 1; continue; break; case BC_CALL://{ stack.pushTyped(bci + length); stack.pushTyped(function->id()); // std::clog << "saving return address: " << function->id() << ":" << bci + length << std::endl; // uint16_t f = stack.popUInt16(); // size_t b = stack.popTyped<size_t>(); // std::clog << "checking return address: " << f << ":" << b << std::endl; // stack.pushTyped(bci + length); // stack.pushTyped(function->id()); function = (BytecodeFunction*) functionById(bytecode->getUInt16(bci + 1)); if (!function) { return new Status("Unresolved function ID\n", bci); } bytecode = function->bytecode(); bci = 0; continue; break;//} case BC_CALLNATIVE: return new Status("Native functions are currently not supported\n", bci); break; case BC_RETURN: { uint16_t new_function_id = stack.popUInt16(); // std::clog << "new func id=" << new_function_id << std::endl; function = (BytecodeFunction*) functionById(new_function_id); if (!function) { return new Status("Unresolved function ID\n", bci); } bytecode = function->bytecode(); size_t new_bci = stack.popTyped<size_t>(); // std::clog << "new bci=" << new_bci << std::endl; bci = new_bci; continue; break; } case BC_BREAK: return new Status("Breakpoints are currently not supported\n", bci); break; default: return new Status("Unknown or unsupported instruction\n", bci); } bci += length; } #ifdef ENABLE_TRACING std::cout << "Result = " << var_map[0].getInt64() << std::endl; #endif return 0; }
void SimpleInterpreter::run(ostream &out) { stack.resize(50); bytecodes.clear(); indices.clear(); vars.clear(); bytecodes.push_back(bytecode); indices.push_back(0); contextID.push_back(0); callsCounter.push_back(0); SP = 0; while (!bytecodes.empty()) { indexType ¤tIndex = indices.back(); Bytecode &bytecode = *bytecodes.back(); Instruction instruction = bytecode.getInsn(currentIndex); size_t instructionLength = bytecodeLength(instruction); #ifdef LOG_INTERPRETER const char* bcName = bytecodeName(instruction, 0); cout << "index: " << currentIndex << ", instruction: " << bcName << endl; #endif switch (instruction) { case BC_DLOAD: pushVariable(bytecode.getDouble(currentIndex + 1)); break; case BC_ILOAD: pushVariable(bytecode.getInt64(currentIndex + 1)); break; case BC_SLOAD: pushVariable(constantById(bytecode.getUInt16(currentIndex + 1)).c_str()); break; case BC_DLOAD0: pushVariable(0.0); break; case BC_ILOAD0: pushVariable((signedIntType) 0); break; case BC_SLOAD0: pushVariable(""); break; case BC_DLOAD1: pushVariable(1.0); break; case BC_ILOAD1: pushVariable((signedIntType) 1); break; case BC_DLOADM1: pushVariable(-1.0); break; case BC_ILOADM1: pushVariable((signedIntType) - 1); break; case BC_DADD: binary_operation(VT_DOUBLE, add<double>); break; case BC_IADD: binary_operation(VT_INT, add < signedIntType > ); break; case BC_DSUB: binary_operation(VT_DOUBLE, sub<double>); break; case BC_ISUB: binary_operation(VT_INT, sub < signedIntType > ); break; case BC_DMUL: binary_operation(VT_DOUBLE, mul<double>); break; case BC_IMUL: binary_operation(VT_INT, mul < signedIntType > ); break; case BC_DDIV: binary_operation(VT_DOUBLE, _div<double>); break; case BC_IDIV: binary_operation(VT_INT, _div < signedIntType > ); break; case BC_IMOD: binary_operation(VT_INT, mod < signedIntType > ); break; case BC_DNEG: unary_operation(VT_DOUBLE, neg<double>); break; case BC_INEG: unary_operation(VT_INT, neg < signedIntType > ); break; case BC_IAOR: binary_operation(VT_INT, _or < signedIntType > ); break; case BC_IAAND: binary_operation(VT_INT, _and < signedIntType > ); break; case BC_IAXOR: binary_operation(VT_INT, _xor < signedIntType > ); break; case BC_IPRINT: out << popVariable().getIntValue(); out.flush(); break; case BC_DPRINT: out << popVariable().getDoubleValue(); out.flush(); break; case BC_SPRINT: out << popVariable().getStringValue(); out.flush(); break; case BC_SWAP: { auto v1 = popVariable(); auto v2 = popVariable(); pushVariable(v1); pushVariable(v2); break; } case BC_STOREDVAR0: case BC_STOREIVAR0: case BC_STORESVAR0: storeVariable(0); break; case BC_STOREDVAR1: case BC_STOREIVAR1: case BC_STORESVAR1: storeVariable(1); break; case BC_STOREDVAR2: case BC_STOREIVAR2: case BC_STORESVAR2: storeVariable(2); break; case BC_STOREDVAR3: case BC_STOREIVAR3: case BC_STORESVAR3: storeVariable(3); break; case BC_LOADDVAR: case BC_LOADIVAR: case BC_LOADSVAR: pushVariable(loadVariable(bytecode.getUInt16(currentIndex + 1))); break; case BC_LOADDVAR0: case BC_LOADIVAR0: case BC_LOADSVAR0: pushVariable(loadVariable(0)); break; case BC_LOADDVAR1: case BC_LOADIVAR1: case BC_LOADSVAR1: pushVariable(loadVariable(1)); break; case BC_LOADIVAR2: case BC_LOADSVAR2: case BC_LOADDVAR2: pushVariable(loadVariable(2)); break; case BC_LOADDVAR3: case BC_LOADIVAR3: case BC_LOADSVAR3: pushVariable(loadVariable(3)); break; case BC_STOREDVAR: case BC_STOREIVAR: case BC_STORESVAR: storeVariable(bytecode.getUInt16(currentIndex + 1)); break; case BC_LOADCTXDVAR: case BC_LOADCTXIVAR: case BC_LOADCTXSVAR: pushVariable(loadVariable(bytecode.getUInt16(currentIndex + 1), bytecode.getUInt16(currentIndex + 3))); break; case BC_STORECTXDVAR: case BC_STORECTXIVAR: case BC_STORECTXSVAR: storeVariable(bytecode.getUInt16(currentIndex + 1), bytecode.getUInt16(currentIndex + 3)); break; case BC_DCMP: binary_operation<double, signedIntType>(VT_DOUBLE, _cmp<double>); break; case BC_ICMP: binary_operation(VT_INT, _cmp < signedIntType > ); break; case BC_JA: { currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_IFICMPNE: { if (!check_condition(_neq<signedIntType>)) break; currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_IFICMPE: { if (!check_condition(_eq<signedIntType>)) break; currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_IFICMPG: { if (!check_condition(_g<signedIntType>)) break; currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_IFICMPGE: { if (!check_condition(_ge<signedIntType>)) break; currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_IFICMPL: { if (!check_condition(_l<signedIntType>)) break; currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_IFICMPLE: { if (!check_condition(_le<signedIntType>)) break; currentIndex += bytecode.getInt16(currentIndex + 1) + 1; continue; } case BC_STOP: { indices.clear(); bytecodes.clear(); continue; } case BC_CALLNATIVE: { callNative(bytecode.getUInt16(currentIndex + 1)); break; } case BC_CALL: { TranslatedFunction *f = functionById(bytecode.getUInt16(currentIndex + 1)); bytecodes.push_back(static_cast<BytecodeFunction *>(f)->bytecode()); indices.push_back(0); contextID.push_back(f->id()); detectCallWithFunctionID(contextID.back()); continue; } case BC_RETURN: { indices.pop_back(); bytecodes.pop_back(); if (!indices.empty()) { indices.back() += bytecodeLength(BC_CALL); } if (callsCounter[contextID.back()] > 0) { callsCounter[contextID.back()]--; } contextID.pop_back(); continue; } case BC_I2D: pushVariable((double) popVariable().getIntValue()); break; case BC_D2I: pushVariable((signedIntType) popVariable().getDoubleValue()); break; case BC_S2I: pushVariable((signedIntType) popVariable().getStringValue()); break; case BC_BREAK: break; case BC_INVALID: throw InterpretationError("BC_Invalid instruction"); default: throw InterpretationError(string("Unknown interpreting instruction: ") + bytecodeName(instruction, 0)); } currentIndex += instructionLength; } }
InterpreterFunction* Context::currentFunction() const { return functionById(currentFunctionId()); }
Bytecode* Context::bytecodeByFunctionId(uint16_t id) { BytecodeFunction* function = functionById(id); return (function == 0) ? 0 : function->bytecode(); }
void Interpreter::funExec(BytecodeFunction* f) { size_t bci = 0; size_t k = 0; while (bci < f->bytecode()->length()) { ++k; Instruction insn = f->bytecode()->getInsn(bci); switch (insn) { case BC_INVALID: { std::cerr << "Invalid instruction!\n"; return; break; } case BC_DLOAD: { Var var(VT_DOUBLE, ""); var.setDoubleValue(f->bytecode()->getDouble(bci + 1)); programStack.push(var); break; } case BC_ILOAD: { Var var(VT_INT, ""); var.setIntValue(f->bytecode()->getInt64(bci + 1)); programStack.push(var); break; } case BC_SLOAD: { Var var(VT_STRING, ""); var.setStringValue(constantById(f->bytecode()->getUInt16(bci + 1)).c_str()); programStack.push(var); break; } case BC_DLOAD0: { Var var(VT_DOUBLE, ""); var.setDoubleValue(0.0); programStack.push(var); break; } case BC_ILOAD0: { Var var(VT_INT, ""); var.setIntValue(0L); programStack.push(var); break; } case BC_SLOAD0: { Var var(VT_STRING, ""); var.setStringValue(""); programStack.push(var); break; } case BC_DLOAD1: { Var var(VT_DOUBLE, ""); var.setDoubleValue(1.0); programStack.push(var); break; } case BC_ILOAD1: { Var var(VT_INT, ""); var.setIntValue(1L); programStack.push(var); break; } case BC_DLOADM1: { Var var(VT_DOUBLE, ""); var.setDoubleValue(-1.0); programStack.push(var); break; } case BC_ILOADM1: { Var var(VT_INT, ""); var.setIntValue(-1L); programStack.push(var); break; } case BC_DADD: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.pop(); Var result(VT_DOUBLE, ""); result.setDoubleValue(leftOperand.getDoubleValue() + rightOperand.getDoubleValue()); programStack.push(result); break; } case BC_IADD: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.pop(); Var result(VT_INT, ""); result.setIntValue(leftOperand.getIntValue() + rightOperand.getIntValue()); programStack.push(result); break; } case BC_DSUB: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.pop(); Var result(VT_DOUBLE, ""); result.setDoubleValue(leftOperand.getDoubleValue() - rightOperand.getDoubleValue()); programStack.push(result); break; } case BC_ISUB: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.pop(); Var result(VT_INT, ""); result.setIntValue(leftOperand.getIntValue() - rightOperand.getIntValue()); programStack.push(result); break; } case BC_DMUL: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.pop(); Var result(VT_DOUBLE, ""); result.setDoubleValue(leftOperand.getDoubleValue() * rightOperand.getDoubleValue()); programStack.push(result); break; } case BC_IMUL: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.pop(); Var result(VT_INT, ""); result.setIntValue(leftOperand.getIntValue() * rightOperand.getIntValue()); programStack.push(result); break; } case BC_DDIV: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.pop(); Var result(VT_DOUBLE, ""); result.setDoubleValue(leftOperand.getDoubleValue() / rightOperand.getDoubleValue()); programStack.push(result); break; } case BC_IDIV: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.pop(); Var result(VT_INT, ""); result.setIntValue(leftOperand.getIntValue() / rightOperand.getIntValue()); programStack.push(result); break; } case BC_IMOD: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.pop(); Var result(VT_INT, ""); result.setIntValue(leftOperand.getIntValue() % rightOperand.getIntValue()); programStack.push(result); break; } case BC_DNEG: { Var operand = programStack.top(); programStack.pop(); Var result(VT_DOUBLE, ""); result.setDoubleValue(-operand.getDoubleValue()); programStack.push(result); break; } case BC_INEG: { Var operand = programStack.top(); programStack.pop(); Var result(VT_INT, ""); result.setIntValue(-operand.getIntValue()); programStack.push(result); break; } case BC_IPRINT: { Var operand = programStack.top(); programStack.pop(); std::cout << operand.getIntValue(); break; } case BC_DPRINT: { Var operand = programStack.top(); programStack.pop(); std::cout << operand.getDoubleValue(); break; } case BC_SPRINT: { Var operand = programStack.top(); programStack.pop(); std::cout << operand.getStringValue(); break; } case BC_I2D: { Var operand = programStack.top(); programStack.pop(); Var result(VT_DOUBLE, ""); result.setDoubleValue(static_cast<double>(operand.getIntValue())); programStack.push(result); break; } case BC_D2I: { Var operand = programStack.top(); programStack.pop(); Var result(VT_INT, ""); result.setIntValue(static_cast<int64_t>(operand.getDoubleValue())); programStack.push(result); break; } case BC_S2I: { Var operand = programStack.top(); programStack.pop(); Var result(VT_INT, ""); result.setIntValue(atoi(operand.getStringValue())); programStack.push(result); break; } case BC_SWAP: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.pop(); programStack.push(leftOperand); programStack.push(rightOperand); break; } case BC_POP: { programStack.pop(); break; } case BC_LOADSVAR0: case BC_LOADIVAR0: case BC_LOADDVAR0: { map<uint16_t, Var>::iterator iter = memory.find(0); if (iter != memory.end()) { programStack.push(iter->second); } else { std::cerr << "Can't load variable 0!\n"; } break; } case BC_LOADSVAR1: case BC_LOADIVAR1: case BC_LOADDVAR1: { map<uint16_t, Var>::iterator iter = memory.find(1); if (iter != memory.end()) { programStack.push(iter->second); } else { std::cerr << "Can't load variable 1!\n"; } break; } case BC_LOADSVAR2: case BC_LOADIVAR2: case BC_LOADDVAR2: { map<uint16_t, Var>::iterator iter = memory.find(2); if (iter != memory.end()) { programStack.push(iter->second); } else { std::cerr << "Can't load variable 2!\n"; } break; } case BC_LOADSVAR3: case BC_LOADIVAR3: case BC_LOADDVAR3: { map<uint16_t, Var>::iterator iter = memory.find(3); if (iter != memory.end()) { programStack.push(iter->second); } else { std::cerr << "Can't load variable 3!\n"; } break; } case BC_STORESVAR0: case BC_STOREIVAR0: case BC_STOREDVAR0: { map<uint16_t, Var>::iterator iter = memory.find(0); if (iter != memory.end()) { iter->second = programStack.top(); } else { memory.insert(make_pair(0, programStack.top())); } programStack.pop(); break; } case BC_STORESVAR1: case BC_STOREIVAR1: case BC_STOREDVAR1: { map<uint16_t, Var>::iterator iter = memory.find(1); if (iter != memory.end()) { iter->second = programStack.top(); } else { memory.insert(make_pair(1, programStack.top())); } programStack.pop(); break; } case BC_STORESVAR2: case BC_STOREIVAR2: case BC_STOREDVAR2: { map<uint16_t, Var>::iterator iter = memory.find(2); if (iter != memory.end()) { iter->second = programStack.top(); } else { memory.insert(make_pair(2, programStack.top())); } programStack.pop(); break; } case BC_STORESVAR3: case BC_STOREIVAR3: case BC_STOREDVAR3: { map<uint16_t, Var>::iterator iter = memory.find(3); if (iter != memory.end()) { iter->second = programStack.top(); } else { memory.insert(make_pair(3, programStack.top())); } programStack.pop(); break; } case BC_LOADDVAR: { uint16_t id = f->bytecode()->getUInt16(bci + 1); map<uint16_t, Var>::iterator iter = memory.find(id); if (iter != memory.end()) { programStack.push(iter->second); } else { //std::cerr << "Can't load variable " << id << "!\n"; Var var(VT_DOUBLE, ""); var.setDoubleValue(0.0); programStack.push(var); } break; } case BC_LOADIVAR: { uint16_t id = f->bytecode()->getUInt16(bci + 1); map<uint16_t, Var>::iterator iter = memory.find(id); if (iter != memory.end()) { programStack.push(iter->second); } else { //std::cerr << "Can't load variable " << id << "!\n"; Var var(VT_INT, ""); var.setIntValue(0); programStack.push(var); } break; } case BC_LOADSVAR: { uint16_t id = f->bytecode()->getUInt16(bci + 1); map<uint16_t, Var>::iterator iter = memory.find(id); if (iter != memory.end()) { programStack.push(iter->second); } else { //std::cerr << "Can't load variable " << id << "!\n"; Var var(VT_STRING, ""); var.setStringValue(""); programStack.push(var); } break; } case BC_STOREDVAR: case BC_STOREIVAR: case BC_STORESVAR: { uint16_t id = f->bytecode()->getUInt16(bci + 1); map<uint16_t, Var>::iterator iter = memory.find(id); if (iter != memory.end()) { iter->second = programStack.top(); } else { memory.insert(make_pair(id, programStack.top())); } programStack.pop(); break; } case BC_DCMP: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.pop(); Var result(VT_INT, ""); if (leftOperand.getDoubleValue() > rightOperand.getDoubleValue()) { result.setIntValue(1); } else if (leftOperand.getDoubleValue() == rightOperand.getDoubleValue()) { result.setIntValue(0); } else { result.setIntValue(-1); } programStack.push(result); break; } case BC_ICMP: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.pop(); Var result(VT_INT, ""); if (leftOperand.getIntValue() > rightOperand.getIntValue()) { result.setIntValue(1); } else if (leftOperand.getIntValue() == rightOperand.getIntValue()) { result.setIntValue(0); } else { result.setIntValue(-1); } programStack.push(result); break; } case BC_JA: { bci += (f->bytecode()->getInt16(bci + 1)); continue; } case BC_IFICMPNE: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.push(leftOperand); if (leftOperand.getIntValue() != rightOperand.getIntValue()) { bci += (f->bytecode()->getInt16(bci + 1)); continue; } break; } case BC_IFICMPE: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.push(leftOperand); if (leftOperand.getIntValue() == rightOperand.getIntValue()) { bci += (f->bytecode()->getInt16(bci + 1)); continue; } break; } case BC_IFICMPG: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.push(leftOperand); if (leftOperand.getIntValue() > rightOperand.getIntValue()) { bci += (f->bytecode()->getInt16(bci + 1)); continue; } break; } case BC_IFICMPGE: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.push(leftOperand); if (leftOperand.getIntValue() >= rightOperand.getIntValue()) { bci += (f->bytecode()->getInt16(bci + 1)); continue; } break; } case BC_IFICMPL: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.push(leftOperand); if (leftOperand.getIntValue() < rightOperand.getIntValue()) { bci += (f->bytecode()->getInt16(bci + 1)); continue; } break; } case BC_IFICMPLE: { Var leftOperand = programStack.top(); programStack.pop(); Var rightOperand = programStack.top(); programStack.push(leftOperand); if (leftOperand.getIntValue() <= rightOperand.getIntValue()) { bci += (f->bytecode()->getInt16(bci + 1)); continue; } break; } case BC_STOP: { return; } case BC_CALL: { int id = f->bytecode()->getUInt16(bci + 1); BytecodeFunction* functionToCall = (BytecodeFunction*) functionById(id); returnAddresses.push(bci + commandLen[insn]); returnLocations.push(f); bci = 0; f = functionToCall; continue; } case BC_RETURN: { f = returnLocations.top(); returnLocations.pop(); bci = returnAddresses.top(); returnAddresses.pop(); continue; } default: { std::cerr << "Unknown instruction!\n"; return; } } bci += commandLen[insn]; } }