blueloveTH %!s(int64=3) %!d(string=hai) anos
pai
achega
bc17e61463
Modificáronse 7 ficheiros con 63 adicións e 29 borrados
  1. 2 1
      src/compiler.h
  2. 2 9
      src/obj.h
  3. 1 0
      src/opcodes.h
  4. 0 17
      src/pocketpy.h
  5. 10 0
      src/pointer.h
  6. 29 2
      src/vm.h
  7. 19 0
      tests/pointer.py

+ 2 - 1
src/compiler.h

@@ -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();
         }
     }

+ 2 - 9
src/obj.h

@@ -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);
 

+ 1 - 0
src/opcodes.h

@@ -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

+ 0 - 17
src/pocketpy.h

@@ -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]);

+ 10 - 0
src/pointer.h

@@ -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;

+ 29 - 2
src/vm.h

@@ -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 - 0
tests/pointer.py

@@ -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()