mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-27 15:00:18 +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."
|
||||
|
||||
@ -8,3 +8,5 @@ void pk__add_module_dis();
|
||||
void pk__add_module_random();
|
||||
void pk__add_module_json();
|
||||
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");
|
||||
@ -23,6 +23,7 @@ typedef double py_f64;
|
||||
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
|
||||
|
||||
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:
|
||||
@ -45,30 +31,32 @@ class date:
|
||||
t = localtime()
|
||||
return date(t.tm_year, t.tm_mon, t.tm_mday)
|
||||
|
||||
def __eq__(self, other: 'date') -> bool:
|
||||
if type(other) is not date:
|
||||
def __cmp(self, other, op):
|
||||
if not isinstance(other, date):
|
||||
return NotImplemented
|
||||
return (self.year, self.month, self.day) == (other.year, other.month, other.day)
|
||||
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:
|
||||
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 __eq__(self, other) -> bool:
|
||||
if type(other) is not datetime:
|
||||
def __cmp(self, other, op):
|
||||
if not isinstance(other, 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)
|
||||
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:
|
||||
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);
|
||||
}
|
||||
@ -58,3 +58,11 @@ bool py_issubclass(py_Type derived, py_Type base) {
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@ -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