mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 03:50:16 +00:00
...
This commit is contained in:
parent
d828fcfecc
commit
1d36ab0235
@ -92,7 +92,7 @@ __NEXT_STEP:;
|
||||
}
|
||||
PUSH(obj);
|
||||
} DISPATCH();
|
||||
TARGET(LOAD_NULL) PUSH(_py_null); DISPATCH();
|
||||
TARGET(LOAD_NULL) PUSH(PY_NULL); DISPATCH();
|
||||
/*****************************************/
|
||||
TARGET(LOAD_FAST) {
|
||||
heap._auto_collect();
|
||||
@ -369,7 +369,7 @@ __NEXT_STEP:;
|
||||
} DISPATCH();
|
||||
/*****************************************/
|
||||
TARGET(BEGIN_CALL)
|
||||
PUSH(_py_begin_call);
|
||||
PUSH(PY_BEGIN_CALL);
|
||||
DISPATCH();
|
||||
TARGET(CALL)
|
||||
_0 = vectorcall(
|
||||
@ -377,7 +377,7 @@ __NEXT_STEP:;
|
||||
(byte.arg>>16) & 0xFFFF, // KWARGC
|
||||
true
|
||||
);
|
||||
if(_0 == _py_op_call) DISPATCH_OP_CALL();
|
||||
if(_0 == PY_OP_CALL) DISPATCH_OP_CALL();
|
||||
PUSH(_0);
|
||||
DISPATCH();
|
||||
TARGET(RETURN_VALUE)
|
||||
@ -391,7 +391,7 @@ __NEXT_STEP:;
|
||||
goto __NEXT_FRAME;
|
||||
}
|
||||
TARGET(YIELD_VALUE)
|
||||
return _py_op_yield;
|
||||
return PY_OP_YIELD;
|
||||
/*****************************************/
|
||||
TARGET(LIST_APPEND) {
|
||||
PyObject* obj = POPX();
|
||||
|
@ -120,6 +120,7 @@ struct PyObject;
|
||||
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_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 {
|
||||
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);
|
||||
}
|
||||
|
||||
// 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;
|
||||
typedef std::unique_ptr<Expr> Expr_;
|
||||
|
||||
|
@ -75,7 +75,7 @@ inline PyObject* Generator::next(){
|
||||
s_backup.clear();
|
||||
vm->callstack.push(std::move(frame));
|
||||
PyObject* ret = vm->_run_top_frame();
|
||||
if(ret == vm->_py_op_yield){
|
||||
if(ret == PY_OP_YIELD){
|
||||
// backup the context
|
||||
frame = std::move(vm->callstack.top());
|
||||
PyObject* ret = frame._s->popx();
|
||||
|
@ -161,6 +161,7 @@ const int kTpFloatIndex = 3;
|
||||
inline bool is_type(PyObject* obj, Type type) {
|
||||
#if DEBUG_EXTRA_CHECK
|
||||
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
|
||||
switch(type.index){
|
||||
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) {
|
||||
#if DEBUG_EXTRA_CHECK
|
||||
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
|
||||
return !is_tagged(obj) && obj->type == type;
|
||||
}
|
||||
|
39
src/vm.h
39
src/vm.h
@ -83,10 +83,6 @@ public:
|
||||
NameDict _modules; // 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* True;
|
||||
PyObject* False;
|
||||
@ -130,7 +126,7 @@ public:
|
||||
PyObject* asStr(PyObject* obj){
|
||||
PyObject* self;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -138,7 +134,7 @@ public:
|
||||
if(is_type(obj, tp_iterator)) return obj;
|
||||
PyObject* self;
|
||||
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");
|
||||
return nullptr;
|
||||
}
|
||||
@ -216,7 +212,7 @@ public:
|
||||
template<typename... Args>
|
||||
PyObject* call(PyObject* callable, Args&&... args){
|
||||
PUSH(callable);
|
||||
PUSH(_py_null);
|
||||
PUSH(PY_NULL);
|
||||
_push_varargs(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;
|
||||
PyObject* self;
|
||||
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);
|
||||
return CAST(i64, ret) > 0;
|
||||
}
|
||||
@ -684,8 +680,8 @@ inline void VM::_log_s_data(const char* title) {
|
||||
if(sp_bases[p] > 0) ss << " ";
|
||||
PyObject* obj = *p;
|
||||
if(obj == nullptr) ss << "(nil)";
|
||||
else if(obj == _py_begin_call) ss << "BEGIN_CALL";
|
||||
else if(obj == _py_null) ss << "NULL";
|
||||
else if(obj == PY_BEGIN_CALL) ss << "BEGIN_CALL";
|
||||
else if(obj == PY_NULL) ss << "NULL";
|
||||
else if(is_int(obj)) ss << CAST(i64, obj);
|
||||
else if(is_float(obj)) ss << CAST(f64, obj);
|
||||
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->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->_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;
|
||||
if(is_varargs){
|
||||
p0 = p1 - 1;
|
||||
while(*p0 != _py_begin_call) p0--;
|
||||
while(*p0 != PY_BEGIN_CALL) p0--;
|
||||
// [BEGIN_CALL, callable, <self>, args..., kwargs...]
|
||||
// ^p0 ^p1 ^_sp
|
||||
ARGC = p1 - (p0 + 3);
|
||||
@ -787,7 +777,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
// ^p0 ^p1 ^_sp
|
||||
}
|
||||
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
|
||||
@ -818,7 +808,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
PyObject* ret = _py_call(p0, callable, args, kwargs);
|
||||
// stack resetting is handled by _py_call
|
||||
if(ret != nullptr) return ret;
|
||||
if(op_call) return _py_op_call;
|
||||
if(op_call) return PY_OP_CALL;
|
||||
return _run_top_frame();
|
||||
}
|
||||
|
||||
@ -831,7 +821,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
PyObject* obj;
|
||||
if(new_f != nullptr){
|
||||
PUSH(new_f);
|
||||
PUSH(_py_null);
|
||||
PUSH(PY_NULL);
|
||||
for(PyObject* obj: args) PUSH(obj);
|
||||
for(PyObject* obj: kwargs) PUSH(obj);
|
||||
obj = vectorcall(ARGC, KWARGC);
|
||||
@ -841,7 +831,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
}
|
||||
PyObject* self;
|
||||
callable = get_unbound_method(obj, __init__, &self, false);
|
||||
if (self != _py_null) {
|
||||
if (self != PY_NULL) {
|
||||
// replace `NULL` with `self`
|
||||
p1[-(ARGC + 2)] = callable;
|
||||
p1[-(ARGC + 1)] = self;
|
||||
@ -859,7 +849,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
// handle `__call__` overload
|
||||
PyObject* self;
|
||||
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 + 1)] = self;
|
||||
// [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
|
||||
// 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){
|
||||
*self = _py_null;
|
||||
*self = PY_NULL;
|
||||
PyObject* objtype = _t(obj);
|
||||
// handle super() proxy
|
||||
if(is_non_tagged_type(obj, tp_super)){
|
||||
@ -1067,8 +1057,7 @@ inline void VM::_error(Exception e){
|
||||
inline void ManagedHeap::mark() {
|
||||
for(PyObject* obj: _no_gc) OBJ_MARK(obj);
|
||||
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){
|
||||
|
Loading…
x
Reference in New Issue
Block a user