mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
fix pointer issues
This commit is contained in:
parent
5b2e301fa7
commit
1999726c18
10
src/obj.h
10
src/obj.h
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
34
src/vm.h
34
src/vm.h
@ -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");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user