mirror of
				https://github.com/pocketpy/pocketpy
				synced 2025-11-04 10:40:19 +00:00 
			
		
		
		
	Compare commits
	
		
			7 Commits
		
	
	
		
			11f709b768
			...
			e51f86c599
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					e51f86c599 | ||
| 
						 | 
					7263550fc1 | ||
| 
						 | 
					f1c969fe76 | ||
| 
						 | 
					f73ebd1f62 | ||
| 
						 | 
					ec4ddc41fb | ||
| 
						 | 
					0572a8f66b | ||
| 
						 | 
					0af8b4c7d2 | 
@ -10,3 +10,4 @@ void pk__add_module_json();
 | 
			
		||||
void pk__add_module_gc();
 | 
			
		||||
void pk__add_module_time();
 | 
			
		||||
void pk__add_module_easing();
 | 
			
		||||
void pk__add_module_traceback();
 | 
			
		||||
@ -126,6 +126,7 @@ py_Type pk_array_iterator__register();
 | 
			
		||||
py_Type pk_slice__register();
 | 
			
		||||
py_Type pk_function__register();
 | 
			
		||||
py_Type pk_nativefunc__register();
 | 
			
		||||
py_Type pk_boundmethod__register();
 | 
			
		||||
py_Type pk_range__register();
 | 
			
		||||
py_Type pk_range_iterator__register();
 | 
			
		||||
py_Type pk_BaseException__register();
 | 
			
		||||
 | 
			
		||||
@ -13,71 +13,93 @@ extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/************* Public Types *************/
 | 
			
		||||
 | 
			
		||||
/// A opaque type that represents a python object. You cannot access its members directly.
 | 
			
		||||
typedef struct py_TValue py_TValue;
 | 
			
		||||
/// An integer that represents a python identifier. This is to achieve string pooling and fast name
 | 
			
		||||
/// resolution.
 | 
			
		||||
typedef uint16_t py_Name;
 | 
			
		||||
/// An integer that represents a python type. `0` is invalid.
 | 
			
		||||
typedef int16_t py_Type;
 | 
			
		||||
 | 
			
		||||
/// A 64-bit integer type. Corresponds to `int` in python.
 | 
			
		||||
typedef int64_t py_i64;
 | 
			
		||||
/// A 64-bit floating-point type. Corresponds to `float` in python.
 | 
			
		||||
typedef double py_f64;
 | 
			
		||||
 | 
			
		||||
/// A generic destructor function.
 | 
			
		||||
typedef void (*py_Dtor)(void*);
 | 
			
		||||
 | 
			
		||||
#define PY_RAISE   // mark a function that can raise an exception
 | 
			
		||||
#define PY_RETURN  // mark a function that can modify `py_retval()` on success
 | 
			
		||||
 | 
			
		||||
/// A string view type. It is helpful for passing strings which are not null-terminated.
 | 
			
		||||
typedef struct c11_sv {
 | 
			
		||||
    const char* data;
 | 
			
		||||
    int size;
 | 
			
		||||
} c11_sv;
 | 
			
		||||
 | 
			
		||||
/// Generic reference.
 | 
			
		||||
/// Mark a function that can raise an exception.
 | 
			
		||||
/// + If the function returns `bool`, then `false` means an exception is raised.
 | 
			
		||||
/// + If the function returns `int`, then `-1` means an exception is raised.
 | 
			
		||||
#define PY_RAISE
 | 
			
		||||
/// Mark a function that returns a value by `py_retval()` on success.
 | 
			
		||||
#define PY_RETURN
 | 
			
		||||
 | 
			
		||||
/// A generic reference to a python object.
 | 
			
		||||
typedef py_TValue* py_Ref;
 | 
			
		||||
/// An object reference which has the same lifespan as the object.
 | 
			
		||||
/// A reference which has the same lifespan as the python object.
 | 
			
		||||
typedef py_TValue* py_ObjectRef;
 | 
			
		||||
/// A global reference which has the same lifespan as the VM.
 | 
			
		||||
typedef py_TValue* py_GlobalRef;
 | 
			
		||||
/// A specific location in the stack.
 | 
			
		||||
