void BytecodeGenerationVisitor::visitFunctionNode(FunctionNode* node) { Bytecode* currentBytecode = bytecode; vector<const AstVar*> prevLocals = locals; locals.clear(); if (code->functionByName(node->name()) == 0) { AstFunction* astFunction = node->body()->scope()->lookupFunction(node->name()); BytecodeFunction *bytecodeFunction = new BytecodeFunction(astFunction); code->addFunction(bytecodeFunction); bytecode = bytecodeFunction->bytecode(); } else { bytecode = ((BytecodeFunction*)(code->functionByName(node->name())))->bytecode(); } VarType prevReturnType = returnType; returnType = node -> returnType(); if (node->body()->nodeAt(0)->isNativeCallNode()) { node->body()->nodeAt(0)->visit(this); // TODO } else { node->body()->visit(this); } locals = prevLocals; returnType = prevReturnType; bytecode = currentBytecode; }
Status* BytecodeVisitor::translateBytecode(Code *code, AstFunction *top) { code_ = code; BytecodeFunction* bf = new BytecodeFunction(top); code_->addFunction(bf); try { translateFunction(top); bf->bytecode()->addInsn(BC_STOP); } catch(std::runtime_error* e) { return Status::Error(e->what()); } catch(...) { return Status::Error("Translate error"); } return Status::Ok(); }
void BytecodeGenerator::secondRun(Scope * scope) { Scope::FunctionIterator it(scope); while (it.hasNext()) { AstFunction *func = it.next(); BytecodeFunction *bcf = (BytecodeFunction*) code->functionByName(func->name()); fBC = bcf->bytecode(); currentFun = bcf->id(); returnType = func->returnType(); func->node()->body()->visit(this); bcf->setLocalsNumber(localsCounter[currentFun]); } for (size_t i = 0; i < scope->childScopeNumber(); ++i) { secondRun(scope->childScopeAt(i)); } }
void BytecodeGenerator::firstRun(Scope * scope) { Scope::FunctionIterator it(scope); while (it.hasNext()) { AstFunction *func = it.next(); BytecodeFunction *bcf = new BytecodeFunction(func); currentFun = code->addFunction(bcf); initFunLocals(currentFun); Scope::VarIterator vi(func->scope()); fBC = bcf->bytecode(); while (vi.hasNext()) { AstVar * var = vi.next(); int index = localsCounter[currentFun]; incFunLocals(currentFun); varIds[var] = make_pair(currentFun, index); storeVar(var); } } for (size_t i = 0; i < scope->childScopeNumber(); ++i) { firstRun(scope->childScopeAt(i)); } }
Bytecode* bc() { return bf_->bytecode(); }
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; }
Bytecode* Context::bytecodeByFunctionId(uint16_t id) { BytecodeFunction* function = functionById(id); return (function == 0) ? 0 : function->bytecode(); }