diff --git a/src/pocketpy.h b/src/pocketpy.h index 220ae1c4..9f063c26 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -88,22 +88,19 @@ void __initializeBuiltinFunctions(VM* _vm) { return vm->PyInt((i64)s[0]); }); - _vm->bindBuiltinFunc<0>("globals", [](VM* vm, const pkpy::ArgList& args) { - const auto& d = vm->top_frame()->f_globals(); - PyVar obj = vm->call(vm->builtins->attribs["dict"]); - for (const auto& [k, v] : d) { - vm->call(obj, __setitem__, pkpy::twoArgs(vm->PyStr(k), v)); - } - return obj; + _vm->bindBuiltinFunc<2>("hasattr", [](VM* vm, const pkpy::ArgList& args) { + return vm->PyBool(vm->getattr(args[0], vm->PyStr_AS_C(args[1]), false) != nullptr); }); - _vm->bindBuiltinFunc<0>("locals", [](VM* vm, const pkpy::ArgList& args) { - const auto& d = vm->top_frame()->f_locals(); - PyVar obj = vm->call(vm->builtins->attribs["dict"]); - for (const auto& [k, v] : d) { - vm->call(obj, __setitem__, pkpy::twoArgs(vm->PyStr(k), v)); - } - return obj; + _vm->bindBuiltinFunc<3>("setattr", [](VM* vm, const pkpy::ArgList& args) { + PyVar obj = args[0]; + vm->setattr(obj, vm->PyStr_AS_C(args[1]), args[2]); + return vm->None; + }); + + _vm->bindBuiltinFunc<2>("getattr", [](VM* vm, const pkpy::ArgList& args) { + _Str name = vm->PyStr_AS_C(args[1]); + return vm->getattr(args[0], name); }); _vm->bindBuiltinFunc<1>("hex", [](VM* vm, const pkpy::ArgList& args) { diff --git a/src/safestl.h b/src/safestl.h index fbf378be..ce34f5df 100644 --- a/src/safestl.h +++ b/src/safestl.h @@ -98,7 +98,6 @@ namespace pkpy { PyVar& operator[](uint8_t i){ return _args[i]; } const PyVar& operator[](uint8_t i) const { return _args[i]; } - // overload = for && ArgList& operator=(ArgList&& other) noexcept { if(this != &other){ __tryRelease(); diff --git a/src/vm.h b/src/vm.h index 4f1ccb4c..3f4ee5fb 100644 --- a/src/vm.h +++ b/src/vm.h @@ -644,15 +644,11 @@ public: return nullptr; } - template - void setattr(PyObject* obj, const _Str& name, T&& value) { - while(obj->is_type(_tp_super)) obj = ((Py_*)obj)->_valueT.get(); - obj->attribs[name] = value; - } - template inline void setattr(PyVar& obj, const _Str& name, T&& value) { - setattr(obj.get(), name, value); + PyObject* p = obj.get(); + while(p->is_type(_tp_super)) p = ((Py_*)p)->_valueT.get(); + p->attribs[name] = std::forward(value); } template diff --git a/tests/_reflection.py b/tests/_reflection.py new file mode 100644 index 00000000..9361f6d6 --- /dev/null +++ b/tests/_reflection.py @@ -0,0 +1,16 @@ +assert type(1) is int +assert type(1.0) is float +assert type(object) is type +assert type(type) is type + +assert hasattr(object, '__base__') +assert hasattr(1, '__add__') +assert hasattr(int, '__add__') + +assert type(1).__add__(1, 2) == 3 +assert getattr(1, '__add__')(2) == 3 + +a = {} +setattr(a, 'b', 1) +assert a.b == 1 +assert getattr(a, 'b') == 1 \ No newline at end of file