/// A specific location in the value stack of the VM.
 | 
			
		||||
typedef py_TValue* py_StackRef;
 | 
			
		||||
/// An item of a container. It invalidates after the container is modified.
 | 
			
		||||
/// An item reference to a container object. It invalidates when the container is modified.
 | 
			
		||||
typedef py_TValue* py_ItemRef;
 | 
			
		||||
 | 
			
		||||
/// Native function signature.
 | 
			
		||||
/// @param argc number of arguments.
 | 
			
		||||
/// @param argv array of arguments. Use `py_arg(i)` macro to get the i-th argument.
 | 
			
		||||
/// @return true if the function is successful.
 | 
			
		||||
/// @return `true` if the function is successful or `false` if an exception is raised.
 | 
			
		||||
typedef bool (*py_CFunction)(int argc, py_StackRef argv) PY_RAISE PY_RETURN;
 | 
			
		||||
 | 
			
		||||
/// Python compiler modes.
 | 
			
		||||
/// + `EXEC_MODE`: for statements.
 | 
			
		||||
/// + `EVAL_MODE`: for expressions.
 | 
			
		||||
/// + `SINGLE_MODE`: for REPL or jupyter notebook execution.
 | 
			
		||||
enum py_CompileMode { EXEC_MODE, EVAL_MODE, SINGLE_MODE };
 | 
			
		||||
 | 
			
		||||
/// A shorthand for `True`.
 | 
			
		||||
extern py_GlobalRef py_True;
 | 
			
		||||
/// A shorthand for `False`.
 | 
			
		||||
extern py_GlobalRef py_False;
 | 
			
		||||
/// A shorthand for `None`.
 | 
			
		||||
extern py_GlobalRef py_None;
 | 
			
		||||
/// A shorthand for `nil`. `nil` is not a valid python object.
 | 
			
		||||
extern py_GlobalRef py_NIL;
 | 
			
		||||
 | 
			
		||||
/************* Global Setup *************/
 | 
			
		||||
 | 
			
		||||
/// Initialize pocketpy and the default VM.
 | 
			
		||||
void py_initialize();
 | 
			
		||||
/// Finalize pocketpy.
 | 
			
		||||
/// Finalize pocketpy and free all VMs.
 | 
			
		||||
void py_finalize();
 | 
			
		||||
/// Get the current VM index.
 | 
			
		||||
int py_currentvm();
 | 
			
		||||
/// Switch to a VM.
 | 
			
		||||
/// @param index index of the VM ranging from 0 to 16 (exclusive). `0` is the default VM.
 | 
			
		||||
void py_switchvm(int index);
 | 
			
		||||
/// Set `sys.argv`. Used for storing command-line arguments.
 | 
			
		||||
void py_sys_setargv(int argc, char** argv);
 | 
			
		||||
 | 
			
		||||
/// Run a source string.
 | 
			
		||||
/// @param source source string.
 | 
			
		||||
/// @param filename filename (for error messages).
 | 
			
		||||
/// @param mode compile mode. Use `EXEC_MODE` for statements `EVAL_MODE` for expressions.
 | 
			
		||||
/// @param module target module. Use NULL for the main module.
 | 
			
		||||
/// @return true if the execution is successful.
 | 
			
		||||
/// @return `true` if the execution is successful or `false` if an exception is raised.
 | 
			
		||||
bool py_exec(const char* source,
 | 
			
		||||
             const char* filename,
 | 
			
		||||
             enum py_CompileMode mode,
 | 
			
		||||
             py_Ref module) PY_RAISE PY_RETURN;
 | 
			
		||||
 | 
			
		||||
#define py_eval(source, module) py_exec((source), "<string>", EVAL_MODE, (module))
 | 
			
		||||
/// Evaluate a source string. Equivalent to `py_exec(source, "<string>", EVAL_MODE, module)`.
 | 
			
		||||
bool py_eval(const char* source, py_Ref module) PY_RAISE PY_RETURN;
 | 
			
		||||
 | 
			
		||||
/// Compile a source string into a code object.
 | 
			
		||||
/// Use python's `exec()` or `eval()` to execute it.
 | 
			
		||||
