blueloveTH hace 3 años
padre
commit
6a82644f9a
Se han modificado 6 ficheros con 138 adiciones y 149 borrados
  1. 4 4
      src/ceval.h
  2. 1 0
      src/obj.h
  3. 6 6
      src/pocketpy.h
  4. 1 1
      src/ref.h
  5. 0 6
      src/tuplelist.h
  6. 126 132
      src/vm.h

+ 4 - 4
src/ceval.h

@@ -180,7 +180,7 @@ PyVar VM::run_frame(Frame* frame){
             if(asBool(expr) != True) _error("AssertionError", msg);
         } continue;
         case OP_EXCEPTION_MATCH: {
-            const auto& e = PyException_AS_C(frame->top());
+            const auto& e = py_cast<Exception>(this, frame->top());
             StrName name = frame->co->names[byte.arg].first;
             frame->push(PyBool(e.match_type(name)));
         } continue;
@@ -212,10 +212,10 @@ PyVar VM::run_frame(Frame* frame){
         case OP_DUP_TOP_VALUE: frame->push(frame->top_value(this)); continue;
         case OP_UNARY_STAR: {
             if(byte.arg > 0){   // rvalue
-                frame->top() = PyStarWrapper({frame->top_value(this), true});
+                frame->top() = py_object(this, StarWrapper(frame->top_value(this), true));
             }else{
                 PyRef_AS_C(frame->top()); // check ref
-                frame->top() = PyStarWrapper({frame->top(), false});
+                frame->top() = py_object(this, StarWrapper(frame->top(), false));
             }
         } continue;
         case OP_CALL_KWARGS_UNPACK: case OP_CALL_KWARGS: {
@@ -286,7 +286,7 @@ PyVar VM::run_frame(Frame* frame){
             Slice s;
             if(start != None) { s.start = (int)py_cast_v<i64>(this, start);}
             if(stop != None) { s.stop = (int)py_cast_v<i64>(this, stop);}
-            frame->push(PySlice(s));
+            frame->push(py_object(this, s));
         } continue;
         case OP_IMPORT_NAME: {
             StrName name = frame->co->names[byte.arg].first;

+ 1 - 0
src/obj.h

@@ -46,6 +46,7 @@ struct Function {
 struct BoundMethod {
     PyVar obj;
     PyVar method;
+    BoundMethod(const PyVar& obj, const PyVar& method) : obj(obj), method(method) {}
 };
 
 struct Range {

+ 6 - 6
src/pocketpy.h

@@ -172,7 +172,7 @@ void init_builtins(VM* _vm) {
             case 3: r.start = py_cast_v<i64>(vm, args[0]); r.stop = py_cast_v<i64>(vm, args[1]); r.step = py_cast_v<i64>(vm, args[2]); break;
             default: vm->TypeError("expected 1-3 arguments, but got " + std::to_string(args.size()));
         }
-        return vm->PyRange(r);
+        return py_object(vm, r);
     });
 
     _vm->bind_method<0>("range", "__iter__", CPP_LAMBDA(
@@ -338,7 +338,7 @@ void init_builtins(VM* _vm) {
         const Str& self (py_cast<Str>(vm, args[0]));
 
         if(is_type(args[1], vm->tp_slice)){
-            Slice s = vm->PySlice_AS_C(args[1]);
+            Slice s = _py_cast_v<Slice>(vm, args[1]);
             s.normalize(self.u8_length());
             return py_object(vm, self.u8_substr(s.start, s.stop));
         }
@@ -458,7 +458,7 @@ void init_builtins(VM* _vm) {
         const List& self = py_cast<List>(vm, args[0]);
 
         if(is_type(args[1], vm->tp_slice)){
-            Slice s = vm->PySlice_AS_C(args[1]);
+            Slice s = _py_cast_v<Slice>(vm, args[1]);
             s.normalize(self.size());
             List new_list;
             for(size_t i = s.start; i < s.stop; i++) new_list.push_back(self[i]);
@@ -500,7 +500,7 @@ void init_builtins(VM* _vm) {
         const Tuple& self = py_cast<Tuple>(vm, args[0]);
 
         if(is_type(args[1], vm->tp_slice)){
-            Slice s = vm->PySlice_AS_C(args[1]);
+            Slice s = _py_cast_v<Slice>(vm, args[1]);
             s.normalize(self.size());
             List new_list;
             for(size_t i = s.start; i < s.stop; i++) new_list.push_back(self[i]);
@@ -608,7 +608,7 @@ void add_module_dis(VM* vm){
     PyVar mod = vm->new_module("dis");
     vm->bind_func<1>(mod, "dis", [](VM* vm, Args& args) {
         PyVar f = args[0];
-        if(is_type(f, vm->tp_bound_method)) f = vm->PyBoundMethod_AS_C(args[0]).method;
+        if(is_type(f, vm->tp_bound_method)) f = py_cast<BoundMethod>(vm, args[0]).method;
         CodeObject_ code = py_cast<Function>(vm, f).code;
         (*vm->_stdout) << vm->disassemble(code);
         return vm->None;
@@ -693,7 +693,7 @@ struct ReMatch {
 
         vm->bind_method<0>(type, "span", [](VM* vm, Args& args) {
             auto& self = vm->_cast<ReMatch>(args[0]);
-            return py_object(vm, pkpy::Args({ py_object(vm, self.start), py_object(vm, self.end) }));
+            return py_object(vm, two_args(py_object(vm, self.start), py_object(vm, self.end)));
         });
 
         vm->bind_method<1>(type, "group", [](VM* vm, Args& args) {

+ 1 - 1
src/ref.h

@@ -127,7 +127,7 @@ struct TupleRef : BaseRef {
         for(int i=0; i<objs.size(); i++){
             PyVarOrNull x;
             if(is_type(objs[i], vm->tp_star_wrapper)){
-                auto& star = vm->PyStarWrapper_AS_C(objs[i]);
+                auto& star = _py_cast<StarWrapper>(vm, objs[i]);
                 if(star.rvalue) vm->ValueError("can't use starred expression here");
                 if(i != objs.size()-1) vm->ValueError("* can only be used at the end");
                 auto ref = vm->PyRef_AS_C(star.obj);

+ 0 - 6
src/tuplelist.h

@@ -26,12 +26,6 @@ namespace pkpy {
             for(int i=0; i<_size; i++) _args[i] = other._args[i];
         }
 
-        Args(std::initializer_list<PyVar> a){
-            _alloc(a.size());
-            int i = 0;
-            for(auto& v: a) _args[i++] = v;
-        }
-
         Args(Args&& other) noexcept {
             this->_args = other._args;
             this->_size = other._size;

+ 126 - 132
src/vm.h

@@ -5,14 +5,6 @@
 
 namespace pkpy{
 
-#define DEF_NATIVE(type, ctype, ptype)                          \
-    inline ctype& Py##type##_AS_C(const PyVar& obj) {           \
-        check_type(obj, ptype);                                 \
-        return OBJ_GET(ctype, obj);                             \
-    }                                                           \
-    inline PyVar Py##type(const ctype& value) { return new_object(ptype, value);} \
-    inline PyVar Py##type(ctype&& value) { return new_object(ptype, std::move(value));}
-
 #define DEF_NATIVE_2(ctype, ptype)                                      \
     template<> ctype& py_cast<ctype>(VM* vm, const PyVar& obj) {        \
         vm->check_type(obj, vm->ptype);                                 \
@@ -166,48 +158,6 @@ public:
         return _exec();
     }
 
-    PyVar _exec(){
-        Frame* frame = top_frame();
-        i64 base_id = frame->id;
-        PyVar ret = nullptr;
-        bool need_raise = false;
-
-        while(true){
-            if(frame->id < base_id) UNREACHABLE();
-            try{
-                if(need_raise){ need_raise = false; _raise(); }
-                ret = run_frame(frame);
-                if(ret == _py_op_yield) return _py_op_yield;
-                if(ret != _py_op_call){
-                    if(frame->id == base_id){      // [ frameBase<- ]
-                        callstack.pop();
-                        return ret;
-                    }else{
-                        callstack.pop();
-                        frame = callstack.top().get();
-                        frame->push(ret);
-                    }
-                }else{
-                    frame = callstack.top().get();  // [ frameBase, newFrame<- ]
-                }
-            }catch(HandledException& e){
-                continue;
-            }catch(UnhandledException& e){
-                PyVar obj = frame->pop();
-                Exception& _e = PyException_AS_C(obj);
-                _e.st_push(frame->snapshot());
-                callstack.pop();
-                if(callstack.empty()) throw _e;
-                frame = callstack.top().get();
-                frame->push(obj);
-                if(frame->id < base_id) throw ToBeRaisedException();
-                need_raise = true;
-            }catch(ToBeRaisedException& e){
-                need_raise = true;
-            }
-        }
-    }
-
     Type _new_type_object(StrName name, Type base=0) {
         PyVar obj = make_sp<PyObject, Py_<Type>>(tp_type, _all_types.size());
         setattr(obj, __base__, _t(base));
@@ -245,70 +195,6 @@ public:
         return new_object(T::_type(this), T(std::forward<Args>(args)...));
     }
 
-    PyVarOrNull getattr(const PyVar& obj, StrName name, bool throw_err=true) {
-        PyVar* val;
-        PyObject* cls;
-
-        if(is_type(obj, tp_super)){
-            const PyVar* root = &obj;
-            int depth = 1;
-            while(true){
-                root = &OBJ_GET(PyVar, *root);
-                if(!is_type(*root, tp_super)) break;
-                depth++;
-            }
-            cls = _t(*root).get();
-            for(int i=0; i<depth; i++) cls = cls->attr(__base__).get();
-
-            val = (*root)->attr().try_get(name);
-            if(val != nullptr) return *val;    
-        }else{
-            if(!obj.is_tagged() && obj->is_attr_valid()){
-                val = obj->attr().try_get(name);
-                if(val != nullptr) return *val;
-            }
-            cls = _t(obj).get();
-        }
-
-        while(cls != None.get()) {
-            val = cls->attr().try_get(name);
-            if(val != nullptr){
-                PyVarOrNull descriptor = getattr(*val, __get__, false);
-                if(descriptor != nullptr){
-                    return call(descriptor, one_arg(obj));
-                }
-                if(is_type(*val, tp_function) || is_type(*val, tp_native_function)){
-                    return PyBoundMethod({obj, *val});
-                }else{
-                    return *val;
-                }
-            }
-            cls = cls->attr(__base__).get();
-        }
-        if(throw_err) AttributeError(obj, name);
-        return nullptr;
-    }
-
-    template<typename T>
-    inline void setattr(PyVar& obj, StrName name, T&& value) {
-        if(obj.is_tagged()) TypeError("cannot set attribute");
-        PyObject* p = obj.get();
-        while(p->type == tp_super) p = static_cast<PyVar*>(p->value())->get();
-        if(!p->is_attr_valid()) TypeError("cannot set attribute");
-        p->attr().set(name, std::forward<T>(value));
-    }
-
-    template<int ARGC>
-    void bind_method(PyVar obj, Str funcName, NativeFuncRaw fn) {
-        check_type(obj, tp_type);
-        setattr(obj, funcName, PyNativeFunc(NativeFunc(fn, ARGC, true)));
-    }
-
-    template<int ARGC>
-    void bind_func(PyVar obj, Str funcName, NativeFuncRaw fn) {
-        setattr(obj, funcName, PyNativeFunc(NativeFunc(fn, ARGC, false)));
-    }
-
     template<int ARGC>
     void bind_func(Str typeName, Str funcName, NativeFuncRaw fn) {
         bind_func<ARGC>(_types[typeName], funcName, fn);     
@@ -360,13 +246,6 @@ public:
         check_type(obj, tp_native_iterator);
         return static_cast<BaseIter*>(obj->value());
     }
-
-    DEF_NATIVE(NativeFunc, NativeFunc, tp_native_function)
-    DEF_NATIVE(BoundMethod, BoundMethod, tp_bound_method)
-    DEF_NATIVE(Range, Range, tp_range)
-    DEF_NATIVE(Slice, Slice, tp_slice)
-    DEF_NATIVE(Exception, Exception, tp_exception)
-    DEF_NATIVE(StarWrapper, StarWrapper, tp_star_wrapper)
     
     // there is only one True/False, so no need to copy them!
     inline bool PyBool_AS_C(const PyVar& obj){
@@ -381,15 +260,6 @@ public:
         _error(Exception(name, msg));
     }
 
-    void _error(Exception e){
-        if(callstack.empty()){
-            e.is_re = false;
-            throw e;
-        }
-        top_frame()->push(PyException(e));
-        _raise();
-    }
-
     void _raise(){
         bool ok = top_frame()->jump_to_exception_handler();
         if(ok) throw HandledException();
@@ -461,6 +331,15 @@ public:
     void init_builtin_types();
     PyVar call(const PyVar& _callable, Args args, const Args& kwargs, bool opCall);
     void unpack_args(Args& args);
+    PyVarOrNull getattr(const PyVar& obj, StrName name, bool throw_err=true);
+    template<typename T>
+    void setattr(PyVar& obj, StrName name, T&& value);
+    template<int ARGC>
+    void bind_method(PyVar obj, Str funcName, NativeFuncRaw fn);
+    template<int ARGC>
+    void bind_func(PyVar obj, Str funcName, NativeFuncRaw fn);
+    void _error(Exception e);
+    PyVar _exec();
 
     template<typename P>
     PyVarRef PyRef(P&& value);
@@ -790,7 +669,7 @@ PyVar VM::call(const PyVar& _callable, Args args, const Args& kwargs, bool opCal
 
     const PyVar* callable = &_callable;
     if(is_type(*callable, tp_bound_method)){
-        auto& bm = PyBoundMethod_AS_C((*callable));
+        auto& bm = py_cast<BoundMethod>(this, *callable);
         callable = &bm.method;      // get unbound method
         args.extend_self(bm.obj);
     }
@@ -855,7 +734,7 @@ void VM::unpack_args(Args& args){
     List unpacked;
     for(int i=0; i<args.size(); i++){
         if(is_type(args[i], tp_star_wrapper)){
-            auto& star = PyStarWrapper_AS_C(args[i]);
+            auto& star = _py_cast<StarWrapper>(this, args[i]);
             if(!star.rvalue) UNREACHABLE();
             PyVar list = asList(star.obj);
             List& list_c = py_cast<List>(this, list);
@@ -867,4 +746,119 @@ void VM::unpack_args(Args& args){
     args = Args::from_list(std::move(unpacked));
 }
 
+PyVarOrNull VM::getattr(const PyVar& obj, StrName name, bool throw_err) {
+    PyVar* val;
+    PyObject* cls;
+
+    if(is_type(obj, tp_super)){
+        const PyVar* root = &obj;
+        int depth = 1;
+        while(true){
+            root = &OBJ_GET(PyVar, *root);
+            if(!is_type(*root, tp_super)) break;
+            depth++;
+        }
+        cls = _t(*root).get();
+        for(int i=0; i<depth; i++) cls = cls->attr(__base__).get();
+
+        val = (*root)->attr().try_get(name);
+        if(val != nullptr) return *val;    
+    }else{
+        if(!obj.is_tagged() && obj->is_attr_valid()){
+            val = obj->attr().try_get(name);
+            if(val != nullptr) return *val;
+        }
+        cls = _t(obj).get();
+    }
+
+    while(cls != None.get()) {
+        val = cls->attr().try_get(name);
+        if(val != nullptr){
+            PyVarOrNull descriptor = getattr(*val, __get__, false);
+            if(descriptor != nullptr){
+                return call(descriptor, one_arg(obj));
+            }
+            if(is_type(*val, tp_function) || is_type(*val, tp_native_function)){
+                return py_object(this, BoundMethod(obj, *val));
+            }else{
+                return *val;
+            }
+        }
+        cls = cls->attr(__base__).get();
+    }
+    if(throw_err) AttributeError(obj, name);
+    return nullptr;
+}
+
+template<typename T>
+void VM::setattr(PyVar& obj, StrName name, T&& value) {
+    if(obj.is_tagged()) TypeError("cannot set attribute");
+    PyObject* p = obj.get();
+    while(p->type == tp_super) p = static_cast<PyVar*>(p->value())->get();
+    if(!p->is_attr_valid()) TypeError("cannot set attribute");
+    p->attr().set(name, std::forward<T>(value));
+}
+
+template<int ARGC>
+void VM::bind_method(PyVar obj, Str funcName, NativeFuncRaw fn) {
+    check_type(obj, tp_type);
+    setattr(obj, funcName, py_object(this, NativeFunc(fn, ARGC, true)));
+}
+
+template<int ARGC>
+void VM::bind_func(PyVar obj, Str funcName, NativeFuncRaw fn) {
+    setattr(obj, funcName, py_object(this, NativeFunc(fn, ARGC, false)));
+}
+
+void VM::_error(Exception e){
+    if(callstack.empty()){
+        e.is_re = false;
+        throw e;
+    }
+    top_frame()->push(py_object(this, e));
+    _raise();
+}
+
+PyVar VM::_exec(){
+    Frame* frame = top_frame();
+    i64 base_id = frame->id;
+    PyVar ret = nullptr;
+    bool need_raise = false;
+
+    while(true){
+        if(frame->id < base_id) UNREACHABLE();
+        try{
+            if(need_raise){ need_raise = false; _raise(); }
+            ret = run_frame(frame);
+            if(ret == _py_op_yield) return _py_op_yield;
+            if(ret != _py_op_call){
+                if(frame->id == base_id){      // [ frameBase<- ]
+                    callstack.pop();
+                    return ret;
+                }else{
+                    callstack.pop();
+                    frame = callstack.top().get();
+                    frame->push(ret);
+                }
+            }else{
+                frame = callstack.top().get();  // [ frameBase, newFrame<- ]
+            }
+        }catch(HandledException& e){
+            continue;
+        }catch(UnhandledException& e){
+            PyVar obj = frame->pop();
+            Exception& _e = py_cast<Exception>(this, obj);
+            _e.st_push(frame->snapshot());
+            callstack.pop();
+            if(callstack.empty()) throw _e;
+            frame = callstack.top().get();
+            frame->push(obj);
+            if(frame->id < base_id) throw ToBeRaisedException();
+            need_raise = true;
+        }catch(ToBeRaisedException& e){
+            need_raise = true;
+        }
+    }
+}
+
 }   // namespace pkpy