This commit is contained in:
blueloveTH 2024-08-12 13:51:44 +08:00
parent 26c553eb9a
commit 26a12bb640

View File

@ -22,7 +22,8 @@ typedef double py_f64;
typedef void (*py_Dtor)(void*); 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 { typedef struct c11_sv {
const char* data; const char* data;
@ -44,7 +45,7 @@ typedef py_TValue* py_ItemRef;
/// @param argc number of arguments. /// @param argc number of arguments.
/// @param argv array of arguments. Use `py_arg(i)` macro to get the i-th argument. /// @param argv array of arguments. Use `py_arg(i)` macro to get the i-th argument.
/// @return true if the function is successful. /// @return true if the function is successful.
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 }; enum py_CompileMode { EXEC_MODE, EVAL_MODE, SINGLE_MODE };
@ -74,7 +75,7 @@ void py_switchvm(int index);
bool py_exec(const char* source, bool py_exec(const char* source,
const char* filename, const char* filename,
enum py_CompileMode mode, 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)) #define py_eval(source, module) py_exec((source), "<string>", EVAL_MODE, (module))
@ -83,7 +84,7 @@ bool py_exec(const char* source,
bool py_compile(const char* source, bool py_compile(const char* source,
const char* filename, const char* filename,
enum py_CompileMode mode, enum py_CompileMode mode,
bool is_dynamic) PY_RAISE; bool is_dynamic) PY_RAISE PY_RETURN;
/// Python equivalent to `globals()`. /// Python equivalent to `globals()`.
void py_newglobals(py_Ref); void py_newglobals(py_Ref);
@ -228,7 +229,7 @@ py_ItemRef py_tpobject(py_Type type);
/// Get the type name. /// Get the type name.
const char* py_tpname(py_Type type); const char* py_tpname(py_Type type);
/// Call a type to create a new instance. /// 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. /// Check if the object is an instance of the given type.
/// Raise `TypeError` if the check fails. /// Raise `TypeError` if the check fails.
@ -323,13 +324,13 @@ void py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFu
/************* Python Equivalents *************/ /************* Python Equivalents *************/
/// Python equivalent to `getattr(self, name)`. /// 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)`. /// Python equivalent to `setattr(self, name, val)`.
bool py_setattr(py_Ref self, py_Name name, py_Ref val) PY_RAISE; bool py_setattr(py_Ref self, py_Name name, py_Ref val) PY_RAISE;
/// Python equivalent to `delattr(self, name)`. /// Python equivalent to `delattr(self, name)`.
bool py_delattr(py_Ref self, py_Name name) PY_RAISE; bool py_delattr(py_Ref self, py_Name name) PY_RAISE;
/// Python equivalent to `self[key]`. /// 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`. /// Python equivalent to `self[key] = val`.
bool py_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE; bool py_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
/// Python equivalent to `del self[key]`. /// Python equivalent to `del self[key]`.
@ -338,7 +339,7 @@ bool py_delitem(py_Ref self, py_Ref key) PY_RAISE;
/// Perform a binary operation. /// Perform a binary operation.
/// The result will be set to `py_retval()`. /// The result will be set to `py_retval()`.
/// The stack remains unchanged after the operation. /// 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_binaryadd(lhs, rhs) py_binaryop(lhs, rhs, __add__, __radd__)
#define py_binarysub(lhs, rhs) py_binaryop(lhs, rhs, __sub__, __rsub__) #define py_binarysub(lhs, rhs) py_binaryop(lhs, rhs, __sub__, __rsub__)
@ -383,7 +384,7 @@ bool py_pushmethod(py_Name name);
/// Assume `argc + kwargc` arguments are already pushed to the stack. /// Assume `argc + kwargc` arguments are already pushed to the stack.
/// The result will be set to `py_retval()`. /// The result will be set to `py_retval()`.
/// The stack size will be reduced by `argc + kwargc`. /// 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. /// Evaluate an expression and push the result to the stack.
/// This function is used for testing. /// This function is used for testing.
bool py_pusheval(const char* expr, py_GlobalRef module) PY_RAISE; bool py_pusheval(const char* expr, py_GlobalRef module) PY_RAISE;
@ -441,7 +442,7 @@ bool KeyError(py_Ref key) PY_RAISE;
/// Python equivalent to `bool(val)`. /// Python equivalent to `bool(val)`.
/// 1: true, 0: false, -1: error /// 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. /// Compare two objects.
/// 1: lhs == rhs, 0: lhs != rhs, -1: error /// 1: lhs == rhs, 0: lhs != rhs, -1: error
@ -460,36 +461,36 @@ int py_less(py_Ref lhs, py_Ref rhs) PY_RAISE;
/// Get the hash value of the object. /// Get the hash value of the object.
bool py_hash(py_Ref, py_i64* out) PY_RAISE; bool py_hash(py_Ref, py_i64* out) PY_RAISE;
/// Get the iterator of the object. /// 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. /// Get the next element from the iterator.
/// 1: success, 0: StopIteration, -1: error /// 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`. /// Python equivalent to `lhs is rhs`.
bool py_isidentical(py_Ref, py_Ref); bool py_isidentical(py_Ref, py_Ref);
/// Call a function. /// Call a function.
/// It prepares the stack and then performs a `vectorcall(argc, 0, false)`. /// It prepares the stack and then performs a `vectorcall(argc, 0, false)`.
/// The result will be set to `py_retval()`. /// The result will be set to `py_retval()`.
/// The stack remains unchanged after the operation. /// 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 #if PK_DEBUG
/// Call a py_CFunction in a safe way. /// Call a py_CFunction in a safe way.
/// This function does extra checks to help you debug `py_CFunction`. /// 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 #else
#define py_callcfunc(f, argc, argv) (f((argc), (argv))) #define py_callcfunc(f, argc, argv) (f((argc), (argv)))
#endif #endif
/// Python equivalent to `str(val)`. /// 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)`. /// 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)`. /// 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)`. /// Python equivalent to `json.dumps(val)`.
bool py_json_dumps(py_Ref val) PY_RAISE; bool py_json_dumps(py_Ref val) PY_RAISE PY_RETURN;
/// Python equivalent to `json.loads(val)`. /// Python equivalent to `json.loads(val)`.
bool py_json_loads(const char* source) PY_RAISE; bool py_json_loads(const char* source) PY_RAISE PY_RETURN;
/************* Unchecked Functions *************/ /************* Unchecked Functions *************/
@ -509,7 +510,7 @@ void py_list_clear(py_Ref self);
void py_list_insert(py_Ref self, int i, py_Ref val); void py_list_insert(py_Ref self, int i, py_Ref val);
/// -1: error, 0: not found, 1: found /// -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 /// true: success, false: error
bool py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE; bool py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
/// -1: error, 0: not found, 1: found (and deleted) /// -1: error, 0: not found, 1: found (and deleted)
@ -526,7 +527,7 @@ int py_dict_len(py_Ref self);
/// An utility function to read a line from stdin for REPL. /// An utility function to read a line from stdin for REPL.
int py_replinput(char* buf, int max_size); int py_replinput(char* buf, int max_size);
/// Python favored string formatting. (just put here, not for users) /// Python favored string formatting.
/// %d: int /// %d: int
/// %i: py_i64 (int64_t) /// %i: py_i64 (int64_t)
/// %f: py_f64 (double) /// %f: py_f64 (double)
@ -604,14 +605,3 @@ enum py_PredefinedTypes {
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #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.
*/