@ -89,7 +111,7 @@ bool py_compile(const char* source,
 | 
			
		||||
/// Python equivalent to `globals()`.
 | 
			
		||||
void py_newglobals(py_Ref);
 | 
			
		||||
/// Python equivalent to `locals()`.
 | 
			
		||||
/// NOTE: Return a temporary object, which expires on the associated function return.
 | 
			
		||||
/// @return a temporary object, which expires on the associated function return.
 | 
			
		||||
void py_newlocals(py_Ref);
 | 
			
		||||
 | 
			
		||||
/************* Values Creation *************/
 | 
			
		||||
@ -161,7 +183,7 @@ py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, py
 | 
			
		||||
/// Create a new object.
 | 
			
		||||
/// @param out output reference.
 | 
			
		||||
/// @param type type of the object.
 | 
			
		||||
/// @param slots number of slots. Use -1 to create a `__dict__`.
 | 
			
		||||
/// @param slots number of slots. Use `-1` to create a `__dict__`.
 | 
			
		||||
/// @param udsize size of your userdata.
 | 
			
		||||
/// @return pointer to the userdata.
 | 
			
		||||
void* py_newobject(py_Ref out, py_Type type, int slots, int udsize);
 | 
			
		||||
@ -474,7 +496,7 @@ bool py_isidentical(py_Ref, py_Ref);
 | 
			
		||||
bool py_call(py_Ref f, int argc, py_Ref argv) PY_RAISE PY_RETURN;
 | 
			
		||||
 | 
			
		||||
#if PK_DEBUG
 | 
			
		||||
/// Call a py_CFunction in a safe way.
 | 
			
		||||
/// Call a `py_CFunction` in a safe way.
 | 
			
		||||
/// This function does extra checks to help you debug `py_CFunction`.
 | 
			
		||||
bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) PY_RAISE PY_RETURN;
 | 
			
		||||
#else
 | 
			
		||||
@ -506,6 +528,7 @@ void py_list_delitem(py_Ref self, int i);
 | 
			
		||||
int py_list_len(py_Ref self);
 | 
			
		||||
void py_list_swap(py_Ref self, int i, int j);
 | 
			
		||||
void py_list_append(py_Ref self, py_Ref val);
 | 
			
		||||
py_ItemRef py_list_emplace(py_Ref self);
 | 
			
		||||
void py_list_clear(py_Ref self);
 | 
			
		||||
void py_list_insert(py_Ref self, int i, py_Ref val);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -239,6 +239,11 @@ class set:
 | 
			
		||||
        if not isinstance(other, set):
 | 
			
		||||
            return NotImplemented
 | 
			
		||||
        return len(self ^ other) == 0
 | 
			
		||||
    
 | 
			
		||||
    def __ne__(self, other):
 | 
			
		||||
        if not isinstance(other, set):
 | 
			
		||||
            return NotImplemented
 | 
			
		||||
        return len(self ^ other) != 0
 | 
			
		||||
 | 
			
		||||
    def isdisjoint(self, other):
 | 
			
		||||
        return len(self & other) == 0
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,12 @@ class complex:
 | 
			
		||||
            return self.real == other and self.imag == 0
 | 
			
		||||
        return NotImplemented
 | 
			
		||||
    
 | 
			
		||||
    def __ne__(self, other):
 | 
			
		||||
        res = self == other
 | 
			
		||||
        if res is NotImplemented:
 | 
			
		||||
            return res
 | 
			
		||||
        return not res
 | 
			
		||||
    
 | 
			
		||||
    def __add__(self, other):
 | 
			
		||||
        if type(other) is complex:
 | 
			
		||||
            return complex(self.real + other.real, self.imag + other.imag)
 | 
			
		||||
 | 
			
		||||
