Compare commits

...

2 Commits

Author SHA1 Message Date
blueloveTH
eb5b84f21a clean up #defines 2024-11-24 14:47:05 +08:00
blueloveTH
4a8776ec6c add inspect module 2024-11-24 12:43:08 +08:00
23 changed files with 221 additions and 19 deletions

View File

@ -11,6 +11,8 @@ void pk__add_module_time();
void pk__add_module_easing(); void pk__add_module_easing();
void pk__add_module_traceback(); void pk__add_module_traceback();
void pk__add_module_enum(); void pk__add_module_enum();
void pk__add_module_inspect();
void pk__add_module_linalg(); void pk__add_module_linalg();
void pk__add_module_array2d(); void pk__add_module_array2d();

View File

@ -672,7 +672,7 @@ enum py_PredefinedTypes {
tp_module, tp_module,
tp_function, tp_function,
tp_nativefunc, tp_nativefunc,
tp_boundmethod, tp_boundmethod, // 2 slots (self, func)
tp_super, // 1 slot + py_Type tp_super, // 1 slot + py_Type
tp_BaseException, // 2 slots (arg + inner_exc) tp_BaseException, // 2 slots (arg + inner_exc)
tp_Exception, tp_Exception,

View File

@ -0,0 +1 @@
def isgeneratorfunction(obj) -> bool: ...

View File

@ -1,6 +1,6 @@
name: pocketpy name: pocketpy
description: A lightweight Python interpreter for game engines. It supports Android/iOS/Windows/Linux/MacOS. description: A lightweight Python interpreter for game engines. It supports Android/iOS/Windows/Linux/MacOS.
version: 2.0.1+8 version: 2.0.2
homepage: https://pocketpy.dev homepage: https://pocketpy.dev
repository: https://github.com/pocketpy/pocketpy repository: https://github.com/pocketpy/pocketpy

49
scripts/check_undef.py Normal file
View File

@ -0,0 +1,49 @@
import re
def check_define_undef_pairs(code):
# 使用正则表达式匹配#define和#undef指令
define_pattern = re.compile(r'#define\s+(\w+)')
undef_pattern = re.compile(r'#undef\s+(\w+)')
# 查找所有的#define和#undef
defines = define_pattern.findall(code)
undefs = undef_pattern.findall(code)
# 使用集合计算差集,找出不匹配的部分
define_set = set(defines)
undef_set = set(undefs)
unmatched_defines = define_set - undef_set
unmatched_undefs = undef_set - define_set
if unmatched_defines or unmatched_undefs:
if unmatched_defines:
print("mismatched #define")
for define in unmatched_defines:
print(f"- {define}")
if unmatched_undefs:
print("mismatched #undef")
for undef in unmatched_undefs:
print(f"- {undef}")
# iterate over all the files in `path` directory
import os
import sys
def check_undef_in_dir(path):
for root, dirs, files in os.walk(path):
for file in files:
if file.endswith(".c") or file.endswith(".h"):
with open(os.path.join(root, file), "r", encoding='utf-8') as f:
print(f"==> {os.path.join(root, file)}")
check_define_undef_pairs(f.read())
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python scripts/check_undef.py <path>")
sys.exit(1)
check_undef_in_dir(sys.argv[1])

View File

@ -322,3 +322,4 @@ void Pools_debug_info(char* buffer, int size) {
); );
} }
#undef LinkedList__apply

View File

@ -2866,3 +2866,26 @@ const static PrattRule rules[TK__COUNT__] = {
[TK_COLON] = { exprSlice0, exprSlice1, PREC_PRIMARY } [TK_COLON] = { exprSlice0, exprSlice1, PREC_PRIMARY }
}; };
// clang-format on // clang-format on
#undef static_assert_expr_size
#undef vtcall
#undef vtemit_
#undef vtemit_del
#undef vtemit_store
#undef vtemit_inplace
#undef vtemit_istore
#undef vtdelete
#undef EXPR_COMMON_HEADER
#undef is_compare_expr
#undef tk
#undef prev
#undef curr
#undef next
#undef advance
#undef mode
#undef ctx
#undef match_newlines
#undef consume
#undef consume_end_stmt
#undef check
#undef match

View File

@ -708,3 +708,4 @@ const char* TokenSymbols[] = {
"yield", "yield",
}; };
#undef is_raw_string_used

View File

@ -1351,3 +1351,20 @@ static bool stack_format_object(VM* self, c11_sv spec) {
c11_sbuf__py_submit(&buf, val); c11_sbuf__py_submit(&buf, val);
return true; return true;
} }
#undef CHECK_RETURN_FROM_EXCEPT_OR_FINALLY
#undef DISPATCH
#undef DISPATCH_JUMP
#undef DISPATCH_JUMP_ABSOLUTE
#undef TOP
#undef SECOND
#undef THIRD
#undef FOURTH
#undef STACK_SHRINK
#undef STACK_GROW
#undef PUSH
#undef POP
#undef POPX
#undef SP
#undef INSERT_THIRD
#undef vectorcall_opcall

