This commit is contained in:
blueloveTH 2024-08-04 22:31:33 +08:00
parent 9c173fdada
commit a87641c04d
8 changed files with 141 additions and 37 deletions

View File

@ -123,6 +123,9 @@ py_Type pk_range_iterator__register();
py_Type pk_BaseException__register(); py_Type pk_BaseException__register();
py_Type pk_Exception__register(); py_Type pk_Exception__register();
py_Type pk_super__register(); py_Type pk_super__register();
py_Type pk_property__register();
py_Type pk_staticmethod__register();
py_Type pk_classmethod__register();
py_TValue pk_builtins__register(); py_TValue pk_builtins__register();

View File

@ -98,6 +98,7 @@ void py_newslice(py_Ref);
void py_newnativefunc(py_Ref out, py_CFunction); void py_newnativefunc(py_Ref out, py_CFunction);
py_Name py_Name
py_newfunction(py_Ref out, const char* sig, py_CFunction f, const char* docstring, int slots); py_newfunction(py_Ref out, const char* sig, py_CFunction f, const char* docstring, int slots);
void py_newboundmethod(py_Ref out, py_Ref self, py_Ref func);
/************* Name Convertions *************/ /************* Name Convertions *************/
py_Name py_name(const char*); py_Name py_name(const char*);

View File

