blueloveTH 1 год назад
Родитель
Сommit
0f47105b27
6 измененных файлов с 87 добавлено и 71 удалено
  1. 2 0
      include/pocketpy/common.h
  2. 56 42
      include/pocketpy/vm.h
  3. 13 13
      src/ceval.cpp
  4. 1 1
      src/dataclasses.cpp
  5. 3 3
      src/pocketpy.cpp
  6. 12 12
      src/vm.cpp

+ 2 - 0
include/pocketpy/common.h

@@ -109,6 +109,8 @@ struct Type {
 #define PK_VAR_LAMBDA(x) ([](VM* vm, ArgsView args) { return VAR(x); })
 #define PK_ACTION(x) ([](VM* vm, ArgsView args) { x; return vm->None; })
 
+#define PK_REGION(name)	1
+
 #ifdef POCKETPY_H
 #define PK_FATAL_ERROR() throw std::runtime_error( "L" + std::to_string(__LINE__) + " FATAL_ERROR()!");
 #else

+ 56 - 42
include/pocketpy/vm.h

@@ -128,7 +128,7 @@ struct ImportContext{
 class VM {
     PK_ALWAYS_PASS_BY_POINTER(VM)
     
-    VM* vm;     // self reference for simplify code
+    VM* vm;     // self reference to simplify code
 public:
     ManagedHeap heap;
     ValueStack s_data;
@@ -152,9 +152,9 @@ public:
     // this is for repr() recursion detection (no need to mark)
     std::set<PyObject*> _repr_recursion_set;
 
-    ImportContext __import_context; // for import
-    PyObject* __last_exception;     // last exception
-    PyObject* __curr_class;         // current class being defined
+    ImportContext __import_context;
+    PyObject* __last_exception;
+    PyObject* __curr_class; 
     PyObject* __cached_object_new;
     std::map<std::string_view, CodeObject_> __cached_codes;
 
@@ -182,45 +182,50 @@ public:
     const bool enable_os;
     VM(bool enable_os=true);
 
-    /********** py_xxx **********/
-    PyObject* py_str(PyObject* obj);
-    PyObject* py_repr(PyObject* obj);
-    PyObject* py_json(PyObject* obj);
-    PyObject* py_iter(PyObject* obj);
-    PyObject* py_next(PyObject*);
-    PyObject* _py_next(const PyTypeInfo*, PyObject*);
-    PyObject* py_import(Str path, bool throw_err=true);
-    PyObject* py_negate(PyObject* obj);
-
-    List py_list(PyObject*);
-    bool py_callable(PyObject* obj);
-    bool py_bool(PyObject* obj);
-    i64 py_hash(PyObject* obj);
-
-    bool py_eq(PyObject* lhs, PyObject* rhs);
-    // new in v1.2.9
-    bool py_lt(PyObject* lhs, PyObject* rhs);
-    bool py_le(PyObject* lhs, PyObject* rhs);
-    bool py_gt(PyObject* lhs, PyObject* rhs);
-    bool py_ge(PyObject* lhs, PyObject* rhs);
-    bool py_ne(PyObject* lhs, PyObject* rhs) { return !py_eq(lhs, rhs); }
-
-    /********** utils **********/
+#if PK_REGION("Python Equivalents")
+    PyObject* py_str(PyObject* obj);                        // x -> str(x)
+    PyObject* py_repr(PyObject* obj);                       // x -> repr(x)
+    PyObject* py_json(PyObject* obj);                       // x -> json.dumps(x)
+    PyObject* py_iter(PyObject* obj);                       // x -> iter(x)
+    PyObject* py_next(PyObject*);                           // x -> next(x)
+    PyObject* _py_next(const PyTypeInfo*, PyObject*);       // x -> next(x) with type info cache
+    PyObject* py_import(Str path, bool throw_err=true);     // x -> __import__(x)
+    PyObject* py_negate(PyObject* obj);                     // x -> -x
+
+    List py_list(PyObject*);                                // x -> list(x)
+    bool py_callable(PyObject* obj);                        // x -> callable(x)
+    bool py_bool(PyObject* obj);                            // x -> bool(x)
+    i64 py_hash(PyObject* obj);                             // x -> hash(x)
+
+    bool py_eq(PyObject* lhs, PyObject* rhs);               // (lhs, rhs) -> lhs == rhs
+    bool py_lt(PyObject* lhs, PyObject* rhs);               // (lhs, rhs) -> lhs < rhs
+    bool py_le(PyObject* lhs, PyObject* rhs);               // (lhs, rhs) -> lhs <= rhs
+    bool py_gt(PyObject* lhs, PyObject* rhs);               // (lhs, rhs) -> lhs > rhs
+    bool py_ge(PyObject* lhs, PyObject* rhs);               // (lhs, rhs) -> lhs >= rhs
+    bool py_ne(PyObject* lhs, PyObject* rhs) {              // (lhs, rhs) -> lhs != rhs
+        return !py_eq(lhs, rhs);
+    }
+#endif
+
+#if PK_REGION("Utility Methods")
     PyObject* new_module(Str name, Str package="");
+    PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled=true);
     ArgsView cast_array_view(PyObject* obj);
     void set_main_argv(int argc, char** argv);
     i64 normalized_index(i64 index, int size);
     Str disassemble(CodeObject_ co);
     void parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step);
+#endif
 
-    /********** name lookup **********/
+#if PK_REGION("Name Lookup Methods")
     PyObject* find_name_in_mro(Type cls, StrName name);
+    PyObject* get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err=true, bool fallback=false);
     PyObject* getattr(PyObject* obj, StrName name, bool throw_err=true);
     void delattr(PyObject* obj, StrName name);