View File

@ -39,3 +39,6 @@ void TypeList__apply(TypeList* self, void (*f)(py_TypeInfo*, void*), void* ctx)
f(info, ctx); f(info, ctx);
} }
} }
#undef CHUNK_SIZE
#undef LOG2_CHUNK_SIZE

View File

@ -215,6 +215,7 @@ void VM__ctor(VM* self) {
pk__add_module_easing(); pk__add_module_easing();
pk__add_module_traceback(); pk__add_module_traceback();
pk__add_module_enum(); pk__add_module_enum();
pk__add_module_inspect();
pk__add_module_conio(); pk__add_module_conio();
pk__add_module_pkpy(); pk__add_module_pkpy();

View File

@ -616,3 +616,6 @@ void pk__add_module_array2d() {
py_bindmethod(array2d, "find_bounding_rect", array2d_find_bounding_rect); py_bindmethod(array2d, "find_bounding_rect", array2d_find_bounding_rect);
py_bindmethod(array2d, "count_neighbors", array2d_count_neighbors); py_bindmethod(array2d, "count_neighbors", array2d_count_neighbors);
} }
#undef INC_COUNT
#undef HANDLE_SLICE

View File

@ -6,6 +6,7 @@
#include "pocketpy/interpreter/vm.h" #include "pocketpy/interpreter/vm.h"
static bool gc_collect(int argc, py_Ref argv){ static bool gc_collect(int argc, py_Ref argv){
PY_CHECK_ARGC(0);
ManagedHeap* heap = &pk_current_vm->heap; ManagedHeap* heap = &pk_current_vm->heap;
int res = ManagedHeap__collect(heap); int res = ManagedHeap__collect(heap);
py_newint(py_retval(), res); py_newint(py_retval(), res);

28
src/modules/inspect.c Normal file
View File

@ -0,0 +1,28 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/common/sstream.h"
#include "pocketpy/interpreter/vm.h"
static bool inspect_isgeneratorfunction(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_Ref obj = argv;
if(py_istype(argv, tp_boundmethod)) {
py_TValue* slots = PyObject__slots(argv->_obj);
obj = &slots[1]; // callable
}
if(py_istype(obj, tp_function)) {
Function* fn = py_touserdata(obj);
py_newbool(py_retval(), fn->decl->type == FuncType_GENERATOR);
} else {
py_newbool(py_retval(), false);
}
return true;
}
void pk__add_module_inspect() {
py_Ref mod = py_newmodule("inspect");
py_bindfunc(mod, "isgeneratorfunction", inspect_isgeneratorfunction);
}

View File

@ -987,3 +987,9 @@ void pk__add_module_linalg() {
{1, 1, 1} {1, 1, 1}
}); });
} }
#undef DEFINE_VEC_FIELD
#undef DEFINE_BOOL_NE
#undef DEF_VECTOR_ELEMENT_WISE
#undef DEF_VECTOR_OPS
#undef DEF_VECTOR_INT_OPS

View File

@ -199,3 +199,6 @@ void pk__add_module_math() {
py_bindfunc(mod, "modf", math_modf); py_bindfunc(mod, "modf", math_modf);
py_bindfunc(mod, "factorial", math_factorial); py_bindfunc(mod, "factorial", math_factorial);
} }
#undef ONE_ARG_FUNC
#undef TWO_ARG_FUNC

View File

@ -67,3 +67,5 @@ void pk__add_module_pkpy() {
py_setdict(mod, py_name("TValue"), TValue_dict); py_setdict(mod, py_name("TValue"), TValue_dict);
py_pop(); py_pop();
} }
#undef DEF_TVALUE_METHODS

View File

@ -303,3 +303,10 @@ __ERROR:
py_printexc(); py_printexc();
c11__abort("failed to add module random"); c11__abort("failed to add module random");
} }
#undef N
#undef M
#undef MATRIX_A
#undef UPPER_MASK
#undef LOWER_MASK
#undef ADD_INST_BOUNDMETHOD

View File

@ -104,3 +104,6 @@ void pk__add_module_time() {
py_bindfunc(mod, "sleep", time_sleep); py_bindfunc(mod, "sleep", time_sleep);
py_bindfunc(mod, "localtime", time_localtime); py_bindfunc(mod, "localtime", time_localtime);
} }
#undef NANOS_PER_SEC
#undef DEF_STRUCT_TIME__PROPERTY

View File

