mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
...
This commit is contained in:
parent
51cf6d42e8
commit
bccabaa872
59
src/ceval.h
59
src/ceval.h
@ -145,7 +145,9 @@ __NEXT_STEP:;
|
||||
PUSH(self);
|
||||
} DISPATCH();
|
||||
TARGET(LOAD_SUBSCR) {
|
||||
TOP() = fast_call_method(SECOND(), __getitem__, 2);
|
||||
PyObject* b = POPX();
|
||||
PyObject* a = TOP();
|
||||
TOP() = call_method(a, __getitem__, b);
|
||||
} DISPATCH();
|
||||
TARGET(STORE_FAST)
|
||||
frame->_locals[byte.arg] = POPX();
|
||||
@ -171,12 +173,13 @@ __NEXT_STEP:;
|
||||
setattr(a, name, val);
|
||||
STACK_SHRINK(2);
|
||||
} DISPATCH();
|
||||
TARGET(STORE_SUBSCR)
|
||||
// val a b -> a b val
|
||||
std::swap(SECOND(), THIRD());
|
||||
std::swap(TOP(), SECOND());
|
||||
fast_call_method(THIRD(), __setitem__, 3);
|
||||
DISPATCH();
|
||||
TARGET(STORE_SUBSCR) {
|
||||
// val a b
|
||||
PyObject* b = POPX();
|
||||
PyObject* a = POPX();
|
||||
PyObject* val = POPX();
|
||||
call_method(a, __setitem__, b, val);
|
||||
} DISPATCH();
|
||||
TARGET(DELETE_FAST) {
|
||||
PyObject* val = frame->_locals[byte.arg];
|
||||
if(val == nullptr) vm->NameError(co->varnames[byte.arg]);
|
||||
@ -207,9 +210,11 @@ __NEXT_STEP:;
|
||||
if(!a->attr().contains(name)) AttributeError(a, name);
|
||||
a->attr().erase(name);
|
||||
} DISPATCH();
|
||||
TARGET(DELETE_SUBSCR)
|
||||
fast_call_method(SECOND(), __delitem__, 2);
|
||||
DISPATCH();
|
||||
TARGET(DELETE_SUBSCR) {
|
||||
PyObject* b = POPX();
|
||||
PyObject* a = POPX();
|
||||
call_method(a, __delitem__, b);
|
||||
} DISPATCH();
|
||||
/*****************************************/
|
||||
TARGET(BUILD_LIST) {
|
||||
PyObject* obj = VAR(STACK_VIEW(byte.arg).to_list());
|
||||
@ -251,9 +256,11 @@ __NEXT_STEP:;
|
||||
PUSH(VAR(ss.str()));
|
||||
} DISPATCH();
|
||||
/*****************************************/
|
||||
TARGET(BINARY_OP)
|
||||
TOP() = fast_call_method(SECOND(), BINARY_SPECIAL_METHODS[byte.arg], 2);
|
||||
DISPATCH();
|
||||
TARGET(BINARY_OP) {
|
||||
PyObject* b = POPX();
|
||||
PyObject* a = TOP();
|
||||
TOP() = call_method(a, BINARY_SPECIAL_METHODS[byte.arg], b);
|
||||
} DISPATCH();
|
||||
|
||||
#define INT_BINARY_OP(op, func) \
|
||||
if(is_both_int(TOP(), SECOND())){ \
|
||||
@ -262,7 +269,9 @@ __NEXT_STEP:;
|
||||
POP(); \
|
||||
TOP() = VAR(a op b); \
|
||||
}else{ \
|
||||
TOP() = fast_call_method(SECOND(), func, 2); \
|
||||
PyObject* b = POPX(); \
|
||||
PyObject* a = TOP(); \
|
||||
TOP() = call_method(a, func, b); \
|
||||
}
|
||||
|
||||
TARGET(BINARY_ADD)
|
||||
@ -323,8 +332,7 @@ __NEXT_STEP:;
|
||||
} DISPATCH();
|
||||
TARGET(CONTAINS_OP) {
|
||||
// a in b -> b __contains__ a
|
||||
std::swap(TOP(), SECOND());
|
||||
PyObject* ret = fast_call_method(SECOND(), __contains__, 2);
|
||||
PyObject* ret = call_method(TOP(), __contains__, SECOND());
|
||||
bool ret_c = CAST(bool, ret);
|
||||
if(byte.arg == 1) ret_c = !ret_c;
|
||||
TOP() = VAR(ret_c);
|
||||
@ -357,6 +365,9 @@ __NEXT_STEP:;
|
||||
frame->jump_abs_break(index);
|
||||
} DISPATCH();
|
||||
/*****************************************/
|
||||
TARGET(BEGIN_CALL)
|
||||
PUSH(_py_begin_call);
|
||||
DISPATCH();
|
||||
TARGET(CALL) {
|
||||
int ARGC = byte.arg & 0xFFFF;
|
||||
int KWARGC = (byte.arg >> 16) & 0xFFFF;
|
||||
@ -406,9 +417,6 @@ __NEXT_STEP:;
|
||||
TARGET(UNARY_NOT)
|
||||
TOP() = VAR(!asBool(TOP()));
|
||||
DISPATCH();
|
||||
TARGET(UNARY_STAR)
|
||||
TOP() = VAR(StarWrapper(TOP()));
|
||||
DISPATCH();
|
||||
/*****************************************/
|
||||
TARGET(GET_ITER)
|
||||
TOP() = asIter(TOP());
|
||||
@ -479,7 +487,18 @@ __NEXT_STEP:;
|
||||
}else{
|
||||
if(iter->next() != nullptr) ValueError("too many values to unpack");
|
||||
}
|
||||
}; DISPATCH();
|
||||
} DISPATCH();
|
||||
TARGET(UNPACK_UNLIMITED) {
|
||||
auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!!
|
||||
PyObject* obj = asIter(POPX());
|
||||
BaseIter* iter = PyIter_AS_C(obj);
|
||||
obj = iter->next();
|
||||
while(obj != nullptr){
|
||||
PUSH(obj);
|
||||
// if(s_data.is_overflow()) StackOverflowError();
|
||||
obj = iter->next();
|
||||
}
|
||||
} DISPATCH();
|
||||
/*****************************************/
|
||||
TARGET(BEGIN_CLASS) {
|
||||
StrName name(byte.arg);
|
||||
|
10
src/expr.h
10
src/expr.h
@ -189,7 +189,7 @@ struct StarredExpr: Expr{
|
||||
|
||||
void emit(CodeEmitContext* ctx) override {
|
||||
child->emit(ctx);
|
||||
ctx->emit(OP_UNARY_STAR, BC_NOARG, line);
|
||||
ctx->emit(OP_UNPACK_UNLIMITED, BC_NOARG, line);
|
||||
}
|
||||
|
||||
bool emit_store(CodeEmitContext* ctx) override {
|
||||
@ -627,6 +627,7 @@ struct CallExpr: Expr{
|
||||
|
||||
void emit(CodeEmitContext* ctx) override {
|
||||
VM* vm = ctx->vm;
|
||||
if(need_unpack()) ctx->emit(OP_BEGIN_CALL, BC_NOARG, line);
|
||||
// if callable is a AttrExpr, we should try to use `fast_call` instead of use `boundmethod` proxy
|
||||
if(callable->is_attrib()){
|
||||
auto p = static_cast<AttribExpr*>(callable.get());
|
||||
@ -645,11 +646,8 @@ struct CallExpr: Expr{
|
||||
}
|
||||
int KWARGC = (int)kwargs.size();
|
||||
int ARGC = (int)args.size();
|
||||
if(KWARGC > 0){
|
||||
ctx->emit(need_unpack() ? OP_CALL_KWARGS_UNPACK : OP_CALL_KWARGS, (KWARGC<<16)|ARGC, line);
|
||||
}else{
|
||||
ctx->emit(need_unpack() ? OP_CALL_UNPACK : OP_CALL, ARGC, line);
|
||||
}
|
||||
if(need_unpack()) ARGC = 0xFFFF;
|
||||
ctx->emit(OP_CALL, (KWARGC<<16)|ARGC, line);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -212,6 +212,8 @@ struct Frame {
|
||||
|
||||
int stack_size() const { return _s->_sp - _sp_base; }
|
||||
|
||||
ArgsView stack_view() const { return ArgsView(_sp_base, _s->_sp); }
|
||||
|
||||
std::string stack_info(){
|
||||
std::stringstream ss;
|
||||
ss << this << ": [";
|
||||
|
4
src/gc.h
4
src/gc.h
@ -141,10 +141,6 @@ template<> inline void gc_mark<BoundMethod>(BoundMethod& t){
|
||||
OBJ_MARK(t.method);
|
||||
}
|
||||
|
||||
template<> inline void gc_mark<StarWrapper>(StarWrapper& t){
|
||||
OBJ_MARK(t.obj);
|
||||
}
|
||||
|
||||
template<> inline void gc_mark<Super>(Super& t){
|
||||
OBJ_MARK(t.first);
|
||||
}
|
||||
|
@ -63,10 +63,15 @@ public:
|
||||
|
||||
inline PyObject* Generator::next(){
|
||||
if(state == 2) return nullptr;
|
||||
vm->_push_new_frame(std::move(frame));
|
||||
// restore the context
|
||||
for(PyObject* obj: s_data) frame._s->push(obj);
|
||||
s_data.clear();
|
||||
vm->callstack.push(std::move(frame));
|
||||
PyObject* ret = vm->_run_top_frame();
|
||||
if(ret == vm->_py_op_yield){
|
||||
// backup the context
|
||||
frame = std::move(vm->callstack.top());
|
||||
for(PyObject* obj: frame.stack_view()) s_data.push_back(obj);
|
||||
vm->callstack.pop();
|
||||
state = 1;
|
||||
return frame._s->popx();
|
||||
|
@ -50,11 +50,6 @@ struct Range {
|
||||
i64 step = 1;
|
||||
};
|
||||
|
||||
struct StarWrapper {
|
||||
PyObject* obj;
|
||||
StarWrapper(PyObject* obj): obj(obj) {}
|
||||
};
|
||||
|
||||
using Super = std::pair<PyObject*, Type>;
|
||||
|
||||
// TODO: re-examine the design of Slice
|
||||
|
@ -76,6 +76,7 @@ OPCODE(LOOP_CONTINUE)
|
||||
OPCODE(LOOP_BREAK)
|
||||
OPCODE(GOTO)
|
||||
/**************************/
|
||||
OPCODE(BEGIN_CALL)
|
||||
OPCODE(CALL)
|
||||
OPCODE(RETURN_VALUE)
|
||||
OPCODE(YIELD_VALUE)
|
||||
@ -86,7 +87,6 @@ OPCODE(SET_ADD)
|
||||
/**************************/
|
||||
OPCODE(UNARY_NEGATIVE)
|
||||
OPCODE(UNARY_NOT)
|
||||
OPCODE(UNARY_STAR)
|
||||
/**************************/
|
||||
OPCODE(GET_ITER)
|
||||
OPCODE(FOR_ITER)
|
||||
@ -96,6 +96,7 @@ OPCODE(IMPORT_STAR)
|
||||
/**************************/
|
||||
OPCODE(UNPACK_SEQUENCE)
|
||||
OPCODE(UNPACK_EX)
|
||||
OPCODE(UNPACK_UNLIMITED)
|
||||
/**************************/
|
||||
OPCODE(BEGIN_CLASS)
|
||||
OPCODE(END_CLASS)
|
||||
|
29
src/vm.h
29
src/vm.h
@ -48,11 +48,10 @@ Str _read_file_cwd(const Str& name, bool* ok);
|
||||
|
||||
class Generator final: public BaseIter {
|
||||
Frame frame;
|
||||
int state; // 0,1,2
|
||||
int state; // 0,1,2
|
||||
List s_data; // backup
|
||||
public:
|
||||
template<typename... Args>
|
||||
Generator(VM* vm, Frame&& frame)
|
||||
: BaseIter(vm), frame(std::move(frame)), state(0) {}
|
||||
Generator(VM* vm, Frame&& frame): BaseIter(vm), frame(std::move(frame)), state(0) {}
|
||||
|
||||
PyObject* next() override;
|
||||
void _gc_mark() const override;
|
||||
@ -103,7 +102,7 @@ public:
|
||||
Type tp_list, tp_tuple;
|
||||
Type tp_function, tp_native_function, tp_iterator, tp_bound_method;
|
||||
Type tp_slice, tp_range, tp_module;
|
||||
Type tp_super, tp_exception, tp_star_wrapper;
|
||||
Type tp_super, tp_exception;
|
||||
|
||||
VM(bool use_stdio) : heap(this){
|
||||
this->vm = this;
|
||||
@ -167,20 +166,6 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
PyObject* fast_call_method(PyObject* obj, StrName name, int ARGC){
|
||||
PyObject* callable = find_name_in_mro(_t(obj), name);
|
||||
if(callable == nullptr) AttributeError(obj, name);
|
||||
// [a, b]
|
||||
// [......., a, b]
|
||||
// [unbound, a, b]
|
||||
// ^^^^^^^
|
||||
s_data._sp++;
|
||||
PyObject** t = s_data._sp;
|
||||
for(; t>s_data._sp-ARGC; t--) *t = t[-1];
|
||||
*t = obj;
|
||||
return _vectorcall(ARGC-1);
|
||||
}
|
||||
|
||||
PyObject* exec(Str source, Str filename, CompileMode mode, PyObject* _module=nullptr){
|
||||
if(_module == nullptr) _module = _main;
|
||||
try {
|
||||
@ -333,6 +318,7 @@ public:
|
||||
}
|
||||
|
||||
void RecursionError() { _error("RecursionError", "maximum recursion depth exceeded"); }
|
||||
void StackOverflowError() { _error("StackOverflowError", ""); }
|
||||
void IOError(const Str& msg) { _error("IOError", msg); }
|
||||
void NotImplementedError(){ _error("NotImplementedError", ""); }
|
||||
void TypeError(const Str& msg){ _error("TypeError", msg); }
|
||||
@ -417,7 +403,6 @@ DEF_NATIVE_2(BoundMethod, tp_bound_method)
|
||||
DEF_NATIVE_2(Range, tp_range)
|
||||
DEF_NATIVE_2(Slice, tp_slice)
|
||||
DEF_NATIVE_2(Exception, tp_exception)
|
||||
DEF_NATIVE_2(StarWrapper, tp_star_wrapper)
|
||||
|
||||
#define PY_CAST_INT(T) \
|
||||
template<> inline T py_cast<T>(VM* vm, PyObject* obj){ \
|
||||
@ -586,8 +571,7 @@ inline i64 VM::hash(PyObject* obj){
|
||||
}
|
||||
|
||||
inline PyObject* VM::asRepr(PyObject* obj){
|
||||
// TODO: fastcall does not take care of super() proxy!
|
||||
return fast_call_method(obj, __repr__, 0);
|
||||
return call_method(obj, __repr__);
|
||||
}
|
||||
|
||||
inline PyObject* VM::new_module(StrName name) {
|
||||
@ -682,7 +666,6 @@ inline void VM::init_builtin_types(){
|
||||
tp_slice = _new_type_object("slice");
|
||||
tp_range = _new_type_object("range");
|
||||
tp_module = _new_type_object("module");
|
||||
tp_star_wrapper = _new_type_object("_star_wrapper");
|
||||
tp_function = _new_type_object("function");
|
||||
tp_native_function = _new_type_object("native_function");
|
||||
tp_iterator = _new_type_object("iterator");
|
||||
|
Loading…
x
Reference in New Issue
Block a user