-    PyObject* get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err=true, bool fallback=false);
     void setattr(PyObject* obj, StrName name, PyObject* value);
+#endif
 
-    /********** execution **********/
+#if PK_REGION("Source Execution Methods")
     CodeObject_ compile(std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope=false);
     Str precompile(std::string_view source, const Str& filename, CompileMode mode);
     PyObject* exec(std::string_view source, Str filename, CompileMode mode, PyObject* _module=nullptr);
@@ -232,8 +237,9 @@ public:
         callstack.emplace(s_data._sp, std::forward<Args>(args)...);
         return __run_top_frame();
     }
+#endif
 
-    /********** invocation **********/
+#if PK_REGION("Invocation Methods")
     PyObject* vectorcall(int ARGC, int KWARGC=0, bool op_call=false);
 
     template<typename... Args>
@@ -255,12 +261,14 @@ public:
         PyObject* callable = get_unbound_method(self, name, &self);
         return call_method(self, callable, args...);
     }
+#endif
 
-    /********** io **********/
+#if PK_REGION("Logging Methods")
     virtual void stdout_write(const Str& s){ _stdout(s.data, s.size); }
     virtual void stderr_write(const Str& s){ _stderr(s.data, s.size); }
+#endif
 
-    /********** bindings **********/
+#if PK_REGION("Magic Bindings")
     void bind__repr__(Type type, PyObject* (*f)(VM*, PyObject*));
     void bind__str__(Type type, PyObject* (*f)(VM*, PyObject*));
     void bind__iter__(Type type, PyObject* (*f)(VM*, PyObject*));
@@ -296,7 +304,9 @@ public:
     void bind__getitem__(Type type, PyObject* (*f)(VM*, PyObject*, PyObject*));
     void bind__setitem__(Type type, void (*f)(VM*, PyObject*, PyObject*, PyObject*));
     void bind__delitem__(Type type, void (*f)(VM*, PyObject*, PyObject*));