@ -116,11 +116,11 @@ void VM__ctor(VM* self) {
validate(tp_dict, pk_dict__register()); validate(tp_dict, pk_dict__register());
validate(tp_dict_items, pk_dict_items__register()); validate(tp_dict_items, pk_dict_items__register());
validate(tp_property, pk_newtype("property", tp_object, NULL, NULL, false, true)); validate(tp_property, pk_property__register());
validate(tp_star_wrapper, pk_newtype("star_wrapper", tp_object, NULL, NULL, false, true)); validate(tp_star_wrapper, pk_newtype("star_wrapper", tp_object, NULL, NULL, false, true));
validate(tp_staticmethod, pk_newtype("staticmethod", tp_object, NULL, NULL, false, true)); validate(tp_staticmethod, pk_staticmethod__register());
validate(tp_classmethod, pk_newtype("classmethod", tp_object, NULL, NULL, false, true)); validate(tp_classmethod, pk_classmethod__register());
validate(tp_NoneType, pk_newtype("NoneType", tp_object, NULL, NULL, false, true)); validate(tp_NoneType, pk_newtype("NoneType", tp_object, NULL, NULL, false, true));
validate(tp_NotImplementedType, validate(tp_NotImplementedType,
@ -134,24 +134,11 @@ void VM__ctor(VM* self) {
self->builtins = pk_builtins__register(); self->builtins = pk_builtins__register();
/* Setup Public Builtin Types */ /* Setup Public Builtin Types */
py_Type public_types[] = {tp_object, py_Type public_types[] = {tp_object, tp_type, tp_int, tp_float,
tp_type, tp_bool, tp_str, tp_list, tp_tuple,
tp_int, tp_slice, tp_range, tp_bytes, tp_dict,
tp_float, tp_property, tp_staticmethod, tp_classmethod, tp_super,
tp_bool, tp_BaseException, tp_Exception, tp_StopIteration, tp_SyntaxError};
tp_str,
tp_list,
tp_tuple,
tp_slice,
tp_range,
tp_bytes,
tp_dict,
tp_property,
tp_super,
tp_BaseException,
tp_Exception,
tp_StopIteration,
tp_SyntaxError};
for(int i = 0; i < c11__count_array(public_types); i++) { for(int i = 0; i < c11__count_array(public_types); i++) {
py_Type t = public_types[i]; py_Type t = public_types[i];
@ -202,7 +189,8 @@ void VM__dtor(VM* self) {
// destroy all objects // destroy all objects
ManagedHeap__dtor(&self->heap); ManagedHeap__dtor(&self->heap);
// clear frames // clear frames
while(self->top_frame) VM__pop_frame(self); while(self->top_frame)
VM__pop_frame(self);
NameDict__dtor(&self->modules); NameDict__dtor(&self->modules);
c11__foreach(py_TypeInfo, &self->types, ti) py_TypeInfo__dtor(ti); c11__foreach(py_TypeInfo, &self->types, ti) py_TypeInfo__dtor(ti);
c11_vector__dtor(&self->types); c11_vector__dtor(&self->types);
@ -218,6 +206,7 @@ void VM__pop_frame(VM* self) {
assert(self->top_frame); assert(self->top_frame);
Frame* frame = self->top_frame; Frame* frame = self->top_frame;
// reset stack pointer // reset stack pointer
self->stack.sp = frame->p0; self->stack.sp = frame->p0;
// pop frame and delete // pop frame and delete
self->top_frame = frame->f_back; self->top_frame = frame->f_back;
@ -382,18 +371,14 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
// [callable, <self>, args..., kwargs...] // [callable, <self>, args..., kwargs...]
// ^p0 ^p1 ^_sp // ^p0 ^p1 ^_sp
#if 0
// handle boundmethod, do a patch // handle boundmethod, do a patch
if(p0->type == tp_boundmethod) { if(p0->type == tp_boundmethod) {
assert(py_isnil(p0 + 1)); // self must be NULL assert(py_isnil(p0 + 1)); // self must be NULL
// BoundMethod& bm = PK_OBJ_GET(BoundMethod, callable); py_TValue* slots = PyObject__slots(p0->_obj);
// callable = bm.func; // get unbound method p0[0] = slots[1]; // callable
// callable_t = _tp(callable); p0[1] = slots[0]; // self
// p1[-(ARGC + 2)] = bm.func;
// p1[-(ARGC + 1)] = bm.self;
// [unbound, self, args..., kwargs...] // [unbound, self, args..., kwargs...]
} }
#endif
py_Ref argv = py_isnil(p0 + 1) ? p0 + 2 : p0 + 1; py_Ref argv = py_isnil(p0 + 1) ? p0 + 2 : p0 + 1;

62
src/public/py_method.c Normal file
View File

@ -0,0 +1,62 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
/* staticmethod */
static bool staticmethod__new__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_newobject(py_retval(), tp_staticmethod, 1, 0);
py_setslot(py_retval(), 0, py_arg(1));
return true;
}
py_Type pk_staticmethod__register(){
py_Type type = pk_newtype("staticmethod", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __new__, staticmethod__new__);
return type;
}
/* classmethod */
static bool classmethod__new__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
py_newobject(py_retval(), tp_classmethod, 1, 0);
py_setslot(py_retval(), 0, py_arg(1));
return true;
}
py_Type pk_classmethod__register(){
py_Type type = pk_newtype("classmethod", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __new__, classmethod__new__);
return type;
}
/* boundmethod */
static bool boundmethod__new__(int argc, py_Ref argv) {
return NotImplementedError();
}
static bool boundmethod__self__getter(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_assign(py_retval(), py_getslot(argv, 0));
return true;
}
static bool boundmethod__func__getter(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_assign(py_retval(), py_getslot(argv, 1));
return true;
}
py_Type pk_boundmethod__register(){
py_Type type = pk_newtype("boundmethod", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __new__, boundmethod__new__);
py_bindproperty(type, "__self__", boundmethod__self__getter, NULL);
py_bindproperty(type, "__func__", boundmethod__func__getter, NULL);
return type;
}

View File

@ -68,8 +68,16 @@ static bool type__base__getter(int argc, py_Ref argv) {
return true; return true;
} }
static bool type__name__getter(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_Type type = py_totype(argv);
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
py_newstr(py_retval(), py_name2str(ti->name));
return true;
}
void pk_object__register() { void pk_object__register() {
// use staticmethod // TODO: use staticmethod
py_bindmagic(tp_object, __new__, object__new__); py_bindmagic(tp_object, __new__, object__new__);
py_bindmagic(tp_object, __hash__, object__hash__); py_bindmagic(tp_object, __hash__, object__hash__);
@ -77,9 +85,9 @@ void pk_object__register() {
py_bindmagic(tp_object, __ne__, object__ne__); py_bindmagic(tp_object, __ne__, object__ne__);
py_bindmagic(tp_object, __repr__, object__repr__); py_bindmagic(tp_object, __repr__, object__repr__);
// type patch...
py_bindmagic(tp_type, __repr__, type__repr__); py_bindmagic(tp_type, __repr__, type__repr__);
py_bindmagic(tp_type, __new__, type__new__); py_bindmagic(tp_type, __new__, type__new__);
py_bindproperty(tp_type, "__base__", type__base__getter, NULL); py_bindproperty(tp_type, "__base__", type__base__getter, NULL);
py_bindproperty(tp_type, "__name__", type__name__getter, NULL);
} }

View File

@ -113,8 +113,9 @@ bool py_getattr(py_Ref self, py_Name name) {
if(py_istype(res, tp_staticmethod)) { if(py_istype(res, tp_staticmethod)) {
res = py_getslot(res, 0); res = py_getslot(res, 0);
} else if(py_istype(res, tp_classmethod)) { } else if(py_istype(res, tp_classmethod)) {
// TODO: make a closure res = py_getslot(res, 0);
assert(false); py_newboundmethod(py_retval(), self, res);
return true;
} }
py_assign(py_retval(), res); py_assign(py_retval(), res);
return true; return true;
@ -125,10 +126,22 @@ bool py_getattr(py_Ref self, py_Name name) {
if(cls_var) { if(cls_var) {
// bound method is non-data descriptor // bound method is non-data descriptor
switch(cls_var->type) { switch(cls_var->type) {
case tp_function: assert(false); case tp_function: {
case tp_nativefunc: assert(false); py_newboundmethod(py_retval(), self, cls_var);
case tp_staticmethod: assert(false); return true;
case tp_classmethod: assert(false); }
case tp_nativefunc: {
py_newboundmethod(py_retval(), self, cls_var);
return true;
}
case tp_staticmethod: {
py_assign(py_retval(), py_getslot(cls_var, 0));
return true;
}
case tp_classmethod: {
py_newboundmethod(py_retval(), py_tpobject(type), py_getslot(cls_var, 0));
return true;
}
default: { default: {
py_assign(py_retval(), cls_var); py_assign(py_retval(), cls_var);
return true; return true;

26
src/public/py_property.c Normal file
View File

@ -0,0 +1,26 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
static bool property__new__(int argc, py_Ref argv) {
py_newobject(py_retval(), tp_property, 2, 0);
if(argc == 1 + 1) {
py_setslot(py_retval(), 0, py_arg(1));
py_setslot(py_retval(), 1, py_None);
} else if(argc == 1 + 2) {
py_setslot(py_retval(), 0, py_arg(1));
py_setslot(py_retval(), 1, py_arg(2));
} else {
return TypeError("property() expected 1 or 2 arguments, got %d", argc);
}
return true;
}
py_Type pk_property__register() {
py_Type type = pk_newtype("property", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __new__, property__new__);
return type;
}

View File

@ -101,6 +101,12 @@ py_Name
return py_name(ud->decl->code.name->data); return py_name(ud->decl->code.name->data);
} }
void py_newboundmethod(py_Ref out, py_Ref self, py_Ref func){
py_newobject(out, tp_boundmethod, 2, 0);
py_setslot(out, 0, self);
py_setslot(out, 1, func);
}
void* py_newobject(py_Ref out, py_Type type, int slots, int udsize) { void* py_newobject(py_Ref out, py_Type type, int slots, int udsize) {
ManagedHeap* heap = &pk_current_vm->heap; ManagedHeap* heap = &pk_current_vm->heap;
PyObject* obj = ManagedHeap__gcnew(heap, type, slots, udsize); PyObject* obj = ManagedHeap__gcnew(heap, type, slots, udsize);