diff --git a/src/cffi.h b/src/cffi.h index a9939502..d565d4a7 100644 --- a/src/cffi.h +++ b/src/cffi.h @@ -269,28 +269,56 @@ struct Pointer{ }; -struct Struct { - PY_CLASS(Struct, c, struct_) +struct Value { + PY_CLASS(Value, c, value_) char* data; Pointer head; const TypeInfo* ctype() const { return head.ctype; } - Struct(const Pointer& head) { - data = new char[head.ctype->size]; - memcpy(data, head.ptr, head.ctype->size); - this->head = Pointer(head.ctype, head.level, data); + Value(const TypeInfo* type) { + data = new char[type->size]; + memset(data, 0, type->size); + this->head = Pointer(type, data); } static void _register(VM* vm, PyVar mod, PyVar type){ vm->bind_static_method<-1>(type, "__new__", CPP_NOT_IMPLEMENTED()); - vm->bind_method<0>(type, "__repr__", [](VM* vm, Args& args) { - Struct& self = CAST(Struct&, args[0]); - StrStream ss; - ss << self.ctype()->name << "(" << ")"; - return VAR(ss.str()); + vm->bind_method<0>(type, "ptr", [](VM* vm, Args& args) { + Value& self = CAST(Value&, args[0]); + return VAR_T(Pointer, self.head); + }); + + vm->bind_method<1>(type, "__getattr__", [](VM* vm, Args& args) { + Value& self = CAST(Value&, args[0]); + const Str& name = CAST(Str&, args[1]); + return self.head._to(vm, name).get(vm); + }); + } +}; + + +struct CType{ + PY_CLASS(CType, c, ctype) + + const TypeInfo* type; + + CType() : type(&_type_infos["void"]) {} + CType(const TypeInfo* type) : type(type) {} + + static void _register(VM* vm, PyVar mod, PyVar type){ + vm->bind_static_method<1>(type, "__new__", [](VM* vm, Args& args) { + const Str& name = CAST(Str&, args[0]); + auto it = _type_infos.find(name); + if (it == _type_infos.end()) vm->TypeError("unknown type: " + name.escape(true)); + return VAR_T(CType, &it->second); + }); + + vm->bind_method<0>(type, "__call__", [](VM* vm, Args& args) { + CType& self = CAST(CType&, args[0]); + return VAR_T(Value, self.type); }); } }; @@ -298,7 +326,8 @@ struct Struct { void add_module_c(VM* vm){ PyVar mod = vm->new_module("c"); PyVar ptr_t = Pointer::register_class(vm, mod); - Struct::register_class(vm, mod); + Value::register_class(vm, mod); + CType::register_class(vm, mod); vm->setattr(mod, "nullptr", VAR_T(Pointer)); diff --git a/src/str.h b/src/str.h index 89d5a494..0364eb0d 100644 --- a/src/str.h +++ b/src/str.h @@ -204,6 +204,7 @@ const StrName __len__ = StrName::get("__len__"); const StrName __get__ = StrName::get("__get__"); const StrName __getattr__ = StrName::get("__getattr__"); const StrName __setattr__ = StrName::get("__setattr__"); +const StrName __call__ = StrName::get("__call__"); const StrName m_eval = StrName::get("eval"); const StrName m_self = StrName::get("self"); diff --git a/src/vm.h b/src/vm.h index 4124748c..0692f3cd 100644 --- a/src/vm.h +++ b/src/vm.h @@ -736,6 +736,11 @@ PyVar VM::call(const PyVar& _callable, Args args, const Args& kwargs, bool opCal if(opCall) return _py_op_call; return _exec(); } + + PyVarOrNull call_f = getattr(_callable, __call__, false, true); + if(call_f != nullptr){ + return call(call_f, std::move(args), kwargs, false); + } TypeError(OBJ_NAME(_t(*callable)).escape(true) + " object is not callable"); return None; } @@ -795,9 +800,12 @@ PyVarOrNull VM::getattr(const PyVar& obj, StrName name, bool throw_err, bool cla } }else{ // this operation is expensive!!! - PyVar* interceptor = cls->attr().try_get(__getattr__); - if(interceptor != nullptr){ - return call(*interceptor, two_args(obj, VAR(name.str()))); + const Str& s = name.str(); + if(s.empty() || s[0] != '_'){ + PyVar* interceptor = cls->attr().try_get(__getattr__); + if(interceptor != nullptr){ + return call(*interceptor, two_args(obj, VAR(s))); + } } } cls = cls->attr(__base__).get();