@ -10,12 +10,12 @@ class timedelta:
 | 
			
		||||
        return f"datetime.timedelta(days={self.days}, seconds={self.seconds})"
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other: 'timedelta') -> bool:
 | 
			
		||||
        if type(other) is not timedelta:
 | 
			
		||||
        if not isinstance(other, timedelta):
 | 
			
		||||
            return NotImplemented
 | 
			
		||||
        return (self.days, self.seconds) == (other.days, other.seconds)
 | 
			
		||||
 | 
			
		||||
    def __ne__(self, other: 'timedelta') -> bool:
 | 
			
		||||
        if type(other) is not timedelta:
 | 
			
		||||
        if not isinstance(other, timedelta):
 | 
			
		||||
            return NotImplemented
 | 
			
		||||
        return (self.days, self.seconds) != (other.days, other.seconds)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -108,7 +108,7 @@ void VM__ctor(VM* self) {
 | 
			
		||||
 | 
			
		||||
    validate(tp_function, pk_function__register());
 | 
			
		||||
    validate(tp_nativefunc, pk_nativefunc__register());
 | 
			
		||||
    validate(tp_boundmethod, pk_newtype("boundmethod", tp_object, NULL, NULL, false, true));
 | 
			
		||||
    validate(tp_boundmethod, pk_boundmethod__register());
 | 
			
		||||
 | 
			
		||||
    validate(tp_super, pk_super__register());
 | 
			
		||||
    validate(tp_BaseException, pk_BaseException__register());
 | 
			
		||||
@ -204,6 +204,7 @@ void VM__ctor(VM* self) {
 | 
			
		||||
    pk__add_module_gc();
 | 
			
		||||
    pk__add_module_time();
 | 
			
		||||
    pk__add_module_easing();
 | 
			
		||||
    pk__add_module_traceback();
 | 
			
		||||
 | 
			
		||||
    // add python builtins
 | 
			
		||||
    do {
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
#include "pocketpy/common/config.h"
 | 
			
		||||
#include "pocketpy/common/export.h"
 | 
			
		||||
#include "pocketpy/pocketpy.h"
 | 
			
		||||
 | 
			
		||||
#include "pocketpy/common/utils.h"
 | 
			
		||||
@ -51,4 +53,7 @@ void pk__add_module_os() {
 | 
			
		||||
 | 
			
		||||
void pk__add_module_sys() {
 | 
			
		||||
    py_Ref mod = py_newmodule("sys");
 | 
			
		||||
    py_newstr(py_emplacedict(mod, py_name("platform")), PY_SYS_PLATFORM_STRING);
 | 
			
		||||
    py_newstr(py_emplacedict(mod, py_name("version")), PK_VERSION);
 | 
			
		||||
    py_newlist(py_emplacedict(mod, py_name("argv")));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								src/modules/traceback.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/modules/traceback.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
#include "pocketpy/pocketpy.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
static bool traceback_format_exc(int argc, py_Ref argv) {
 | 
			
		||||
    PY_CHECK_ARGC(0);
 | 
			
		||||
    char* s = py_formatexc();
 | 
			
		||||
    if(!s) {
 | 
			
		||||
        py_newnone(py_retval());
 | 
			
		||||
    } else {
 | 
			
		||||
        py_newstr(py_retval(), s);
 | 
			
		||||
        free(s);
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool traceback_print_exc(int argc, py_Ref argv) {
 | 
			
		||||
    PY_CHECK_ARGC(0);
 | 
			
		||||
    py_printexc();
 | 
			
		||||
    py_newnone(py_retval());
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pk__add_module_traceback() {
 | 
			
		||||
    py_Ref mod = py_newmodule("traceback");
 | 
			
		||||
 | 
			
		||||
    py_bindfunc(mod, "format_exc", traceback_format_exc);
 | 
			
		||||
    py_bindfunc(mod, "print_exc", traceback_print_exc);
 | 
			
		||||
}
 | 
			
		||||
@ -74,3 +74,7 @@ bool py_exec(const char* source, const char* filename, enum py_CompileMode mode,
 | 
			
		||||
    CodeObject__dtor(&co);
 | 
			
		||||
    return ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool py_eval(const char* source, py_Ref module) {
 | 
			
		||||
    return py_exec(source, "<string>", EVAL_MODE, module);
 | 
			
		||||
}
 | 
			
		||||
@ -67,6 +67,15 @@ int py_currentvm() {
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_sys_setargv(int argc, char** argv) {
 | 
			
		||||
    py_GlobalRef sys = py_getmodule("sys");
 | 
			
		||||
    py_Ref argv_list = py_getdict(sys, py_name("argv"));
 | 
			
		||||
    py_list_clear(argv_list);
 | 
			
		||||
    for(int i = 0; i < argc; i++) {
 | 
			
		||||
        py_newstr(py_list_emplace(argv_list), argv[i]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* pk_opname(Opcode op) {
 | 
			
		||||
    const static char* OP_NAMES[] = {
 | 
			
		||||
#define OPCODE(name) #name,
 | 
			
		||||
 | 
			
		||||
@ -613,7 +613,7 @@ static void function__gc_mark(void* ud) {
 | 
			
		||||
    CodeObject__gc_mark(&func->decl->code);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool function__doc__getter(int argc, py_Ref argv) {
 | 
			
		||||
static bool function__doc__(int argc, py_Ref argv) {
 | 
			
		||||
    PY_CHECK_ARGC(1);
 | 
			
		||||
    Function* func = py_touserdata(py_arg(0));
 | 
			
		||||
    if(func->decl->docstring){
 | 
			
		||||
@ -630,7 +630,7 @@ py_Type pk_function__register() {
 | 
			
		||||
 | 
			
		||||
    pk__tp_set_marker(type, function__gc_mark);
 | 
			
		||||
 | 
			
		||||
    py_bindproperty(type, "__doc__", function__doc__getter, NULL);
 | 
			
		||||
    py_bindproperty(type, "__doc__", function__doc__, NULL);
 | 
			
		||||
    return type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -14,34 +14,34 @@ void py_newlist(py_Ref out) {
 | 
			
		||||
 | 
			
		||||
void py_newlistn(py_Ref out, int n) {
 | 
			
		||||
    py_newlist(out);
 | 
			
		||||
    List* userdata = py_touserdata(out);
 | 
			
		||||
    c11_vector__reserve(userdata, n);
 | 
			
		||||
    userdata->count = n;
 | 
			
		||||
    List* ud = py_touserdata(out);
 | 
			
		||||
    c11_vector__reserve(ud, n);
 | 
			
		||||
    ud->count = n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Ref py_list_data(py_Ref self) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    return userdata->data;
 | 
			
		||||
    List* ud = py_touserdata(self);
 | 
			
		||||
    return ud->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Ref py_list_getitem(py_Ref self, int i) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    return c11__at(py_TValue, userdata, i);
 | 
			
		||||
    List* ud = py_touserdata(self);
 | 
			
		||||
    return c11__at(py_TValue, ud, i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_list_setitem(py_Ref self, int i, py_Ref val) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    c11__setitem(py_TValue, userdata, i, *val);
 | 
			
		||||
    List* ud = py_touserdata(self);
 | 
			
		||||
    c11__setitem(py_TValue, ud, i, *val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_list_delitem(py_Ref self, int i) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    c11_vector__erase(py_TValue, userdata, i);
 | 
			
		||||
    List* ud = py_touserdata(self);
 | 
			
		||||
    c11_vector__erase(py_TValue, ud, i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int py_list_len(py_Ref self) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    return userdata->count;
 | 
			
		||||
    List* ud = py_touserdata(self);
 | 
			
		||||
    return ud->count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_list_swap(py_Ref self, int i, int j) {
 | 
			
		||||
@ -52,18 +52,24 @@ void py_list_swap(py_Ref self, int i, int j) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_list_append(py_Ref self, py_Ref val) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    c11_vector__push(py_TValue, userdata, *val);
 | 
			
		||||
    List* ud = py_touserdata(self);
 | 
			
		||||
    c11_vector__push(py_TValue, ud, *val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_ItemRef py_list_emplace(py_Ref self) {
 | 
			
		||||
    List* ud = py_touserdata(self);
 | 
			
		||||
    c11_vector__emplace(ud);
 | 
			
		||||
    return &c11_vector__back(py_TValue, ud);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_list_clear(py_Ref self) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    c11_vector__clear(userdata);
 | 
			
		||||
    List* ud = py_touserdata(self);
 | 
			
		||||
    c11_vector__clear(ud);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void py_list_insert(py_Ref self, int i, py_Ref val) {
 | 
			
		||||
    List* userdata = py_touserdata(self);
 | 
			
		||||
    c11_vector__insert(py_TValue, userdata, i, *val);
 | 
			
		||||
    List* ud = py_touserdata(self);
 | 
			
		||||
    c11_vector__insert(py_TValue, ud, i, *val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
////////////////////////////////
 | 
			
		||||
 | 
			
		||||
@ -13,9 +13,9 @@ static bool staticmethod__new__(int argc, py_Ref argv) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Type pk_staticmethod__register(){
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
@ -28,7 +28,7 @@ static bool classmethod__new__(int argc, py_Ref argv) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Type pk_classmethod__register(){
 | 
			
		||||
py_Type pk_classmethod__register() {
 | 
			
		||||
    py_Type type = pk_newtype("classmethod", tp_object, NULL, NULL, false, true);
 | 
			
		||||
 | 
			
		||||
    py_bindmagic(type, __new__, classmethod__new__);
 | 
			
		||||
@ -36,22 +36,49 @@ py_Type pk_classmethod__register(){
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* boundmethod */
 | 
			
		||||
static bool boundmethod__self__getter(int argc, py_Ref argv) {
 | 
			
		||||
static bool boundmethod__self__(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) {
 | 
			
		||||
static bool boundmethod__func__(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);
 | 
			
		||||
static bool boundmethod__eq__(int argc, py_Ref argv) {
 | 
			
		||||
    PY_CHECK_ARGC(2);
 | 
			
		||||
    if(!py_istype(py_arg(1), tp_boundmethod)) {
 | 
			
		||||
        py_newbool(py_retval(), false);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    for(int i = 0; i < 2; i++) {
 | 
			
		||||
        int res = py_equal(py_getslot(&argv[0], i), py_getslot(&argv[1], i));
 | 
			
		||||
        if(res == -1) return false;
 | 
			
		||||
        if(!res) {
 | 
			
		||||
            py_newbool(py_retval(), false);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    py_newbool(py_retval(), true);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    py_bindproperty(type, "__self__", boundmethod__self__getter, NULL);
 | 
			
		||||
    py_bindproperty(type, "__func__", boundmethod__func__getter, NULL);
 | 
			
		||||
static bool boundmethod__ne__(int argc, py_Ref argv) {
 | 
			
		||||
    bool ok = boundmethod__eq__(argc, argv);
 | 
			
		||||
    if(!ok) return false;
 | 
			
		||||
    bool res = py_tobool(py_retval());
 | 
			
		||||
    py_newbool(py_retval(), !res);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
py_Type pk_boundmethod__register() {
 | 
			
		||||
    py_Type type = pk_newtype("boundmethod", tp_object, NULL, NULL, false, true);
 | 
			
		||||
    py_bindproperty(type, "__self__", boundmethod__self__, NULL);
 | 
			
		||||
    py_bindproperty(type, "__func__", boundmethod__func__, NULL);
 | 
			
		||||
    py_bindmagic(type, __eq__, boundmethod__eq__);
 | 
			
		||||
    py_bindmagic(type, __ne__, boundmethod__ne__);
 | 
			
		||||
    return type;
 | 
			
		||||
}
 | 
			
		||||
@ -44,7 +44,7 @@ static bool object__repr__(int argc, py_Ref argv) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool object__dict__getter(int argc, py_Ref argv) {
 | 
			
		||||
static bool object__dict__(int argc, py_Ref argv) {
 | 
			
		||||
    PY_CHECK_ARGC(1);
 | 
			
		||||
    if(argv->is_ptr && argv->_obj->slots == -1) {
 | 
			
		||||
        pk_mappingproxy__namedict(py_retval(), argv);
 | 
			
		||||
@ -70,7 +70,7 @@ static bool type__new__(int argc, py_Ref argv) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool type__base__getter(int argc, py_Ref argv) {
 | 
			
		||||
static bool type__base__(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);
 | 
			
		||||
@ -82,7 +82,7 @@ static bool type__base__getter(int argc, py_Ref argv) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool type__name__getter(int argc, py_Ref argv) {
 | 
			
		||||
static bool type__name__(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);
 | 
			
		||||
@ -95,7 +95,7 @@ static bool type__getitem__(int argc, py_Ref argv) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool type__module__getter(int argc, py_Ref argv) {
 | 
			
		||||
static bool type__module__(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);
 | 
			
		||||
@ -116,13 +116,13 @@ void pk_object__register() {
 | 
			
		||||
    py_bindmagic(tp_object, __eq__, object__eq__);
 | 
			
		||||
    py_bindmagic(tp_object, __ne__, object__ne__);
 | 
			
		||||
    py_bindmagic(tp_object, __repr__, object__repr__);
 | 
			
		||||
    py_bindproperty(tp_object, "__dict__", object__dict__getter, NULL);
 | 
			
		||||
    py_bindproperty(tp_object, "__dict__", object__dict__, NULL);
 | 
			
		||||
 | 
			
		||||
    py_bindmagic(tp_type, __repr__, type__repr__);
 | 
			
		||||
    py_bindmagic(tp_type, __new__, type__new__);
 | 
			
		||||
    py_bindmagic(tp_type, __getitem__, type__getitem__);
 | 
			
		||||
    py_bindproperty(tp_type, "__module__", type__module__getter, NULL);
 | 
			
		||||
    py_bindproperty(tp_type, "__module__", type__module__, NULL);
 | 
			
		||||
 | 
			
		||||
    py_bindproperty(tp_type, "__base__", type__base__getter, NULL);
 | 
			
		||||
    py_bindproperty(tp_type, "__name__", type__name__getter, NULL);
 | 
			
		||||
    py_bindproperty(tp_type, "__base__", type__base__, NULL);
 | 
			
		||||
    py_bindproperty(tp_type, "__name__", type__name__, NULL);
 | 
			
		||||
}
 | 
			
		||||
@ -25,14 +25,14 @@ static bool property_setter(int argc, py_Ref argv) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool property_fget__getter(int argc, py_Ref argv) {
 | 
			
		||||
static bool property_fget(int argc, py_Ref argv) {
 | 
			
		||||
    PY_CHECK_ARGC(1);
 | 
			
		||||
    py_Ref fget = py_getslot(argv, 0);
 | 
			
		||||
    py_assign(py_retval(), fget);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool property_fset__getter(int argc, py_Ref argv) {
 | 
			
		||||
static bool property_fset(int argc, py_Ref argv) {
 | 
			
		||||
    PY_CHECK_ARGC(1);
 | 
			
		||||
    py_Ref fset = py_getslot(argv, 1);
 | 
			
		||||
    py_assign(py_retval(), fset);
 | 
			
		||||
@ -45,7 +45,7 @@ py_Type pk_property__register() {
 | 
			
		||||
    py_bindmagic(type, __new__, property__new__);
 | 
			
		||||
    py_bindmethod(type, "setter", property_setter);
 | 
			
		||||
 | 
			
		||||
    py_bindproperty(type, "fget", property_fget__getter, NULL);
 | 
			
		||||
    py_bindproperty(type, "fset", property_fset__getter, NULL);
 | 
			
		||||
    py_bindproperty(type, "fget", property_fget, NULL);
 | 
			
		||||
    py_bindproperty(type, "fset", property_fset, NULL);
 | 
			
		||||
    return type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -42,21 +42,21 @@ static bool slice__repr__(int argc, py_Ref argv) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool slice_start__getter(int argc, py_Ref argv) {
 | 
			
		||||
static bool slice_start(int argc, py_Ref argv) {
 | 
			
		||||
    py_Ref self = py_arg(0);
 | 
			
		||||
    py_TValue* val = py_getslot(self, 0);
 | 
			
		||||
    py_assign(py_retval(), val);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool slice_stop__getter(int argc, py_Ref argv) {
 | 
			
		||||
static bool slice_stop(int argc, py_Ref argv) {
 | 
			
		||||
    py_Ref self = py_arg(0);
 | 
			
		||||
    py_TValue* val = py_getslot(self, 1);
 | 
			
		||||
    py_assign(py_retval(), val);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool slice_step__getter(int argc, py_Ref argv) {
 | 
			
		||||
static bool slice_step(int argc, py_Ref argv) {
 | 
			
		||||
    py_Ref self = py_arg(0);
 | 
			
		||||
    py_TValue* val = py_getslot(self, 2);
 | 
			
		||||
    py_assign(py_retval(), val);
 | 
			
		||||
@ -69,8 +69,8 @@ py_Type pk_slice__register() {
 | 
			
		||||
    py_bindmagic(type, __new__, slice__new__);
 | 
			
		||||
    py_bindmagic(type, __repr__, slice__repr__);
 | 
			
		||||
 | 
			
		||||
    py_bindproperty(type, "start", slice_start__getter, NULL);
 | 
			
		||||
    py_bindproperty(type, "stop", slice_stop__getter, NULL);
 | 
			
		||||
    py_bindproperty(type, "step", slice_step__getter, NULL);
 | 
			
		||||
    py_bindproperty(type, "start", slice_start, NULL);
 | 
			
		||||
    py_bindproperty(type, "stop", slice_stop, NULL);
 | 
			
		||||
    py_bindproperty(type, "step", slice_step, NULL);
 | 
			
		||||
    return type;
 | 
			
		||||
}
 | 
			
		||||
@ -38,6 +38,7 @@ int main(int argc, char** argv) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    py_initialize();
 | 
			
		||||
    py_sys_setargv(argc, argv);
 | 
			
		||||
 | 
			
		||||
    if(argc == 1) {
 | 
			
		||||
        printf("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ") ");
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
exit()
 | 
			
		||||
 | 
			
		||||
from linalg import mat3x3, vec2, vec3
 | 
			
		||||
import random
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								tests/80_sys.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								tests/80_sys.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
assert len(sys.argv) == 2
 | 
			
		||||
assert (sys.argv[1] == 'tests/80_sys.py'), sys.argv
 | 
			
		||||
@ -7,7 +7,7 @@ except KeyError:
 | 
			
		||||
    actual = traceback.format_exc()
 | 
			
		||||
 | 
			
		||||
expected = '''Traceback (most recent call last):
 | 
			
		||||
  File "80_traceback.py", line 5
 | 
			
		||||
  File "tests/80_traceback.py", line 5
 | 
			
		||||
    b = a[6]
 | 
			
		||||
KeyError: 6'''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +0,0 @@
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
assert len(sys.argv) == 2
 | 
			
		||||
assert sys.argv[1] == 'tests/87_sys.py'
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
exit()
 | 
			
		||||
 | 
			
		||||
from array2d import array2d
 | 
			
		||||
 | 
			
		||||
# test error args for __init__
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
exit()
 | 
			
		||||
 | 
			
		||||
from dataclasses import dataclass, asdict
 | 
			
		||||
 | 
			
		||||
@dataclass
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
exit()
 | 
			
		||||
 | 
			
		||||
from enum import Enum
 | 
			
		||||
 | 
			
		||||
class A(Enum):
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
exit()
 | 
			
		||||
 | 
			
		||||
from pickle import dumps, loads, _wrap, _unwrap
 | 
			
		||||
 | 
			
		||||
def test(x):
 | 
			
		||||
@ -46,7 +46,7 @@ a = object()
 | 
			
		||||
b = object()
 | 
			
		||||
if a is   not b:
 | 
			
		||||
    assert True
 | 
			
		||||
if a  is  0:
 | 
			
		||||
if a  ==  0:
 | 
			
		||||
    assert False
 | 
			
		||||
 | 
			
		||||
def g(x):
 | 
			
		||||
@ -84,10 +84,13 @@ def test(a):
 | 
			
		||||
assert test(1) == '1.40'
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    assert test(0) == '0.00'
 | 
			
		||||
    x = test(0)
 | 
			
		||||
    print('x:', x)
 | 
			
		||||
    exit(1)
 | 
			
		||||
except UnboundLocalError:
 | 
			
		||||
    pass
 | 
			
		||||
except NameError:
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
g = 1
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user