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 BasePointer;
class Pointer;
class VM;
class Frame;
class PkExportedResource {};
typedef std::shared_ptr<const BasePointer> _Pointer;
typedef PyVar (*_CppFunc)(VM*, const pkpy::ArgList&);
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 {
_Str name;
_Code code;
@ -72,7 +80,7 @@ public:
};
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);

View File

@ -58,15 +58,19 @@ void __initializeBuiltinFunctions(VM* _vm) {
_vm->bindMethod("pointer", "set", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2, true);
_Pointer& p = std::get<_Pointer>(args[0]->_native);
p->set(vm, vm->topFrame(), args[1]);
Pointer& p = std::get<Pointer>(args[0]->_native);
// 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;
});
_vm->bindMethod("pointer", "get", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1, true);
_Pointer& p = std::get<_Pointer>(args[0]->_native);
return p->get(vm, vm->topFrame());
Pointer& p = std::get<Pointer>(args[0]->_native);
// 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) {
@ -131,6 +135,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
std::vector<_Str> names;
for (auto& [k, _] : args[0]->attribs) names.push_back(k);
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);
}
PyVarList ret;

View File

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