@ -167,7 +167,7 @@ static void Dict__compact_entries(Dict* self) {
} }
self->entries.length = n; self->entries.length = n;
// update indices // update indices
for(int i = 0; i < self->capacity; i++) { for(uint32_t i = 0; i < self->capacity; i++) {
for(int j = 0; j < PK_DICT_MAX_COLLISION; j++) { for(int j = 0; j < PK_DICT_MAX_COLLISION; j++) {
int idx = self->indices[i]._[j]; int idx = self->indices[i]._[j];
if(idx == -1) continue; if(idx == -1) continue;
@ -203,7 +203,7 @@ static bool Dict__set(Dict* self, py_TValue* key, py_TValue* val) {
if(res == -1) return false; // error if(res == -1) return false; // error
} }
// no empty slot found // no empty slot found
if(self->capacity >= self->entries.length * 10) { if(self->capacity >= (uint32_t)self->entries.length * 10) {
// raise error if we reach the minimum load factor (10%) // raise error if we reach the minimum load factor (10%)
return RuntimeError("dict has too much collision: %d/%d/%d", return RuntimeError("dict has too much collision: %d/%d/%d",
self->entries.length, self->entries.length,
@ -623,3 +623,5 @@ bool py_dict_apply(py_Ref self, bool (*f)(py_Ref, py_Ref, void*), void* ctx) {
} }
return true; return true;
} }
#undef PK_DICT_MAX_COLLISION

View File

@ -51,8 +51,6 @@ DEF_NUM_BINARY_OP(__le__, <=, py_newbool, py_newbool)
DEF_NUM_BINARY_OP(__gt__, >, py_newbool, py_newbool) DEF_NUM_BINARY_OP(__gt__, >, py_newbool, py_newbool)
DEF_NUM_BINARY_OP(__ge__, >=, py_newbool, py_newbool) DEF_NUM_BINARY_OP(__ge__, >=, py_newbool, py_newbool)
#undef DEF_NUM_BINARY_OP
static bool int__neg__(int argc, py_Ref argv) { static bool int__neg__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
py_i64 val = py_toint(&argv[0]); py_i64 val = py_toint(&argv[0]);
@ -203,8 +201,6 @@ DEF_INT_BITWISE_OP(__xor__, ^)
DEF_INT_BITWISE_OP(__lshift__, <<) DEF_INT_BITWISE_OP(__lshift__, <<)
DEF_INT_BITWISE_OP(__rshift__, >>) DEF_INT_BITWISE_OP(__rshift__, >>)
#undef DEF_INT_BITWISE_OP
static bool int__repr__(int argc, py_Ref argv) { static bool int__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
py_i64 val = py_toint(&argv[0]); py_i64 val = py_toint(&argv[0]);
@ -442,8 +438,6 @@ DEF_BOOL_BITWISE(__and__, &&)
DEF_BOOL_BITWISE(__or__, ||) DEF_BOOL_BITWISE(__or__, ||)
DEF_BOOL_BITWISE(__xor__, !=) DEF_BOOL_BITWISE(__xor__, !=)
#undef DEF_BOOL_BITWISE
void pk_number__register() { void pk_number__register() {
/****** tp_int & tp_float ******/ /****** tp_int & tp_float ******/
py_bindmagic(tp_int, __add__, int__add__); py_bindmagic(tp_int, __add__, int__add__);
@ -521,3 +515,7 @@ void pk_number__register() {
py_bindmagic(tp_bool, __or__, bool__or__); py_bindmagic(tp_bool, __or__, bool__or__);
py_bindmagic(tp_bool, __xor__, bool__xor__); py_bindmagic(tp_bool, __xor__, bool__xor__);
} }
#undef DEF_NUM_BINARY_OP
#undef DEF_INT_BITWISE_OP
#undef DEF_BOOL_BITWISE

View File

@ -680,3 +680,5 @@ bool py_str(py_Ref val) {
bool py_repr(py_Ref val) { return pk_callmagic(__repr__, 1, val); } bool py_repr(py_Ref val) { return pk_callmagic(__repr__, 1, val); }
bool py_len(py_Ref val) { return pk_callmagic(__len__, 1, val); } bool py_len(py_Ref val) { return pk_callmagic(__len__, 1, val); }
#undef DEF_STR_CMP_OP

49
tests/97_inspect.py Normal file
View File

@ -0,0 +1,49 @@
from inspect import isgeneratorfunction
def f(a, b):
return a + b
assert not isgeneratorfunction(f)
def g(a, b):
yield a
yield b
assert isgeneratorfunction(g)
class A:
@staticmethod
def non_gen(a, b):
return a + b
@staticmethod
def gen(a, b):
yield a
yield b
@classmethod
def non_gen_class(cls, a, b):
return a + b
@classmethod
def gen_class(cls, a, b):
yield a
yield b
def not_gen_instance(self, a, b):
return a + b
def gen_instance(self, a, b):
yield a
yield b
a = A()
assert not isgeneratorfunction(a.non_gen)
assert isgeneratorfunction(a.gen)
assert not isgeneratorfunction(A.non_gen)
assert isgeneratorfunction(A.gen)
assert not isgeneratorfunction(a.non_gen_class)
assert isgeneratorfunction(a.gen_class)
assert not isgeneratorfunction(A.non_gen_class)
assert isgeneratorfunction(A.gen_class)
assert not isgeneratorfunction(a.not_gen_instance)
assert isgeneratorfunction(a.gen_instance)
assert not isgeneratorfunction(A.not_gen_instance)
assert isgeneratorfunction(A.gen_instance)