#include "runtime/interpreter.hpp"#include "runtime/frameObject.hpp"#include "runtime/universe.hpp"#include "runtime/functionObject.hpp"#include "runtime/stringTable.hpp"#include "runtime/module.hpp"#include "runtime/traceback.hpp"#include "runtime/generator.hpp"#include "runtime/cellObject.hpp"#include "util/arrayList.hpp"#include "util/map.hpp"#include "util/handles.hpp"#include "object/hiString.hpp"#include "object/hiInteger.hpp"#include "object/hiList.hpp"#include "object/hiDict.hpp"#include "memory/oopClosure.hpp"#include <string.h>#define PUSH(x) _frame->stack()->append((x))#define POP() _frame->stack()->pop()#define TOP() _frame->stack()->top()#define STACK_LEVEL() _frame->stack()->size()#define PEEK(x) _frame->stack()->get((x))#define EMPTY() (_frame->stack()->size() == 0)#define HI_TRUE Universe::HiTrue#define HI_FALSE Universe::HiFalse#define ST(x) StringTable::get_instance()->STR(x)#define STR(x) x##_strInterpreter* Interpreter::_instance = NULL;Interpreter* Interpreter::get_instance() {if (_instance == NULL) {_instance = new Interpreter();}return _instance;}Interpreter::Interpreter() {_frame = NULL;_exception_class = NULL;_pending_exception = NULL;_trace_back = NULL;_int_status = IS_OK;// prepare for import builtin, this should be created first_builtins = new ModuleObject(new HiDict());_builtins->put(new HiString("object"), ObjectKlass::get_instance()->type_object());_builtins->put(new HiString("True"), Universe::HiTrue);_builtins->put(new HiString("False"), Universe::HiFalse);_builtins->put(new HiString("None"), Universe::HiNone);_builtins->put(new HiString("len"), new FunctionObject(len));_builtins->put(new HiString("iter"), new FunctionObject(iter));_builtins->put(new HiString("type"), new FunctionObject(type_of));_builtins->put(new HiString("isinstance"),new FunctionObject(isinstance));_builtins->put(new HiString("super"), new FunctionObject(builtin_super));_builtins->put(new HiString("sysgc"), new FunctionObject(sysgc));_builtins->put(new HiString("int"), IntegerKlass::get_instance()->type_object());_builtins->put(new HiString("object"), ObjectKlass::get_instance()->type_object());_builtins->put(new HiString("str"), StringKlass::get_instance()->type_object());_builtins->put(new HiString("list"), ListKlass::get_instance()->type_object());_builtins->put(new HiString("dict"), DictKlass::get_instance()->type_object());}void Interpreter::initialize() {_builtins->extend(ModuleObject::import_module(new HiString("builtin")));Universe::stop_iteration = _builtins->get(new HiString("StopIteration"));_modules = new HiDict();_modules->put(new HiString("__builtins__"), _builtins);}void Interpreter::build_frame(HiObject* callable, ObjList args, int op_arg) {if (callable->klass() == NativeFunctionKlass::get_instance()) {PUSH(((FunctionObject*)callable)->call(args));}else if (callable->klass() == MethodKlass::get_instance()) {MethodObject* method = (MethodObject*) callable;// return value is ignored here, because they are handled// by other pathes.if (!args) {args = new ArrayList<HiObject*>(1);}args->insert(0, method->owner());build_frame(method->func(), args, op_arg + 1);}else if (MethodObject::is_yield_function(callable)) {Generator* gtor = new Generator((FunctionObject*) callable, args, op_arg);PUSH(gtor);return;}else if (callable->klass() == FunctionKlass::get_instance()) {FrameObject* frame = new FrameObject((FunctionObject*) callable, args, op_arg);frame->set_sender(_frame);_frame = frame;}else if (callable->klass() == TypeKlass::get_instance()) {HiObject* inst = ((HiTypeObject*)callable)->own_klass()->allocate_instance(callable, args);PUSH(inst);}else {HiObject* m = callable->get_klass_attr(ST(call));if (m != Universe::HiNone)build_frame(m, args, op_arg);else {callable->print();printf("\nError : can not call a normal object.\n");}}}void Interpreter::leave_frame() {destroy_frame();PUSH(_ret_value);}void Interpreter::destroy_frame() {FrameObject* temp = _frame;_frame = _frame->sender();delete temp;}HiObject* Interpreter::call_virtual(HiObject* func, ObjList args) {if (func->klass() == NativeFunctionKlass::get_instance()) {// we do not create a virtual frame, but native frame.return ((FunctionObject*)func)->call(args);}else if (func->klass() == MethodKlass::get_instance()) {MethodObject* method = (MethodObject*) func;if (!args) {args = new ArrayList<HiObject*>(1);}args->insert(0, method->owner());return call_virtual(method->func(), args);}else if (MethodObject::is_function(func)) {int size = args ? args->size() : 0;FrameObject* frame = new FrameObject((FunctionObject*) func, args, size);frame->set_entry_frame(true);enter_frame(frame);eval_frame();destroy_frame();return _ret_value;}return Universe::HiNone;}void Interpreter::enter_frame(FrameObject* frame) {frame->set_sender(_frame);_frame = frame;}void Interpreter::run(CodeObject* codes) {_frame = new FrameObject(codes);_frame->locals()->put(ST(name), new HiString("__main__"));eval_frame();if (_int_status == IS_EXCEPTION) {_int_status = IS_OK;_trace_back->print();_pending_exception->print();printf("\n");_trace_back = NULL;_pending_exception = NULL;_exception_class = NULL;}destroy_frame();}HiDict* Interpreter::run_mod(CodeObject* codes, HiString* mod_name) {FrameObject* frame = new FrameObject(codes);frame->set_entry_frame(true);frame->locals()->put(ST(name), mod_name);enter_frame(frame);eval_frame();HiDict* result = frame->locals();destroy_frame();return result;}void Interpreter::eval_frame() {Block* b;FunctionObject* fo;ArrayList<HiObject*>* args = NULL;HiObject *v, *w, *u;unsigned char op_code;bool has_argument;int op_arg;while (_frame->has_more_codes()) {if (_int_status != IS_OK)goto fast_handle_exception;op_code = _frame->get_op_code();has_argument = (op_code & 0xFF) >= ByteCode::HAVE_ARGUMENT;op_arg = -1;if (has_argument) {op_arg = _frame->get_op_arg();}switch (op_code) {case ByteCode::POP_TOP:POP();break;case ByteCode::ROT_TWO:v = POP();w = POP();PUSH(v);PUSH(w);break;case ByteCode::ROT_THREE:v = POP();w = POP();u = POP();PUSH(v);PUSH(u);PUSH(w);break;case ByteCode::DUP_TOP:PUSH(TOP());break;case ByteCode::LOAD_CONST:PUSH(_frame->consts()->get(op_arg));break;case ByteCode::LOAD_NAME:v = _frame->names()->get(op_arg);w = _frame->locals()->get(v);if (w != Universe::HiNone) {PUSH(w);break;}w = _frame->globals()->get(v);if (w != Universe::HiNone) {PUSH(w);break;}w = _builtins->get(v);if (w != Universe::HiNone) {PUSH(w);break;}PUSH(Universe::HiNone);break;case ByteCode::LOAD_FAST:PUSH(_frame->fast_locals()->get(op_arg));break;case ByteCode::LOAD_GLOBAL:v = _frame->names()->get(op_arg);w = _frame->globals()->get(v);if (w != Universe::HiNone) {PUSH(w);break;}w = _builtins->get(v);if (w != Universe::HiNone) {PUSH(w);break;}PUSH(Universe::HiNone);break;case ByteCode::LOAD_ATTR:v = POP();w = _frame->_names->get(op_arg);PUSH(v->getattr(w));break;case ByteCode::LOAD_LOCALS:PUSH(_frame->_locals);break;case ByteCode::LOAD_CLOSURE:v = _frame->closure()->get(op_arg);if (v == NULL) {_frame->closure()->set(op_arg, (_frame->get_cell_from_parameter(op_arg)));}v = _frame->closure()->get(op_arg);if (v->klass() == CellKlass::get_instance()) {PUSH(v);}elsePUSH(new CellObject(_frame->closure(), op_arg));break;case ByteCode::LOAD_DEREF:v = _frame->closure()->get(op_arg);if (v->klass() == CellKlass::get_instance()) {v = ((CellObject*)v)->value();}PUSH(v);break;case ByteCode::STORE_NAME:v = _frame->names()->get(op_arg);_frame->locals()->put(v, POP());break;case ByteCode::STORE_FAST:_frame->_fast_locals->set(op_arg, POP());break;case ByteCode::STORE_GLOBAL:v = _frame->names()->get(op_arg);_frame->globals()->put(v, POP());break;case ByteCode::STORE_SUBSCR:u = POP();v = POP();w = POP();v->store_subscr(u, w);break;case ByteCode::STORE_MAP:w = POP();u = POP();v = TOP();((HiDict*)v)->put(w, u);break;case ByteCode::STORE_ATTR:u = POP();v = _frame->_names->get(op_arg);w = POP();u->setattr(v, w);break;case ByteCode::STORE_DEREF:_frame->closure()->set(op_arg, POP());break;case ByteCode::BINARY_SUBSCR:v = POP();w = POP();PUSH(w->subscr(v));break;case ByteCode::PRINT_ITEM:v = POP();v->print();break;case ByteCode::PRINT_NEWLINE:printf("\n");break;case ByteCode::INPLACE_DIVIDE:case ByteCode::BINARY_DIVIDE:v = POP();w = POP();PUSH(w->div(v));break;case ByteCode::INPLACE_ADD:case ByteCode::BINARY_ADD:v = POP();w = POP();PUSH(w->add(v));break;case ByteCode::BINARY_SUBTRACT:v = POP();w = POP();PUSH(w->sub(v));break;case ByteCode::BINARY_MULTIPLY:v = POP();w = POP();PUSH(w->mul(v));break;case ByteCode::INPLACE_MODULO: // drop downcase ByteCode::BINARY_MODULO:v = POP();w = POP();PUSH(w->mod(v));break;case ByteCode::MAKE_CLOSURE:v = POP();fo = new FunctionObject(v);fo->set_closure((HiList*)(POP()));fo->set_globals(_frame->globals());if (op_arg > 0) {args = new ArrayList<HiObject*>(op_arg);while (op_arg--) {args->set(op_arg, POP());}}fo->set_default(args);if (args != NULL) {args = NULL;}PUSH(fo);break;case ByteCode::MAKE_FUNCTION:v = POP();fo = new FunctionObject(v);fo->set_globals(_frame->globals());if (op_arg > 0) {args = new ArrayList<HiObject*>(op_arg);while (op_arg--) {args->set(op_arg, POP());}}fo->set_default(args);if (args != NULL) {args = NULL;}PUSH(fo);break;case ByteCode::CALL_FUNCTION:if (op_arg > 0) {int na = op_arg & 0xff;int nk = op_arg >> 8;int arg_cnt = na + 2 * nk;args = new ArrayList<HiObject*>(arg_cnt);while (arg_cnt--) {args->set(arg_cnt, POP());}}build_frame(POP(), args, op_arg);if (args != NULL) {args = NULL;}break;case ByteCode::RETURN_VALUE:_ret_value = POP();_int_status = IS_RETURN;break;case ByteCode::COMPARE_OP:w = POP();v = POP();switch(op_arg) {case ByteCode::GREATER:PUSH(v->greater(w));break;case ByteCode::LESS:PUSH(v->less(w));break;case ByteCode::EQUAL:PUSH(v->equal(w));break;case ByteCode::NOT_EQUAL:PUSH(v->not_equal(w));break;case ByteCode::GREATER_EQUAL:PUSH(v->ge(w));break;case ByteCode::LESS_EQUAL:PUSH(v->le(w));break;case ByteCode::IN:PUSH(w->contains(v));break;case ByteCode::IS:if (v == w)PUSH(HI_TRUE);elsePUSH(HI_FALSE);break;case ByteCode::IS_NOT:if (v == w)PUSH(HI_TRUE);elsePUSH(HI_FALSE);break;case ByteCode::EXC_MATCH:{bool found = false;Klass* k = ((HiTypeObject*)v)->own_klass();if (v == w)found = true;else {for (int i = 0; i < k->mro()->size(); i++) {if (v->klass()->mro()->get(i) == w) {found = true;break;}}}if (found)PUSH(Universe::HiTrue);elsePUSH(Universe::HiFalse);break;}default:printf("Error: Unrecognized compare op %d\n", op_arg);}break;case ByteCode::DELETE_SUBSCR:w = POP();v = POP();v->del_subscr(w);break;case ByteCode::POP_JUMP_IF_FALSE:v = POP();if (v == Universe::HiFalse)_frame->set_pc(op_arg);break;case ByteCode::JUMP_FORWARD:_frame->set_pc(op_arg + _frame->get_pc());break;case ByteCode::JUMP_ABSOLUTE:_frame->set_pc(op_arg);break;case ByteCode::SETUP_FINALLY:case ByteCode::SETUP_EXCEPT:case ByteCode::SETUP_LOOP:_frame->loop_stack()->add(new Block(op_code, _frame->get_pc() + op_arg,STACK_LEVEL()));break;case ByteCode::POP_BLOCK:b = _frame->loop_stack()->pop();while (STACK_LEVEL() > b->_level) {POP();}break;case ByteCode::BREAK_LOOP:_int_status = IS_BREAK;break;case ByteCode::CONTINUE_LOOP:_int_status = IS_CONTINUE;_ret_value = (HiObject*)((long)op_arg);break;case ByteCode::END_FINALLY:// TODO: restore exceptionsv = POP();if (((long)v) & 0x1) {_int_status = (Status)(((long)v) >> 1);if (_int_status == IS_RETURN)_ret_value = POP();else if (_int_status == IS_CONTINUE)_frame->_pc = (int)((long)(POP()));}else if (v != Universe::HiNone) {_exception_class = v;_pending_exception = POP();_trace_back = POP();_int_status = IS_EXCEPTION;}break;case ByteCode::BUILD_TUPLE: // drop down, we need thiscase ByteCode::BUILD_LIST:v = new HiList();while (op_arg--) {((HiList*)v)->set(op_arg, POP());}PUSH(v);break;case ByteCode::BUILD_MAP:v = new HiDict();PUSH(v);break;case ByteCode::BUILD_CLASS:v = POP();u = POP();w = POP();v = Klass::create_klass(v, u, w);PUSH(v);break;case ByteCode::GET_ITER:v = POP();PUSH(v->iter());break;case ByteCode::FOR_ITER:v = TOP();w = v->next();if (w == NULL) {// we may encounter a StopIteration, ignore it.//assert(_int_status == IS_EXCEPTION && _pending_exception != NULL);_frame->_pc += op_arg;_int_status = IS_OK;_pending_exception = NULL;}else {PUSH(w);}break;case ByteCode::UNPACK_SEQUENCE:v = POP();while (op_arg--) {PUSH(v->subscr(new HiInteger(op_arg)));}break;case ByteCode::IMPORT_NAME:POP();POP();v = _frame->names()->get(op_arg);w = _modules->get(v);if (w != Universe::HiNone) {PUSH(w);break;}w = ModuleObject::import_module(v);_modules->put(v, w);PUSH(w);break;case ByteCode::IMPORT_FROM:v = _frame->names()->get(op_arg);w = TOP();u = ((ModuleObject*)w)->get(v);PUSH(u);break;case ByteCode::DUP_TOPX:for (int i = 0; i < op_arg; i++) {int index = STACK_LEVEL() - op_arg;PUSH(PEEK(index));}break;case ByteCode::CALL_FUNCTION_VAR:v = POP();if (op_arg > 0 || (v && ((HiList*)v)->size() > 0)) {int na = op_arg & 0xff;int nk = op_arg >> 8;int arg_cnt = na + 2 * nk;args = new ArrayList<HiObject*>();while (arg_cnt--) {args->set(arg_cnt, POP());}int s = ((HiList*)v)->size();for (int i = 0; i < s; i++) {args->add(((HiList*)v)->get(i));}na += s;op_arg = (nk << 8) | na;}build_frame(POP(), args, op_arg);if (args != NULL) {args = NULL;}break;case ByteCode::RAISE_VARARGS:w = v = u = NULL;switch (op_arg) {case 3:u = POP();case 2:v = POP();case 1:w = POP();break;}do_raise(w, v, u);break;case ByteCode::YIELD_VALUE:// we are assured that we're in the progress// of evalating generator._int_status = IS_YIELD;_ret_value = TOP();return;default:printf("Error: Unrecognized byte code %d\n", op_code);}fast_handle_exception:while (_int_status != IS_OK && _frame->_loop_stack->size() != 0) {b = _frame->_loop_stack->get(_frame->_loop_stack->size()-1);if (_int_status == IS_CONTINUE && b->_type == ByteCode::SETUP_LOOP) {_frame->_pc = (int)((long)_ret_value);_int_status = IS_OK;break;}b = _frame->_loop_stack->pop();while (STACK_LEVEL() > b->_level) {POP();}if (_int_status == IS_BREAK && b->_type == ByteCode::SETUP_LOOP) {_frame->_pc = b->_target;;_int_status = IS_OK;}else if (b->_type == ByteCode::SETUP_FINALLY ||(_int_status == IS_EXCEPTION&& b->_type == ByteCode::SETUP_EXCEPT)) {if (_int_status == IS_EXCEPTION) {// traceback, value, exception classPUSH(_trace_back);PUSH(_pending_exception);PUSH(_exception_class);_trace_back = NULL;_pending_exception = NULL;_exception_class = NULL;}else {if (_int_status == IS_RETURN ||_int_status == IS_CONTINUE)PUSH(_ret_value);PUSH((HiObject*)(((long)_int_status << 1) | 0x1));}_frame->_pc = b->_target;;_int_status = IS_OK;}}// has pending exception and no handler found, unwind stack.if (_int_status != IS_OK && _frame->_loop_stack->size() == 0) {if (_int_status == IS_EXCEPTION) {_ret_value = NULL;((Traceback*)_trace_back)->record_frame(_frame);}if (_int_status == IS_RETURN)_int_status = IS_OK;if (_frame->is_first_frame() ||_frame->is_entry_frame())return;leave_frame();}}}void Interpreter::oops_do(OopClosure* f) {f->do_oop((HiObject**)&_builtins);f->do_oop((HiObject**)&_modules);f->do_oop((HiObject**)&_ret_value);f->do_oop((HiObject**)&_exception_class);f->do_oop((HiObject**)&_pending_exception);f->do_oop((HiObject**)&_trace_back);if (_frame)_frame->oops_do(f);}Interpreter::Status Interpreter::do_raise(HiObject* exc, HiObject* val, HiObject* tb) {assert(exc != NULL);_int_status = IS_EXCEPTION;if (tb == NULL) {tb = new Traceback();}if (val != NULL) {_exception_class = exc;_pending_exception = val;_trace_back = tb;return IS_EXCEPTION;}if (exc->klass() == TypeKlass::get_instance()) {_pending_exception = call_virtual(exc, NULL);_exception_class = exc;}else {_pending_exception = exc;_exception_class = _pending_exception->klass()->type_object();}_trace_back = tb;return IS_EXCEPTION;}HiObject* Interpreter::eval_generator(Generator* g) {Handle handle(g);enter_frame(g->frame());g->frame()->set_entry_frame(true);eval_frame();if (_int_status != IS_YIELD) {_int_status = IS_OK;leave_frame();((Generator*)handle())->set_frame(NULL);return NULL;}_int_status = IS_OK;_frame = _frame->sender();return _ret_value;}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。