fix pointer issues

This commit is contained in:
blueloveTH 2022-11-20 22:09:56 +08:00
parent 5b2e301fa7
commit 1999726c18
3 changed files with 40 additions and 17 deletions

View File

@ -14,13 +14,21 @@ const _Float _FLOAT_INF_NEG = -INFINITY;
class CodeObject; class CodeObject;
class BasePointer; class BasePointer;
class Pointer;
class VM; class VM;
class Frame;
class PkExportedResource {}; class PkExportedResource {};
typedef std::shared_ptr<const BasePointer> _Pointer; typedef std::shared_ptr<const BasePointer> _Pointer;
typedef PyVar (*_CppFunc)(VM*, const pkpy::ArgList&); typedef PyVar (*_CppFunc)(VM*, const pkpy::ArgList&);
typedef std::shared_ptr<CodeObject> _Code; typedef std::shared_ptr<CodeObject> _Code;
struct Pointer {
Frame* frame; // the frame that created this pointer
_Pointer ptr; // the internal pointer
Pointer(Frame* frame, _Pointer ptr) : frame(frame), ptr(ptr) {}
};
struct Function { struct Function {
_Str name; _Str name;
_Code code; _Code code;
@ -72,7 +80,7 @@ public:
}; };
typedef std::shared_ptr<Function> _Func; typedef std::shared_ptr<Function> _Func;
typedef std::variant<_Int,_Float,bool,_Str,PyVarList,_CppFunc,_Func,std::shared_ptr<_Iterator>,_BoundedMethod,_Range,_Slice,_Pointer> _Value; typedef std::variant<_Int,_Float,bool,_Str,PyVarList,_CppFunc,_Func,std::shared_ptr<_Iterator>,_BoundedMethod,_Range,_Slice,_Pointer,Pointer> _Value;
const int _SIZEOF_VALUE = sizeof(_Value); const int _SIZEOF_VALUE = sizeof(_Value);

View File

@ -58,15 +58,19 @@ void __initializeBuiltinFunctions(VM* _vm) {
_vm->bindMethod("pointer", "set", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("pointer", "set", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2, true); vm->__checkArgSize(args, 2, true);
_Pointer& p = std::get<_Pointer>(args[0]->_native); Pointer& p = std::get<Pointer>(args[0]->_native);
p->set(vm, vm->topFrame(), args[1]); // this check is unsafe, but it's the best we can do
if(!vm->__isFrameValid(p.frame)) vm->nullPointerError();
p.ptr->set(vm, p.frame, args[1]);
return vm->None; return vm->None;
}); });
_vm->bindMethod("pointer", "get", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("pointer", "get", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1, true); vm->__checkArgSize(args, 1, true);
_Pointer& p = std::get<_Pointer>(args[0]->_native); Pointer& p = std::get<Pointer>(args[0]->_native);
return p->get(vm, vm->topFrame()); // this check is unsafe, but it's the best we can do
if(!vm->__isFrameValid(p.frame)) vm->nullPointerError();
return p.ptr->get(vm, p.frame);
}); });
_vm->bindBuiltinFunc("eval", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("eval", [](VM* vm, const pkpy::ArgList& args) {
@ -131,6 +135,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
std::vector<_Str> names; std::vector<_Str> names;
for (auto& [k, _] : args[0]->attribs) names.push_back(k); for (auto& [k, _] : args[0]->attribs) names.push_back(k);
for (auto& [k, _] : args[0]->_type->attribs) { for (auto& [k, _] : args[0]->_type->attribs) {
if (k.str().find("__") == 0) continue;
if (std::find(names.begin(), names.end(), k) == names.end()) names.push_back(k); if (std::find(names.begin(), names.end(), k) == names.end()) names.push_back(k);
} }
PyVarList ret; PyVarList ret;

View File

@ -45,7 +45,7 @@ typedef void(*PrintFn)(const VM*, const char*);
class VM: public PkExportedResource{ class VM: public PkExportedResource{
private: private:
std::stack< std::unique_ptr<Frame> > callstack; std::deque< std::unique_ptr<Frame> > callstack;
PyVarDict _modules; // 3rd modules PyVarDict _modules; // 3rd modules
PyVar __py2py_call_signal; PyVar __py2py_call_signal;
@ -209,9 +209,8 @@ private:
} break; } break;
case OP_UNARY_REF: case OP_UNARY_REF:
{ {
PyVar obj = frame->__pop(); _Pointer p = PyPointer_AS_C(frame->__pop());
_Pointer p = PyPointer_AS_C(obj); frame->push(newObject(_tp_user_pointer, Pointer(frame, p)));
frame->push(newObject(_tp_user_pointer, p));
} break; } break;
case OP_POP_JUMP_IF_FALSE: case OP_POP_JUMP_IF_FALSE:
if(!PyBool_AS_C(asBool(frame->popValue(this)))) frame->jump(byte.arg); if(!PyBool_AS_C(asBool(frame->popValue(this)))) frame->jump(byte.arg);
@ -365,9 +364,16 @@ public:
return asRepr(obj); return asRepr(obj);
} }
bool __isFrameValid(Frame* frame){
for(const auto& f : callstack){
if(f.get() == frame) return true;
}
return false;
}
Frame* topFrame(){ Frame* topFrame(){
if(callstack.size() == 0) UNREACHABLE(); if(callstack.size() == 0) UNREACHABLE();
return callstack.top().get(); return callstack.back().get();
} }
PyVar asRepr(const PyVar& obj){ PyVar asRepr(const PyVar& obj){
@ -504,7 +510,7 @@ public:
throw RuntimeError("RecursionError", "maximum recursion depth exceeded", _cleanErrorAndGetSnapshots()); throw RuntimeError("RecursionError", "maximum recursion depth exceeded", _cleanErrorAndGetSnapshots());
} }
Frame* frame = new Frame(code.get(), _module, locals); Frame* frame = new Frame(code.get(), _module, locals);
callstack.push(std::unique_ptr<Frame>(frame)); callstack.emplace_back(std::unique_ptr<Frame>(frame));
return frame; return frame;
} }
@ -519,16 +525,16 @@ public:
if(frame == frameBase){ // [ frameBase<- ] if(frame == frameBase){ // [ frameBase<- ]
break; break;
}else{ }else{
callstack.pop(); callstack.pop_back();
frame = callstack.top().get(); frame = callstack.back().get();
frame->push(ret); frame->push(ret);
} }
}else{ }else{
frame = callstack.top().get(); // [ frameBase, newFrame<- ] frame = callstack.back().get(); // [ frameBase, newFrame<- ]
} }
} }
callstack.pop(); callstack.pop_back();
return ret; return ret;
} }
@ -772,9 +778,9 @@ private:
std::stack<_Str> snapshots; std::stack<_Str> snapshots;
while (!callstack.empty()){ while (!callstack.empty()){
if(snapshots.size() < 8){ if(snapshots.size() < 8){
snapshots.push(callstack.top()->errorSnapshot()); snapshots.push(callstack.back()->errorSnapshot());
} }
callstack.pop(); callstack.pop_back();
} }
return snapshots; return snapshots;
} }
@ -788,6 +794,10 @@ public:
_error("SystemError", msg); _error("SystemError", msg);
} }
void nullPointerError(){
_error("NullPointerError", "pointer is invalid");
}
void zeroDivisionError(){ void zeroDivisionError(){
_error("ZeroDivisionError", "division by zero"); _error("ZeroDivisionError", "division by zero");
} }