mirror of
				https://github.com/pocketpy/pocketpy
				synced 2025-10-31 17:00:17 +00:00 
			
		
		
		
	Compare commits
	
		
			11 Commits
		
	
	
		
			145b36b677
			...
			26a12bb640
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 26a12bb640 | ||
|  | 26c553eb9a | ||
|  | a5725824b4 | ||
|  | b01234d27e | ||
|  | e2d4f57859 | ||
|  | 8b32296c9c | ||
|  | 81fe369b44 | ||
|  | c016a728b6 | ||
|  | 04229f438f | ||
|  | a6adcfd0c1 | ||
|  | 3eec499b95 | 
							
								
								
									
										21
									
								
								build.sh
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								build.sh
									
									
									
									
									
								
							| @ -7,10 +7,7 @@ if ! type -P clang >/dev/null 2>&1; then | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| echo "It takes a moment to finish building." | ||||
| echo "" | ||||
| echo "> Running prebuild.py... " | ||||
| 
 | ||||
| python prebuild.py | ||||
| 
 | ||||
| if [ $? -ne 0 ]; then | ||||
| @ -22,23 +19,7 @@ SRC=$(find src/ -name "*.c") | ||||
| 
 | ||||
| echo "> Compiling and linking source files... " | ||||
| 
 | ||||
| FLAGS="-std=c11 -O1 -Wfatal-errors -Iinclude -DNDEBUG" | ||||
| 
 | ||||
| if [[ "$OSTYPE" == "darwin"* ]]; then | ||||
|     LIB_EXTENSION=".dylib" | ||||
|     FLAGS="$FLAGS -undefined dynamic_lookup" | ||||
|     LINK_FLAGS="" | ||||
| else | ||||
|     LIB_EXTENSION=".so" | ||||
|     LINK_FLAGS="-Wl,-rpath=." | ||||
| fi | ||||
| 
 | ||||
| clang $FLAGS -o libpocketpy$LIB_EXTENSION $SRC -fPIC -shared -lm | ||||
| 
 | ||||
| # compile main.cpp and link to libpocketpy.so | ||||
| echo "> Compiling main.c and linking to libpocketpy$LIB_EXTENSION..." | ||||
| 
 | ||||
| clang $FLAGS -o main -O1 src2/main.c -L. -lpocketpy $LINK_FLAGS | ||||
| clang -std=c11 -O2 -Wfatal-errors -Iinclude -DNDEBUG -o main src2/main.c $SRC -lm | ||||
| 
 | ||||
| if [ $? -eq 0 ]; then | ||||
|     echo "Build completed. Type \"./main\" to enter REPL." | ||||
|  | ||||
| @ -7,4 +7,6 @@ void pk__add_module_math(); | ||||
| void pk__add_module_dis(); | ||||
| void pk__add_module_random(); | ||||
| void pk__add_module_json(); | ||||
| void pk__add_module_gc(); | ||||
| void pk__add_module_gc(); | ||||
| void pk__add_module_time(); | ||||
| void pk__add_module_easing(); | ||||
|  | ||||
| @ -31,3 +31,4 @@ typedef struct py_TValue { | ||||
| // 16 bytes to make py_arg() macro work
 | ||||
| static_assert(sizeof(py_CFunction) <= 8, "sizeof(py_CFunction) > 8"); | ||||
| static_assert(sizeof(py_TValue) == 16, "sizeof(py_TValue) != 16"); | ||||
| static_assert(offsetof(py_TValue, extra) == 4, "offsetof(py_TValue, extra) != 4"); | ||||
| @ -22,7 +22,8 @@ typedef double py_f64; | ||||
| 
 | ||||
| typedef void (*py_Dtor)(void*); | ||||
| 
 | ||||
| #define PY_RAISE  // mark a function that can raise an exception
 | ||||
| #define PY_RAISE   // mark a function that can raise an exception
 | ||||
| #define PY_RETURN  // mark a function that can modify `py_retval()` on success
 | ||||
| 
 | ||||
| typedef struct c11_sv { | ||||
|     const char* data; | ||||
| @ -44,7 +45,7 @@ typedef py_TValue* py_ItemRef; | ||||
| /// @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.
 | ||||
| typedef bool (*py_CFunction)(int argc, py_StackRef argv) PY_RAISE; | ||||
| typedef bool (*py_CFunction)(int argc, py_StackRef argv) PY_RAISE PY_RETURN; | ||||
| 
 | ||||
| enum py_CompileMode { EXEC_MODE, EVAL_MODE, SINGLE_MODE }; | ||||
| 
 | ||||
| @ -74,14 +75,16 @@ void py_switchvm(int index); | ||||
| bool py_exec(const char* source, | ||||
|              const char* filename, | ||||
|              enum py_CompileMode mode, | ||||
|              py_Ref module) PY_RAISE; | ||||
|              py_Ref module) PY_RAISE PY_RETURN; | ||||
| 
 | ||||
| #define py_eval(source, module) py_exec((source), "<string>", EVAL_MODE, (module)) | ||||
| 
 | ||||
| /// Compile a source string into a code object.
 | ||||
| /// Use python's `exec()` or `eval()` to execute it.
 | ||||
| bool py_compile(const char* source, | ||||
|                 const char* filename, | ||||
|                 enum py_CompileMode mode, | ||||
|                 bool is_dynamic) PY_RAISE; | ||||
|                 bool is_dynamic) PY_RAISE PY_RETURN; | ||||
| 
 | ||||
| /// Python equivalent to `globals()`.
 | ||||
| void py_newglobals(py_Ref); | ||||
| @ -170,7 +173,7 @@ py_i64 py_toint(py_Ref); | ||||
| /// Convert a `float` object in python to `double`.
 | ||||
| py_f64 py_tofloat(py_Ref); | ||||
| /// Cast a `int` or `float` object in python to `double`.
 | ||||
| /// If successful, returns true and set the value to `out`.
 | ||||
| /// If successful, return true and set the value to `out`.
 | ||||
| /// Otherwise, return false and raise `TypeError`.
 | ||||
| bool py_castfloat(py_Ref, py_f64* out) PY_RAISE; | ||||
| /// Convert a `bool` object in python to `bool`.
 | ||||
| @ -201,6 +204,9 @@ void* py_touserdata(py_Ref); | ||||
| 
 | ||||
| /// Get the type of the object.
 | ||||
| py_Type py_typeof(py_Ref self); | ||||
| /// Get type by module and name. e.g. `py_gettype("time", py_name("struct_time"))`.
 | ||||
| /// Return `0` if not found.
 | ||||
| py_Type py_gettype(const char* module, py_Name name); | ||||
| /// Check if the object is exactly the given type.
 | ||||
| bool py_istype(py_Ref, py_Type); | ||||
| /// Check if the object is an instance of the given type.
 | ||||
| @ -223,7 +229,7 @@ py_ItemRef py_tpobject(py_Type type); | ||||
| /// Get the type name.
 | ||||
| const char* py_tpname(py_Type type); | ||||
| /// Call a type to create a new instance.
 | ||||
| bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE; | ||||
| bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE PY_RETURN; | ||||
| 
 | ||||
| /// Check if the object is an instance of the given type.
 | ||||
| /// Raise `TypeError` if the check fails.
 | ||||
| @ -276,6 +282,9 @@ void py_setslot(py_Ref self, int i, py_Ref val); | ||||
| /// Get the current `function` object from the stack.
 | ||||
| /// Return `NULL` if not available.
 | ||||
