This commit is contained in:
blueloveTH 2022-11-20 22:34:38 +08:00
parent 1999726c18
commit bc17e61463
7 changed files with 63 additions and 29 deletions

View File

@ -60,7 +60,7 @@ public:
rules[TK("%")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
rules[TK("+")] = { nullptr, METHOD(exprBinaryOp), PREC_TERM };
rules[TK("-")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_TERM };
rules[TK("*")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
rules[TK("*")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_FACTOR };
rules[TK("/")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
rules[TK("//")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
rules[TK("**")] = { nullptr, METHOD(exprBinaryOp), PREC_EXPONENT };
@ -450,6 +450,7 @@ public:
case TK("-"): emitCode(OP_UNARY_NEGATIVE); break;
case TK("not"): emitCode(OP_UNARY_NOT); break;
case TK("&"): emitCode(OP_UNARY_REF); break;
case TK("*"): emitCode(OP_UNARY_DEREF); break;
default: UNREACHABLE();
}
}

View File

@ -10,11 +10,10 @@ const _Int _Int_MAX_NEG = -9223372036854775807LL;
const _Float _FLOAT_INF_POS = INFINITY;
const _Float _FLOAT_INF_NEG = -INFINITY;
#define PK_VERSION "0.2.9"
#define PK_VERSION "0.3.0"
class CodeObject;
class BasePointer;
class Pointer;
class VM;
class Frame;
class PkExportedResource {};
@ -23,12 +22,6 @@ 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;
@ -80,7 +73,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,Pointer> _Value;
typedef std::variant<_Int,_Float,bool,_Str,PyVarList,_CppFunc,_Func,std::shared_ptr<_Iterator>,_BoundedMethod,_Range,_Slice,_Pointer> _Value;
const int _SIZEOF_VALUE = sizeof(_Value);

View File

@ -60,5 +60,6 @@ OPCODE(BUILD_STRING) // arg is the expr count, build a string from the to
OPCODE(GOTO)
OPCODE(UNARY_REF) // for &
OPCODE(UNARY_DEREF) // for *
#endif

View File

@ -56,23 +56,6 @@ void __initializeBuiltinFunctions(VM* _vm) {
return vm->PyStr(tvm->readStdin());
});
_vm->bindMethod("pointer", "set", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2, true);
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);
// 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->__checkArgSize(args, 1);
const _Str& expr = vm->PyStr_AS_C(args[0]);

View File

@ -55,6 +55,16 @@ struct CompoundPointer : BasePointer {
CompoundPointer(std::vector<_Pointer> pointers) : pointers(pointers) {}
CompoundPointer(std::vector<_Pointer>&& pointers) : pointers(pointers) {}
PyVar get(VM* vm, Frame* frame) const;
void set(VM* vm, Frame* frame, PyVar val) const;
void del(VM* vm, Frame* frame) const;
};
struct UserPointer : BasePointer {
const _Pointer p;
Frame* frame;
UserPointer(_Pointer p, Frame* frame) : p(p), frame(frame) {}
PyVar get(VM* vm, Frame* frame) const;
void set(VM* vm, Frame* frame, PyVar val) const;
void del(VM* vm, Frame* frame) const;

View File

@ -209,8 +209,17 @@ private:
} break;
case OP_UNARY_REF:
{
_Pointer p = PyPointer_AS_C(frame->__pop());
frame->push(newObject(_tp_user_pointer, Pointer(frame, p)));
// _pointer to pointer
const _Pointer& p = PyPointer_AS_C(frame->__pop());
_Pointer up = std::make_shared<UserPointer>(p, frame);
frame->push(newObject(_tp_user_pointer, std::move(up)));
} break;
case OP_UNARY_DEREF:
{
// pointer to _pointer
PyVar obj = frame->popValue(this);
__checkType(obj, _tp_user_pointer);
frame->push(PyPointer(std::get<_Pointer>(obj->_native)));
} break;
case OP_POP_JUMP_IF_FALSE:
if(!PyBool_AS_C(asBool(frame->popValue(this)))) frame->jump(byte.arg);
@ -941,6 +950,24 @@ void CompoundPointer::del(VM* vm, Frame* frame) const{
for (auto& ptr : pointers) ptr->del(vm, frame);
}
PyVar UserPointer::get(VM* vm, Frame* frame) const{
frame = this->frame;
// this check is unsafe, but it's the best we can do
if(!vm->__isFrameValid(frame)) vm->nullPointerError();
return p->get(vm, frame);
}
void UserPointer::set(VM* vm, Frame* frame, PyVar val) const{
frame = this->frame;
// this check is unsafe, but it's the best we can do
if(!vm->__isFrameValid(frame)) vm->nullPointerError();
p->set(vm, frame, val);
}
void UserPointer::del(VM* vm, Frame* frame) const{
vm->typeError("delete is unsupported");
}
/***** Frame's Impl *****/
inline PyVar Frame::__deref_pointer(VM* vm, PyVar v){
if(v->isType(vm->_tp_pointer)) return vm->PyPointer_AS_C(v)->get(vm, this);

19
tests/pointer.py Normal file
View File

@ -0,0 +1,19 @@
a = 1
assert a == 1
assert *&a == 1
b = &a
*b = 2
assert a == 2
def swap(a,b):
t = *a
*a = *b
*b = t
def f():
a,b = 5,6
swap(&a,&b)
assert a == 6
assert b == 5
f()