mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 12:00:18 +00:00
...
This commit is contained in:
parent
d828fcfecc
commit
1d36ab0235
@ -92,7 +92,7 @@ __NEXT_STEP:;
|
|||||||
}
|
}
|
||||||
PUSH(obj);
|
PUSH(obj);
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(LOAD_NULL) PUSH(_py_null); DISPATCH();
|
TARGET(LOAD_NULL) PUSH(PY_NULL); DISPATCH();
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
TARGET(LOAD_FAST) {
|
TARGET(LOAD_FAST) {
|
||||||
heap._auto_collect();
|
heap._auto_collect();
|
||||||
@ -369,7 +369,7 @@ __NEXT_STEP:;
|
|||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
TARGET(BEGIN_CALL)
|
TARGET(BEGIN_CALL)
|
||||||
PUSH(_py_begin_call);
|
PUSH(PY_BEGIN_CALL);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
TARGET(CALL)
|
TARGET(CALL)
|
||||||
_0 = vectorcall(
|
_0 = vectorcall(
|
||||||
@ -377,7 +377,7 @@ __NEXT_STEP:;
|
|||||||
(byte.arg>>16) & 0xFFFF, // KWARGC
|
(byte.arg>>16) & 0xFFFF, // KWARGC
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
if(_0 == _py_op_call) DISPATCH_OP_CALL();
|
if(_0 == PY_OP_CALL) DISPATCH_OP_CALL();
|
||||||
PUSH(_0);
|
PUSH(_0);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
TARGET(RETURN_VALUE)
|
TARGET(RETURN_VALUE)
|
||||||
@ -391,7 +391,7 @@ __NEXT_STEP:;
|
|||||||
goto __NEXT_FRAME;
|
goto __NEXT_FRAME;
|
||||||
}
|
}
|
||||||
TARGET(YIELD_VALUE)
|
TARGET(YIELD_VALUE)
|
||||||
return _py_op_yield;
|
return PY_OP_YIELD;
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
TARGET(LIST_APPEND) {
|
TARGET(LIST_APPEND) {
|
||||||
PyObject* obj = POPX();
|
PyObject* obj = POPX();
|
||||||
|
@ -120,6 +120,7 @@ struct PyObject;
|
|||||||
inline bool is_tagged(PyObject* p) noexcept { return (BITS(p) & 0b11) != 0b00; }
|
inline bool is_tagged(PyObject* p) noexcept { return (BITS(p) & 0b11) != 0b00; }
|
||||||
inline bool is_int(PyObject* p) noexcept { return (BITS(p) & 0b11) == 0b01; }
|
inline bool is_int(PyObject* p) noexcept { return (BITS(p) & 0b11) == 0b01; }
|
||||||
inline bool is_float(PyObject* p) noexcept { return (BITS(p) & 0b11) == 0b10; }
|
inline bool is_float(PyObject* p) noexcept { return (BITS(p) & 0b11) == 0b10; }
|
||||||
|
inline bool is_special(PyObject* p) noexcept { return (BITS(p) & 0b11) == 0b11; }
|
||||||
|
|
||||||
inline bool is_both_int_or_float(PyObject* a, PyObject* b) noexcept {
|
inline bool is_both_int_or_float(PyObject* a, PyObject* b) noexcept {
|
||||||
return is_tagged(a) && is_tagged(b);
|
return is_tagged(a) && is_tagged(b);
|
||||||
@ -129,6 +130,12 @@ inline bool is_both_int(PyObject* a, PyObject* b) noexcept {
|
|||||||
return is_int(a) && is_int(b);
|
return is_int(a) && is_int(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// special singals, is_tagged() for them is true
|
||||||
|
inline PyObject* const PY_NULL = (PyObject*)0b000011;
|
||||||
|
inline PyObject* const PY_BEGIN_CALL = (PyObject*)0b010011;
|
||||||
|
inline PyObject* const PY_OP_CALL = (PyObject*)0b100011;
|
||||||
|
inline PyObject* const PY_OP_YIELD = (PyObject*)0b110011;
|
||||||
|
|
||||||
struct Expr;
|
struct Expr;
|
||||||
typedef std::unique_ptr<Expr> Expr_;
|
typedef std::unique_ptr<Expr> Expr_;
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ inline PyObject* Generator::next(){
|
|||||||
s_backup.clear();
|
s_backup.clear();
|
||||||
vm->callstack.push(std::move(frame));
|
vm->callstack.push(std::move(frame));
|
||||||
PyObject* ret = vm->_run_top_frame();
|
PyObject* ret = vm->_run_top_frame();
|
||||||
if(ret == vm->_py_op_yield){
|
if(ret == PY_OP_YIELD){
|
||||||
// backup the context
|
// backup the context
|
||||||
frame = std::move(vm->callstack.top());
|
frame = std::move(vm->callstack.top());
|
||||||
PyObject* ret = frame._s->popx();
|
PyObject* ret = frame._s->popx();
|
||||||
|
@ -161,6 +161,7 @@ const int kTpFloatIndex = 3;
|
|||||||
inline bool is_type(PyObject* obj, Type type) {
|
inline bool is_type(PyObject* obj, Type type) {
|
||||||
#if DEBUG_EXTRA_CHECK
|
#if DEBUG_EXTRA_CHECK
|
||||||
if(obj == nullptr) throw std::runtime_error("is_type() called with nullptr");
|
if(obj == nullptr) throw std::runtime_error("is_type() called with nullptr");
|
||||||
|
if(is_special(obj)) throw std::runtime_error("is_type() called with special object");
|
||||||
#endif
|
#endif
|
||||||
switch(type.index){
|
switch(type.index){
|
||||||
case kTpIntIndex: return is_int(obj);
|
case kTpIntIndex: return is_int(obj);
|
||||||
@ -172,6 +173,7 @@ inline bool is_type(PyObject* obj, Type type) {
|
|||||||
inline bool is_non_tagged_type(PyObject* obj, Type type) {
|
inline bool is_non_tagged_type(PyObject* obj, Type type) {
|
||||||
#if DEBUG_EXTRA_CHECK
|
#if DEBUG_EXTRA_CHECK
|
||||||
if(obj == nullptr) throw std::runtime_error("is_non_tagged_type() called with nullptr");
|
if(obj == nullptr) throw std::runtime_error("is_non_tagged_type() called with nullptr");
|
||||||
|
if(is_special(obj)) throw std::runtime_error("is_non_tagged_type() called with special object");
|
||||||
#endif
|
#endif
|
||||||
return !is_tagged(obj) && obj->type == type;
|
return !is_tagged(obj) && obj->type == type;
|
||||||
}
|
}
|
||||||
|
39
src/vm.h
39
src/vm.h
@ -83,10 +83,6 @@ public:
|
|||||||
NameDict _modules; // loaded modules
|
NameDict _modules; // loaded modules
|
||||||
std::map<StrName, Str> _lazy_modules; // lazy loaded modules
|
std::map<StrName, Str> _lazy_modules; // lazy loaded modules
|
||||||
|
|
||||||
PyObject* _py_null;
|
|
||||||
PyObject* _py_begin_call;
|
|
||||||
PyObject* _py_op_call;
|
|
||||||
PyObject* _py_op_yield;
|
|
||||||
PyObject* None;
|
PyObject* None;
|
||||||
PyObject* True;
|
PyObject* True;
|
||||||
PyObject* False;
|
PyObject* False;
|
||||||
@ -130,7 +126,7 @@ public:
|
|||||||
PyObject* asStr(PyObject* obj){
|
PyObject* asStr(PyObject* obj){
|
||||||
PyObject* self;
|
PyObject* self;
|
||||||
PyObject* f = get_unbound_method(obj, __str__, &self, false);
|
PyObject* f = get_unbound_method(obj, __str__, &self, false);
|
||||||
if(self != _py_null) return call_method(self, f);
|
if(self != PY_NULL) return call_method(self, f);
|
||||||
return asRepr(obj);
|
return asRepr(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +134,7 @@ public:
|
|||||||
if(is_type(obj, tp_iterator)) return obj;
|
if(is_type(obj, tp_iterator)) return obj;
|
||||||
PyObject* self;
|
PyObject* self;
|
||||||
PyObject* iter_f = get_unbound_method(obj, __iter__, &self, false);
|
PyObject* iter_f = get_unbound_method(obj, __iter__, &self, false);
|
||||||
if(self != _py_null) return call_method(self, iter_f);
|
if(self != PY_NULL) return call_method(self, iter_f);
|
||||||
TypeError(OBJ_NAME(_t(obj)).escape() + " object is not iterable");
|
TypeError(OBJ_NAME(_t(obj)).escape() + " object is not iterable");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -216,7 +212,7 @@ public:
|
|||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
PyObject* call(PyObject* callable, Args&&... args){
|
PyObject* call(PyObject* callable, Args&&... args){
|
||||||
PUSH(callable);
|
PUSH(callable);
|
||||||
PUSH(_py_null);
|
PUSH(PY_NULL);
|
||||||
_push_varargs(args...);
|
_push_varargs(args...);
|
||||||
return vectorcall(sizeof...(args));
|
return vectorcall(sizeof...(args));
|
||||||
}
|
}
|
||||||
@ -549,7 +545,7 @@ inline bool VM::asBool(PyObject* obj){
|
|||||||
if(is_float(obj)) return CAST(f64, obj) != 0.0;
|
if(is_float(obj)) return CAST(f64, obj) != 0.0;
|
||||||
PyObject* self;
|
PyObject* self;
|
||||||
PyObject* len_f = get_unbound_method(obj, __len__, &self, false);
|
PyObject* len_f = get_unbound_method(obj, __len__, &self, false);
|
||||||
if(self != _py_null){
|
if(self != PY_NULL){
|
||||||
PyObject* ret = call_method(self, len_f);
|
PyObject* ret = call_method(self, len_f);
|
||||||
return CAST(i64, ret) > 0;
|
return CAST(i64, ret) > 0;
|
||||||
}
|
}
|
||||||
@ -684,8 +680,8 @@ inline void VM::_log_s_data(const char* title) {
|
|||||||
if(sp_bases[p] > 0) ss << " ";
|
if(sp_bases[p] > 0) ss << " ";
|
||||||
PyObject* obj = *p;
|
PyObject* obj = *p;
|
||||||
if(obj == nullptr) ss << "(nil)";
|
if(obj == nullptr) ss << "(nil)";
|
||||||
else if(obj == _py_begin_call) ss << "BEGIN_CALL";
|
else if(obj == PY_BEGIN_CALL) ss << "BEGIN_CALL";
|
||||||
else if(obj == _py_null) ss << "NULL";
|
else if(obj == PY_NULL) ss << "NULL";
|
||||||
else if(is_int(obj)) ss << CAST(i64, obj);
|
else if(is_int(obj)) ss << CAST(i64, obj);
|
||||||
else if(is_float(obj)) ss << CAST(f64, obj);
|
else if(is_float(obj)) ss << CAST(f64, obj);
|
||||||
else if(is_type(obj, tp_str)) ss << CAST(Str, obj).escape();
|
else if(is_type(obj, tp_str)) ss << CAST(Str, obj).escape();
|
||||||
@ -744,12 +740,6 @@ inline void VM::init_builtin_types(){
|
|||||||
this->True = heap._new<Dummy>(tp_bool, {});
|
this->True = heap._new<Dummy>(tp_bool, {});
|
||||||
this->False = heap._new<Dummy>(tp_bool, {});
|
this->False = heap._new<Dummy>(tp_bool, {});
|
||||||
|
|
||||||
Type _internal_type = _new_type_object("_internal");
|
|
||||||
this->_py_null = heap._new<Dummy>(_internal_type, {});
|
|
||||||
this->_py_begin_call = heap._new<Dummy>(_internal_type, {});
|
|
||||||
this->_py_op_call = heap._new<Dummy>(_internal_type, {});
|
|
||||||
this->_py_op_yield = heap._new<Dummy>(_internal_type, {});
|
|
||||||
|
|
||||||
this->builtins = new_module("builtins");
|
this->builtins = new_module("builtins");
|
||||||
this->_main = new_module("__main__");
|
this->_main = new_module("__main__");
|
||||||
|
|
||||||
@ -777,7 +767,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
|||||||
PyObject** p1 = s_data._sp - KWARGC*2;
|
PyObject** p1 = s_data._sp - KWARGC*2;
|
||||||
if(is_varargs){
|
if(is_varargs){
|
||||||
p0 = p1 - 1;
|
p0 = p1 - 1;
|
||||||
while(*p0 != _py_begin_call) p0--;
|
while(*p0 != PY_BEGIN_CALL) p0--;
|
||||||
// [BEGIN_CALL, callable, <self>, args..., kwargs...]
|
// [BEGIN_CALL, callable, <self>, args..., kwargs...]
|
||||||
// ^p0 ^p1 ^_sp
|
// ^p0 ^p1 ^_sp
|
||||||
ARGC = p1 - (p0 + 3);
|
ARGC = p1 - (p0 + 3);
|
||||||
@ -787,7 +777,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
|||||||
// ^p0 ^p1 ^_sp
|
// ^p0 ^p1 ^_sp
|
||||||
}
|
}
|
||||||
PyObject* callable = p1[-(ARGC + 2)];
|
PyObject* callable = p1[-(ARGC + 2)];
|
||||||
bool method_call = p1[-(ARGC + 1)] != _py_null;
|
bool method_call = p1[-(ARGC + 1)] != PY_NULL;
|
||||||
|
|
||||||
|
|
||||||
// handle boundmethod, do a patch
|
// handle boundmethod, do a patch
|
||||||
@ -818,7 +808,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
|||||||
PyObject* ret = _py_call(p0, callable, args, kwargs);
|
PyObject* ret = _py_call(p0, callable, args, kwargs);
|
||||||
// stack resetting is handled by _py_call
|
// stack resetting is handled by _py_call
|
||||||
if(ret != nullptr) return ret;
|
if(ret != nullptr) return ret;
|
||||||
if(op_call) return _py_op_call;
|
if(op_call) return PY_OP_CALL;
|
||||||
return _run_top_frame();
|
return _run_top_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -831,7 +821,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
|||||||
PyObject* obj;
|
PyObject* obj;
|
||||||
if(new_f != nullptr){
|
if(new_f != nullptr){
|
||||||
PUSH(new_f);
|
PUSH(new_f);
|
||||||
PUSH(_py_null);
|
PUSH(PY_NULL);
|
||||||
for(PyObject* obj: args) PUSH(obj);
|
for(PyObject* obj: args) PUSH(obj);
|
||||||
for(PyObject* obj: kwargs) PUSH(obj);
|
for(PyObject* obj: kwargs) PUSH(obj);
|
||||||
obj = vectorcall(ARGC, KWARGC);
|
obj = vectorcall(ARGC, KWARGC);
|
||||||
@ -841,7 +831,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
|||||||
}
|
}
|
||||||
PyObject* self;
|
PyObject* self;
|
||||||
callable = get_unbound_method(obj, __init__, &self, false);
|
callable = get_unbound_method(obj, __init__, &self, false);
|
||||||
if (self != _py_null) {
|
if (self != PY_NULL) {
|
||||||
// replace `NULL` with `self`
|
// replace `NULL` with `self`
|
||||||
p1[-(ARGC + 2)] = callable;
|
p1[-(ARGC + 2)] = callable;
|
||||||
p1[-(ARGC + 1)] = self;
|
p1[-(ARGC + 1)] = self;
|
||||||
@ -859,7 +849,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
|||||||
// handle `__call__` overload
|
// handle `__call__` overload
|
||||||
PyObject* self;
|
PyObject* self;
|
||||||
PyObject* call_f = get_unbound_method(callable, __call__, &self, false);
|
PyObject* call_f = get_unbound_method(callable, __call__, &self, false);
|
||||||
if(self != _py_null){
|
if(self != PY_NULL){
|
||||||
p1[-(ARGC + 2)] = call_f;
|
p1[-(ARGC + 2)] = call_f;
|
||||||
p1[-(ARGC + 1)] = self;
|
p1[-(ARGC + 1)] = self;
|
||||||
// [call_f, self, args..., kwargs...]
|
// [call_f, self, args..., kwargs...]
|
||||||
@ -984,7 +974,7 @@ inline PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){
|
|||||||
// used by OP_LOAD_METHOD
|
// used by OP_LOAD_METHOD
|
||||||
// try to load a unbound method (fallback to `getattr` if not found)
|
// try to load a unbound method (fallback to `getattr` if not found)
|
||||||
inline PyObject* VM::get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err, bool fallback){
|
inline PyObject* VM::get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err, bool fallback){
|
||||||
*self = _py_null;
|
*self = PY_NULL;
|
||||||
PyObject* objtype = _t(obj);
|
PyObject* objtype = _t(obj);
|
||||||
// handle super() proxy
|
// handle super() proxy
|
||||||
if(is_non_tagged_type(obj, tp_super)){
|
if(is_non_tagged_type(obj, tp_super)){
|
||||||
@ -1067,8 +1057,7 @@ inline void VM::_error(Exception e){
|
|||||||
inline void ManagedHeap::mark() {
|
inline void ManagedHeap::mark() {
|
||||||
for(PyObject* obj: _no_gc) OBJ_MARK(obj);
|
for(PyObject* obj: _no_gc) OBJ_MARK(obj);
|
||||||
for(auto& frame : vm->callstack.data()) frame._gc_mark();
|
for(auto& frame : vm->callstack.data()) frame._gc_mark();
|
||||||
// TODO: avoid use nullptr?
|
for(PyObject* obj: vm->s_data) if(obj!=nullptr) OBJ_MARK(obj);
|
||||||
for(PyObject* obj: vm->s_data) if(obj != nullptr) OBJ_MARK(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Str obj_type_name(VM *vm, Type type){
|
inline Str obj_type_name(VM *vm, Type type){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user