| py_StackRef py_inspect_currentfunction(); | ||||
| /// Get the current `module` object where the code is executed.
 | ||||
| /// Return `NULL` if not available.
 | ||||
| py_GlobalRef py_inspect_currentmodule(); | ||||
| 
 | ||||
| /************* Bindings *************/ | ||||
| 
 | ||||
| @ -315,13 +324,13 @@ void py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFu | ||||
| /************* Python Equivalents *************/ | ||||
| 
 | ||||
| /// Python equivalent to `getattr(self, name)`.
 | ||||
| bool py_getattr(py_Ref self, py_Name name) PY_RAISE; | ||||
| bool py_getattr(py_Ref self, py_Name name) PY_RAISE PY_RETURN; | ||||
| /// Python equivalent to `setattr(self, name, val)`.
 | ||||
| bool py_setattr(py_Ref self, py_Name name, py_Ref val) PY_RAISE; | ||||
| /// Python equivalent to `delattr(self, name)`.
 | ||||
| bool py_delattr(py_Ref self, py_Name name) PY_RAISE; | ||||
| /// Python equivalent to `self[key]`.
 | ||||
| bool py_getitem(py_Ref self, py_Ref key) PY_RAISE; | ||||
| bool py_getitem(py_Ref self, py_Ref key) PY_RAISE PY_RETURN; | ||||
| /// Python equivalent to `self[key] = val`.
 | ||||
| bool py_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE; | ||||
| /// Python equivalent to `del self[key]`.
 | ||||
| @ -330,7 +339,7 @@ bool py_delitem(py_Ref self, py_Ref key) PY_RAISE; | ||||
| /// Perform a binary operation.
 | ||||
| /// The result will be set to `py_retval()`.
 | ||||
| /// The stack remains unchanged after the operation.
 | ||||
| bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) PY_RAISE; | ||||
| bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) PY_RAISE PY_RETURN; | ||||
| 
 | ||||
| #define py_binaryadd(lhs, rhs) py_binaryop(lhs, rhs, __add__, __radd__) | ||||
| #define py_binarysub(lhs, rhs) py_binaryop(lhs, rhs, __sub__, __rsub__) | ||||
| @ -358,6 +367,8 @@ void py_push(py_Ref src); | ||||
| void py_pushnil(); | ||||
| /// Push a `None` object to the stack.
 | ||||
| void py_pushnone(); | ||||
| /// Push a `py_Name` to the stack. This is used for keyword arguments.
 | ||||
| void py_pushname(py_Name name); | ||||
| /// Pop an object from the stack.
 | ||||
| void py_pop(); | ||||
| /// Shrink the stack by n.
 | ||||
| @ -373,7 +384,10 @@ bool py_pushmethod(py_Name name); | ||||
| /// Assume `argc + kwargc` arguments are already pushed to the stack.
 | ||||
| /// The result will be set to `py_retval()`.
 | ||||
| /// The stack size will be reduced by `argc + kwargc`.
 | ||||
| bool py_vectorcall(uint16_t argc, uint16_t kwargc) PY_RAISE; | ||||
| bool py_vectorcall(uint16_t argc, uint16_t kwargc) PY_RAISE PY_RETURN; | ||||
| /// Evaluate an expression and push the result to the stack.
 | ||||
| /// This function is used for testing.
 | ||||
| bool py_pusheval(const char* expr, py_GlobalRef module) PY_RAISE; | ||||
| 
 | ||||
| /************* Modules *************/ | ||||
| 
 | ||||
| @ -428,7 +442,7 @@ bool KeyError(py_Ref key) PY_RAISE; | ||||
| 
 | ||||
| /// Python equivalent to `bool(val)`.
 | ||||
| /// 1: true, 0: false, -1: error
 | ||||
| int py_bool(py_Ref val) PY_RAISE; | ||||
| int py_bool(py_Ref val) PY_RAISE PY_RETURN; | ||||
| 
 | ||||
| /// Compare two objects.
 | ||||
| /// 1: lhs == rhs, 0: lhs != rhs, -1: error
 | ||||
| @ -447,34 +461,36 @@ int py_less(py_Ref lhs, py_Ref rhs) PY_RAISE; | ||||
| /// Get the hash value of the object.
 | ||||
| bool py_hash(py_Ref, py_i64* out) PY_RAISE; | ||||
| /// Get the iterator of the object.
 | ||||
| bool py_iter(py_Ref) PY_RAISE; | ||||
| bool py_iter(py_Ref) PY_RAISE PY_RETURN; | ||||
| /// Get the next element from the iterator.
 | ||||
| /// 1: success, 0: StopIteration, -1: error
 | ||||
| int py_next(py_Ref) PY_RAISE; | ||||
| int py_next(py_Ref) PY_RAISE PY_RETURN; | ||||
| /// Python equivalent to `lhs is rhs`.
 | ||||
| bool py_isidentical(py_Ref, py_Ref); | ||||
| /// Call a function.
 | ||||
| /// It prepares the stack and then performs a `vectorcall(argc, 0, false)`.
 | ||||
| /// The result will be set to `py_retval()`.
 | ||||
| /// The stack remains unchanged after the operation.
 | ||||
| bool py_call(py_Ref f, int argc, py_Ref argv) PY_RAISE; | ||||
| 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.
 | ||||
| /// This function does extra checks to help you debug `py_CFunction`.
 | ||||
| bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) PY_RAISE; | ||||
| bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) PY_RAISE PY_RETURN; | ||||
| #else | ||||
| #define py_callcfunc(f, argc, argv) (f((argc), (argv))) | ||||
| #endif | ||||
| 
 | ||||
| /// Python equivalent to `str(val)`.
 | ||||
| bool py_str(py_Ref val) PY_RAISE; | ||||
| bool py_str(py_Ref val) PY_RAISE PY_RETURN; | ||||
| /// Python equivalent to `repr(val)`.
 | ||||
| bool py_repr(py_Ref val) PY_RAISE; | ||||
| bool py_repr(py_Ref val) PY_RAISE PY_RETURN; | ||||
| /// Python equivalent to `len(val)`.
 | ||||
| bool py_len(py_Ref val) PY_RAISE; | ||||
| bool py_len(py_Ref val) PY_RAISE PY_RETURN; | ||||
| /// Python equivalent to `json.dumps(val)`.
 | ||||
| bool py_json(py_Ref val) PY_RAISE; | ||||
| bool py_json_dumps(py_Ref val) PY_RAISE PY_RETURN; | ||||
| /// Python equivalent to `json.loads(val)`.
 | ||||
| bool py_json_loads(const char* source) PY_RAISE PY_RETURN; | ||||
| 
 | ||||
| /************* Unchecked Functions *************/ | ||||
| 
 | ||||
| @ -494,7 +510,7 @@ void py_list_clear(py_Ref self); | ||||
| void py_list_insert(py_Ref self, int i, py_Ref val); | ||||
| 
 | ||||
| /// -1: error, 0: not found, 1: found
 | ||||
| int py_dict_getitem(py_Ref self, py_Ref key) PY_RAISE; | ||||
| int py_dict_getitem(py_Ref self, py_Ref key) PY_RAISE PY_RETURN; | ||||
| /// true: success, false: error
 | ||||
| bool py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE; | ||||
| /// -1: error, 0: not found, 1: found (and deleted)
 | ||||
| @ -511,7 +527,7 @@ int py_dict_len(py_Ref self); | ||||
| /// An utility function to read a line from stdin for REPL.
 | ||||
| int py_replinput(char* buf, int max_size); | ||||
| 
 | ||||