-    // new style binding api
+#endif
+
+#if PK_REGION("General Bindings")
     PyObject* bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, UserData userdata={}, BindType bt=BindType::DEFAULT);
     PyObject* bind_func(Type type, StrName name, int argc, NativeFuncC fn, UserData userdata={}, BindType bt=BindType::DEFAULT){
         return bind_func(_t(type), name, argc, fn, userdata, bt);
@@ -304,19 +314,21 @@ public:
     PyObject* bind_property(PyObject*, const char*, NativeFuncC fget, NativeFuncC fset=nullptr);
     template<typename T, typename F, bool ReadOnly=false>
     PyObject* bind_field(PyObject*, const char*, F T::*);
-    // without docstring
+
     PyObject* bind(PyObject*, const char*, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT);
     template<typename Ret, typename... Params>
     PyObject* bind(PyObject*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
     template<typename Ret, typename T, typename... Params>
     PyObject* bind(PyObject*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
-    // with docstring
+
     PyObject* bind(PyObject*, const char*, const char*, NativeFuncC, UserData userdata={}, BindType bt=BindType::DEFAULT);
     template<typename Ret, typename... Params>
     PyObject* bind(PyObject*, const char*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
     template<typename Ret, typename T, typename... Params>
     PyObject* bind(PyObject*, const char*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
-    /********** error **********/
+#endif
+
+#if PK_REGION("Error Reporting Methods")
     void _error(PyObject*);
     void StackOverflowError() { __builtin_error("StackOverflowError"); }
     void IOError(const Str& msg) { __builtin_error("IOError", msg); }
@@ -337,10 +349,9 @@ public:
     void BinaryOptError(const char* op, PyObject* _0, PyObject* _1);
     void AttributeError(PyObject* obj, StrName name);
     void AttributeError(const Str& msg){ __builtin_error("AttributeError", msg); }
+#endif
 
-    /********** type **********/
-    PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled=true);
-    const PyTypeInfo* _inst_type_info(PyObject* obj);
+#if PK_REGION("Type Checking Methods")
     bool isinstance(PyObject* obj, Type base);
     bool issubclass(Type cls, Type base);
     void check_type(PyObject* obj, Type type){ if(!is_type(obj, type)) TypeError(type, _tp(obj)); }
@@ -348,8 +359,10 @@ public:
     PyObject* _t(PyObject* obj){ return _all_types[_tp(obj)].obj; }
     PyObject* _t(Type t){ return _all_types[t.index].obj; }
     Type _tp(PyObject* obj){ return is_small_int(obj) ? tp_int : obj->type; }
+    const PyTypeInfo* _tp_info(PyObject* obj);
+#endif
 
-    /********** user type **********/
+#if PK_REGION("User Type Registration")
     template<typename T>
     Type _tp_user(){ return _find_type_in_cxx_typeid_map<T>(); }
     template<typename T>
@@ -379,6 +392,7 @@ public:
         }
         return it->second;
     }
+#endif
 
     /********** private **********/
     virtual ~VM();

+ 13 - 13
src/ceval.cpp

@@ -17,7 +17,7 @@ namespace pkpy{
 
 #define BINARY_F_COMPARE(func, op, rfunc)                           \
         PyObject* ret;                                              \
-        const PyTypeInfo* _ti = _inst_type_info(_0);                \
+        const PyTypeInfo* _ti = _tp_info(_0);                \
         if(_ti->m##func){                               \
             ret = _ti->m##func(this, _0, _1);           \
         }else{                                          \
@@ -48,7 +48,7 @@ void VM::__op_unpack_sequence(uint16_t arg){
     }else{
         auto _lock = heap.gc_scope_lock();  // lock the gc via RAII!!
         _0 = py_iter(_0);
-        const PyTypeInfo* ti = _inst_type_info(_0);
+        const PyTypeInfo* ti = _tp_info(_0);
         for(int i=0; i<arg; i++){
             PyObject* _1 = _py_next(ti, _0);
             if(_1 == StopIteration) ValueError("not enough values to unpack");
@@ -224,7 +224,7 @@ __NEXT_STEP:;
     case OP_LOAD_SUBSCR:{
         PyObject* _1 = POPX();    // b
         PyObject* _0 = TOP();     // a
-        auto _ti = _inst_type_info(_0);
+        auto _ti = _tp_info(_0);
         if(_ti->m__getitem__){
             TOP() = _ti->m__getitem__(this, _0, _1);
         }else{
@@ -235,7 +235,7 @@ __NEXT_STEP:;
         PyObject* _1 = frame->_locals[byte.arg];
         if(_1 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
         PyObject* _0 = TOP();     // a
-        auto _ti = _inst_type_info(_0);
+        auto _ti = _tp_info(_0);
         if(_ti->m__getitem__){
             TOP() = _ti->m__getitem__(this, _0, _1);
         }else{
@@ -245,7 +245,7 @@ __NEXT_STEP:;
     case OP_LOAD_SUBSCR_SMALL_INT:{
         PyObject* _1 = (PyObject*)(uintptr_t)byte.arg;
         PyObject* _0 = TOP();     // a
-        auto _ti = _inst_type_info(_0);
+        auto _ti = _tp_info(_0);
         if(_ti->m__getitem__){
             TOP() = _ti->m__getitem__(this, _0, _1);
         }else{
@@ -279,7 +279,7 @@ __NEXT_STEP:;
         PyObject* _2 = POPX();        // b
         PyObject* _1 = POPX();        // a
         PyObject* _0 = POPX();        // val
-        auto _ti = _inst_type_info(_1);
+        auto _ti = _tp_info(_1);
         if(_ti->m__setitem__){
             _ti->m__setitem__(this, _1, _2, _0);
         }else{
@@ -291,7 +291,7 @@ __NEXT_STEP:;
         if(_2 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
         PyObject* _1 = POPX();        // a
         PyObject* _0 = POPX();        // val
-        auto _ti = _inst_type_info(_1);
+        auto _ti = _tp_info(_1);
         if(_ti->m__setitem__){
             _ti->m__setitem__(this, _1, _2, _0);
         }else{
@@ -324,7 +324,7 @@ __NEXT_STEP:;
     case OP_DELETE_SUBSCR:{
         PyObject* _1 = POPX();
         PyObject* _0 = POPX();
-        auto _ti = _inst_type_info(_0);
+        auto _ti = _tp_info(_0);
         if(_ti->m__delitem__){
             _ti->m__delitem__(this, _0, _1);
         }else{
@@ -423,7 +423,7 @@ __NEXT_STEP:;
     } DISPATCH()
     /*****************************************/
 #define BINARY_OP_SPECIAL(func)                         \
-        _ti = _inst_type_info(_0);                      \
+        _ti = _tp_info(_0);                      \
         if(_ti->m##func){                               \
             TOP() = _ti->m##func(this, _0, _1);         \
         }else{                                          \
@@ -589,7 +589,7 @@ __NEXT_STEP:;
     } DISPATCH()
     case OP_CONTAINS_OP:{
         // a in b -> b __contains__ a
-        auto _ti = _inst_type_info(TOP());
+        auto _ti = _tp_info(TOP());
         PyObject* _0;
         if(_ti->m__contains__){
             _0 = _ti->m__contains__(this, TOP(), SECOND());
@@ -749,7 +749,7 @@ __NEXT_STEP:;
         DISPATCH()
     case OP_UNARY_INVERT:{
         PyObject* _0;
-        auto _ti = _inst_type_info(TOP());
+        auto _ti = _tp_info(TOP());
         if(_ti->m__invert__) _0 = _ti->m__invert__(this, TOP());
         else _0 = call_method(TOP(), __invert__);
         TOP() = _0;
@@ -790,7 +790,7 @@ __NEXT_STEP:;
     } DISPATCH()
     case OP_FOR_ITER_UNPACK:{
         PyObject* _0 = TOP();
-        const PyTypeInfo* _ti = _inst_type_info(_0);
+        const PyTypeInfo* _ti = _tp_info(_0);
         if(_ti->m__next__){
             unsigned n = _ti->m__next__(this, _0);
             if(n == 0){
@@ -850,7 +850,7 @@ __NEXT_STEP:;
     case OP_UNPACK_EX: {
         auto _lock = heap.gc_scope_lock();  // lock the gc via RAII!!
         PyObject* _0 = py_iter(POPX());
-        const PyTypeInfo* _ti = _inst_type_info(_0);
+        const PyTypeInfo* _ti = _tp_info(_0);
         PyObject* _1;
         for(int i=0; i<byte.arg; i++){
             _1 = _py_next(_ti, _0);

+ 1 - 1
src/dataclasses.cpp

@@ -104,7 +104,7 @@ void add_module_dataclasses(VM* vm){
     });
 
     vm->bind_func(mod, "asdict", 1, [](VM* vm, ArgsView args){
-        const auto& fields = vm->_inst_type_info(args[0])->annotated_fields;
+        const auto& fields = vm->_tp_info(args[0])->annotated_fields;
         const NameDict& obj_d = args[0]->attr();
         Dict d(vm);
         for(StrName field: fields){

+ 3 - 3
src/pocketpy.cpp

@@ -249,7 +249,7 @@ void __init_builtins(VM* _vm) {
     });
 
     _vm->bind_func(_vm->builtins, "len", 1, [](VM* vm, ArgsView args){
-        const PyTypeInfo* ti = vm->_inst_type_info(args[0]);
+        const PyTypeInfo* ti = vm->_tp_info(args[0]);
         if(ti->m__len__) return VAR(ti->m__len__(vm, args[0]));
         return vm->call_method(args[0], __len__);
     });
@@ -691,7 +691,7 @@ void __init_builtins(VM* _vm) {
         const Str& self = _CAST(Str&, args[0]);
         SStream ss;
         PyObject* it = vm->py_iter(args[1]);     // strong ref
-        const PyTypeInfo* info = vm->_inst_type_info(args[1]);
+        const PyTypeInfo* info = vm->_tp_info(args[1]);
         PyObject* obj = vm->_py_next(info, it);
         while(obj != vm->StopIteration){
             if(!ss.empty()) ss << self;
@@ -913,7 +913,7 @@ void __init_builtins(VM* _vm) {
         auto _lock = vm->heap.gc_scope_lock();
         List& self = _CAST(List&, args[0]);
         PyObject* it = vm->py_iter(args[1]);     // strong ref
-        const PyTypeInfo* info = vm->_inst_type_info(args[1]);
+        const PyTypeInfo* info = vm->_tp_info(args[1]);
         PyObject* obj = vm->_py_next(info, it);
         while(obj != vm->StopIteration){
             self.push_back(obj);

+ 12 - 12
src/vm.cpp

@@ -84,7 +84,7 @@ namespace pkpy{
     }
 
     PyObject* VM::py_str(PyObject* obj){
-        const PyTypeInfo* ti = _inst_type_info(obj);
+        const PyTypeInfo* ti = _tp_info(obj);
         if(ti->m__str__) return ti->m__str__(this, obj);
         PyObject* self;
         PyObject* f = get_unbound_method(obj, __str__, &self, false);
@@ -93,7 +93,7 @@ namespace pkpy{
     }
 
     PyObject* VM::py_repr(PyObject* obj){
-        const PyTypeInfo* ti = _inst_type_info(obj);
+        const PyTypeInfo* ti = _tp_info(obj);
         if(ti->m__repr__) return ti->m__repr__(this, obj);
         return call_method(obj, __repr__);
     }
@@ -104,7 +104,7 @@ namespace pkpy{
     }
 
     PyObject* VM::py_iter(PyObject* obj){
-        const PyTypeInfo* ti = _inst_type_info(obj);
+        const PyTypeInfo* ti = _tp_info(obj);
         if(ti->m__iter__) return ti->m__iter__(this, obj);
         PyObject* self;
         PyObject* iter_f = get_unbound_method(obj, __iter__, &self, false);
@@ -212,14 +212,14 @@ namespace pkpy{
         return obj;
     }
 
-    const PyTypeInfo* VM::_inst_type_info(PyObject* obj){
+    const PyTypeInfo* VM::_tp_info(PyObject* obj){
         if(is_small_int(obj)) return &_all_types[tp_int];
         return &_all_types[obj->type];
     }
 
     bool VM::py_eq(PyObject* lhs, PyObject* rhs){
         if(lhs == rhs) return true;
-        const PyTypeInfo* ti = _inst_type_info(lhs);
+        const PyTypeInfo* ti = _tp_info(lhs);
         PyObject* res;
         if(ti->m__eq__){
             res = ti->m__eq__(this, lhs, rhs);
@@ -228,7 +228,7 @@ namespace pkpy{
         res = call_method(lhs, __eq__, rhs);
         if(res != vm->NotImplemented) return res == vm->True;
 
-        ti = _inst_type_info(rhs);
+        ti = _tp_info(rhs);
         if(ti->m__eq__){
             res = ti->m__eq__(this, rhs, lhs);
             if(res != vm->NotImplemented) return res == vm->True;
@@ -255,7 +255,7 @@ namespace pkpy{
     }
 
     PyObject* VM::py_next(PyObject* obj){
-        const PyTypeInfo* ti = _inst_type_info(obj);
+        const PyTypeInfo* ti = _tp_info(obj);
         return _py_next(ti, obj);
     }
 
@@ -394,7 +394,7 @@ namespace pkpy{
     }
 
 PyObject* VM::py_negate(PyObject* obj){
-    const PyTypeInfo* ti = _inst_type_info(obj);
+    const PyTypeInfo* ti = _tp_info(obj);
     if(ti->m__neg__) return ti->m__neg__(this, obj);
     return call_method(obj, __neg__);
 }
@@ -418,7 +418,7 @@ List VM::py_list(PyObject* it){
     auto _lock = heap.gc_scope_lock();
     it = py_iter(it);
     List list;
-    const PyTypeInfo* info = _inst_type_info(it);
+    const PyTypeInfo* info = _tp_info(it);
     PyObject* obj = _py_next(info, it);
     while(obj != StopIteration){
         list.push_back(obj);
@@ -473,7 +473,7 @@ void VM::parse_int_slice(const Slice& s, int length, int& start, int& stop, int&
 
 i64 VM::py_hash(PyObject* obj){
     // https://docs.python.org/3.10/reference/datamodel.html#object.__hash__
-    const PyTypeInfo* ti = _inst_type_info(obj);
+    const PyTypeInfo* ti = _tp_info(obj);
     if(ti->m__hash__) return ti->m__hash__(this, obj);
 
     PyObject* self;
@@ -814,7 +814,7 @@ void VM::__unpack_as_list(ArgsView args, List& list){
             // maybe this check should be done in the compile time
             if(w.level != 1) TypeError("expected level 1 star wrapper");
             PyObject* _0 = py_iter(w.obj);
-            const PyTypeInfo* info = _inst_type_info(_0);
+            const PyTypeInfo* info = _tp_info(_0);
             PyObject* _1 = _py_next(info, _0);
             while(_1 != StopIteration){
                 list.push_back(_1);
@@ -1048,7 +1048,7 @@ PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
 }
 
 void VM::delattr(PyObject *_0, StrName _name){
-    const PyTypeInfo* ti = _inst_type_info(_0);
+    const PyTypeInfo* ti = _tp_info(_0);
     if(ti->m__delattr__ && ti->m__delattr__(this, _0, _name)) return;
     if(is_tagged(_0) || !_0->is_attr_valid()) TypeError("cannot delete attribute");
     if(!_0->attr().del(_name)) AttributeError(_0, _name);