mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
add TValue[T]
This commit is contained in:
parent
bf208c3733
commit
35f973059c
@ -15,3 +15,4 @@ void pk__add_module_linalg();
|
|||||||
void pk__add_module_array2d();
|
void pk__add_module_array2d();
|
||||||
|
|
||||||
void pk__add_module_conio();
|
void pk__add_module_conio();
|
||||||
|
void pk__add_module_pkpy();
|
7
include/typings/pkpy.pyi
Normal file
7
include/typings/pkpy.pyi
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from typing import Self
|
||||||
|
|
||||||
|
class TValue[T]:
|
||||||
|
def __new__(cls, value: T) -> Self: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self) -> T: ...
|
@ -217,6 +217,7 @@ void VM__ctor(VM* self) {
|
|||||||
pk__add_module_enum();
|
pk__add_module_enum();
|
||||||
|
|
||||||
pk__add_module_conio();
|
pk__add_module_conio();
|
||||||
|
pk__add_module_pkpy();
|
||||||
|
|
||||||
// add python builtins
|
// add python builtins
|
||||||
do {
|
do {
|
||||||
|
69
src/modules/pkpy.c
Normal file
69
src/modules/pkpy.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include "pocketpy/pocketpy.h"
|
||||||
|
|
||||||
|
#include "pocketpy/common/utils.h"
|
||||||
|
#include "pocketpy/objects/object.h"
|
||||||
|
#include "pocketpy/common/sstream.h"
|
||||||
|
#include "pocketpy/interpreter/vm.h"
|
||||||
|
|
||||||
|
#define DEF_TVALUE_METHODS(T, Field) \
|
||||||
|
static bool TValue_##T##__new__(int argc, py_Ref argv) { \
|
||||||
|
PY_CHECK_ARGC(2); \
|
||||||
|
PY_CHECK_ARG_TYPE(0, tp_type); \
|
||||||
|
PY_CHECK_ARG_TYPE(1, tp_##T); \
|
||||||
|
*py_retval() = (py_TValue){ \
|
||||||
|
.type = py_totype(&argv[0]), \
|
||||||
|
.is_ptr = false, \
|
||||||
|
.Field = py_to##T(&argv[1]), \
|
||||||
|
}; \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
static bool TValue_##T##_value(int argc, py_Ref argv) { \
|
||||||
|
PY_CHECK_ARGC(1); \
|
||||||
|
py_new##T(py_retval(), argv->Field); \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
static bool TValue_##T##__repr__(int argc, py_Ref argv) { \
|
||||||
|
PY_CHECK_ARGC(1); \
|
||||||
|
py_newstr(py_retval(), "<TValue_" #T " object>"); \
|
||||||
|
return true; \
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF_TVALUE_METHODS(int, _i64)
|
||||||
|
DEF_TVALUE_METHODS(float, _f64)
|
||||||
|
DEF_TVALUE_METHODS(vec2, _vec2)
|
||||||
|
DEF_TVALUE_METHODS(vec2i, _vec2i)
|
||||||
|
|
||||||
|
void pk__add_module_pkpy() {
|
||||||
|
py_Ref mod = py_newmodule("pkpy");
|
||||||
|
|
||||||
|
py_Type ttype;
|
||||||
|
py_Ref TValue_dict = py_pushtmp();
|
||||||
|
py_newdict(TValue_dict);
|
||||||
|
|
||||||
|
ttype = pk_newtype("TValue_int", tp_object, mod, NULL, false, false);
|
||||||
|
py_bindmagic(ttype, __new__, TValue_int__new__);
|
||||||
|
py_bindmagic(ttype, __repr__, TValue_int__repr__);
|
||||||
|
py_bindproperty(ttype, "value", TValue_int_value, NULL);
|
||||||
|
py_dict_setitem(TValue_dict, py_tpobject(tp_int), py_tpobject(ttype));
|
||||||
|
|
||||||
|
ttype = pk_newtype("TValue_float", tp_object, mod, NULL, false, false);
|
||||||
|
py_bindmagic(ttype, __new__, TValue_float__new__);
|
||||||
|
py_bindmagic(ttype, __repr__, TValue_float__repr__);
|
||||||
|
py_bindproperty(ttype, "value", TValue_float_value, NULL);
|
||||||
|
py_dict_setitem(TValue_dict, py_tpobject(tp_float), py_tpobject(ttype));
|
||||||
|
|
||||||
|
ttype = pk_newtype("TValue_vec2", tp_object, mod, NULL, false, false);
|
||||||
|
py_bindmagic(ttype, __new__, TValue_vec2__new__);
|
||||||
|
py_bindmagic(ttype, __repr__, TValue_vec2__repr__);
|
||||||
|
py_bindproperty(ttype, "value", TValue_vec2_value, NULL);
|
||||||
|
py_dict_setitem(TValue_dict, py_tpobject(tp_vec2), py_tpobject(ttype));
|
||||||
|
|
||||||
|
ttype = pk_newtype("TValue_vec2i", tp_object, mod, NULL, false, false);
|
||||||
|
py_bindmagic(ttype, __new__, TValue_vec2i__new__);
|
||||||
|
py_bindmagic(ttype, __repr__, TValue_vec2i__repr__);
|
||||||
|
py_bindproperty(ttype, "value", TValue_vec2i_value, NULL);
|
||||||
|
py_dict_setitem(TValue_dict, py_tpobject(tp_vec2i), py_tpobject(ttype));
|
||||||
|
|
||||||
|
py_setdict(mod, py_name("TValue"), TValue_dict);
|
||||||
|
py_pop();
|
||||||
|
}
|
@ -12,7 +12,7 @@ static VM* pk_all_vm[16];
|
|||||||
static py_TValue _True, _False, _None, _NIL;
|
static py_TValue _True, _False, _None, _NIL;
|
||||||
|
|
||||||
void py_initialize() {
|
void py_initialize() {
|
||||||
if(pk_current_vm){
|
if(pk_current_vm) {
|
||||||
// c11__abort("py_initialize() can only be called once!");
|
// c11__abort("py_initialize() can only be called once!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -31,8 +31,11 @@ void py_initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
py_GlobalRef py_True() { return &_True; }
|
py_GlobalRef py_True() { return &_True; }
|
||||||
|
|
||||||
py_GlobalRef py_False() { return &_False; }
|
py_GlobalRef py_False() { return &_False; }
|
||||||
|
|
||||||
py_GlobalRef py_None() { return &_None; }
|
py_GlobalRef py_None() { return &_None; }
|
||||||
|
|
||||||
py_GlobalRef py_NIL() { return &_NIL; }
|
py_GlobalRef py_NIL() { return &_NIL; }
|
||||||
|
|
||||||
void py_finalize() {
|
void py_finalize() {
|
||||||
@ -59,7 +62,7 @@ void py_switchvm(int index) {
|
|||||||
pk_current_vm = pk_all_vm[index] = malloc(sizeof(VM));
|
pk_current_vm = pk_all_vm[index] = malloc(sizeof(VM));
|
||||||
memset(pk_current_vm, 0, sizeof(VM));
|
memset(pk_current_vm, 0, sizeof(VM));
|
||||||
VM__ctor(pk_all_vm[index]);
|
VM__ctor(pk_all_vm[index]);
|
||||||
}else{
|
} else {
|
||||||
pk_current_vm = pk_all_vm[index];
|
pk_current_vm = pk_all_vm[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,13 +81,9 @@ int py_currentvm() {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* py_getvmctx(){
|
void* py_getvmctx() { return pk_current_vm->ctx; }
|
||||||
return pk_current_vm->ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void py_setvmctx(void* ctx){
|
void py_setvmctx(void* ctx) { pk_current_vm->ctx = ctx; }
|
||||||
pk_current_vm->ctx = ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void py_sys_setargv(int argc, char** argv) {
|
void py_sys_setargv(int argc, char** argv) {
|
||||||
py_GlobalRef sys = py_getmodule("sys");
|
py_GlobalRef sys = py_getmodule("sys");
|
||||||
@ -161,11 +160,21 @@ bool py_pushmethod(py_Name name) {
|
|||||||
|
|
||||||
bool pk_loadmethod(py_StackRef self, py_Name name) {
|
bool pk_loadmethod(py_StackRef self, py_Name name) {
|
||||||
// NOTE: `out` and `out_self` may overlap with `self`
|
// NOTE: `out` and `out_self` may overlap with `self`
|
||||||
|
py_Type type;
|
||||||
|
|
||||||
if(name == __new__ && py_istype(self, tp_type)) {
|
if(name == __new__) {
|
||||||
// __new__ acts like a @staticmethod
|
// __new__ acts like a @staticmethod
|
||||||
// T.__new__(...)
|
if(py_istype(self, tp_type)) {
|
||||||
py_Ref cls_var = py_tpfindmagic(py_totype(self), name);
|
// T.__new__(...)
|
||||||
|
type = py_totype(self);
|
||||||
|
} else if(py_istype(self, tp_super)) {
|
||||||
|
// super().__new__(...)
|
||||||
|
type = *(py_Type*)py_touserdata(self);
|
||||||
|
} else {
|
||||||
|
// invalid usage of `__new__`
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
py_Ref cls_var = py_tpfindmagic(type, name);
|
||||||
if(cls_var) {
|
if(cls_var) {
|
||||||
self[0] = *cls_var;
|
self[0] = *cls_var;
|
||||||
self[1] = *py_NIL();
|
self[1] = *py_NIL();
|
||||||
@ -174,7 +183,6 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
py_Type type;
|
|
||||||
// handle super() proxy
|
// handle super() proxy
|
||||||
if(py_istype(self, tp_super)) {
|
if(py_istype(self, tp_super)) {
|
||||||
type = *(py_Type*)py_touserdata(self);
|
type = *(py_Type*)py_touserdata(self);
|
||||||
|
@ -87,11 +87,11 @@ int py_next(py_Ref val) {
|
|||||||
bool py_getattr(py_Ref self, py_Name name) {
|
bool py_getattr(py_Ref self, py_Name name) {
|
||||||
// https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
|
// https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
|
||||||
py_Type type = self->type;
|
py_Type type = self->type;
|
||||||
// handle super() proxy
|
// handle super() proxy (disabled)
|
||||||
if(py_istype(self, tp_super)) {
|
// if(py_istype(self, tp_super)) {
|
||||||
self = py_getslot(self, 0);
|
// self = py_getslot(self, 0);
|
||||||
type = *(py_Type*)py_touserdata(self);
|
// type = *(py_Type*)py_touserdata(self);
|
||||||
}
|
// }
|
||||||
|
|
||||||
py_Ref cls_var = py_tpfindname(type, name);
|
py_Ref cls_var = py_tpfindname(type, name);
|
||||||
if(cls_var) {
|
if(cls_var) {
|
||||||
@ -183,11 +183,11 @@ bool py_getattr(py_Ref self, py_Name name) {
|
|||||||
|
|
||||||
bool py_setattr(py_Ref self, py_Name name, py_Ref val) {
|
bool py_setattr(py_Ref self, py_Name name, py_Ref val) {
|
||||||
py_Type type = self->type;
|
py_Type type = self->type;
|
||||||
// handle super() proxy
|
// handle super() proxy (disabled)
|
||||||
if(py_istype(self, tp_super)) {
|
// if(py_istype(self, tp_super)) {
|
||||||
self = py_getslot(self, 0);
|
// self = py_getslot(self, 0);
|
||||||
type = *(py_Type*)py_touserdata(self);
|
// type = *(py_Type*)py_touserdata(self);
|
||||||
}
|
// }
|
||||||
|
|
||||||
py_Ref cls_var = py_tpfindname(type, name);
|
py_Ref cls_var = py_tpfindname(type, name);
|
||||||
if(cls_var) {
|
if(cls_var) {
|
||||||
|
@ -6,7 +6,7 @@ except ValueError:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# test some python magics
|
# test some python magics
|
||||||
class A:
|
class TestMagics:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.d = {}
|
self.d = {}
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ class A:
|
|||||||
def __delitem__(self, index):
|
def __delitem__(self, index):
|
||||||
del self.d[index]
|
del self.d[index]
|
||||||
|
|
||||||
a = A()
|
a = TestMagics()
|
||||||
a['1'] = 3
|
a['1'] = 3
|
||||||
assert '1' in a
|
assert '1' in a
|
||||||
assert '2' not in a
|
assert '2' not in a
|
||||||
@ -72,7 +72,21 @@ assert int(Number()) == 2
|
|||||||
assert round(Number()) == tuple()
|
assert round(Number()) == tuple()
|
||||||
assert round(Number(), 1) == (1,)
|
assert round(Number(), 1) == (1,)
|
||||||
|
|
||||||
|
class Z:
|
||||||
|
def __new__(cls, x):
|
||||||
|
return cls, x
|
||||||
|
|
||||||
|
class B(Z):
|
||||||
|
def __new__(cls, x):
|
||||||
|
return super().__new__(cls, x)
|
||||||
|
|
||||||
|
assert Z(1) == (Z, 1)
|
||||||
|
assert B(1) == (B, 1)
|
||||||
|
|
||||||
|
from pkpy import TValue
|
||||||
|
|
||||||
|
class fixed(TValue[int]):
|
||||||
|
def __new__(cls, value: str):
|
||||||
|
return super().__new__(cls, int(value))
|
||||||
|
|
||||||
|
assert fixed('123').value == 123
|
||||||
|
Loading…
x
Reference in New Issue
Block a user