| /// Python favored string formatting. (just put here, not for users)
 | ||||
| /// Python favored string formatting.
 | ||||
| /// %d: int
 | ||||
| /// %i: py_i64 (int64_t)
 | ||||
| /// %f: py_f64 (double)
 | ||||
| @ -589,14 +605,3 @@ enum py_PredefinedTypes { | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
| Some notes: | ||||
| 
 | ||||
| ## Macros | ||||
| 1. Function macros are partial functions. They can be used as normal expressions. Use the same | ||||
| naming convention as functions. | ||||
| 2. Snippet macros are `do {...} while(0)` blocks. They cannot be used as expressions. Use | ||||
| `UPPER_CASE` naming convention. | ||||
| 3. Constant macros are used for global constants. Use `UPPER_CASE` or k-prefix naming convention. | ||||
| */ | ||||
| @ -1,117 +0,0 @@ | ||||
| from typing import Generic, TypeVar | ||||
| 
 | ||||
| def malloc(size: int) -> 'void_p': ... | ||||
| def free(ptr: 'void_p') -> None: ... | ||||
| def memset(ptr: 'void_p', value: int, size: int) -> None: ... | ||||
| def memcpy(dst: 'void_p', src: 'void_p', size: int) -> None: ... | ||||
| 
 | ||||
| T = TypeVar('T') | ||||
| Tp = TypeVar('Tp', bound='void_p') | ||||
| 
 | ||||
| def p_cast(ptr: 'void_p', cls: type[T]) -> T: | ||||
|     """Cast a pointer to a specific type.""" | ||||
| def p_value(ptr: 'void_p') -> int: | ||||
|     """Get the value of a pointer.""" | ||||
| def pp_deref(ptr: Tp) -> Tp: | ||||
|     """Dereference a double pointer.""" | ||||
| 
 | ||||
| class void_p: | ||||
|     def __init__(self, addr: int): ... | ||||
|     def __eq__(self, other: 'void_p') -> bool: ... | ||||
|     def __ne__(self, other: 'void_p') -> bool: ... | ||||
|     def __lt__(self, other: 'void_p') -> bool: ... | ||||
|     def __le__(self, other: 'void_p') -> bool: ... | ||||
|     def __gt__(self, other: 'void_p') -> bool: ... | ||||
|     def __ge__(self, other: 'void_p') -> bool: ... | ||||
|     def __hash__(self) -> int: ... | ||||
|     def __repr__(self) -> str: ... | ||||
| 
 | ||||
| class Pointer(Generic[T], void_p): | ||||
|     def read(self) -> T: ... | ||||
|     def write(self, value: T) -> None: ... | ||||
|     def __getitem__(self, index: int) -> T: ... | ||||
|     def __setitem__(self, index: int, value: T) -> None: ... | ||||
| 
 | ||||
| class char_p(Pointer[int]): | ||||
|     def read_string(self) -> str: ... | ||||
|     def write_string(self, value: str) -> None: ... | ||||
| 
 | ||||
| class uchar_p(Pointer[int]): pass | ||||
| class short_p(Pointer[int]): pass | ||||
| class ushort_p(Pointer[int]): pass | ||||
| class int_p(Pointer[int]): pass | ||||
| class uint_p(Pointer[int]): pass | ||||
| class long_p(Pointer[int]): pass | ||||
| class ulong_p(Pointer[int]): pass | ||||
| class longlong_p(Pointer[int]): pass | ||||
| class ulonglong_p(Pointer[int]): pass | ||||
| class float_p(Pointer[float]): pass | ||||
| class double_p(Pointer[float]): pass | ||||
| class bool_p(Pointer[bool]): pass | ||||
| 
 | ||||
| class struct: | ||||
|     def __init__(self, size: int): ... | ||||
|     def addr(self) -> 'void_p': ... | ||||
|     def copy(self) -> 'struct': ... | ||||
|     def sizeof(self) -> int: ... | ||||
|     def __eq__(self, other: 'struct') -> bool: ... | ||||
|     def __ne__(self, other: 'struct') -> bool: ... | ||||
| 
 | ||||
|     def hex(self) -> str: ... | ||||
|     @staticmethod | ||||
|     def fromhex(s: str) -> 'struct': ... | ||||
| 
 | ||||
|     def read_char(self, offset=0) -> int: ... | ||||
|     def read_uchar(self, offset=0) -> int: ... | ||||
|     def read_short(self, offset=0) -> int: ... | ||||
|     def read_ushort(self, offset=0) -> int: ... | ||||
|     def read_int(self, offset=0) -> int: ... | ||||
|     def read_uint(self, offset=0) -> int: ... | ||||
|     def read_long(self, offset=0) -> int: ... | ||||
|     def read_ulong(self, offset=0) -> int: ... | ||||
|     def read_longlong(self, offset=0) -> int: ... | ||||
|     def read_ulonglong(self, offset=0) -> int: ... | ||||
|     def read_float(self, offset=0) -> float: ... | ||||
|     def read_double(self, offset=0) -> float: ... | ||||
|     def read_bool(self, offset=0) -> bool: ... | ||||
|     def read_void_p(self, offset=0) -> 'void_p': ... | ||||
|     def write_char(self, value: int, offset=0) -> None: ... | ||||
|     def write_uchar(self, value: int, offset=0) -> None: ... | ||||
|     def write_short(self, value: int, offset=0) -> None: ... | ||||
|     def write_ushort(self, value: int, offset=0) -> None: ... | ||||
|     def write_int(self, value: int, offset=0) -> None: ... | ||||
|     def write_uint(self, value: int, offset=0) -> None: ... | ||||
|     def write_long(self, value: int, offset=0) -> None: ... | ||||
|     def write_ulong(self, value: int, offset=0) -> None: ... | ||||
|     def write_longlong(self, value: int, offset=0) -> None: ... | ||||
|     def write_ulonglong(self, value: int, offset=0) -> None: ... | ||||
|     def write_float(self, value: float, offset=0) -> None: ... | ||||
|     def write_double(self, value: float, offset=0) -> None: ... | ||||
|     def write_bool(self, value: bool, offset=0) -> None: ... | ||||
|     def write_void_p(self, value: 'void_p', offset=0) -> None: ... | ||||
| 
 | ||||
| def char_(val: int) -> struct: ... | ||||
| def uchar_(val: int) -> struct: ... | ||||
| def short_(val: int) -> struct: ... | ||||
| def ushort_(val: int) -> struct: ... | ||||
| def int_(val: int) -> struct: ... | ||||
| def uint_(val: int) -> struct: ... | ||||
| def long_(val: int) -> struct: ... | ||||
| def ulong_(val: int) -> struct: ... | ||||
| def longlong_(val: int) -> struct: ... | ||||
| def ulonglong_(val: int) -> struct: ... | ||||
| def float_(val: float) -> struct: ... | ||||
| def double_(val: float) -> struct: ... | ||||
| def bool_(val: bool) -> struct: ... | ||||
| 
 | ||||
| class _StructLike(Generic[T]): | ||||
|     def tostruct(self) -> struct: ... | ||||
|     @classmethod | ||||
|     def fromstruct(cls, s: struct) -> T: ... | ||||
| 
 | ||||
|     def addr(self) -> 'Pointer[T]': ... | ||||
|     def copy(self) -> T: ... | ||||
|     def sizeof(self) -> int: ... | ||||
|     def __eq__(self, other: T) -> bool: ... | ||||
|     def __ne__(self, other: T) -> bool: ... | ||||
| 
 | ||||
| @ -1,4 +1,5 @@ | ||||
| from time import localtime | ||||
| import operator | ||||
| 
 | ||||
| class timedelta: | ||||
|     def __init__(self, days=0, seconds=0): | ||||
| @ -13,25 +14,10 @@ class timedelta: | ||||
|             return NotImplemented | ||||
|         return (self.days, self.seconds) == (other.days, other.seconds) | ||||
| 
 | ||||
|     def __lt__(self, other: 'timedelta') -> bool: | ||||
|     def __ne__(self, other: 'timedelta') -> bool: | ||||
|         if type(other) is not timedelta: | ||||
|             return NotImplemented | ||||
|         return (self.days, self.seconds) < (other.days, other.seconds) | ||||
| 
 | ||||
|     def __le__(self, other: 'timedelta') -> bool: | ||||
|         if type(other) is not timedelta: | ||||
|             return NotImplemented | ||||
|         return (self.days, self.seconds) <= (other.days, other.seconds) | ||||
| 
 | ||||
|     def __gt__(self, other: 'timedelta') -> bool: | ||||
|         if type(other) is not timedelta: | ||||
|             return NotImplemented | ||||
|         return (self.days, self.seconds) > (other.days, other.seconds) | ||||
| 
 | ||||
|     def __ge__(self, other: 'timedelta') -> bool: | ||||
|         if type(other) is not timedelta: | ||||
|             return NotImplemented | ||||
|         return (self.days, self.seconds) >= (other.days, other.seconds) | ||||
|         return (self.days, self.seconds) != (other.days, other.seconds) | ||||
| 
 | ||||
| 
 | ||||
| class date: | ||||
| @ -44,31 +30,33 @@ class date: | ||||
|     def today(): | ||||
|         t = localtime() | ||||
|         return date(t.tm_year, t.tm_mon, t.tm_mday) | ||||
|      | ||||
|     def __cmp(self, other, op): | ||||
|         if not isinstance(other, date): | ||||
|             return NotImplemented | ||||
|         if self.year != other.year: | ||||
|             return op(self.year, other.year) | ||||
|         if self.month != other.month: | ||||
|             return op(self.month, other.month) | ||||
|         return op(self.day, other.day) | ||||
| 
 | ||||
|     def __eq__(self, other: 'date') -> bool: | ||||
|         if type(other) is not date: | ||||
|             return NotImplemented | ||||
|         return (self.year, self.month, self.day) == (other.year, other.month, other.day) | ||||
|         return self.__cmp(other, operator.eq) | ||||
|      | ||||
|     def __ne__(self, other: 'date') -> bool: | ||||
|         return self.__cmp(other, operator.ne) | ||||
| 
 | ||||
|     def __lt__(self, other: 'date') -> bool: | ||||
|         if type(other) is not date: | ||||
|             return NotImplemented | ||||
|         return (self.year, self.month, self.day) < (other.year, other.month, other.day) | ||||
|         return self.__cmp(other, operator.lt) | ||||
| 
 | ||||
|     def __le__(self, other: 'date') -> bool: | ||||
|         if type(other) is not date: | ||||
|             return NotImplemented | ||||
|         return (self.year, self.month, self.day) <= (other.year, other.month, other.day) | ||||
|         return self.__cmp(other, operator.le) | ||||
| 
 | ||||
|     def __gt__(self, other: 'date') -> bool: | ||||
|         if type(other) is not date: | ||||
|             return NotImplemented | ||||
|         return (self.year, self.month, self.day) > (other.year, other.month, other.day) | ||||
|         return self.__cmp(other, operator.gt) | ||||
| 
 | ||||
|     def __ge__(self, other: 'date') -> bool: | ||||
|         if type(other) is not date: | ||||
|             return NotImplemented | ||||
|         return (self.year, self.month, self.day) >= (other.year, other.month, other.day) | ||||
|         return self.__cmp(other, operator.ge) | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return f"{self.year}-{self.month:02}-{self.day:02}" | ||||
| @ -108,41 +96,37 @@ class datetime(date): | ||||
|     def __repr__(self): | ||||
|         return f"datetime.datetime({self.year}, {self.month}, {self.day}, {self.hour}, {self.minute}, {self.second})" | ||||
| 
 | ||||
|     def __cmp(self, other, op): | ||||
|         if not isinstance(other, datetime): | ||||
|             return NotImplemented | ||||
|         if self.year != other.year: | ||||
|             return op(self.year, other.year) | ||||
|         if self.month != other.month: | ||||
|             return op(self.month, other.month) | ||||
|         if self.day != other.day: | ||||
|             return op(self.day, other.day) | ||||
|         if self.hour != other.hour: | ||||
|             return op(self.hour, other.hour) | ||||
|         if self.minute != other.minute: | ||||
|             return op(self.minute, other.minute) | ||||
|         return op(self.second, other.second) | ||||
| 
 | ||||
|     def __eq__(self, other) -> bool: | ||||
|         if type(other) is not datetime: | ||||
|             return NotImplemented | ||||
|         return (self.year, self.month, self.day, self.hour, self.minute, self.second) ==\ | ||||
|             (other.year, other.month, other.day, | ||||
|              other.hour, other.minute, other.second) | ||||
| 
 | ||||
|         return self.__cmp(other, operator.eq) | ||||
|      | ||||
|     def __ne__(self, other) -> bool: | ||||
|         return self.__cmp(other, operator.ne) | ||||
|      | ||||
|     def __lt__(self, other) -> bool: | ||||
|         if type(other) is not datetime: | ||||
|             return NotImplemented | ||||
|         return (self.year, self.month, self.day, self.hour, self.minute, self.second) <\ | ||||
|             (other.year, other.month, other.day, | ||||
|              other.hour, other.minute, other.second) | ||||
| 
 | ||||
|         return self.__cmp(other, operator.lt) | ||||
|      | ||||
|     def __le__(self, other) -> bool: | ||||
|         if type(other) is not datetime: | ||||
|             return NotImplemented | ||||
|         return (self.year, self.month, self.day, self.hour, self.minute, self.second) <=\ | ||||
|             (other.year, other.month, other.day, | ||||
|              other.hour, other.minute, other.second) | ||||
| 
 | ||||
|         return self.__cmp(other, operator.le) | ||||
|      | ||||
|     def __gt__(self, other) -> bool: | ||||
|         if type(other) is not datetime: | ||||
|             return NotImplemented | ||||
|         return (self.year, self.month, self.day, self.hour, self.minute, self.second) >\ | ||||
|             (other.year, other.month, other.day, | ||||
|              other.hour, other.minute, other.second) | ||||
| 
 | ||||
|         return self.__cmp(other, operator.gt) | ||||
|      | ||||
|     def __ge__(self, other) -> bool: | ||||
|         if type(other) is not datetime: | ||||
|             return NotImplemented | ||||
|         return (self.year, self.month, self.day, self.hour, self.minute, self.second) >=\ | ||||
|             (other.year, other.month, other.day, | ||||
|              other.hour, other.minute, other.second) | ||||
|         return self.__cmp(other, operator.ge) | ||||
| 
 | ||||
|     def timestamp(self) -> float: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|  | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -202,6 +202,8 @@ void VM__ctor(VM* self) { | ||||
|     pk__add_module_random(); | ||||
|     pk__add_module_json(); | ||||
|     pk__add_module_gc(); | ||||
|     pk__add_module_time(); | ||||
|     pk__add_module_easing(); | ||||
| 
 | ||||
|     // add python builtins
 | ||||
|     do { | ||||
| @ -329,7 +331,9 @@ py_Type pk_newtype(const char* name, | ||||
| } | ||||
| 
 | ||||
| py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, void (*dtor)(void*)) { | ||||
|     return pk_newtype(name, base, module, dtor, false, false); | ||||
|     py_Type type = pk_newtype(name, base, module, dtor, false, false); | ||||
|     if(module) py_setdict(module, py_name(name), py_tpobject(type)); | ||||
|     return type; | ||||
| } | ||||
| 
 | ||||
| static bool | ||||
|  | ||||
							
								
								
									
										251
									
								
								src/modules/easing.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										251
									
								
								src/modules/easing.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,251 @@ | ||||
| #include "pocketpy/pocketpy.h" | ||||
| #include "pocketpy/interpreter/vm.h" | ||||
| 
 | ||||
| #include "math.h" | ||||
| 
 | ||||
| // https://easings.net/
 | ||||
| 
 | ||||
| const double kPi = 3.1415926545; | ||||
| 
 | ||||
| static double easeLinear(double x) { return x; } | ||||
| 
 | ||||
| static double easeInSine(double x) { return 1.0 - cos(x * kPi / 2); } | ||||
| 
 | ||||
| static double easeOutSine(double x) { return sin(x * kPi / 2); } | ||||
| 
 | ||||
| static double easeInOutSine(double x) { return -(cos(kPi * x) - 1) / 2; } | ||||
| 
 | ||||
| static double easeInQuad(double x) { return x * x; } | ||||
| 
 | ||||
| static double easeOutQuad(double x) { return 1 - pow(1 - x, 2); } | ||||
| 
 | ||||
| static double easeInOutQuad(double x) { | ||||
|     if(x < 0.5) { | ||||
|         return 2 * x * x; | ||||
|     } else { | ||||
|         return 1 - pow(-2 * x + 2, 2) / 2; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static double easeInCubic(double x) { return x * x * x; } | ||||
| 
 | ||||
| static double easeOutCubic(double x) { return 1 - pow(1 - x, 3); } | ||||
| 
 | ||||
| static double easeInOutCubic(double x) { | ||||
|     if(x < 0.5) { | ||||
|         return 4 * x * x * x; | ||||
|     } else { | ||||
|         return 1 - pow(-2 * x + 2, 3) / 2; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static double easeInQuart(double x) { return pow(x, 4); } | ||||
| 
 | ||||
| static double easeOutQuart(double x) { return 1 - pow(1 - x, 4); } | ||||
| 
 | ||||
| static double easeInOutQuart(double x) { | ||||
|     if(x < 0.5) { | ||||
|         return 8 * pow(x, 4); | ||||
|     } else { | ||||
|         return 1 - pow(-2 * x + 2, 4) / 2; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static double easeInQuint(double x) { return pow(x, 5); } | ||||
| 
 | ||||
| static double easeOutQuint(double x) { return 1 - pow(1 - x, 5); } | ||||
| 
 | ||||
| static double easeInOutQuint(double x) { | ||||
|     if(x < 0.5) { | ||||
|         return 16 * pow(x, 5); | ||||
|     } else { | ||||
|         return 1 - pow(-2 * x + 2, 5) / 2; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static double easeInExpo(double x) { return x == 0 ? 0 : pow(2, 10 * x - 10); } | ||||
| 
 | ||||
| static double easeOutExpo(double x) { return x == 1 ? 1 : 1 - pow(2, -10 * x); } | ||||
| 
 | ||||
| static double easeInOutExpo(double x) { | ||||
|     if(x == 0) { | ||||
|         return 0; | ||||
|     } else if(x == 1) { | ||||
|         return 1; | ||||
|     } else if(x < 0.5) { | ||||
|         return pow(2, 20 * x - 10) / 2; | ||||
|     } else { | ||||
|         return (2 - pow(2, -20 * x + 10)) / 2; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static double easeInCirc(double x) { return 1 - sqrt(1 - pow(x, 2)); } | ||||
| 
 | ||||
| static double easeOutCirc(double x) { return sqrt(1 - pow(x - 1, 2)); } | ||||
| 
 | ||||
| static double easeInOutCirc(double x) { | ||||
|     if(x < 0.5) { | ||||
|         return (1 - sqrt(1 - pow(2 * x, 2))) / 2; | ||||
|     } else { | ||||
|         return (sqrt(1 - pow(-2 * x + 2, 2)) + 1) / 2; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static double easeInBack(double x) { | ||||
|     const double c1 = 1.70158; | ||||
|     const double c3 = c1 + 1; | ||||
|     return c3 * x * x * x - c1 * x * x; | ||||
| } | ||||
| 
 | ||||
| static double easeOutBack(double x) { | ||||
|     const double c1 = 1.70158; | ||||
|     const double c3 = c1 + 1; | ||||
|     return 1 + c3 * pow(x - 1, 3) + c1 * pow(x - 1, 2); | ||||
| } | ||||
| 
 | ||||
| static double easeInOutBack(double x) { | ||||
|     const double c1 = 1.70158; | ||||
|     const double c2 = c1 * 1.525; | ||||
|     if(x < 0.5) { | ||||
|         return (pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2; | ||||
|     } else { | ||||
|         return (pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static double easeInElastic(double x) { | ||||
|     const double c4 = (2 * kPi) / 3; | ||||
|     if(x == 0) { | ||||
|         return 0; | ||||
|     } else if(x == 1) { | ||||
|         return 1; | ||||
|     } else { | ||||
|         return -pow(2, 10 * x - 10) * sin((x * 10 - 10.75) * c4); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static double easeOutElastic(double x) { | ||||
|     const double c4 = (2 * kPi) / 3; | ||||
|     if(x == 0) { | ||||
|         return 0; | ||||
|     } else if(x == 1) { | ||||
|         return 1; | ||||
|     } else { | ||||
|         return pow(2, -10 * x) * sin((x * 10 - 0.75) * c4) + 1; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static double easeInOutElastic(double x) { | ||||
|     const double c5 = (2 * kPi) / 4.5; | ||||
|     if(x == 0) { | ||||
|         return 0; | ||||
|     } else if(x == 1) { | ||||
|         return 1; | ||||
|     } else if(x < 0.5) { | ||||
|         return -(pow(2, 20 * x - 10) * sin((20 * x - 11.125) * c5)) / 2; | ||||
|     } else { | ||||
|         return (pow(2, -20 * x + 10) * sin((20 * x - 11.125) * c5)) / 2 + 1; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static double easeOutBounce(double x) { | ||||
|     const double n1 = 7.5625; | ||||
|     const double d1 = 2.75; | ||||
|     if(x < 1 / d1) { | ||||
|         return n1 * x * x; | ||||
|     } else if(x < 2 / d1) { | ||||
|         x -= 1.5 / d1; | ||||
|         return n1 * x * x + 0.75; | ||||
|     } else if(x < 2.5 / d1) { | ||||
|         x -= 2.25 / d1; | ||||
|         return n1 * x * x + 0.9375; | ||||
|     } else { | ||||
|         x -= 2.625 / d1; | ||||
|         return n1 * x * x + 0.984375; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static double easeInBounce(double x) { return 1 - easeOutBounce(1 - x); } | ||||
| 
 | ||||
| static double easeInOutBounce(double x) { | ||||
|     return x < 0.5 ? (1 - easeOutBounce(1 - 2 * x)) / 2 : (1 + easeOutBounce(2 * x - 1)) / 2; | ||||
| } | ||||
| 
 | ||||
| #define DEF_EASE(name)                                                                             \ | ||||
|     static bool easing_##name(int argc, py_Ref argv) {                                             \ | ||||
|         PY_CHECK_ARGC(1);                                                                          \ | ||||
|         py_f64 t;                                                                                  \ | ||||
|         if(!py_castfloat(argv, &t)) return false;                                                  \ | ||||
|         py_newfloat(py_retval(), ease##name(t));                                                   \ | ||||
|         return true;                                                                               \ | ||||
|     } | ||||
| 
 | ||||
| DEF_EASE(Linear) | ||||
| DEF_EASE(InSine) | ||||
| DEF_EASE(OutSine) | ||||
| DEF_EASE(InOutSine) | ||||
| DEF_EASE(InQuad) | ||||
| DEF_EASE(OutQuad) | ||||
| DEF_EASE(InOutQuad) | ||||
| DEF_EASE(InCubic) | ||||
| DEF_EASE(OutCubic) | ||||
| DEF_EASE(InOutCubic) | ||||
| DEF_EASE(InQuart) | ||||
| DEF_EASE(OutQuart) | ||||
| DEF_EASE(InOutQuart) | ||||
| DEF_EASE(InQuint) | ||||
| DEF_EASE(OutQuint) | ||||
| DEF_EASE(InOutQuint) | ||||
| DEF_EASE(InExpo) | ||||
| DEF_EASE(OutExpo) | ||||
| DEF_EASE(InOutExpo) | ||||
| DEF_EASE(InCirc) | ||||
| DEF_EASE(OutCirc) | ||||
| DEF_EASE(InOutCirc) | ||||
| DEF_EASE(InBack) | ||||
| DEF_EASE(OutBack) | ||||
| DEF_EASE(InOutBack) | ||||
| DEF_EASE(InElastic) | ||||
| DEF_EASE(OutElastic) | ||||
| DEF_EASE(InOutElastic) | ||||
| DEF_EASE(InBounce) | ||||
| DEF_EASE(OutBounce) | ||||
| DEF_EASE(InOutBounce) | ||||
| 
 | ||||
| #undef DEF_EASE | ||||
| 
 | ||||
| void pk__add_module_easing() { | ||||
|     py_GlobalRef mod = py_newmodule("easing"); | ||||
| 
 | ||||
|     py_bindfunc(mod, "Linear", easing_Linear); | ||||
|     py_bindfunc(mod, "InSine", easing_InSine); | ||||
|     py_bindfunc(mod, "OutSine", easing_OutSine); | ||||
|     py_bindfunc(mod, "InOutSine", easing_InOutSine); | ||||
|     py_bindfunc(mod, "InQuad", easing_InQuad); | ||||
|     py_bindfunc(mod, "OutQuad", easing_OutQuad); | ||||
|     py_bindfunc(mod, "InOutQuad", easing_InOutQuad); | ||||
|     py_bindfunc(mod, "InCubic", easing_InCubic); | ||||
|     py_bindfunc(mod, "OutCubic", easing_OutCubic); | ||||
|     py_bindfunc(mod, "InOutCubic", easing_InOutCubic); | ||||
|     py_bindfunc(mod, "InQuart", easing_InQuart); | ||||
|     py_bindfunc(mod, "OutQuart", easing_OutQuart); | ||||
|     py_bindfunc(mod, "InOutQuart", easing_InOutQuart); | ||||
|     py_bindfunc(mod, "InQuint", easing_InQuint); | ||||
|     py_bindfunc(mod, "OutQuint", easing_OutQuint); | ||||
|     py_bindfunc(mod, "InOutQuint", easing_InOutQuint); | ||||
|     py_bindfunc(mod, "InExpo", easing_InExpo); | ||||
|     py_bindfunc(mod, "OutExpo", easing_OutExpo); | ||||
|     py_bindfunc(mod, "InOutExpo", easing_InOutExpo); | ||||
|     py_bindfunc(mod, "InCirc", easing_InCirc); | ||||
|     py_bindfunc(mod, "OutCirc", easing_OutCirc); | ||||
|     py_bindfunc(mod, "InOutCirc", easing_InOutCirc); | ||||
|     py_bindfunc(mod, "InBack", easing_InBack); | ||||
|     py_bindfunc(mod, "OutBack", easing_OutBack); | ||||
|     py_bindfunc(mod, "InOutBack", easing_InOutBack); | ||||
|     py_bindfunc(mod, "InElastic", easing_InElastic); | ||||
|     py_bindfunc(mod, "OutElastic", easing_OutElastic); | ||||
|     py_bindfunc(mod, "InOutElastic", easing_InOutElastic); | ||||
|     py_bindfunc(mod, "InBounce", easing_InBounce); | ||||
|     py_bindfunc(mod, "OutBounce", easing_OutBounce); | ||||
|     py_bindfunc(mod, "InOutBounce", easing_InOutBounce); | ||||
| } | ||||
| @ -10,13 +10,12 @@ static bool json_loads(int argc, py_Ref argv) { | ||||
|     PY_CHECK_ARGC(1); | ||||
|     PY_CHECK_ARG_TYPE(0, tp_str); | ||||
|     const char* source = py_tostr(argv); | ||||
|     py_GlobalRef mod = py_getmodule("json"); | ||||
|     return py_exec(source, "<json>", EVAL_MODE, mod); | ||||
|     return py_json_loads(source); | ||||
| } | ||||
| 
 | ||||
| static bool json_dumps(int argc, py_Ref argv) { | ||||
|     PY_CHECK_ARGC(1); | ||||
|     return py_json(argv); | ||||
|     return py_json_dumps(argv); | ||||
| } | ||||
| 
 | ||||
| void pk__add_module_json() { | ||||
| @ -98,14 +97,26 @@ static bool json__write_object(c11_sbuf* buf, py_TValue* obj) { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool py_json(py_Ref val) { | ||||
| bool py_json_dumps(py_Ref val) { | ||||
|     c11_sbuf buf; | ||||
|     c11_sbuf__ctor(&buf); | ||||
|     bool ok = json__write_object(&buf, val); | ||||
|     if(!ok){ | ||||
|     if(!ok) { | ||||
|         c11_sbuf__dtor(&buf); | ||||
|         return false; | ||||
|     } | ||||
|     c11_sbuf__py_submit(&buf, py_retval()); | ||||
|     return true; | ||||
| } | ||||
| } | ||||
| 
 | ||||
| bool py_json_loads(const char* source) { | ||||
|     py_GlobalRef mod = py_getmodule("json"); | ||||
|     return py_exec(source, "<json>", EVAL_MODE, mod); | ||||
| } | ||||
| 
 | ||||
| bool py_pusheval(const char* expr, py_GlobalRef module) { | ||||
|     bool ok = py_exec(expr, "<string>", EVAL_MODE, module); | ||||
|     if(!ok) return false; | ||||
|     py_push(py_retval()); | ||||
|     return true; | ||||
| } | ||||
|  | ||||
							
								
								
									
										103
									
								
								src/modules/time.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/modules/time.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| #include "pocketpy/pocketpy.h" | ||||
| #include "pocketpy/interpreter/vm.h" | ||||
| #include "time.h" | ||||
| 
 | ||||
| #define NANOS_PER_SEC 1000000000 | ||||
| 
 | ||||
| static bool get_ns(int64_t* out) { | ||||
|     struct timespec tms; | ||||
|     /* The C11 way */ | ||||
|     if(!timespec_get(&tms, TIME_UTC)) { | ||||
|         return py_exception(tp_OSError, "%s", "timespec_get() failed"); | ||||
|     } | ||||
|     /* seconds, multiplied with 1 billion */ | ||||
|     int64_t nanos = tms.tv_sec * NANOS_PER_SEC; | ||||
|     /* Add full nanoseconds */ | ||||
|     nanos += tms.tv_nsec; | ||||
|     *out = nanos; | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| static bool time_time(int argc, py_Ref argv) { | ||||
|     PY_CHECK_ARGC(0); | ||||
|     int64_t nanos; | ||||
|     if(!get_ns(&nanos)) return false; | ||||
|     py_newfloat(py_retval(), (double)nanos / NANOS_PER_SEC); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| static bool time_time_ns(int argc, py_Ref argv) { | ||||
|     PY_CHECK_ARGC(0); | ||||
|     int64_t nanos; | ||||
|     if(!get_ns(&nanos)) return false; | ||||
|     py_newint(py_retval(), nanos); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| static bool time_sleep(int argc, py_Ref argv) { | ||||
|     PY_CHECK_ARGC(1); | ||||
|     py_f64 secs; | ||||
|     if(!py_castfloat(argv, &secs)) return false; | ||||
| 
 | ||||
|     int64_t start; | ||||
|     if(!get_ns(&start)) return false; | ||||
|     const int64_t end = start + secs * 1000000000; | ||||
|     while(true) { | ||||
|         int64_t now; | ||||
|         if(!get_ns(&now)) return false; | ||||
|         if(now >= end) break; | ||||
|     } | ||||
|     py_newnone(py_retval()); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| static bool time_localtime(int argc, py_Ref argv) { | ||||
|     PY_CHECK_ARGC(0); | ||||
|     py_Type tp_struct_time = py_gettype("time", py_name("struct_time")); | ||||
|     assert(tp_struct_time); | ||||
|     struct tm* ud = py_newobject(py_retval(), tp_struct_time, 0, sizeof(struct tm)); | ||||
|     time_t t = time(NULL); | ||||
|     *ud = *localtime(&t); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| #define DEF_STRUCT_TIME__PROPERTY(name, expr)                                                      \ | ||||
|     static bool struct_time__##name(int argc, py_Ref argv) {                                       \ | ||||
|         PY_CHECK_ARGC(1);                                                                          \ | ||||
|         struct tm* tm = py_touserdata(argv);                                                       \ | ||||
|         py_newint(py_retval(), expr);                                                              \ | ||||
|         return true;                                                                               \ | ||||
|     } | ||||
| 
 | ||||
| DEF_STRUCT_TIME__PROPERTY(tm_year, tm->tm_year + 1900) | ||||
| DEF_STRUCT_TIME__PROPERTY(tm_mon, tm->tm_mon + 1) | ||||
| DEF_STRUCT_TIME__PROPERTY(tm_mday, tm->tm_mday) | ||||
| DEF_STRUCT_TIME__PROPERTY(tm_hour, tm->tm_hour) | ||||
| DEF_STRUCT_TIME__PROPERTY(tm_min, tm->tm_min) | ||||
| DEF_STRUCT_TIME__PROPERTY(tm_sec, tm->tm_sec) | ||||
| DEF_STRUCT_TIME__PROPERTY(tm_wday, (tm->tm_wday + 6) % 7) | ||||
| DEF_STRUCT_TIME__PROPERTY(tm_yday, tm->tm_yday + 1) | ||||
| DEF_STRUCT_TIME__PROPERTY(tm_isdst, tm->tm_isdst) | ||||
| 
 | ||||
| #undef DEF_STRUCT_TIME__PROPERTY | ||||
| 
 | ||||
| void pk__add_module_time() { | ||||
|     py_Ref mod = py_newmodule("time"); | ||||
| 
 | ||||
|     py_Type tp_struct_time = py_newtype("struct_time", tp_object, mod, NULL); | ||||
| 
 | ||||
|     py_bindproperty(tp_struct_time, "tm_year", struct_time__tm_year, NULL); | ||||
|     py_bindproperty(tp_struct_time, "tm_mon", struct_time__tm_mon, NULL); | ||||
|     py_bindproperty(tp_struct_time, "tm_mday", struct_time__tm_mday, NULL); | ||||
|     py_bindproperty(tp_struct_time, "tm_hour", struct_time__tm_hour, NULL); | ||||
|     py_bindproperty(tp_struct_time, "tm_min", struct_time__tm_min, NULL); | ||||
|     py_bindproperty(tp_struct_time, "tm_sec", struct_time__tm_sec, NULL); | ||||
|     py_bindproperty(tp_struct_time, "tm_wday", struct_time__tm_wday, NULL); | ||||
|     py_bindproperty(tp_struct_time, "tm_yday", struct_time__tm_yday, NULL); | ||||
|     py_bindproperty(tp_struct_time, "tm_isdst", struct_time__tm_isdst, NULL); | ||||
| 
 | ||||
|     py_bindfunc(mod, "time", time_time); | ||||
|     py_bindfunc(mod, "time_ns", time_time_ns); | ||||
|     py_bindfunc(mod, "sleep", time_sleep); | ||||
|     py_bindfunc(mod, "localtime", time_localtime); | ||||
| } | ||||
| @ -57,4 +57,12 @@ bool py_issubclass(py_Type derived, py_Type base) { | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| py_Type py_typeof(py_Ref self) { return self->type; } | ||||
| py_Type py_typeof(py_Ref self) { return self->type; } | ||||
| 
 | ||||
| py_Type py_gettype(const char* module, py_Name name) { | ||||
|     py_Ref mod = py_getmodule(module); | ||||
|     if(!mod) return 0; | ||||
|     py_Ref object = py_getdict(mod, name); | ||||
|     if(object && py_istype(object, tp_type)) return py_totype(object); | ||||
|     return 0; | ||||
| } | ||||
| @ -21,9 +21,6 @@ py_Ref py_getdict(py_Ref self, py_Name name) { | ||||
| 
 | ||||
| void py_setdict(py_Ref self, py_Name name, py_Ref val) { | ||||
|     assert(self && self->is_ptr); | ||||
|     // if(py_isidentical(self, &pk_current_vm->main)){
 | ||||
|     //     printf("Setting main: %s\n", py_name2str(name));
 | ||||
|     // }
 | ||||
|     if(!py_ismagicname(name) || self->type != tp_type) { | ||||
|         NameDict__set(PyObject__dict(self->_obj), name, *val); | ||||
|     } else { | ||||
| @ -67,6 +64,12 @@ py_StackRef py_inspect_currentfunction(){ | ||||
|     return frame->p0; | ||||
| } | ||||
| 
 | ||||
| py_GlobalRef py_inspect_currentmodule(){ | ||||
|     Frame* frame = pk_current_vm->top_frame; | ||||
|     if(!frame) return NULL; | ||||
|     return frame->module; | ||||
| } | ||||
| 
 | ||||
| void py_assign(py_Ref dst, py_Ref src) { *dst = *src; } | ||||
| 
 | ||||
| /* Stack References */ | ||||
| @ -100,8 +103,12 @@ void py_pushnone() { | ||||
|     py_newnone(vm->stack.sp++); | ||||
| } | ||||
| 
 | ||||
| void py_pushname(py_Name name){ | ||||
|     VM* vm = pk_current_vm; | ||||
|     py_newint(vm->stack.sp++, name); | ||||
| } | ||||
| 
 | ||||
| py_Ref py_pushtmp() { | ||||
|     VM* vm = pk_current_vm; | ||||
|     py_newnil(vm->stack.sp++); | ||||
|     return py_peek(-1); | ||||
|     return vm->stack.sp++; | ||||
| } | ||||
| @ -4,11 +4,6 @@ import datetime | ||||
| def test_timedelta(): | ||||
|     assert datetime.timedelta(days=1) == datetime.timedelta(days=1) | ||||
|     assert datetime.timedelta(days=1) != datetime.timedelta(days=2) | ||||
|     assert datetime.timedelta(days=1, seconds=1) >= datetime.timedelta(days=1) | ||||
|     assert datetime.timedelta(days=0, seconds=1) <= datetime.timedelta(days=1) | ||||
|     assert datetime.timedelta(days=1, seconds=1) < datetime.timedelta(days=2) | ||||
|     assert datetime.timedelta(days=1, seconds=1) > datetime.timedelta(days=0) | ||||
| 
 | ||||
| 
 | ||||
| def test_date(): | ||||
|     assert datetime.date(2023, 8, 5) == datetime.date(2023, 8, 5) | ||||
| @ -18,7 +13,6 @@ def test_date(): | ||||
|     assert datetime.date(2024, 8, 5) > datetime.date(2023, 8, 6) | ||||
|     assert datetime.date(2023, 8, 5) < datetime.date(2024, 8, 6) | ||||
| 
 | ||||
| 
 | ||||
| def test_datetime(): | ||||
|     assert datetime.datetime( | ||||
|         2023, 8, 5, 12, 0, 0) == datetime.datetime(2023, 8, 5, 12, 0, 0) | ||||
| @ -33,7 +27,6 @@ def test_datetime(): | ||||
|     assert datetime.datetime( | ||||
|         2023, 8, 5, 12, 0, 0) <= datetime.datetime(2023, 8, 5, 12, 1, 0) | ||||
| 
 | ||||
| 
 | ||||
| test_timedelta() | ||||
| test_date() | ||||
| test_datetime() | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| from linalg import mat3x3, vec2, vec3, vec4 | ||||
| from linalg import mat3x3, vec2, vec3 | ||||
| import random | ||||
| import sys | ||||
| import math | ||||
| @ -69,25 +69,6 @@ element_value_list = [getattr(test_vec3, attr) for attr in element_name_list] | ||||
| copy_element_value_list = [getattr(test_vec3, attr) for attr in element_name_list] | ||||
| assert element_value_list == copy_element_value_list | ||||
| 
 | ||||
| # test vec4-------------------------------------------------------------------- | ||||
| # 生成随机测试目标 | ||||
| min_num = -10.0 | ||||
| max_num = 10.0 | ||||
| test_vec4 = vec4(*tuple([random.uniform(min_num, max_num) for _ in range(4)])) | ||||
| static_test_vec4_float = vec4(3.1886954323, -1098399.59932453432, 9.00000000000002765, 4565400000000.0000000045) | ||||
| static_test_vec4_int = vec4(278, -13919730938747, 1364223456756456, -37) | ||||
| 
 | ||||
| # test __repr__ | ||||
| assert str(static_test_vec4_float).startswith('vec4(') | ||||
| assert str(static_test_vec4_int).startswith('vec4(') | ||||
| 
 | ||||
| # test copy | ||||
| element_name_list = ['x', 'y', 'z', 'w'] | ||||
| element_value_list = [getattr(test_vec4, attr) for attr in element_name_list] | ||||
| copy_element_value_list = [getattr(test_vec4.copy(), attr) for attr in element_name_list] | ||||
| assert element_value_list == copy_element_value_list | ||||
| 
 | ||||
| 
 | ||||
| # test mat3x3-------------------------------------------------------------------- | ||||
| def mat_to_str_list(mat): | ||||
|     ret = [[0,0,0], [0,0,0], [0,0,0]] | ||||
| @ -446,13 +427,6 @@ assert test_mat_copy.inverse_transform_point(test_vec2_copy) == test_mat_copy.in | ||||
| # test inverse_transform_vector | ||||
| assert test_mat_copy.inverse_transform_vector(test_vec2_copy) == test_mat_copy.inverse().transform_vector(test_vec2_copy) | ||||
| 
 | ||||
| import c | ||||
| a = vec4(1, 2, 3, 4) | ||||
| b = a.tostruct() | ||||
| assert a.sizeof() == 16 | ||||
| assert b.sizeof() == 16 | ||||
| assert vec4.fromstruct(b) == a | ||||
| 
 | ||||
| val = vec2.angle(vec2(-1, 0), vec2(0, -1)) | ||||
| assert 1.57 < val < 1.58 | ||||
| 
 | ||||
| @ -466,12 +440,6 @@ class mymat3x3(mat3x3): | ||||
|      | ||||
| assert mymat3x3().f() | ||||
| 
 | ||||
| 
 | ||||
| # test assign | ||||
| c = vec4(1, 2, 3, 4) | ||||
| assert c.copy_(vec4(5, 6, 7, 8)) is None | ||||
| assert c == vec4(5, 6, 7, 8) | ||||
| 
 | ||||
| d = mat3x3.identity() | ||||
| assert d.copy_(mat3x3.zeros()) is None | ||||
| assert d == mat3x3.zeros() | ||||
| @ -491,9 +459,7 @@ except IndexError: | ||||
| # test vec * vec | ||||
| assert vec2(1, 2) * vec2(3, 4) == vec2(3, 8) | ||||
| assert vec3(1, 2, 3) * vec3(4, 5, 6) == vec3(4, 10, 18) | ||||
| assert vec4(1, 2, 3, 4) * vec4(5, 6, 7, 8) == vec4(5, 12, 21, 32) | ||||
| 
 | ||||
| # test vec.__getitem__ | ||||
| assert vec2(1, 2)[0] == 1 and vec2(1, 2)[1] == 2 | ||||
| assert vec3(1, 2, 3)[0] == 1 and vec3(1, 2, 3)[1] == 2 and vec3(1, 2, 3)[2] == 3 | ||||
| assert vec4(1, 2, 3, 4)[0] == 1 and vec4(1, 2, 3, 4)[1] == 2 and vec4(1, 2, 3, 4)[2] == 3 and vec4(1, 2, 3, 4)[3] == 4 | ||||
| assert vec3(1, 2, 3)[0] == 1 and vec3(1, 2, 3)[1] == 2 and vec3(1, 2, 3)[2] == 3 | ||||
| @ -259,14 +259,15 @@ DEALINGS IN THE SOFTWARE. | ||||
|     var Module = { | ||||
|       onRuntimeInitialized: function () { | ||||
|         Module.ccall('py_initialize', null, [], []); | ||||
|         console.log("py_initialize() called"); | ||||
|       }, | ||||
|       print: function (text) { | ||||
|         console.log(text); | ||||
|         code_output.innerText += text + '\n'; | ||||
|       }, | ||||
|       onabort: function (what) { | ||||
|         code_output.innerText += 'Aborted: ' + what + '\n'; | ||||
|         Module.ccall('py_finalize', null, [], []); | ||||
|         console.log("py_finalize() called"); | ||||
|       } | ||||
|     }; | ||||
|   </script> | ||||
| @ -294,6 +295,7 @@ DEALINGS IN THE SOFTWARE. | ||||
|           'py_exec', 'boolean', ['string', 'string', 'number', 'number'], | ||||
|           [source, 'main.py', 0, 0] | ||||
|         ); | ||||
|         console.log("py_exec() called"); | ||||
|         if (!ok) { | ||||
|           Module.ccall('py_printexc', null, [], []); | ||||
|           Module.ccall('py_clearexc', null, ['number'], [0]); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user