mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 20:10:17 +00:00
...
This commit is contained in:
parent
9c173fdada
commit
a87641c04d
@ -123,6 +123,9 @@ py_Type pk_range_iterator__register();
|
||||
py_Type pk_BaseException__register();
|
||||
py_Type pk_Exception__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();
|
||||
|
||||
|
@ -98,6 +98,7 @@ void py_newslice(py_Ref);
|
||||
void py_newnativefunc(py_Ref out, py_CFunction);
|
||||
py_Name
|
||||
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 *************/
|
||||
py_Name py_name(const char*);
|
||||
|
@ -116,11 +116,11 @@ void VM__ctor(VM* self) {
|
||||
validate(tp_dict, pk_dict__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_staticmethod, pk_newtype("staticmethod", tp_object, NULL, NULL, false, true));
|
||||
validate(tp_classmethod, pk_newtype("classmethod", tp_object, NULL, NULL, false, true));
|
||||
validate(tp_staticmethod, pk_staticmethod__register());
|
||||
validate(tp_classmethod, pk_classmethod__register());
|
||||
|
||||
validate(tp_NoneType, pk_newtype("NoneType", tp_object, NULL, NULL, false, true));
|
||||
validate(tp_NotImplementedType,
|
||||
@ -134,24 +134,11 @@ void VM__ctor(VM* self) {
|
||||
self->builtins = pk_builtins__register();
|
||||
|
||||
/* Setup Public Builtin Types */
|
||||
py_Type public_types[] = {tp_object,
|
||||
tp_type,
|
||||
tp_int,
|
||||
tp_float,
|
||||
tp_bool,
|
||||
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};
|
||||
py_Type public_types[] = {tp_object, tp_type, tp_int, tp_float,
|
||||
tp_bool, tp_str, tp_list, tp_tuple,
|
||||
tp_slice, tp_range, tp_bytes, tp_dict,
|
||||
tp_property, tp_staticmethod, tp_classmethod, tp_super,
|
||||
tp_BaseException, tp_Exception, tp_StopIteration, tp_SyntaxError};
|
||||
|
||||
for(int i = 0; i < c11__count_array(public_types); i++) {
|
||||
py_Type t = public_types[i];
|
||||
@ -202,7 +189,8 @@ void VM__dtor(VM* self) {
|
||||
// destroy all objects
|
||||
ManagedHeap__dtor(&self->heap);
|
||||
// clear frames
|
||||
while(self->top_frame) VM__pop_frame(self);
|
||||
while(self->top_frame)
|
||||
VM__pop_frame(self);
|
||||
NameDict__dtor(&self->modules);
|
||||
c11__foreach(py_TypeInfo, &self->types, ti) py_TypeInfo__dtor(ti);
|
||||
c11_vector__dtor(&self->types);
|
||||
@ -218,6 +206,7 @@ void VM__pop_frame(VM* self) {
|
||||
assert(self->top_frame);
|
||||
Frame* frame = self->top_frame;
|
||||
// reset stack pointer
|
||||
|
||||
self->stack.sp = frame->p0;
|
||||
// pop frame and delete
|
||||
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...]
|
||||
// ^p0 ^p1 ^_sp
|
||||
|
||||
#if 0
|
||||
// handle boundmethod, do a patch
|
||||
if(p0->type == tp_boundmethod) {
|
||||
assert(py_isnil(p0 + 1)); // self must be NULL
|
||||
// BoundMethod& bm = PK_OBJ_GET(BoundMethod, callable);
|
||||
// callable = bm.func; // get unbound method
|
||||
// callable_t = _tp(callable);
|
||||
// p1[-(ARGC + 2)] = bm.func;
|
||||
// p1[-(ARGC + 1)] = bm.self;
|
||||
py_TValue* slots = PyObject__slots(p0->_obj);
|
||||
p0[0] = slots[1]; // callable
|
||||
p0[1] = slots[0]; // self
|
||||
// [unbound, self, args..., kwargs...]
|
||||
}
|
||||
#endif
|
||||
|
||||
py_Ref argv = py_isnil(p0 + 1) ? p0 + 2 : p0 + 1;
|
||||
|
||||
|
62
src/public/py_method.c
Normal file
62
src/public/py_method.c
Normal 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;
|
||||
}
|
@ -68,8 +68,16 @@ static bool type__base__getter(int argc, py_Ref argv) {
|
||||
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() {
|
||||
// use staticmethod
|
||||
// TODO: use staticmethod
|
||||
py_bindmagic(tp_object, __new__, object__new__);
|
||||
|
||||
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, __repr__, object__repr__);
|
||||
|
||||
// type patch...
|
||||
py_bindmagic(tp_type, __repr__, type__repr__);
|
||||
py_bindmagic(tp_type, __new__, type__new__);
|
||||
|
||||
py_bindproperty(tp_type, "__base__", type__base__getter, NULL);
|
||||
py_bindproperty(tp_type, "__name__", type__name__getter, NULL);
|
||||
}
|
@ -113,8 +113,9 @@ bool py_getattr(py_Ref self, py_Name name) {
|
||||
if(py_istype(res, tp_staticmethod)) {
|
||||
res = py_getslot(res, 0);
|
||||
} else if(py_istype(res, tp_classmethod)) {
|
||||
// TODO: make a closure
|
||||
assert(false);
|
||||
res = py_getslot(res, 0);
|
||||
py_newboundmethod(py_retval(), self, res);
|
||||
return true;
|
||||
}
|
||||
py_assign(py_retval(), res);
|
||||
return true;
|
||||
@ -125,10 +126,22 @@ bool py_getattr(py_Ref self, py_Name name) {
|
||||
if(cls_var) {
|
||||
// bound method is non-data descriptor
|
||||
switch(cls_var->type) {
|
||||
case tp_function: assert(false);
|
||||
case tp_nativefunc: assert(false);
|
||||
case tp_staticmethod: assert(false);
|
||||
case tp_classmethod: assert(false);
|
||||
case tp_function: {
|
||||
py_newboundmethod(py_retval(), self, cls_var);
|
||||
return true;
|
||||
}
|
||||
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: {
|
||||
py_assign(py_retval(), cls_var);
|
||||
return true;
|
||||
|
26
src/public/py_property.c
Normal file
26
src/public/py_property.c
Normal 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;
|
||||
}
|
@ -101,6 +101,12 @@ py_Name
|
||||
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) {
|
||||
ManagedHeap* heap = &pk_current_vm->heap;
|
||||
PyObject* obj = ManagedHeap__gcnew(heap, type, slots, udsize);
|
||||
|
Loading…
x
Reference in New Issue
Block a user