mirror of
https://github.com/pocketpy/pocketpy
synced 2025-12-10 12:10:16 +00:00
Compare commits
14 Commits
50ec46fe83
...
65295f3e29
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65295f3e29 | ||
|
|
56097f6927 | ||
|
|
7ca97f03a7 | ||
|
|
ee29eadcd3 | ||
|
|
4254de48bf | ||
|
|
693026c6c4 | ||
|
|
33bea83e53 | ||
|
|
26f53bf85d | ||
|
|
f28335f1f7 | ||
|
|
9fbaca3b13 | ||
|
|
4e8920b280 | ||
|
|
0918256c90 | ||
|
|
90eb50a3a5 | ||
|
|
1735e0d3b8 |
@ -7,12 +7,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define PK_INLINE inline
|
||||
#else
|
||||
#define PK_INLINE static inline
|
||||
#endif
|
||||
|
||||
#define PK_REGION(name) 1
|
||||
|
||||
#define PK_SLICE_LOOP(i, start, stop, step) \
|
||||
|
||||
@ -38,38 +38,26 @@ typedef struct Frame {
|
||||
struct Frame* f_back;
|
||||
const Bytecode* ip;
|
||||
const CodeObject* co;
|
||||
py_TValue module; // weak ref
|
||||
PyObject* function; // a function object or NULL (global scope)
|
||||
py_TValue* p0; // unwinding base
|
||||
py_TValue* locals; // locals base
|
||||
py_TValue module; // weak ref
|
||||
py_StackRef function; // a function object or NULL (global scope)
|
||||
py_StackRef p0; // unwinding base
|
||||
py_StackRef locals; // locals base
|
||||
const CodeObject* locals_co;
|
||||
UnwindTarget* uw_list;
|
||||
} Frame;
|
||||
|
||||
Frame* Frame__new(const CodeObject* co,
|
||||
py_TValue* module,
|
||||
const py_TValue* function,
|
||||
py_TValue* p0,
|
||||
py_TValue* locals,
|
||||
py_StackRef function,
|
||||
py_StackRef p0,
|
||||
py_StackRef locals,
|
||||
const CodeObject* locals_co);
|
||||
void Frame__delete(Frame* self);
|
||||
|
||||
PK_INLINE int Frame__ip(const Frame* self) { return self->ip - (Bytecode*)self->co->codes.data; }
|
||||
|
||||
PK_INLINE int Frame__lineno(const Frame* self) {
|
||||
int ip = Frame__ip(self);
|
||||
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).lineno;
|
||||
}
|
||||
|
||||
PK_INLINE int Frame__iblock(const Frame* self) {
|
||||
int ip = Frame__ip(self);
|
||||
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).iblock;
|
||||
}
|
||||
|
||||
PK_INLINE py_TValue* Frame__f_locals_try_get(Frame* self, py_Name name) {
|
||||
return FastLocals__try_get_by_name(self->locals, self->locals_co, name);
|
||||
}
|
||||
|
||||
int Frame__ip(const Frame* self);
|
||||
int Frame__lineno(const Frame* self);
|
||||
int Frame__iblock(const Frame* self);
|
||||
py_TValue* Frame__f_locals_try_get(Frame* self, py_Name name);
|
||||
py_TValue* Frame__f_closure_try_get(Frame* self, py_Name name);
|
||||
|
||||
int Frame__prepare_jump_exception_handler(Frame* self, ValueStack*);
|
||||
|
||||
@ -51,6 +51,7 @@ extern py_GlobalRef py_None;
|
||||
extern py_GlobalRef py_NIL;
|
||||
|
||||
/************* Global Setup *************/
|
||||
|
||||
/// Initialize pocketpy and the default VM.
|
||||
void py_initialize();
|
||||
/// Finalize pocketpy.
|
||||
@ -73,67 +74,102 @@ bool py_exec(const char* source,
|
||||
py_Ref module) PY_RAISE;
|
||||
|
||||
/************* Values Creation *************/
|
||||
void py_newint(py_Ref, py_i64);
|
||||
void py_newfloat(py_Ref, py_f64);
|
||||
void py_newbool(py_Ref, bool);
|
||||
void py_newstr(py_Ref, const char*);
|
||||
void py_newstrn(py_Ref, const char*, int);
|
||||
unsigned char* py_newbytes(py_Ref, int);
|
||||
void py_newnone(py_Ref);
|
||||
void py_newnotimplemented(py_Ref out);
|
||||
void py_newellipsis(py_Ref out);
|
||||
void py_newnil(py_Ref);
|
||||
|
||||
/// Create a tuple with n UNINITIALIZED elements.
|
||||
/// Create an `int` object.
|
||||
void py_newint(py_Ref, py_i64);
|
||||
/// Create a `float` object.
|
||||
void py_newfloat(py_Ref, py_f64);
|
||||
/// Create a `bool` object.
|
||||
void py_newbool(py_Ref, bool);
|
||||
/// Create a `str` object from a null-terminated string (utf-8).
|
||||
void py_newstr(py_Ref, const char*);
|
||||
/// Create a `str` object from a char array (utf-8).
|
||||
void py_newstrn(py_Ref, const char*, int);
|
||||
/// Create a `bytes` object with `n` UNINITIALIZED bytes.
|
||||
unsigned char* py_newbytes(py_Ref, int n);
|
||||
/// Create a `None` object.
|
||||
void py_newnone(py_Ref);
|
||||
/// Create a `NotImplemented` object.
|
||||
void py_newnotimplemented(py_Ref out);
|
||||
/// Create a `...` object.
|
||||
void py_newellipsis(py_Ref out);
|
||||
/// Create a `nil` object. `nil` is an invalid representation of an object.
|
||||
/// Don't use it unless you know what you are doing.
|
||||
void py_newnil(py_Ref);
|
||||
/// Create a `tuple` with `n` UNINITIALIZED elements.
|
||||
/// You should initialize all elements before using it.
|
||||
void py_newtuple(py_Ref, int n);
|
||||
/// Create a list.
|
||||
/// Create an empty `list`.
|
||||
void py_newlist(py_Ref);
|
||||
/// Create a list with n UNINITIALIZED elements.
|
||||
/// Create a `list` with `n` UNINITIALIZED elements.
|
||||
/// You should initialize all elements before using it.
|
||||
void py_newlistn(py_Ref, int n);
|
||||
|
||||
/// Create an empty `dict`.
|
||||
void py_newdict(py_Ref);
|
||||
/// Create an UNINITIALIZED `slice` object.
|
||||
/// You should use `py_setslot()` to set `start`, `stop`, and `step`.
|
||||
void py_newslice(py_Ref);
|
||||
/// Create a `nativefunc` object.
|
||||
void py_newnativefunc(py_Ref out, py_CFunction);
|
||||
/// Create a `function` object.
|
||||
py_Name
|
||||
py_newfunction(py_Ref out, const char* sig, py_CFunction f, const char* docstring, int slots);
|
||||
/// Create a `boundmethod` object.
|
||||
void py_newboundmethod(py_Ref out, py_Ref self, py_Ref func);
|
||||
|
||||
/************* Name Convertions *************/
|
||||
|
||||
/// Convert a null-terminated string to a name.
|
||||
py_Name py_name(const char*);
|
||||
/// Convert a name to a null-terminated string.
|
||||
const char* py_name2str(py_Name);
|
||||
/// Convert a name to a `c11_sv`.
|
||||
py_Name py_namev(c11_sv name);
|
||||
/// Convert a `c11_sv` to a name.
|
||||
c11_sv py_name2sv(py_Name);
|
||||
|
||||
#define py_ismagicname(name) (name <= __missing__)
|
||||
|
||||
/************* Meta Operations *************/
|
||||
|
||||
/// Create a new type.
|
||||
/// @param name name of the type.
|
||||
/// @param base base type.
|
||||
/// @param module module where the type is defined. Use NULL for built-in types.
|
||||
/// @param dtor destructor function. Use NULL if not needed.
|
||||
/// @param module module where the type is defined. Use `NULL` for built-in types.
|
||||
/// @param dtor destructor function. Use `NULL` if not needed.
|
||||
py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, void (*dtor)(void*));
|
||||
|
||||
/// Create a new object.
|
||||
/// @param out output reference.
|
||||
/// @param type type of the object.
|
||||
/// @param slots number of slots. Use -1 to create a `__dict__`.
|
||||
/// @param udsize size of your userdata. You can use `py_touserdata()` to get the pointer to it.
|
||||
/// @param udsize size of your userdata.
|
||||
/// @return pointer to the userdata.
|
||||
void* py_newobject(py_Ref out, py_Type type, int slots, int udsize);
|
||||
|
||||
/************* Type Cast *************/
|
||||
py_i64 py_toint(py_Ref);
|
||||
py_f64 py_tofloat(py_Ref);
|
||||
bool py_castfloat(py_Ref, py_f64* out) PY_RAISE;
|
||||
bool py_tobool(py_Ref);
|
||||
py_Type py_totype(py_Ref);
|
||||
const char* py_tostr(py_Ref);
|
||||
const char* py_tostrn(py_Ref, int* size);
|
||||
c11_sv py_tosv(py_Ref);
|
||||
unsigned char* py_tobytes(py_Ref, int* size);
|
||||
|
||||
/// Convert an `int` object in python to `int64_t`.
|
||||
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`.
|
||||
/// Otherwise, return false and raise `TypeError`.
|
||||
bool py_castfloat(py_Ref, py_f64* out) PY_RAISE;
|
||||
/// Convert a `bool` object in python to `bool`.
|
||||
bool py_tobool(py_Ref);
|
||||
/// Convert a `type` object in python to `py_Type`.
|
||||
py_Type py_totype(py_Ref);
|
||||
/// Convert a `str` object in python to null-terminated string.
|
||||
const char* py_tostr(py_Ref);
|
||||
/// Convert a `str` object in python to char array.
|
||||
const char* py_tostrn(py_Ref, int* size);
|
||||
/// Convert a `str` object in python to `c11_sv`.
|
||||
c11_sv py_tosv(py_Ref);
|
||||
/// Convert a `bytes` object in python to char array.
|
||||
unsigned char* py_tobytes(py_Ref, int* size);
|
||||
/// Convert a user-defined object to its userdata.
|
||||
void* py_touserdata(py_Ref);
|
||||
|
||||
#define py_isint(self) py_istype(self, tp_int)
|
||||
@ -147,14 +183,20 @@ void* py_touserdata(py_Ref);
|
||||
#define py_isnil(self) py_istype(self, 0)
|
||||
#define py_isnone(self) py_istype(self, tp_NoneType)
|
||||
|
||||
/// Get the type of the object.
|
||||
py_Type py_typeof(py_Ref self);
|
||||
/// 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.
|
||||
bool py_isinstance(py_Ref obj, py_Type type);
|
||||
/// Check if the derived type is a subclass of the base type.
|
||||
bool py_issubclass(py_Type derived, py_Type base);
|
||||
|
||||
/// Search the magic method from the given type to the base type.
|
||||
/// Return `NULL` if not found.
|
||||
py_GlobalRef py_tpfindmagic(py_Type, py_Name name);
|
||||
/// Search the name from the given type to the base type.
|
||||
/// Return `NULL` if not found.
|
||||
py_GlobalRef py_tpfindname(py_Type, py_Name name);
|
||||
/// Get the type object of the given type.
|
||||
py_GlobalRef py_tpobject(py_Type type);
|
||||
@ -162,10 +204,12 @@ py_GlobalRef py_tpobject(py_Type type);
|
||||
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;
|
||||
/// Find the magic method from the given type only.
|
||||
/// Get the magic method from the given type only.
|
||||
/// The returned reference is always valid. However, its value may be `nil`.
|
||||
py_GlobalRef py_tpmagic(py_Type type, py_Name name);
|
||||
|
||||
/// Check if the object is an instance of the given type.
|
||||
/// Raise `TypeError` if the check fails.
|
||||
bool py_checktype(py_Ref self, py_Type type) PY_RAISE;
|
||||
|
||||
#define py_checkint(self) py_checktype(self, tp_int)
|
||||
@ -174,36 +218,62 @@ bool py_checktype(py_Ref self, py_Type type) PY_RAISE;
|
||||
#define py_checkstr(self) py_checktype(self, tp_str)
|
||||
|
||||
/************* References *************/
|
||||
/// Get the reference to the i-th register.
|
||||
/// Get the i-th register.
|
||||
/// All registers are located in a contiguous memory.
|
||||
py_GlobalRef py_getreg(int i);
|
||||
/// Set the reference to the i-th register.
|
||||
/// Set the i-th register.
|
||||
void py_setreg(int i, py_Ref val);
|
||||
|
||||
/// Equivalent to `*dst = *src`.
|
||||
void py_assign(py_Ref dst, py_Ref src);
|
||||
/// The return value of the most recent call.
|
||||
/// Get the last return value.
|
||||
py_GlobalRef py_retval();
|
||||
|
||||
/// Get the reference of the object's `__dict__`.
|
||||
/// The object must have a `__dict__`.
|
||||
/// Returns a reference to the value or NULL if not found.
|
||||
/// Get an item from the object's `__dict__`.
|
||||
/// Return `NULL` if not found.
|
||||
py_ObjectRef py_getdict(py_Ref self, py_Name name);
|
||||
/// Set an item to the object's `__dict__`.
|
||||
void py_setdict(py_Ref self, py_Name name, py_Ref val);
|
||||
/// Delete an item from the object's `__dict__`.
|
||||
/// Return `true` if the deletion is successful.
|
||||
bool py_deldict(py_Ref self, py_Name name);
|
||||
/// Prepare an insertion to the object's `__dict__`.
|
||||
py_ObjectRef py_emplacedict(py_Ref self, py_Name name);
|
||||
|
||||
/// Get the reference of the i-th slot of the object.
|
||||
/// The object must have slots and `i` must be in range.
|
||||
/// Get the i-th slot of the object.
|
||||
/// The object must have slots and `i` must be in valid range.
|
||||
py_ObjectRef py_getslot(py_Ref self, int i);
|
||||
/// Set the i-th slot of the object.
|
||||
void py_setslot(py_Ref self, int i, py_Ref val);
|
||||
|
||||
/************* Inspection *************/
|
||||
|
||||
/// Get the current `function` object from the stack.
|
||||
/// Return `NULL` if not available.
|
||||
py_StackRef py_inspect_currentfunction();
|
||||
|
||||
/************* Bindings *************/
|
||||
// new style decl-based bindings
|
||||
|
||||
/// Bind a function to the object via "decl-based" style.
|
||||
/// @param obj the target object.
|
||||
/// @param sig signature of the function. e.g. `add(x, y)`.
|
||||
/// @param f function to bind.
|
||||
void py_bind(py_Ref obj, const char* sig, py_CFunction f);
|
||||
// old style argc-based bindings
|
||||
/// Bind a method to type via "argc-based" style.
|
||||
/// @param type the target type.
|
||||
/// @param name name of the method.
|
||||
/// @param f function to bind.
|
||||
void py_bindmethod(py_Type type, const char* name, py_CFunction f);
|
||||
/// Bind a function to the object via "argc-based" style.
|
||||
/// @param obj the target object.
|
||||
/// @param name name of the function.
|
||||
/// @param f function to bind.
|
||||
void py_bindfunc(py_Ref obj, const char* name, py_CFunction f);
|
||||
/// Bind a property to type.
|
||||
/// @param type the target type.
|
||||
/// @param name name of the property.
|
||||
/// @param getter getter function.
|
||||
/// @param setter setter function. Use `NULL` if not needed.
|
||||
void py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFunction setter);
|
||||
|
||||
#define py_bindmagic(type, __magic__, f) py_newnativefunc(py_tpmagic((type), __magic__), (f))
|
||||
@ -216,18 +286,25 @@ void py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFu
|
||||
|
||||
#define py_offset(p, i) ((py_Ref)((char*)p + ((i) << 4)))
|
||||
#define py_arg(i) py_offset(argv, i)
|
||||
/************* Python Equivalents *************/
|
||||
bool py_getattr(py_Ref self, py_Name name) PY_RAISE;
|
||||
bool py_setattr(py_Ref self, py_Name name, py_Ref val) PY_RAISE;
|
||||
bool py_delattr(py_Ref self, py_Name name) PY_RAISE;
|
||||
|
||||
/************* Python Equivalents *************/
|
||||
|
||||
/// Python equivalent to `getattr(self, name)`.
|
||||
bool py_getattr(py_Ref self, py_Name name) PY_RAISE;
|
||||
/// 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;
|
||||
/// 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]`.
|
||||
bool py_delitem(py_Ref self, py_Ref key) PY_RAISE;
|
||||
|
||||
/// Perform a binary operation on the stack.
|
||||
/// It assumes `lhs` and `rhs` are already pushed to the stack.
|
||||
/// 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;
|
||||
|
||||
#define py_binaryadd(lhs, rhs) py_binaryop(lhs, rhs, __add__, __radd__)
|
||||
@ -246,32 +323,36 @@ bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) PY_RAISE;
|
||||
#define py_binarymatmul(lhs, rhs) py_binaryop(lhs, rhs, __matmul__, 0)
|
||||
|
||||
/************* Stack Operations *************/
|
||||
/// Return a reference to the i-th object from the top of the stack.
|
||||
/// i should be negative, e.g. (-1) means TOS.
|
||||
|
||||
/// Get the i-th object from the top of the stack.
|
||||
/// `i` should be negative, e.g. (-1) means TOS.
|
||||
py_StackRef py_peek(int i);
|
||||
/// Push the object to the stack.
|
||||
void py_push(py_Ref src);
|
||||
/// Push a nil object to the stack.
|
||||
/// Push a `nil` object to the stack.
|
||||
void py_pushnil();
|
||||
/// Pop an object from the stack.
|
||||
void py_pop();
|
||||
/// Shrink the stack by n.
|
||||
void py_shrink(int n);
|
||||
/// Get a temporary variable from the stack and returns the reference to it.
|
||||
/// Get a temporary variable from the stack.
|
||||
py_StackRef py_pushtmp();
|
||||
/// Gets the unbound method of the object.
|
||||
/// Assumes the object is located at the top of the stack.
|
||||
/// If returns true: [self] -> [unbound, self]
|
||||
/// If returns false: [self] -> [self] (no change)
|
||||
/// Get the unbound method of the object.
|
||||
/// Assume the object is located at the top of the stack.
|
||||
/// If return true: `[self] -> [unbound, self]`.
|
||||
/// If return false: `[self] -> [self]` (no change).
|
||||
bool py_pushmethod(py_Name name);
|
||||
/// A stack operation that calls a function.
|
||||
/// It assumes `argc + kwargc` arguments are already pushed to the stack.
|
||||
/// Call a callable object.
|
||||
/// 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;
|
||||
|
||||
/************* Modules *************/
|
||||
|
||||
/// Create a new module.
|
||||
py_TmpRef py_newmodule(const char* path);
|
||||
/// Get a module by path.
|
||||
py_TmpRef py_getmodule(const char* path);
|
||||
|
||||
/// Import a module.
|
||||
@ -280,23 +361,24 @@ py_TmpRef py_getmodule(const char* path);
|
||||
int py_import(const char* path) PY_RAISE;
|
||||
|
||||
/************* Errors *************/
|
||||
/// Raise an exception by name and message. Always returns false.
|
||||
|
||||
/// Raise an exception by type and message. Always return false.
|
||||
bool py_exception(py_Type type, const char* fmt, ...) PY_RAISE;
|
||||
/// Raise an expection object. Always returns false.
|
||||
/// Raise an expection object. Always return false.
|
||||
bool py_raise(py_Ref) PY_RAISE;
|
||||
/// Print the current exception.
|
||||
void py_printexc();
|
||||
/// Format the current exception.
|
||||
/// Format the current exception and return a null-terminated string.
|
||||
/// The result should be freed by the caller.
|
||||
char* py_formatexc();
|
||||
/// Check if an exception is raised.
|
||||
bool py_checkexc();
|
||||
/// Check if the exception is an instance of the given type.
|
||||
bool py_matchexc(py_Type type);
|
||||
/// Clear the current exception.
|
||||
/// @param p0 the unwinding point. Use `NULL` if not needed.
|
||||
void py_clearexc(py_StackRef p0);
|
||||
|
||||
#define IOError(...) py_exception(tp_IOError, __VA_ARGS__)
|
||||
#define OSError(...) py_exception(tp_OSError, __VA_ARGS__)
|
||||
#define NameError(n) py_exception(tp_NameError, "name '%n' is not defined", (n))
|
||||
#define TypeError(...) py_exception(tp_TypeError, __VA_ARGS__)
|
||||
#define RuntimeError(...) py_exception(tp_RuntimeError, __VA_ARGS__)
|
||||
@ -313,14 +395,18 @@ bool StopIteration();
|
||||
bool KeyError(py_Ref key) PY_RAISE;
|
||||
|
||||
/************* Operators *************/
|
||||
int py_equal(py_Ref lhs, py_Ref rhs) PY_RAISE;
|
||||
int py_less(py_Ref lhs, py_Ref rhs) PY_RAISE;
|
||||
|
||||
/// Equivalent to `bool(val)`.
|
||||
/// Returns 1 if `val` is truthy, otherwise 0.
|
||||
/// Returns -1 if an error occurred.
|
||||
/// Python equivalent to `bool(val)`.
|
||||
/// 1: true, 0: false, -1: error
|
||||
int py_bool(py_Ref val) PY_RAISE;
|
||||
|
||||
/// Compare two objects.
|
||||
/// 1: lhs == rhs, 0: lhs != rhs, -1: error
|
||||
int py_equal(py_Ref lhs, py_Ref rhs) PY_RAISE;
|
||||
/// Compare two objects.
|
||||
/// 1: lhs < rhs, 0: lhs >= rhs, -1: error
|
||||
int py_less(py_Ref lhs, py_Ref rhs) PY_RAISE;
|
||||
|
||||
#define py_eq(lhs, rhs) py_binaryop(lhs, rhs, __eq__, __eq__)
|
||||
#define py_ne(lhs, rhs) py_binaryop(lhs, rhs, __ne__, __ne__)
|
||||
#define py_lt(lhs, rhs) py_binaryop(lhs, rhs, __lt__, __gt__)
|
||||
@ -328,6 +414,7 @@ int py_bool(py_Ref val) PY_RAISE;
|
||||
#define py_gt(lhs, rhs) py_binaryop(lhs, rhs, __gt__, __lt__)
|
||||
#define py_ge(lhs, rhs) py_binaryop(lhs, rhs, __ge__, __le__)
|
||||
|
||||
/// 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;
|
||||
@ -341,40 +428,41 @@ bool py_isidentical(py_Ref, py_Ref);
|
||||
/// 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;
|
||||
/// Call a non-magic method.
|
||||
/// It prepares the stack and then performs a `vectorcall(argc+1, 0, false)`.
|
||||
/// The result will be set to `py_retval()`.
|
||||
/// The stack remains unchanged after the operation.
|
||||
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) PY_RAISE;
|
||||
|
||||
/// Python equivalent to `str(val)`.
|
||||
bool py_str(py_Ref val) PY_RAISE;
|
||||
/// Python equivalent to `repr(val)`.
|
||||
bool py_repr(py_Ref val) PY_RAISE;
|
||||
/// Python equivalent to `len(val)`.
|
||||
bool py_len(py_Ref val) PY_RAISE;
|
||||
|
||||
/************* Unchecked Functions *************/
|
||||
py_ObjectRef py_tuple__data(py_Ref self);
|
||||
py_ObjectRef py_tuple__getitem(py_Ref self, int i);
|
||||
void py_tuple__setitem(py_Ref self, int i, py_Ref val);
|
||||
int py_tuple__len(py_Ref self);
|
||||
|
||||
py_TmpRef py_list__data(py_Ref self);
|
||||
py_TmpRef py_list__getitem(py_Ref self, int i);
|
||||
void py_list__setitem(py_Ref self, int i, py_Ref val);
|
||||
void py_list__delitem(py_Ref self, int i);
|
||||
int py_list__len(py_Ref self);
|
||||
void py_list__append(py_Ref self, py_Ref val);
|
||||
void py_list__clear(py_Ref self);
|
||||
void py_list__insert(py_Ref self, int i, py_Ref val);
|
||||
void py_list__reverse(py_Ref self);
|
||||
py_ObjectRef py_tuple_data(py_Ref self);
|
||||
py_ObjectRef py_tuple_getitem(py_Ref self, int i);
|
||||
void py_tuple_setitem(py_Ref self, int i, py_Ref val);
|
||||
int py_tuple_len(py_Ref self);
|
||||
|
||||
py_TmpRef py_dict__getitem(py_Ref self, py_Ref key) PY_RAISE;
|
||||
void py_dict__setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
|
||||
void py_dict__delitem(py_Ref self, py_Ref key) PY_RAISE;
|
||||
bool py_dict__contains(py_Ref self, py_Ref key);
|
||||
int py_dict__len(py_Ref self);
|
||||
bool py_dict__apply(py_Ref self, bool (*f)(py_Ref key, py_Ref val, void* ctx), void* ctx);
|
||||
py_TmpRef py_list_data(py_Ref self);
|
||||
py_TmpRef py_list_getitem(py_Ref self, int i);
|
||||
void py_list_setitem(py_Ref self, int i, py_Ref val);
|
||||
void py_list_delitem(py_Ref self, int i);
|
||||
int py_list_len(py_Ref self);
|
||||
void py_list_append(py_Ref self, py_Ref val);
|
||||
void py_list_clear(py_Ref self);
|
||||
void py_list_insert(py_Ref self, int i, py_Ref val);
|
||||
void py_list_reverse(py_Ref self);
|
||||
|
||||
py_TmpRef py_dict_getitem(py_Ref self, py_Ref key) PY_RAISE;
|
||||
void py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
|
||||
void py_dict_delitem(py_Ref self, py_Ref key) PY_RAISE;
|
||||
bool py_dict_contains(py_Ref self, py_Ref key) PY_RAISE;
|
||||
int py_dict_len(py_Ref self);
|
||||
bool py_dict_apply(py_Ref self, bool (*f)(py_Ref key, py_Ref val, void* ctx), void* ctx) PY_RAISE;
|
||||
|
||||
/************* Others *************/
|
||||
|
||||
/// 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)
|
||||
@ -415,8 +503,8 @@ enum py_PredefinedTypes {
|
||||
tp_function,
|
||||
tp_nativefunc,
|
||||
tp_boundmethod,
|
||||
tp_super, // 1 slot + py_Type
|
||||
tp_BaseException,
|
||||
tp_super, // 1 slot + py_Type
|
||||
tp_BaseException, // 2 slots (arg + inner exc)
|
||||
tp_Exception,
|
||||
tp_bytes,
|
||||
tp_mappingproxy,
|
||||
|
||||
@ -2262,7 +2262,7 @@ static Error* read_literal(Compiler* self, py_Ref out) {
|
||||
consume(TK_RPAREN);
|
||||
py_newtuple(out, count);
|
||||
for(int i = 0; i < count; i++) {
|
||||
py_tuple__setitem(out, i, &cpnts[i]);
|
||||
py_tuple_setitem(out, i, &cpnts[i]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -2544,9 +2544,9 @@ static Error* compile_try_except(Compiler* self) {
|
||||
Ctx__emit_(ctx(), OP_PUSH_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
||||
Ctx__emit_store_name(ctx(), name_scope(self), as_name, BC_KEEPLINE);
|
||||
}
|
||||
check(compile_block_body(self, compile_stmt));
|
||||
// pop the exception
|
||||
Ctx__emit_(ctx(), OP_POP_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
||||
check(compile_block_body(self, compile_stmt));
|
||||
patches[patches_length++] = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
|
||||
Ctx__patch_jump(ctx(), patch);
|
||||
} while(curr()->type == TK_EXCEPT);
|
||||
|
||||
@ -54,7 +54,7 @@ static bool format_object(py_Ref obj, c11_sv spec);
|
||||
|
||||
#define vectorcall_opcall(argc, kwargc) \
|
||||
do { \
|
||||
FrameResult res = VM__vectorcall(self, (argc), (kwargc), true); \
|
||||
FrameResult res = VM__vectorcall(self, (argc), (kwargc), true); \
|
||||
switch(res) { \
|
||||
case RES_RETURN: PUSH(&self->last_retval); break; \
|
||||
case RES_CALL: frame = self->top_frame; goto __NEXT_FRAME; \
|
||||
@ -271,12 +271,12 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
if(magic->type == tp_nativefunc) {
|
||||
if(!magic->_cfunc(2, SECOND())) goto __ERROR;
|
||||
POP();
|
||||
*TOP() = self->last_retval;
|
||||
} else {
|
||||
INSERT_THIRD(); // [?, a, b]
|
||||
*THIRD() = *magic; // [__getitem__, a, b]
|
||||
if(!py_vectorcall(1, 0)) goto __ERROR;
|
||||
}
|
||||
*TOP() = self->last_retval;
|
||||
DISPATCH();
|
||||
}
|
||||
TypeError("'%t' object is not subscriptable", SECOND()->type);
|
||||
@ -423,6 +423,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
py_newint(SP()++, 0); // [complex, NULL, 0]
|
||||
*SP()++ = tmp; // [complex, NULL, 0, x]
|
||||
if(!py_vectorcall(2, 0)) goto __ERROR;
|
||||
PUSH(py_retval());
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_BUILD_BYTES: {
|
||||
@ -437,7 +438,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
py_newtuple(&tmp, byte.arg);
|
||||
py_TValue* begin = SP() - byte.arg;
|
||||
for(int i = 0; i < byte.arg; i++) {
|
||||
py_tuple__setitem(&tmp, i, begin + i);
|
||||
py_tuple_setitem(&tmp, i, begin + i);
|
||||
}
|
||||
SP() = begin;
|
||||
PUSH(&tmp);
|
||||
@ -448,7 +449,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
py_newlistn(&tmp, byte.arg);
|
||||
py_TValue* begin = SP() - byte.arg;
|
||||
for(int i = 0; i < byte.arg; i++) {
|
||||
py_list__setitem(&tmp, i, begin + i);
|
||||
py_list_setitem(&tmp, i, begin + i);
|
||||
}
|
||||
SP() = begin;
|
||||
PUSH(&tmp);
|
||||
@ -459,7 +460,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
py_Ref tmp = py_pushtmp();
|
||||
py_newdict(tmp);
|
||||
for(int i = 0; i < byte.arg * 2; i += 2) {
|
||||
py_dict__setitem(tmp, begin + i, begin + i + 1);
|
||||
py_dict_setitem(tmp, begin + i, begin + i + 1);
|
||||
if(py_checkexc()) goto __ERROR;
|
||||
}
|
||||
SP() = begin;
|
||||
@ -476,7 +477,12 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
py_push(py_retval()); // empty set
|
||||
py_Name id_add = py_name("add");
|
||||
for(int i = 0; i < byte.arg; i++) {
|
||||
if(!py_callmethod(TOP(), id_add, 1, begin + i)) goto __ERROR;
|
||||
py_push(TOP());
|
||||
if(!py_pushmethod(id_add)) {
|
||||
c11__abort("OP_BUILD_SET: failed to load method 'add'");
|
||||
}
|
||||
py_push(begin + i);
|
||||
if(!py_vectorcall(1, 0)) goto __ERROR;
|
||||
}
|
||||
py_TValue tmp = *TOP();
|
||||
SP() = begin;
|
||||
@ -529,14 +535,14 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
if(magic->type == tp_nativefunc) {
|
||||
if(!magic->_cfunc(2, SECOND())) goto __ERROR;
|
||||
POP();
|
||||
*TOP() = self->last_retval;
|
||||
} else {
|
||||
INSERT_THIRD(); // [?, b, a]
|
||||
*THIRD() = *magic; // [__contains__, a, b]
|
||||
if(!py_vectorcall(1, 0)) goto __ERROR;
|
||||
}
|
||||
bool res = py_tobool(TOP());
|
||||
if(byte.arg) py_newbool(TOP(), !res);
|
||||
bool res = py_tobool(py_retval());
|
||||
if(byte.arg) res = !res;
|
||||
py_newbool(SP()++, res);
|
||||
DISPATCH();
|
||||
}
|
||||
TypeError("'%t' type does not support '__contains__'", SECOND()->type);
|
||||
@ -662,9 +668,9 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
py_TValue* kwargs = py_getslot(&curr[1], 0);
|
||||
if(kwargs->type == tp_dict) {
|
||||
py_TValue* p = buf + n;
|
||||
if(!py_dict__apply(kwargs, unpack_dict_to_buffer, &p)) goto __ERROR;
|
||||
if(!py_dict_apply(kwargs, unpack_dict_to_buffer, &p)) goto __ERROR;
|
||||
n = p - buf;
|
||||
kwargc += py_dict__len(kwargs) - 1;
|
||||
kwargc += py_dict_len(kwargs) - 1;
|
||||
} else {
|
||||
TypeError("**kwargs must be a dict, got '%t'", kwargs->type);
|
||||
goto __ERROR;
|
||||
@ -700,18 +706,26 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
/////////
|
||||
case OP_LIST_APPEND: {
|
||||
// [list, iter, value]
|
||||
py_list__append(THIRD(), TOP());
|
||||
py_list_append(THIRD(), TOP());
|
||||
POP();
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_DICT_ADD: {
|
||||
// [dict, iter, key, value]
|
||||
py_dict__setitem(FOURTH(), SECOND(), TOP());
|
||||
py_dict_setitem(FOURTH(), SECOND(), TOP());
|
||||
if(py_checkexc()) goto __ERROR;
|
||||
STACK_SHRINK(2);
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_SET_ADD: {
|
||||
// [set, iter, value]
|
||||
py_push(THIRD()); // [| set]
|
||||
if(!py_pushmethod(py_name("add"))) {
|
||||
c11__abort("OP_SET_ADD: failed to load method 'add'");
|
||||
} // [|add() set]
|
||||
py_push(THIRD());
|
||||
if(!py_vectorcall(1, 0)) goto __ERROR;
|
||||
POP();
|
||||
DISPATCH();
|
||||
}
|
||||
/////////
|
||||
@ -824,7 +838,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
py_newlistn(SP()++, exceed);
|
||||
for(int i = 0; i < exceed; i++) {
|
||||
py_list__setitem(TOP(), i, p + byte.arg + i);
|
||||
py_list_setitem(TOP(), i, p + byte.arg + i);
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
@ -36,9 +36,9 @@ void UnwindTarget__delete(UnwindTarget* self) { free(self); }
|
||||
|
||||
Frame* Frame__new(const CodeObject* co,
|
||||
py_TValue* module,
|
||||
const py_TValue* function,
|
||||
py_TValue* p0,
|
||||
py_TValue* locals,
|
||||
py_StackRef function,
|
||||
py_StackRef p0,
|
||||
py_StackRef locals,
|
||||
const CodeObject* locals_co) {
|
||||
static_assert(sizeof(Frame) <= kPoolFrameBlockSize, "!(sizeof(Frame) <= kPoolFrameBlockSize)");
|
||||
Frame* self = PoolFrame_alloc();
|
||||
@ -46,7 +46,7 @@ Frame* Frame__new(const CodeObject* co,
|
||||
self->ip = (Bytecode*)co->codes.data - 1;
|
||||
self->co = co;
|
||||
self->module = *module;
|
||||
self->function = function ? function->_obj : NULL;
|
||||
self->function = function;
|
||||
self->p0 = p0;
|
||||
self->locals = locals;
|
||||
self->locals_co = locals_co;
|
||||
@ -133,7 +133,23 @@ void Frame__set_unwind_target(Frame* self, py_TValue* sp) {
|
||||
|
||||
py_TValue* Frame__f_closure_try_get(Frame* self, py_Name name) {
|
||||
if(self->function == NULL) return NULL;
|
||||
Function* ud = PyObject__userdata(self->function);
|
||||
Function* ud = py_touserdata(self->function);
|
||||
if(ud->closure == NULL) return NULL;
|
||||
return NameDict__try_get(ud->closure, name);
|
||||
}
|
||||
|
||||
int Frame__ip(const Frame* self) { return self->ip - (Bytecode*)self->co->codes.data; }
|
||||
|
||||
int Frame__lineno(const Frame* self) {
|
||||
int ip = Frame__ip(self);
|
||||
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).lineno;
|
||||
}
|
||||
|
||||
int Frame__iblock(const Frame* self) {
|
||||
int ip = Frame__ip(self);
|
||||
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).iblock;
|
||||
}
|
||||
|
||||
py_TValue* Frame__f_locals_try_get(Frame* self, py_Name name) {
|
||||
return FastLocals__try_get_by_name(self->locals, self->locals_co, name);
|
||||
}
|
||||
@ -135,8 +135,8 @@ void VM__ctor(VM* self) {
|
||||
// inject some builtin expections
|
||||
#define INJECT_BUILTIN_EXC(name) \
|
||||
do { \
|
||||
py_Type type = pk_newtype(#name, tp_Exception, &self->builtins, NULL, false, true); \
|
||||
py_setdict(&self->builtins, py_name(#name), py_tpobject(type)); \
|
||||
py_Type type = pk_newtype(#name, tp_Exception, &self->builtins, NULL, false, true); \
|
||||
py_setdict(&self->builtins, py_name(#name), py_tpobject(type)); \
|
||||
validate(tp_##name, type); \
|
||||
} while(0)
|
||||
|
||||
@ -167,9 +167,8 @@ void VM__ctor(VM* self) {
|
||||
tp_BaseException, tp_Exception, tp_StopIteration, tp_SyntaxError};
|
||||
|
||||
for(int i = 0; i < c11__count_array(public_types); i++) {
|
||||
py_Type t = public_types[i];
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, t);
|
||||
py_setdict(&self->builtins, ti->name, py_tpobject(t));
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, public_types[i]);
|
||||
py_setdict(&self->builtins, ti->name, &ti->self);
|
||||
}
|
||||
|
||||
py_newnotimplemented(py_emplacedict(&self->builtins, py_name("NotImplemented")));
|
||||
@ -180,6 +179,15 @@ void VM__ctor(VM* self) {
|
||||
pk__add_module_math();
|
||||
pk__add_module_dis();
|
||||
|
||||
// add python builtins
|
||||
do {
|
||||
bool ok = py_exec(kPythonLibs__set, "<builtins>", EXEC_MODE, &self->builtins);
|
||||
if(!ok) {
|
||||
py_printexc();
|
||||
c11__abort("failed to load python builtins!");
|
||||
}
|
||||
} while(0);
|
||||
|
||||
self->main = *py_newmodule("__main__");
|
||||
}
|
||||
|
||||
@ -320,7 +328,7 @@ static bool
|
||||
py_Ref vargs = &buffer[decl->starred_arg];
|
||||
py_newtuple(vargs, exceed_argc);
|
||||
for(int j = 0; j < exceed_argc; j++) {
|
||||
py_tuple__setitem(vargs, j, t++);
|
||||
py_tuple_setitem(vargs, j, t++);
|
||||
}
|
||||
} else {
|
||||
// kwdefaults override
|
||||
@ -353,7 +361,7 @@ static bool
|
||||
py_Ref tmp = py_pushtmp();
|
||||
c11_sv key_sv = py_name2sv(key);
|
||||
py_newstrn(tmp, key_sv.data, key_sv.size);
|
||||
py_dict__setitem(&buffer[decl->starred_kwarg], tmp, &p1[2 * j + 1]);
|
||||
py_dict_setitem(&buffer[decl->starred_kwarg], tmp, &p1[2 * j + 1]);
|
||||
py_pop();
|
||||
if(py_checkexc()) return false;
|
||||
}
|
||||
@ -551,7 +559,6 @@ void ManagedHeap__mark(ManagedHeap* self) {
|
||||
// mark frame
|
||||
for(Frame* frame = vm->top_frame; frame; frame = frame->f_back) {
|
||||
mark_value(&frame->module);
|
||||
if(frame->function) mark_object(frame->function);
|
||||
}
|
||||
// mark vm's registers
|
||||
mark_value(&vm->last_retval);
|
||||
@ -563,7 +570,7 @@ void ManagedHeap__mark(ManagedHeap* self) {
|
||||
|
||||
void pk_print_stack(VM* self, Frame* frame, Bytecode byte) {
|
||||
return;
|
||||
if(frame == NULL) return;
|
||||
if(frame == NULL || py_isnil(&self->main)) return;
|
||||
|
||||
py_TValue* sp = self->stack.sp;
|
||||
c11_sbuf buf;
|
||||
@ -576,11 +583,11 @@ void pk_print_stack(VM* self, Frame* frame, Bytecode byte) {
|
||||
case tp_bool: c11_sbuf__write_cstr(&buf, p->_bool ? "True" : "False"); break;
|
||||
case tp_NoneType: c11_sbuf__write_cstr(&buf, "None"); break;
|
||||
case tp_list: {
|
||||
pk_sprintf(&buf, "list(%d)", py_list__len(p));
|
||||
pk_sprintf(&buf, "list(%d)", py_list_len(p));
|
||||
break;
|
||||
}
|
||||
case tp_tuple: {
|
||||
pk_sprintf(&buf, "tuple(%d)", py_tuple__len(p));
|
||||
pk_sprintf(&buf, "tuple(%d)", py_tuple_len(p));
|
||||
break;
|
||||
}
|
||||
case tp_function: {
|
||||
|
||||
@ -37,8 +37,8 @@ static bool math_fsum(int argc, py_Ref argv) {
|
||||
py_Ref list = py_arg(0);
|
||||
double sum = 0;
|
||||
double c = 0;
|
||||
for(int i = 0; i < py_list__len(list); i++) {
|
||||
py_Ref item = py_list__getitem(list, i);
|
||||
for(int i = 0; i < py_list_len(list); i++) {
|
||||
py_Ref item = py_list_getitem(list, i);
|
||||
double x;
|
||||
if(!py_castfloat(item, &x)) return false;
|
||||
double y = x - c;
|
||||
@ -136,8 +136,8 @@ static bool math_modf(int argc, py_Ref argv) {
|
||||
double i;
|
||||
double f = modf(py_tofloat(py_arg(0)), &i);
|
||||
py_newtuple(py_retval(), 2);
|
||||
py_Ref _0 = py_tuple__getitem(py_retval(), 0);
|
||||
py_Ref _1 = py_tuple__getitem(py_retval(), 1);
|
||||
py_Ref _0 = py_tuple_getitem(py_retval(), 0);
|
||||
py_Ref _1 = py_tuple_getitem(py_retval(), 1);
|
||||
py_newfloat(_0, f);
|
||||
py_newfloat(_1, i);
|
||||
return true;
|
||||
@ -160,8 +160,8 @@ void pk__add_module_math() {
|
||||
|
||||
py_newfloat(py_emplacedict(mod, py_name("pi")), 3.1415926535897932384);
|
||||
py_newfloat(py_emplacedict(mod, py_name("e")), 2.7182818284590452354);
|
||||
py_newfloat(py_emplacedict(mod, py_name("inf")), 1.0 / 0.0);
|
||||
py_newfloat(py_emplacedict(mod, py_name("nan")), 0.0 / 0.0);
|
||||
py_newfloat(py_emplacedict(mod, py_name("inf")), INFINITY);
|
||||
py_newfloat(py_emplacedict(mod, py_name("nan")), NAN);
|
||||
|
||||
py_bindfunc(mod, "ceil", math_ceil);
|
||||
py_bindfunc(mod, "fabs", math_fabs);
|
||||
|
||||
@ -31,13 +31,13 @@ static bool os_chdir(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARG_TYPE(0, tp_str);
|
||||
const char* path = py_tostr(py_arg(0));
|
||||
int code = platform_chdir(path);
|
||||
if(code != 0) return OSError("chdir() failed: %d", code);
|
||||
if(code != 0) return py_exception(tp_OSError, "chdir() failed: %d", code);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool os_getcwd(int argc, py_Ref argv) {
|
||||
char buf[1024];
|
||||
if(!platform_getcwd(buf, sizeof(buf))) return OSError("getcwd() failed");
|
||||
if(!platform_getcwd(buf, sizeof(buf))) return py_exception(tp_OSError, "getcwd() failed");
|
||||
py_newstr(py_retval(), buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -101,9 +101,9 @@ FuncDecl_ FuncDecl__build(c11_sv name,
|
||||
}
|
||||
if(starred_arg.size) { FuncDecl__add_starred_arg(decl, py_namev(starred_arg)); }
|
||||
assert(py_istype(kwdefaults, tp_tuple));
|
||||
assert(py_tuple__len(kwdefaults) == kwargc);
|
||||
assert(py_tuple_len(kwdefaults) == kwargc);
|
||||
for(int i = 0; i < kwargc; i++) {
|
||||
FuncDecl__add_kwarg(decl, py_namev(kwargs[i]), py_tuple__getitem(kwdefaults, i));
|
||||
FuncDecl__add_kwarg(decl, py_namev(kwargs[i]), py_tuple_getitem(kwdefaults, i));
|
||||
}
|
||||
if(starred_kwarg.size) FuncDecl__add_starred_kwarg(decl, py_namev(starred_kwarg));
|
||||
decl->docstring = docstring;
|
||||
|
||||
@ -115,8 +115,6 @@ bool py_call(py_Ref f, int argc, py_Ref argv) {
|
||||
}
|
||||
}
|
||||
|
||||
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; }
|
||||
|
||||
bool py_vectorcall(uint16_t argc, uint16_t kwargc) {
|
||||
VM* vm = pk_current_vm;
|
||||
return VM__vectorcall(vm, argc, kwargc, false) != RES_ERROR;
|
||||
|
||||
@ -148,12 +148,12 @@ __SUCCESS:
|
||||
|
||||
//////////////////////////
|
||||
|
||||
static bool builtins__repr(int argc, py_Ref argv) {
|
||||
static bool builtins_repr(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
return py_repr(argv);
|
||||
}
|
||||
|
||||
static bool builtins__exit(int argc, py_Ref argv) {
|
||||
static bool builtins_exit(int argc, py_Ref argv) {
|
||||
int code = 0;
|
||||
if(argc > 1) return TypeError("exit() takes at most 1 argument");
|
||||
if(argc == 1) {
|
||||
@ -165,20 +165,20 @@ static bool builtins__exit(int argc, py_Ref argv) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool builtins__len(int argc, py_Ref argv) {
|
||||
static bool builtins_len(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
return py_len(argv);
|
||||
}
|
||||
|
||||
static bool builtins__reversed(int argc, py_Ref argv) {
|
||||
static bool builtins_reversed(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
// convert _0 to list object
|
||||
if(!py_tpcall(tp_list, 1, argv)) return false;
|
||||
py_list__reverse(py_retval());
|
||||
py_list_reverse(py_retval());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins__hex(int argc, py_Ref argv) {
|
||||
static bool builtins_hex(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_int);
|
||||
|
||||
@ -208,12 +208,12 @@ static bool builtins__hex(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins__iter(int argc, py_Ref argv) {
|
||||
static bool builtins_iter(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
return py_iter(argv);
|
||||
}
|
||||
|
||||
static bool builtins__next(int argc, py_Ref argv) {
|
||||
static bool builtins_next(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
int res = py_next(argv);
|
||||
if(res == -1) return false;
|
||||
@ -221,7 +221,7 @@ static bool builtins__next(int argc, py_Ref argv) {
|
||||
return py_exception(tp_StopIteration, "");
|
||||
}
|
||||
|
||||
static bool builtins__sorted(int argc, py_Ref argv) {
|
||||
static bool builtins_sorted(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(3);
|
||||
// convert _0 to list object
|
||||
if(!py_tpcall(tp_list, 1, py_arg(0))) return false;
|
||||
@ -238,7 +238,7 @@ static bool builtins__sorted(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins__hash(int argc, py_Ref argv) {
|
||||
static bool builtins_hash(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_i64 val;
|
||||
if(!py_hash(argv, &val)) return false;
|
||||
@ -246,12 +246,12 @@ static bool builtins__hash(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins__abs(int argc, py_Ref argv) {
|
||||
static bool builtins_abs(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
return pk_callmagic(__abs__, 1, argv);
|
||||
}
|
||||
|
||||
static bool builtins__sum(int argc, py_Ref argv) {
|
||||
static bool builtins_sum(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
|
||||
if(!py_iter(py_arg(0))) return false;
|
||||
@ -288,7 +288,7 @@ static bool builtins__sum(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins__print(int argc, py_Ref argv) {
|
||||
static bool builtins_print(int argc, py_Ref argv) {
|
||||
int length;
|
||||
py_TValue* args = pk_arrayview(argv, &length);
|
||||
assert(args != NULL);
|
||||
@ -314,24 +314,24 @@ static bool NoneType__repr__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins__exec(int argc, py_Ref argv) {
|
||||
static bool builtins_exec(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_str);
|
||||
return py_exec(py_tostr(argv), "<exec>", EXEC_MODE, NULL);
|
||||
}
|
||||
|
||||
static bool builtins__eval(int argc, py_Ref argv) {
|
||||
static bool builtins_eval(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_str);
|
||||
return py_exec(py_tostr(argv), "<eval>", EVAL_MODE, NULL);
|
||||
}
|
||||
|
||||
static bool builtins__isinstance(int argc, py_Ref argv) {
|
||||
static bool builtins_isinstance(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
if(py_istuple(py_arg(1))) {
|
||||
int length = py_tuple__len(py_arg(1));
|
||||
int length = py_tuple_len(py_arg(1));
|
||||
for(int i = 0; i < length; i++) {
|
||||
py_Ref item = py_tuple__getitem(py_arg(1), i);
|
||||
py_Ref item = py_tuple_getitem(py_arg(1), i);
|
||||
if(!py_checktype(item, tp_type)) return false;
|
||||
if(py_isinstance(py_arg(0), py_totype(item))) {
|
||||
py_newbool(py_retval(), true);
|
||||
@ -347,7 +347,7 @@ static bool builtins__isinstance(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins__issubclass(int argc, py_Ref argv) {
|
||||
static bool builtins_issubclass(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
if(!py_checktype(py_arg(0), tp_type)) return false;
|
||||
if(!py_checktype(py_arg(1), tp_type)) return false;
|
||||
@ -355,7 +355,7 @@ static bool builtins__issubclass(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins__getattr(int argc, py_Ref argv) {
|
||||
static bool builtins_getattr(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
py_Name name = py_namev(py_tosv(py_arg(1)));
|
||||
if(argc == 2) {
|
||||
@ -365,7 +365,8 @@ static bool builtins__getattr(int argc, py_Ref argv) {
|
||||
bool ok = py_getattr(py_arg(0), name);
|
||||
if(!ok && py_matchexc(tp_AttributeError)) {
|
||||
py_clearexc(p0);
|
||||
return py_arg(2); // default value
|
||||
py_assign(py_retval(), py_arg(2));
|
||||
return true; // default value
|
||||
}
|
||||
return ok;
|
||||
} else {
|
||||
@ -374,29 +375,64 @@ static bool builtins__getattr(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins_setattr(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(3);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
py_Name name = py_namev(py_tosv(py_arg(1)));
|
||||
return py_setattr(py_arg(0), name, py_arg(2));
|
||||
}
|
||||
|
||||
static bool builtins_hasattr(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
py_Name name = py_namev(py_tosv(py_arg(1)));
|
||||
py_StackRef p0 = py_peek(0);
|
||||
bool ok = py_getattr(py_arg(0), name);
|
||||
if(ok) {
|
||||
py_newbool(py_retval(), true);
|
||||
return true;
|
||||
}
|
||||
if(py_matchexc(tp_AttributeError)) {
|
||||
py_clearexc(p0);
|
||||
py_newbool(py_retval(), false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool builtins_delattr(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
py_Name name = py_namev(py_tosv(py_arg(1)));
|
||||
return py_delattr(py_arg(0), name);
|
||||
}
|
||||
|
||||
py_TValue pk_builtins__register() {
|
||||
py_Ref builtins = py_newmodule("builtins");
|
||||
py_bindfunc(builtins, "repr", builtins__repr);
|
||||
py_bindfunc(builtins, "exit", builtins__exit);
|
||||
py_bindfunc(builtins, "len", builtins__len);
|
||||
py_bindfunc(builtins, "reversed", builtins__reversed);
|
||||
py_bindfunc(builtins, "hex", builtins__hex);
|
||||
py_bindfunc(builtins, "iter", builtins__iter);
|
||||
py_bindfunc(builtins, "next", builtins__next);
|
||||
py_bindfunc(builtins, "hash", builtins__hash);
|
||||
py_bindfunc(builtins, "abs", builtins__abs);
|
||||
py_bindfunc(builtins, "sum", builtins__sum);
|
||||
py_bindfunc(builtins, "repr", builtins_repr);
|
||||
py_bindfunc(builtins, "exit", builtins_exit);
|
||||
py_bindfunc(builtins, "len", builtins_len);
|
||||
py_bindfunc(builtins, "reversed", builtins_reversed);
|
||||
py_bindfunc(builtins, "hex", builtins_hex);
|
||||
py_bindfunc(builtins, "iter", builtins_iter);
|
||||
py_bindfunc(builtins, "next", builtins_next);
|
||||
py_bindfunc(builtins, "hash", builtins_hash);
|
||||
py_bindfunc(builtins, "abs", builtins_abs);
|
||||
py_bindfunc(builtins, "sum", builtins_sum);
|
||||
|
||||
py_bindfunc(builtins, "exec", builtins__exec);
|
||||
py_bindfunc(builtins, "eval", builtins__eval);
|
||||
py_bindfunc(builtins, "exec", builtins_exec);
|
||||
py_bindfunc(builtins, "eval", builtins_eval);
|
||||
|
||||
py_bind(builtins, "print(*args, sep=' ', end='\\n')", builtins__print);
|
||||
py_bind(builtins, "sorted(iterable, key=None, reverse=False)", builtins__sorted);
|
||||
py_bind(builtins, "print(*args, sep=' ', end='\\n')", builtins_print);
|
||||
py_bind(builtins, "sorted(iterable, key=None, reverse=False)", builtins_sorted);
|
||||
|
||||
py_bindfunc(builtins, "isinstance", builtins__isinstance);
|
||||
py_bindfunc(builtins, "issubclass", builtins__issubclass);
|
||||
py_bindfunc(builtins, "isinstance", builtins_isinstance);
|
||||
py_bindfunc(builtins, "issubclass", builtins_issubclass);
|
||||
|
||||
py_bindfunc(builtins, "getattr", builtins__getattr);
|
||||
py_bindfunc(builtins, "getattr", builtins_getattr);
|
||||
py_bindfunc(builtins, "setattr", builtins_setattr);
|
||||
py_bindfunc(builtins, "hasattr", builtins_hasattr);
|
||||
py_bindfunc(builtins, "delattr", builtins_delattr);
|
||||
|
||||
// None __repr__
|
||||
py_bindmagic(tp_NoneType, __repr__, NoneType__repr__);
|
||||
@ -416,7 +452,7 @@ static bool function__closure__getter(int argc, py_Ref argv) {
|
||||
c11__foreach(NameDict_KV, ud->closure, it) {
|
||||
// printf("%s -> %s\n", py_name2str(it->key), py_tpname(it->value.type));
|
||||
py_newstr(r0, py_name2str(it->key));
|
||||
py_dict__setitem(retval, r0, &it->value);
|
||||
py_dict_setitem(retval, r0, &it->value);
|
||||
if(py_checkexc()) {
|
||||
py_shrink(2);
|
||||
return false;
|
||||
@ -435,7 +471,7 @@ py_Type pk_function__register() {
|
||||
return type;
|
||||
}
|
||||
|
||||
static bool nativefunc__repr(int argc, py_Ref argv) {
|
||||
static bool nativefunc__repr__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_newstr(py_retval(), "<nativefunc object>");
|
||||
return true;
|
||||
@ -443,7 +479,7 @@ static bool nativefunc__repr(int argc, py_Ref argv) {
|
||||
|
||||
py_Type pk_nativefunc__register() {
|
||||
py_Type type = pk_newtype("nativefunc", tp_object, NULL, NULL, false, true);
|
||||
py_bindmagic(type, __repr__, nativefunc__repr);
|
||||
py_bindmagic(type, __repr__, nativefunc__repr__);
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -455,8 +491,7 @@ static bool super__new__(int argc, py_Ref argv) {
|
||||
if(argc == 1) {
|
||||
// super()
|
||||
if(frame->function) {
|
||||
// class_arg = PK_OBJ_GET(Function, frame->_callable)._class;
|
||||
Function* func = PyObject__userdata(frame->function);
|
||||
Function* func = py_touserdata(frame->function);
|
||||
*class_arg = *(py_Type*)PyObject__userdata(func->clazz);
|
||||
if(frame->locals_co->nlocals > 0) self_arg = &frame->locals[0];
|
||||
}
|
||||
|
||||
@ -13,11 +13,11 @@ typedef struct array_iterator {
|
||||
|
||||
py_TValue* pk_arrayview(py_Ref self, int* length) {
|
||||
if(self->type == tp_list) {
|
||||
*length = py_list__len(self);
|
||||
return py_list__data(self);
|
||||
*length = py_list_len(self);
|
||||
return py_list_data(self);
|
||||
}
|
||||
if(self->type == tp_tuple) {
|
||||
*length = py_tuple__len(self);
|
||||
*length = py_tuple_len(self);
|
||||
return PyObject__slots(self->_obj);
|
||||
}
|
||||
return NULL;
|
||||
|
||||
@ -35,6 +35,7 @@ static void Dict__ctor(Dict* self, int capacity) {
|
||||
self->indices = malloc(self->capacity * sizeof(DictIndex));
|
||||
memset(self->indices, -1, self->capacity * sizeof(DictIndex));
|
||||
c11_vector__ctor(&self->entries, sizeof(DictEntry));
|
||||
c11_vector__reserve(&self->entries, capacity);
|
||||
}
|
||||
|
||||
static void Dict__dtor(Dict* self) {
|
||||
@ -216,13 +217,13 @@ static bool dict__init__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARG_TYPE(1, tp_list);
|
||||
Dict* self = py_touserdata(argv);
|
||||
py_Ref list = py_arg(1);
|
||||
for(int i = 0; i < py_list__len(list); i++) {
|
||||
py_Ref tuple = py_list__getitem(list, i);
|
||||
if(!py_istuple(tuple) || py_tuple__len(tuple) != 2) {
|
||||
for(int i = 0; i < py_list_len(list); i++) {
|
||||
py_Ref tuple = py_list_getitem(list, i);
|
||||
if(!py_istuple(tuple) || py_tuple_len(tuple) != 2) {
|
||||
return TypeError("dict.__init__() argument must be a list of tuple-2");
|
||||
}
|
||||
py_Ref key = py_tuple__getitem(tuple, 0);
|
||||
py_Ref val = py_tuple__getitem(tuple, 1);
|
||||
py_Ref key = py_tuple_getitem(tuple, 0);
|
||||
py_Ref val = py_tuple_getitem(tuple, 1);
|
||||
if(!Dict__set(self, key, val)) return false;
|
||||
}
|
||||
return true;
|
||||
@ -335,14 +336,14 @@ static bool dict__ne__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dict__clear(int argc, py_Ref argv) {
|
||||
static bool dict_clear(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
Dict* self = py_touserdata(argv);
|
||||
Dict__clear(self);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dict__copy(int argc, py_Ref argv) {
|
||||
static bool dict_copy(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
Dict* self = py_touserdata(argv);
|
||||
Dict* new_dict = py_newobject(py_retval(), tp_dict, 0, sizeof(Dict));
|
||||
@ -355,7 +356,7 @@ static bool dict__copy(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dict__update(int argc, py_Ref argv) {
|
||||
static bool dict_update(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
PY_CHECK_ARG_TYPE(1, tp_dict);
|
||||
Dict* self = py_touserdata(argv);
|
||||
@ -368,7 +369,7 @@ static bool dict__update(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dict__get(int argc, py_Ref argv) {
|
||||
static bool dict_get(int argc, py_Ref argv) {
|
||||
Dict* self = py_touserdata(argv);
|
||||
if(argc > 3) return TypeError("get() takes at most 3 arguments (%d given)", argc);
|
||||
py_Ref default_val = argc == 3 ? py_arg(2) : py_None;
|
||||
@ -378,7 +379,7 @@ static bool dict__get(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dict__pop(int argc, py_Ref argv) {
|
||||
static bool dict_pop(int argc, py_Ref argv) {
|
||||
Dict* self = py_touserdata(argv);
|
||||
if(argc < 2 || argc > 3) return TypeError("pop() takes 2 or 3 arguments (%d given)", argc);
|
||||
py_Ref default_val = argc == 3 ? py_arg(2) : py_None;
|
||||
@ -387,7 +388,7 @@ static bool dict__pop(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dict__items(int argc, py_Ref argv) {
|
||||
static bool dict_items(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
Dict* self = py_touserdata(argv);
|
||||
DictIterator* ud = py_newobject(py_retval(), tp_dict_items, 1, sizeof(DictIterator));
|
||||
@ -396,7 +397,7 @@ static bool dict__items(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dict__keys(int argc, py_Ref argv) {
|
||||
static bool dict_keys(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
Dict* self = py_touserdata(argv);
|
||||
py_newtuple(py_retval(), self->length);
|
||||
@ -406,13 +407,13 @@ static bool dict__keys(int argc, py_Ref argv) {
|
||||
while(1) {
|
||||
DictEntry* entry = DictIterator__next(&iter);
|
||||
if(!entry) break;
|
||||
py_tuple__setitem(py_retval(), i++, &entry->key);
|
||||
py_tuple_setitem(py_retval(), i++, &entry->key);
|
||||
}
|
||||
assert(i == self->length);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dict__values(int argc, py_Ref argv) {
|
||||
static bool dict_values(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
Dict* self = py_touserdata(argv);
|
||||
py_newtuple(py_retval(), self->length);
|
||||
@ -422,7 +423,7 @@ static bool dict__values(int argc, py_Ref argv) {
|
||||
while(1) {
|
||||
DictEntry* entry = DictIterator__next(&iter);
|
||||
if(!entry) break;
|
||||
py_tuple__setitem(py_retval(), i++, &entry->val);
|
||||
py_tuple_setitem(py_retval(), i++, &entry->val);
|
||||
}
|
||||
assert(i == self->length);
|
||||
return true;
|
||||
@ -442,14 +443,14 @@ py_Type pk_dict__register() {
|
||||
py_bindmagic(type, __eq__, dict__eq__);
|
||||
py_bindmagic(type, __ne__, dict__ne__);
|
||||
|
||||
py_bindmethod(type, "clear", dict__clear);
|
||||
py_bindmethod(type, "copy", dict__copy);
|
||||
py_bindmethod(type, "update", dict__update);
|
||||
py_bindmethod(type, "get", dict__get);
|
||||
py_bindmethod(type, "pop", dict__pop);
|
||||
py_bindmethod(type, "items", dict__items);
|
||||
py_bindmethod(type, "keys", dict__keys);
|
||||
py_bindmethod(type, "values", dict__values);
|
||||
py_bindmethod(type, "clear", dict_clear);
|
||||
py_bindmethod(type, "copy", dict_copy);
|
||||
py_bindmethod(type, "update", dict_update);
|
||||
py_bindmethod(type, "get", dict_get);
|
||||
py_bindmethod(type, "pop", dict_pop);
|
||||
py_bindmethod(type, "items", dict_items);
|
||||
py_bindmethod(type, "keys", dict_keys);
|
||||
py_bindmethod(type, "values", dict_values);
|
||||
|
||||
py_setdict(py_tpobject(type), __hash__, py_None);
|
||||
return type;
|
||||
@ -468,8 +469,8 @@ static bool dict_items__next__(int argc, py_Ref argv) {
|
||||
DictEntry* entry = (DictIterator__next(iter));
|
||||
if(entry) {
|
||||
py_newtuple(py_retval(), 2);
|
||||
py_tuple__setitem(py_retval(), 0, &entry->key);
|
||||
py_tuple__setitem(py_retval(), 1, &entry->val);
|
||||
py_tuple_setitem(py_retval(), 0, &entry->key);
|
||||
py_tuple_setitem(py_retval(), 1, &entry->val);
|
||||
return true;
|
||||
}
|
||||
return StopIteration();
|
||||
@ -489,7 +490,7 @@ void py_newdict(py_Ref out) {
|
||||
Dict__ctor(ud, 8);
|
||||
}
|
||||
|
||||
py_Ref py_dict__getitem(py_Ref self, py_Ref key) {
|
||||
py_Ref py_dict_getitem(py_Ref self, py_Ref key) {
|
||||
assert(py_isdict(self));
|
||||
Dict* ud = py_touserdata(self);
|
||||
DictEntry* entry;
|
||||
@ -498,19 +499,19 @@ py_Ref py_dict__getitem(py_Ref self, py_Ref key) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void py_dict__delitem(py_Ref self, py_Ref key) {
|
||||
void py_dict_delitem(py_Ref self, py_Ref key) {
|
||||
assert(py_isdict(self));
|
||||
Dict* ud = py_touserdata(self);
|
||||
Dict__pop(ud, key);
|
||||
}
|
||||
|
||||
void py_dict__setitem(py_Ref self, py_Ref key, py_Ref val) {
|
||||
void py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) {
|
||||
assert(py_isdict(self));
|
||||
Dict* ud = py_touserdata(self);
|
||||
Dict__set(ud, key, val);
|
||||
}
|
||||
|
||||
bool py_dict__contains(py_Ref self, py_Ref key) {
|
||||
bool py_dict_contains(py_Ref self, py_Ref key) {
|
||||
assert(py_isdict(self));
|
||||
Dict* ud = py_touserdata(self);
|
||||
DictEntry* entry;
|
||||
@ -518,13 +519,13 @@ bool py_dict__contains(py_Ref self, py_Ref key) {
|
||||
return ok && entry != NULL;
|
||||
}
|
||||
|
||||
int py_dict__len(py_Ref self) {
|
||||
int py_dict_len(py_Ref self) {
|
||||
assert(py_isdict(self));
|
||||
Dict* ud = py_touserdata(self);
|
||||
return ud->length;
|
||||
}
|
||||
|
||||
bool py_dict__apply(py_Ref self, bool (*f)(py_Ref, py_Ref, void*), void* ctx) {
|
||||
bool py_dict_apply(py_Ref self, bool (*f)(py_Ref, py_Ref, void*), void* ctx) {
|
||||
Dict* ud = py_touserdata(self);
|
||||
for(int i = 0; i < ud->entries.count; i++) {
|
||||
DictEntry* entry = c11__at(DictEntry, &ud->entries, i);
|
||||
|
||||
@ -52,8 +52,10 @@ static void BaseException__dtor(void* ud) {
|
||||
|
||||
static bool _py_BaseException__new__(int argc, py_Ref argv) {
|
||||
py_Type cls = py_totype(argv);
|
||||
BaseException* ud = py_newobject(py_retval(), cls, 1, sizeof(BaseException));
|
||||
BaseException* ud = py_newobject(py_retval(), cls, 2, sizeof(BaseException));
|
||||
c11_vector__ctor(&ud->stacktrace, sizeof(BaseExceptionFrame));
|
||||
py_setslot(py_retval(), 0, py_NIL);
|
||||
py_setslot(py_retval(), 1, py_NIL);
|
||||
ud->lineno_backup = -1;
|
||||
ud->code_backup = NULL;
|
||||
return true;
|
||||
@ -138,35 +140,46 @@ void py_printexc() {
|
||||
free(msg);
|
||||
}
|
||||
|
||||
static void c11_sbuf__write_exc(c11_sbuf* self, py_Ref exc){
|
||||
if(true) { c11_sbuf__write_cstr(self, "Traceback (most recent call last):\n"); }
|
||||
|
||||
BaseException* ud = py_touserdata(exc);
|
||||
|
||||
for(int i = ud->stacktrace.count - 1; i >= 0; i--) {
|
||||
BaseExceptionFrame* frame = c11__at(BaseExceptionFrame, &ud->stacktrace, i);
|
||||
SourceData__snapshot(frame->src,
|
||||
self,
|
||||
frame->lineno,
|
||||
NULL,
|
||||
frame->name ? frame->name->data : NULL);
|
||||
c11_sbuf__write_char(self, '\n');
|
||||
}
|
||||
|
||||
const char* name = py_tpname(exc->type);
|
||||
bool ok = py_str(exc);
|
||||
if(!ok) c11__abort("py_printexc(): failed to convert exception to string");
|
||||
const char* message = py_tostr(py_retval());
|
||||
|
||||
c11_sbuf__write_cstr(self, name);
|
||||
c11_sbuf__write_cstr(self, ": ");
|
||||
c11_sbuf__write_cstr(self, message);
|
||||
}
|
||||
|
||||
char* py_formatexc() {
|
||||
VM* vm = pk_current_vm;
|
||||
if(py_isnil(&vm->curr_exception)) return NULL;
|
||||
c11_sbuf ss;
|
||||
c11_sbuf__ctor(&ss);
|
||||
|
||||
if(true) { c11_sbuf__write_cstr(&ss, "Traceback (most recent call last):\n"); }
|
||||
|
||||
BaseException* ud = py_touserdata(&vm->curr_exception);
|
||||
|
||||
for(int i = ud->stacktrace.count - 1; i >= 0; i--) {
|
||||
BaseExceptionFrame* frame = c11__at(BaseExceptionFrame, &ud->stacktrace, i);
|
||||
SourceData__snapshot(frame->src,
|
||||
&ss,
|
||||
frame->lineno,
|
||||
NULL,
|
||||
frame->name ? frame->name->data : NULL);
|
||||
c11_sbuf__write_char(&ss, '\n');
|
||||
py_Ref inner = py_getslot(&vm->curr_exception, 1);
|
||||
if(py_isnil(inner)) {
|
||||
c11_sbuf__write_exc(&ss, &vm->curr_exception);
|
||||
} else {
|
||||
c11_sbuf__write_exc(&ss, inner);
|
||||
c11_sbuf__write_cstr(&ss, "\n\nDuring handling of the above exception, another exception occurred:\n\n");
|
||||
c11_sbuf__write_exc(&ss, &vm->curr_exception);
|
||||
}
|
||||
|
||||
const char* name = py_tpname(vm->curr_exception.type);
|
||||
bool ok = py_str(&vm->curr_exception);
|
||||
if(!ok) c11__abort("py_printexc(): failed to convert exception to string");
|
||||
const char* message = py_tostr(py_retval());
|
||||
|
||||
c11_sbuf__write_cstr(&ss, name);
|
||||
c11_sbuf__write_cstr(&ss, ": ");
|
||||
c11_sbuf__write_cstr(&ss, message);
|
||||
|
||||
c11_string* res = c11_sbuf__submit(&ss);
|
||||
char* dup = malloc(res->size + 1);
|
||||
memcpy(dup, res->data, res->size);
|
||||
@ -196,6 +209,10 @@ bool py_exception(py_Type type, const char* fmt, ...) {
|
||||
bool py_raise(py_Ref exc) {
|
||||
assert(py_isinstance(exc, tp_BaseException));
|
||||
VM* vm = pk_current_vm;
|
||||
if(!py_isnil(&vm->curr_exception)){
|
||||
// inner exception
|
||||
py_setslot(exc, 1, &vm->curr_exception);
|
||||
}
|
||||
vm->curr_exception = *exc;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -19,47 +19,47 @@ void py_newlistn(py_Ref out, int n) {
|
||||
userdata->count = n;
|
||||
}
|
||||
|
||||
py_Ref py_list__data(py_Ref self) {
|
||||
py_Ref py_list_data(py_Ref self) {
|
||||
List* userdata = py_touserdata(self);
|
||||
return userdata->data;
|
||||
}
|
||||
|
||||
py_Ref py_list__getitem(py_Ref self, int i) {
|
||||
py_Ref py_list_getitem(py_Ref self, int i) {
|
||||
List* userdata = py_touserdata(self);
|
||||
return c11__at(py_TValue, userdata, i);
|
||||
}
|
||||
|
||||
void py_list__setitem(py_Ref self, int i, py_Ref val) {
|
||||
void py_list_setitem(py_Ref self, int i, py_Ref val) {
|
||||
List* userdata = py_touserdata(self);
|
||||
c11__setitem(py_TValue, userdata, i, *val);
|
||||
}
|
||||
|
||||
void py_list__delitem(py_Ref self, int i) {
|
||||
void py_list_delitem(py_Ref self, int i) {
|
||||
List* userdata = py_touserdata(self);
|
||||
c11_vector__erase(py_TValue, userdata, i);
|
||||
}
|
||||
|
||||
int py_list__len(py_Ref self) {
|
||||
int py_list_len(py_Ref self) {
|
||||
List* userdata = py_touserdata(self);
|
||||
return userdata->count;
|
||||
}
|
||||
|
||||
void py_list__append(py_Ref self, py_Ref val) {
|
||||
void py_list_append(py_Ref self, py_Ref val) {
|
||||
List* userdata = py_touserdata(self);
|
||||
c11_vector__push(py_TValue, userdata, *val);
|
||||
}
|
||||
|
||||
void py_list__clear(py_Ref self) {
|
||||
void py_list_clear(py_Ref self) {
|
||||
List* userdata = py_touserdata(self);
|
||||
c11_vector__clear(userdata);
|
||||
}
|
||||
|
||||
void py_list__insert(py_Ref self, int i, py_Ref val) {
|
||||
void py_list_insert(py_Ref self, int i, py_Ref val) {
|
||||
List* userdata = py_touserdata(self);
|
||||
c11_vector__insert(py_TValue, userdata, i, *val);
|
||||
}
|
||||
|
||||
void py_list__reverse(py_Ref self) {
|
||||
void py_list_reverse(py_Ref self) {
|
||||
List* userdata = py_touserdata(self);
|
||||
c11__reverse(py_TValue, userdata);
|
||||
}
|
||||
@ -67,7 +67,7 @@ void py_list__reverse(py_Ref self) {
|
||||
////////////////////////////////
|
||||
static bool list__len__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_i64 res = py_list__len(py_arg(0));
|
||||
py_i64 res = py_list_len(py_arg(0));
|
||||
py_newint(py_retval(), res);
|
||||
return true;
|
||||
}
|
||||
@ -107,7 +107,7 @@ static bool list__new__(int argc, py_Ref argv) {
|
||||
if(p) {
|
||||
py_newlistn(py_retval(), length);
|
||||
for(int i = 0; i < length; i++) {
|
||||
py_list__setitem(py_retval(), i, p + i);
|
||||
py_list_setitem(py_retval(), i, p + i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -125,7 +125,7 @@ static bool list__new__(int argc, py_Ref argv) {
|
||||
return false;
|
||||
}
|
||||
if(!res) break;
|
||||
py_list__append(list, py_retval());
|
||||
py_list_append(list, py_retval());
|
||||
}
|
||||
*py_retval() = *list;
|
||||
py_shrink(2);
|
||||
@ -216,9 +216,9 @@ static bool list__mul__(int argc, py_Ref argv) {
|
||||
|
||||
static bool list__rmul__(int argc, py_Ref argv) { return list__mul__(argc, argv); }
|
||||
|
||||
static bool list__append(int argc, py_Ref argv) {
|
||||
static bool list_append(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
py_list__append(py_arg(0), py_arg(1));
|
||||
py_list_append(py_arg(0), py_arg(1));
|
||||
py_newnone(py_retval());
|
||||
return true;
|
||||
}
|
||||
@ -243,7 +243,7 @@ static bool list__repr__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool list__extend(int argc, py_Ref argv) {
|
||||
static bool list_extend(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
PY_CHECK_ARG_TYPE(1, tp_list);
|
||||
@ -253,11 +253,11 @@ static bool list__extend(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool list__count(int argc, py_Ref argv) {
|
||||
static bool list_count(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
int count = 0;
|
||||
for(int i = 0; i < py_list__len(py_arg(0)); i++) {
|
||||
int res = py_equal(py_list__getitem(py_arg(0), i), py_arg(1));
|
||||
for(int i = 0; i < py_list_len(py_arg(0)); i++) {
|
||||
int res = py_equal(py_list_getitem(py_arg(0), i), py_arg(1));
|
||||
if(res == -1) return false;
|
||||
if(res) count++;
|
||||
}
|
||||
@ -265,14 +265,14 @@ static bool list__count(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool list__clear(int argc, py_Ref argv) {
|
||||
static bool list_clear(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_list__clear(py_arg(0));
|
||||
py_list_clear(py_arg(0));
|
||||
py_newnone(py_retval());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool list__copy(int argc, py_Ref argv) {
|
||||
static bool list_copy(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_newlist(py_retval());
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
@ -281,15 +281,15 @@ static bool list__copy(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool list__index(int argc, py_Ref argv) {
|
||||
static bool list_index(int argc, py_Ref argv) {
|
||||
if(argc > 3) return TypeError("index() takes at most 3 arguments");
|
||||
int start = 0;
|
||||
if(argc == 3) {
|
||||
PY_CHECK_ARG_TYPE(2, tp_int);
|
||||
start = py_toint(py_arg(2));
|
||||
}
|
||||
for(int i = start; i < py_list__len(py_arg(0)); i++) {
|
||||
int res = py_equal(py_list__getitem(py_arg(0), i), py_arg(1));
|
||||
for(int i = start; i < py_list_len(py_arg(0)); i++) {
|
||||
int res = py_equal(py_list_getitem(py_arg(0), i), py_arg(1));
|
||||
if(res == -1) return false;
|
||||
if(res) {
|
||||
py_newint(py_retval(), i);
|
||||
@ -299,7 +299,7 @@ static bool list__index(int argc, py_Ref argv) {
|
||||
return ValueError("list.index(x): x not in list");
|
||||
}
|
||||
|
||||
static bool list__reverse(int argc, py_Ref argv) {
|
||||
static bool list_reverse(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
c11__reverse(py_TValue, self);
|
||||
@ -307,13 +307,13 @@ static bool list__reverse(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool list__remove(int argc, py_Ref argv) {
|
||||
static bool list_remove(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
for(int i = 0; i < py_list__len(py_arg(0)); i++) {
|
||||
int res = py_equal(py_list__getitem(py_arg(0), i), py_arg(1));
|
||||
for(int i = 0; i < py_list_len(py_arg(0)); i++) {
|
||||
int res = py_equal(py_list_getitem(py_arg(0), i), py_arg(1));
|
||||
if(res == -1) return false;
|
||||
if(res) {
|
||||
py_list__delitem(py_arg(0), i);
|
||||
py_list_delitem(py_arg(0), i);
|
||||
py_newnone(py_retval());
|
||||
return true;
|
||||
}
|
||||
@ -321,7 +321,7 @@ static bool list__remove(int argc, py_Ref argv) {
|
||||
return ValueError("list.remove(x): x not in list");
|
||||
}
|
||||
|
||||
static bool list__pop(int argc, py_Ref argv) {
|
||||
static bool list_pop(int argc, py_Ref argv) {
|
||||
int index;
|
||||
if(argc == 1) {
|
||||
index = -1;
|
||||
@ -339,7 +339,7 @@ static bool list__pop(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool list__insert(int argc, py_Ref argv) {
|
||||
static bool list_insert(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(3);
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
@ -375,7 +375,7 @@ static int lt_with_key(py_TValue* a, py_TValue* b, py_TValue* key) {
|
||||
}
|
||||
|
||||
// sort(self, key=None, reverse=False)
|
||||
static bool list__sort(int argc, py_Ref argv) {
|
||||
static bool list_sort(int argc, py_Ref argv) {
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
|
||||
py_Ref key = py_arg(1);
|
||||
@ -423,19 +423,19 @@ py_Type pk_list__register() {
|
||||
py_bindmagic(type, __iter__, list__iter__);
|
||||
py_bindmagic(type, __contains__, list__contains__);
|
||||
|
||||
py_bindmethod(type, "append", list__append);
|
||||
py_bindmethod(type, "extend", list__extend);
|
||||
py_bindmethod(type, "count", list__count);
|
||||
py_bindmethod(type, "clear", list__clear);
|
||||
py_bindmethod(type, "copy", list__copy);
|
||||
py_bindmethod(type, "index", list__index);
|
||||
py_bindmethod(type, "reverse", list__reverse);
|
||||
py_bindmethod(type, "remove", list__remove);
|
||||
py_bindmethod(type, "pop", list__pop);
|
||||
py_bindmethod(type, "insert", list__insert);
|
||||
py_bindmethod(type, "sort", list__sort);
|
||||
py_bindmethod(type, "append", list_append);
|
||||
py_bindmethod(type, "extend", list_extend);
|
||||
py_bindmethod(type, "count", list_count);
|
||||
py_bindmethod(type, "clear", list_clear);
|
||||
py_bindmethod(type, "copy", list_copy);
|
||||
py_bindmethod(type, "index", list_index);
|
||||
py_bindmethod(type, "reverse", list_reverse);
|
||||
py_bindmethod(type, "remove", list_remove);
|
||||
py_bindmethod(type, "pop", list_pop);
|
||||
py_bindmethod(type, "insert", list_insert);
|
||||
py_bindmethod(type, "sort", list_sort);
|
||||
|
||||
py_bind(py_tpobject(type), "sort(self, key=None, reverse=False)", list__sort);
|
||||
py_bind(py_tpobject(type), "sort(self, key=None, reverse=False)", list_sort);
|
||||
|
||||
py_setdict(py_tpobject(type), __hash__, py_None);
|
||||
return type;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#define DEF_NUM_BINARY_OP(name, op, rint, rfloat) \
|
||||
static bool _py_int##name(int argc, py_Ref argv) { \
|
||||
static bool int##name(int argc, py_Ref argv) { \
|
||||
PY_CHECK_ARGC(2); \
|
||||
if(py_isint(&argv[1])) { \
|
||||
py_i64 lhs = py_toint(&argv[0]); \
|
||||
@ -20,7 +20,7 @@
|
||||
} \
|
||||
return true; \
|
||||
} \
|
||||
static bool _py_float##name(int argc, py_Ref argv) { \
|
||||
static bool float##name(int argc, py_Ref argv) { \
|
||||
PY_CHECK_ARGC(2); \
|
||||
py_f64 lhs = py_tofloat(&argv[0]); \
|
||||
py_f64 rhs; \
|
||||
@ -45,21 +45,21 @@ DEF_NUM_BINARY_OP(__ge__, >=, py_newbool, py_newbool)
|
||||
|
||||
#undef DEF_NUM_BINARY_OP
|
||||
|
||||
static bool _py_int__neg__(int argc, py_Ref argv) {
|
||||
static bool int__neg__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_i64 val = py_toint(&argv[0]);
|
||||
py_newint(py_retval(), -val);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_float__neg__(int argc, py_Ref argv) {
|
||||
static bool float__neg__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_f64 val = py_tofloat(&argv[0]);
|
||||
py_newfloat(py_retval(), -val);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_int__truediv__(int argc, py_Ref argv) {
|
||||
static bool int__truediv__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
py_i64 lhs = py_toint(&argv[0]);
|
||||
py_f64 rhs;
|
||||
@ -71,7 +71,7 @@ static bool _py_int__truediv__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_float__truediv__(int argc, py_Ref argv) {
|
||||
static bool float__truediv__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
py_f64 lhs = py_tofloat(&argv[0]);
|
||||
py_f64 rhs;
|
||||
@ -85,7 +85,7 @@ static bool _py_float__truediv__(int argc, py_Ref argv) {
|
||||
|
||||
#define ZeroDivisionError(msg) false
|
||||
|
||||
static bool _py_number__pow__(int argc, py_Ref argv) {
|
||||
static bool number__pow__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
if(py_isint(&argv[0]) && py_isint(&argv[1])) {
|
||||
py_i64 lhs = py_toint(&argv[0]);
|
||||
@ -119,7 +119,7 @@ static bool _py_number__pow__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_int__floordiv__(int argc, py_Ref argv) {
|
||||
static bool int__floordiv__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
py_i64 lhs = py_toint(&argv[0]);
|
||||
if(py_isint(&argv[1])) {
|
||||
@ -132,7 +132,7 @@ static bool _py_int__floordiv__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_int__mod__(int argc, py_Ref argv) {
|
||||
static bool int__mod__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
py_i64 lhs = py_toint(&argv[0]);
|
||||
if(py_isint(&argv[1])) {
|
||||
@ -145,14 +145,14 @@ static bool _py_int__mod__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_int__invert__(int argc, py_Ref argv) {
|
||||
static bool int__invert__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_i64 val = py_toint(&argv[0]);
|
||||
py_newint(py_retval(), ~val);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_int__bit_length(int argc, py_Ref argv) {
|
||||
static bool int_bit_length(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_i64 x = py_toint(py_arg(0));
|
||||
if(x < 0) x = -x;
|
||||
@ -166,7 +166,7 @@ static bool _py_int__bit_length(int argc, py_Ref argv) {
|
||||
}
|
||||
|
||||
#define DEF_INT_BITWISE_OP(name, op) \
|
||||
static bool _py_int##name(int argc, py_Ref argv) { \
|
||||
static bool int##name(int argc, py_Ref argv) { \
|
||||
PY_CHECK_ARGC(2); \
|
||||
py_i64 lhs = py_toint(&argv[0]); \
|
||||
if(py_isint(&argv[1])) { \
|
||||
@ -186,7 +186,7 @@ DEF_INT_BITWISE_OP(__rshift__, >>)
|
||||
|
||||
#undef DEF_INT_BITWISE_OP
|
||||
|
||||
static bool _py_int__repr__(int argc, py_Ref argv) {
|
||||
static bool int__repr__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_i64 val = py_toint(&argv[0]);
|
||||
char buf[32];
|
||||
@ -195,7 +195,7 @@ static bool _py_int__repr__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_float__repr__(int argc, py_Ref argv) {
|
||||
static bool float__repr__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_f64 val = py_tofloat(&argv[0]);
|
||||
c11_sbuf buf;
|
||||
@ -223,7 +223,7 @@ static py_i64 c11_8bytes__hash(union c11_8bytes u) {
|
||||
return u._i64;
|
||||
}
|
||||
|
||||
static bool _py_int__hash__(int argc, py_Ref argv) {
|
||||
static bool int__hash__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_i64 val = py_toint(&argv[0]);
|
||||
union c11_8bytes u = {._i64 = val};
|
||||
@ -231,7 +231,7 @@ static bool _py_int__hash__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_float__hash__(int argc, py_Ref argv) {
|
||||
static bool float__hash__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_f64 val = py_tofloat(&argv[0]);
|
||||
union c11_8bytes u = {._f64 = val};
|
||||
@ -239,21 +239,21 @@ static bool _py_float__hash__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_int__abs__(int argc, py_Ref argv) {
|
||||
static bool int__abs__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_i64 val = py_toint(&argv[0]);
|
||||
py_newint(py_retval(), val < 0 ? -val : val);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_float__abs__(int argc, py_Ref argv) {
|
||||
static bool float__abs__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_f64 val = py_tofloat(&argv[0]);
|
||||
py_newfloat(py_retval(), val < 0 ? -val : val);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_int__new__(int argc, py_Ref argv) {
|
||||
static bool int__new__(int argc, py_Ref argv) {
|
||||
if(argc == 1 + 0) {
|
||||
// int() == 0
|
||||
py_newint(py_retval(), 0);
|
||||
@ -308,7 +308,7 @@ static bool _py_int__new__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_float__new__(int argc, py_Ref argv) {
|
||||
static bool float__new__(int argc, py_Ref argv) {
|
||||
if(argc == 1 + 0) {
|
||||
// float() == 0.0
|
||||
py_newfloat(py_retval(), 0.0);
|
||||
@ -356,7 +356,7 @@ static bool _py_float__new__(int argc, py_Ref argv) {
|
||||
}
|
||||
|
||||
// tp_bool
|
||||
static bool _py_bool__new__(int argc, py_Ref argv) {
|
||||
static bool bool__new__(int argc, py_Ref argv) {
|
||||
assert(argc > 0);
|
||||
if(argc == 1){
|
||||
py_newbool(py_retval(), false);
|
||||
@ -371,21 +371,21 @@ static bool _py_bool__new__(int argc, py_Ref argv) {
|
||||
return TypeError("bool() takes at most 1 argument");
|
||||
}
|
||||
|
||||
static bool _py_bool__hash__(int argc, py_Ref argv) {
|
||||
static bool bool__hash__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
bool res = py_tobool(argv);
|
||||
py_newint(py_retval(), res);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_bool__repr__(int argc, py_Ref argv) {
|
||||
static bool bool__repr__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
bool res = py_tobool(argv);
|
||||
py_newstr(py_retval(), res ? "True" : "False");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_bool__eq__(int argc, py_Ref argv) {
|
||||
static bool bool__eq__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
bool lhs = py_tobool(&argv[0]);
|
||||
if(argv[1].type == tp_bool) {
|
||||
@ -397,7 +397,7 @@ static bool _py_bool__eq__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_bool__ne__(int argc, py_Ref argv) {
|
||||
static bool bool__ne__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
bool lhs = py_tobool(&argv[0]);
|
||||
if(argv[1].type == tp_bool) {
|
||||
@ -411,74 +411,74 @@ static bool _py_bool__ne__(int argc, py_Ref argv) {
|
||||
|
||||
void pk_number__register() {
|
||||
/****** tp_int & tp_float ******/
|
||||
py_bindmagic(tp_int, __add__, _py_int__add__);
|
||||
py_bindmagic(tp_float, __add__, _py_float__add__);
|
||||
py_bindmagic(tp_int, __sub__, _py_int__sub__);
|
||||
py_bindmagic(tp_float, __sub__, _py_float__sub__);
|
||||
py_bindmagic(tp_int, __mul__, _py_int__mul__);
|
||||
py_bindmagic(tp_float, __mul__, _py_float__mul__);
|
||||
py_bindmagic(tp_int, __add__, int__add__);
|
||||
py_bindmagic(tp_float, __add__, float__add__);
|
||||
py_bindmagic(tp_int, __sub__, int__sub__);
|
||||
py_bindmagic(tp_float, __sub__, float__sub__);
|
||||
py_bindmagic(tp_int, __mul__, int__mul__);
|
||||
py_bindmagic(tp_float, __mul__, float__mul__);
|
||||
|
||||
py_bindmagic(tp_int, __eq__, _py_int__eq__);
|
||||
py_bindmagic(tp_float, __eq__, _py_float__eq__);
|
||||
py_bindmagic(tp_int, __ne__, _py_int__ne__);
|
||||
py_bindmagic(tp_float, __ne__, _py_float__ne__);
|
||||
py_bindmagic(tp_int, __lt__, _py_int__lt__);
|
||||
py_bindmagic(tp_float, __lt__, _py_float__lt__);
|
||||
py_bindmagic(tp_int, __le__, _py_int__le__);
|
||||
py_bindmagic(tp_float, __le__, _py_float__le__);
|
||||
py_bindmagic(tp_int, __gt__, _py_int__gt__);
|
||||
py_bindmagic(tp_float, __gt__, _py_float__gt__);
|
||||
py_bindmagic(tp_int, __ge__, _py_int__ge__);
|
||||
py_bindmagic(tp_float, __ge__, _py_float__ge__);
|
||||
py_bindmagic(tp_int, __eq__, int__eq__);
|
||||
py_bindmagic(tp_float, __eq__, float__eq__);
|
||||
py_bindmagic(tp_int, __ne__, int__ne__);
|
||||
py_bindmagic(tp_float, __ne__, float__ne__);
|
||||
py_bindmagic(tp_int, __lt__, int__lt__);
|
||||
py_bindmagic(tp_float, __lt__, float__lt__);
|
||||
py_bindmagic(tp_int, __le__, int__le__);
|
||||
py_bindmagic(tp_float, __le__, float__le__);
|
||||
py_bindmagic(tp_int, __gt__, int__gt__);
|
||||
py_bindmagic(tp_float, __gt__, float__gt__);
|
||||
py_bindmagic(tp_int, __ge__, int__ge__);
|
||||
py_bindmagic(tp_float, __ge__, float__ge__);
|
||||
|
||||
// __neg__
|
||||
py_bindmagic(tp_int, __neg__, _py_int__neg__);
|
||||
py_bindmagic(tp_float, __neg__, _py_float__neg__);
|
||||
py_bindmagic(tp_int, __neg__, int__neg__);
|
||||
py_bindmagic(tp_float, __neg__, float__neg__);
|
||||
|
||||
// __repr__
|
||||
py_bindmagic(tp_int, __repr__, _py_int__repr__);
|
||||
py_bindmagic(tp_float, __repr__, _py_float__repr__);
|
||||
py_bindmagic(tp_int, __repr__, int__repr__);
|
||||
py_bindmagic(tp_float, __repr__, float__repr__);
|
||||
|
||||
// __hash__
|
||||
py_bindmagic(tp_int, __hash__, _py_int__hash__);
|
||||
py_bindmagic(tp_float, __hash__, _py_float__hash__);
|
||||
py_bindmagic(tp_int, __hash__, int__hash__);
|
||||
py_bindmagic(tp_float, __hash__, float__hash__);
|
||||
|
||||
// __abs__
|
||||
py_bindmagic(tp_int, __abs__, _py_int__abs__);
|
||||
py_bindmagic(tp_float, __abs__, _py_float__abs__);
|
||||
py_bindmagic(tp_int, __abs__, int__abs__);
|
||||
py_bindmagic(tp_float, __abs__, float__abs__);
|
||||
|
||||
// __new__
|
||||
py_bindmagic(tp_int, __new__, _py_int__new__);
|
||||
py_bindmagic(tp_float, __new__, _py_float__new__);
|
||||
py_bindmagic(tp_int, __new__, int__new__);
|
||||
py_bindmagic(tp_float, __new__, float__new__);
|
||||
|
||||
// __truediv__
|
||||
py_bindmagic(tp_int, __truediv__, _py_int__truediv__);
|
||||
py_bindmagic(tp_float, __truediv__, _py_float__truediv__);
|
||||
py_bindmagic(tp_int, __truediv__, int__truediv__);
|
||||
py_bindmagic(tp_float, __truediv__, float__truediv__);
|
||||
|
||||
// __pow__
|
||||
py_bindmagic(tp_int, __pow__, _py_number__pow__);
|
||||
py_bindmagic(tp_float, __pow__, _py_number__pow__);
|
||||
py_bindmagic(tp_int, __pow__, number__pow__);
|
||||
py_bindmagic(tp_float, __pow__, number__pow__);
|
||||
|
||||
// __floordiv__ & __mod__
|
||||
py_bindmagic(tp_int, __floordiv__, _py_int__floordiv__);
|
||||
py_bindmagic(tp_int, __mod__, _py_int__mod__);
|
||||
py_bindmagic(tp_int, __floordiv__, int__floordiv__);
|
||||
py_bindmagic(tp_int, __mod__, int__mod__);
|
||||
|
||||
// int.__invert__ & int.<BITWISE OP>
|
||||
py_bindmagic(tp_int, __invert__, _py_int__invert__);
|
||||
py_bindmagic(tp_int, __invert__, int__invert__);
|
||||
|
||||
py_bindmagic(tp_int, __and__, _py_int__and__);
|
||||
py_bindmagic(tp_int, __or__, _py_int__or__);
|
||||
py_bindmagic(tp_int, __xor__, _py_int__xor__);
|
||||
py_bindmagic(tp_int, __lshift__, _py_int__lshift__);
|
||||
py_bindmagic(tp_int, __rshift__, _py_int__rshift__);
|
||||
py_bindmagic(tp_int, __and__, int__and__);
|
||||
py_bindmagic(tp_int, __or__, int__or__);
|
||||
py_bindmagic(tp_int, __xor__, int__xor__);
|
||||
py_bindmagic(tp_int, __lshift__, int__lshift__);
|
||||
py_bindmagic(tp_int, __rshift__, int__rshift__);
|
||||
|
||||
// int.bit_length
|
||||
py_bindmethod(tp_int, "bit_length", _py_int__bit_length);
|
||||
py_bindmethod(tp_int, "bit_length", int_bit_length);
|
||||
|
||||
/* tp_bool */
|
||||
py_bindmagic(tp_bool, __new__, _py_bool__new__);
|
||||
py_bindmagic(tp_bool, __hash__, _py_bool__hash__);
|
||||
py_bindmagic(tp_bool, __repr__, _py_bool__repr__);
|
||||
py_bindmagic(tp_bool, __eq__, _py_bool__eq__);
|
||||
py_bindmagic(tp_bool, __ne__, _py_bool__ne__);
|
||||
py_bindmagic(tp_bool, __new__, bool__new__);
|
||||
py_bindmagic(tp_bool, __hash__, bool__hash__);
|
||||
py_bindmagic(tp_bool, __repr__, bool__repr__);
|
||||
py_bindmagic(tp_bool, __eq__, bool__eq__);
|
||||
py_bindmagic(tp_bool, __ne__, bool__ne__);
|
||||
}
|
||||
@ -64,7 +64,11 @@ static bool type__base__getter(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_Type type = py_totype(argv);
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
|
||||
py_assign(py_retval(), py_tpobject(ti->base));
|
||||
if(ti->base){
|
||||
py_assign(py_retval(), py_tpobject(ti->base));
|
||||
}else{
|
||||
py_newnone(py_retval());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -71,7 +71,10 @@ int py_next(py_Ref val) {
|
||||
VM* vm = pk_current_vm;
|
||||
vm->is_stopiteration = false;
|
||||
py_Ref tmp = py_tpfindmagic(val->type, __next__);
|
||||
if(!tmp) return TypeError("'%t' object is not an iterator", val->type);
|
||||
if(!tmp) {
|
||||
TypeError("'%t' object is not an iterator", val->type);
|
||||
return -1;
|
||||
}
|
||||
py_StackRef p0 = py_peek(0);
|
||||
if(py_call(tmp, 1, val)) return true;
|
||||
if(vm->curr_exception.type == tp_StopIteration) {
|
||||
|
||||
@ -42,10 +42,35 @@ static bool slice__repr__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool slice_start__getter(int argc, py_Ref argv) {
|
||||
py_Ref self = py_arg(0);
|
||||
py_TValue* val = py_getslot(self, 0);
|
||||
py_assign(py_retval(), val);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool slice_stop__getter(int argc, py_Ref argv) {
|
||||
py_Ref self = py_arg(0);
|
||||
py_TValue* val = py_getslot(self, 1);
|
||||
py_assign(py_retval(), val);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool slice_step__getter(int argc, py_Ref argv) {
|
||||
py_Ref self = py_arg(0);
|
||||
py_TValue* val = py_getslot(self, 2);
|
||||
py_assign(py_retval(), val);
|
||||
return true;
|
||||
}
|
||||
|
||||
py_Type pk_slice__register() {
|
||||
py_Type type = pk_newtype("slice", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __new__, slice__new__);
|
||||
py_bindmagic(type, __repr__, slice__repr__);
|
||||
|
||||
py_bindproperty(type, "start", slice_start__getter, NULL);
|
||||
py_bindproperty(type, "stop", slice_stop__getter, NULL);
|
||||
py_bindproperty(type, "step", slice_step__getter, NULL);
|
||||
return type;
|
||||
}
|
||||
@ -212,7 +212,7 @@ DEF_STR_CMP_OP(__ge__, c11_sv__cmp, res >= 0)
|
||||
|
||||
#undef DEF_STR_CMP_OP
|
||||
|
||||
static bool str__lower(int argc, py_Ref argv) {
|
||||
static bool str_lower(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
int total_size = sizeof(c11_string) + self->size + 1;
|
||||
@ -227,7 +227,7 @@ static bool str__lower(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str__upper(int argc, py_Ref argv) {
|
||||
static bool str_upper(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
int total_size = sizeof(c11_string) + self->size + 1;
|
||||
@ -242,7 +242,7 @@ static bool str__upper(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str__startswith(int argc, py_Ref argv) {
|
||||
static bool str_startswith(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
@ -251,7 +251,7 @@ static bool str__startswith(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str__endswith(int argc, py_Ref argv) {
|
||||
static bool str_endswith(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
@ -260,7 +260,7 @@ static bool str__endswith(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str__join(int argc, py_Ref argv) {
|
||||
static bool str_join(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
|
||||
py_Ref _1 = py_arg(1);
|
||||
@ -268,11 +268,11 @@ static bool str__join(int argc, py_Ref argv) {
|
||||
py_TValue* p;
|
||||
int length;
|
||||
if(py_istype(_1, tp_list)) {
|
||||
p = py_list__getitem(_1, 0);
|
||||
length = py_list__len(_1);
|
||||
p = py_list_getitem(_1, 0);
|
||||
length = py_list_len(_1);
|
||||
} else if(py_istype(_1, tp_tuple)) {
|
||||
p = py_tuple__getitem(_1, 0);
|
||||
length = py_tuple__len(_1);
|
||||
p = py_tuple_getitem(_1, 0);
|
||||
length = py_tuple_len(_1);
|
||||
} else {
|
||||
return TypeError("join() argument must be a list or tuple");
|
||||
}
|
||||
@ -292,7 +292,7 @@ static bool str__join(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str__replace(int argc, py_Ref argv) {
|
||||
static bool str_replace(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(3);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
@ -306,7 +306,7 @@ static bool str__replace(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str__split(int argc, py_Ref argv) {
|
||||
static bool str_split(int argc, py_Ref argv) {
|
||||
c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
|
||||
c11_vector res;
|
||||
if(argc > 2) return TypeError("split() takes at most 2 arguments");
|
||||
@ -323,13 +323,13 @@ static bool str__split(int argc, py_Ref argv) {
|
||||
py_newlistn(py_retval(), res.count);
|
||||
for(int i = 0; i < res.count; i++) {
|
||||
c11_sv item = c11__getitem(c11_sv, &res, i);
|
||||
py_newstrn(py_list__getitem(py_retval(), i), item.data, item.size);
|
||||
py_newstrn(py_list_getitem(py_retval(), i), item.data, item.size);
|
||||
}
|
||||
c11_vector__dtor(&res);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str__count(int argc, py_Ref argv) {
|
||||
static bool str_count(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
@ -355,19 +355,19 @@ static bool str__strip_impl(bool left, bool right, int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str__strip(int argc, py_Ref argv) {
|
||||
static bool str_strip(int argc, py_Ref argv) {
|
||||
return str__strip_impl(true, true, argc, argv);
|
||||
}
|
||||
|
||||
static bool str__lstrip(int argc, py_Ref argv) {
|
||||
static bool str_lstrip(int argc, py_Ref argv) {
|
||||
return str__strip_impl(true, false, argc, argv);
|
||||
}
|
||||
|
||||
static bool str__rstrip(int argc, py_Ref argv) {
|
||||
static bool str_rstrip(int argc, py_Ref argv) {
|
||||
return str__strip_impl(false, true, argc, argv);
|
||||
}
|
||||
|
||||
static bool str__zfill(int argc, py_Ref argv) {
|
||||
static bool str_zfill(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
@ -423,15 +423,15 @@ static bool str__widthjust_impl(bool left, int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str__ljust(int argc, py_Ref argv) {
|
||||
static bool str_ljust(int argc, py_Ref argv) {
|
||||
return str__widthjust_impl(true, argc, argv);
|
||||
}
|
||||
|
||||
static bool str__rjust(int argc, py_Ref argv) {
|
||||
static bool str_rjust(int argc, py_Ref argv) {
|
||||
return str__widthjust_impl(false, argc, argv);
|
||||
}
|
||||
|
||||
static bool str__find(int argc, py_Ref argv) {
|
||||
static bool str_find(int argc, py_Ref argv) {
|
||||
if(argc > 3) return TypeError("find() takes at most 3 arguments");
|
||||
int start = 0;
|
||||
if(argc == 3) {
|
||||
@ -446,8 +446,8 @@ static bool str__find(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str__index(int argc, py_Ref argv) {
|
||||
bool ok = str__find(argc, argv);
|
||||
static bool str_index(int argc, py_Ref argv) {
|
||||
bool ok = str_find(argc, argv);
|
||||
if(!ok) return false;
|
||||
if(py_toint(py_retval()) == -1) return ValueError("substring not found");
|
||||
return true;
|
||||
@ -476,22 +476,22 @@ py_Type pk_str__register() {
|
||||
py_bindmagic(tp_str, __gt__, str__gt__);
|
||||
py_bindmagic(tp_str, __ge__, str__ge__);
|
||||
|
||||
py_bindmethod(tp_str, "lower", str__lower);
|
||||
py_bindmethod(tp_str, "upper", str__upper);
|
||||
py_bindmethod(tp_str, "startswith", str__startswith);
|
||||
py_bindmethod(tp_str, "endswith", str__endswith);
|
||||
py_bindmethod(tp_str, "join", str__join);
|
||||
py_bindmethod(tp_str, "replace", str__replace);
|
||||
py_bindmethod(tp_str, "split", str__split);
|
||||
py_bindmethod(tp_str, "count", str__count);
|
||||
py_bindmethod(tp_str, "strip", str__strip);
|
||||
py_bindmethod(tp_str, "lstrip", str__lstrip);
|
||||
py_bindmethod(tp_str, "rstrip", str__rstrip);
|
||||
py_bindmethod(tp_str, "zfill", str__zfill);
|
||||
py_bindmethod(tp_str, "ljust", str__ljust);
|
||||
py_bindmethod(tp_str, "rjust", str__rjust);
|
||||
py_bindmethod(tp_str, "find", str__find);
|
||||
py_bindmethod(tp_str, "index", str__index);
|
||||
py_bindmethod(tp_str, "lower", str_lower);
|
||||
py_bindmethod(tp_str, "upper", str_upper);
|
||||
py_bindmethod(tp_str, "startswith", str_startswith);
|
||||
py_bindmethod(tp_str, "endswith", str_endswith);
|
||||
py_bindmethod(tp_str, "join", str_join);
|
||||
py_bindmethod(tp_str, "replace", str_replace);
|
||||
py_bindmethod(tp_str, "split", str_split);
|
||||
py_bindmethod(tp_str, "count", str_count);
|
||||
py_bindmethod(tp_str, "strip", str_strip);
|
||||
py_bindmethod(tp_str, "lstrip", str_lstrip);
|
||||
py_bindmethod(tp_str, "rstrip", str_rstrip);
|
||||
py_bindmethod(tp_str, "zfill", str_zfill);
|
||||
py_bindmethod(tp_str, "ljust", str_ljust);
|
||||
py_bindmethod(tp_str, "rjust", str_rjust);
|
||||
py_bindmethod(tp_str, "find", str_find);
|
||||
py_bindmethod(tp_str, "index", str_index);
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
@ -13,17 +13,17 @@ void py_newtuple(py_Ref out, int n) {
|
||||
out->_obj = obj;
|
||||
}
|
||||
|
||||
py_Ref py_tuple__getitem(py_Ref self, int i) { return py_getslot(self, i); }
|
||||
py_Ref py_tuple_getitem(py_Ref self, int i) { return py_getslot(self, i); }
|
||||
|
||||
py_Ref py_tuple__data(py_Ref self) { return PyObject__slots(self->_obj); }
|
||||
py_Ref py_tuple_data(py_Ref self) { return PyObject__slots(self->_obj); }
|
||||
|
||||
void py_tuple__setitem(py_Ref self, int i, py_Ref val) { py_setslot(self, i, val); }
|
||||
void py_tuple_setitem(py_Ref self, int i, py_Ref val) { py_setslot(self, i, val); }
|
||||
|
||||
int py_tuple__len(py_Ref self) { return self->_obj->slots; }
|
||||
int py_tuple_len(py_Ref self) { return self->_obj->slots; }
|
||||
|
||||
//////////////
|
||||
static bool tuple__len__(int argc, py_Ref argv) {
|
||||
py_newint(py_retval(), py_tuple__len(argv));
|
||||
py_newint(py_retval(), py_tuple_len(argv));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ static bool tuple__repr__(int argc, py_Ref argv) {
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
c11_sbuf__write_char(&buf, '(');
|
||||
int length = py_tuple__len(argv);
|
||||
int length = py_tuple_len(argv);
|
||||
for(int i = 0; i < length; i++) {
|
||||
py_TValue* val = py_getslot(argv, i);
|
||||
bool ok = py_repr(val);
|
||||
@ -58,10 +58,10 @@ static bool tuple__new__(int argc, py_Ref argv) {
|
||||
if(!ok) return false;
|
||||
py_Ref tmp = py_pushtmp();
|
||||
*tmp = *py_retval(); // backup the list
|
||||
int length = py_list__len(tmp);
|
||||
int length = py_list_len(tmp);
|
||||
py_newtuple(py_retval(), length);
|
||||
for(int i = 0; i < py_tuple__len(py_retval()); i++) {
|
||||
py_tuple__setitem(py_retval(), i, py_list__getitem(tmp, i));
|
||||
for(int i = 0; i < py_tuple_len(py_retval()); i++) {
|
||||
py_tuple_setitem(py_retval(), i, py_list_getitem(tmp, i));
|
||||
}
|
||||
py_pop();
|
||||
return true;
|
||||
@ -71,7 +71,7 @@ static bool tuple__new__(int argc, py_Ref argv) {
|
||||
|
||||
static bool tuple__getitem__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
int length = py_tuple__len(argv);
|
||||
int length = py_tuple_len(argv);
|
||||
py_Ref _1 = py_arg(1);
|
||||
if(_1->type == tp_int) {
|
||||
int index = py_toint(py_arg(1));
|
||||
@ -84,11 +84,11 @@ static bool tuple__getitem__(int argc, py_Ref argv) {
|
||||
if(!ok) return false;
|
||||
py_Ref tmp = py_pushtmp();
|
||||
py_newlist(tmp);
|
||||
PK_SLICE_LOOP(i, start, stop, step) py_list__append(tmp, py_getslot(argv, i));
|
||||
PK_SLICE_LOOP(i, start, stop, step) py_list_append(tmp, py_getslot(argv, i));
|
||||
// convert list to tuple
|
||||
py_newtuple(py_retval(), py_list__len(tmp));
|
||||
for(int i = 0; i < py_tuple__len(py_retval()); i++) {
|
||||
py_tuple__setitem(py_retval(), i, py_list__getitem(tmp, i));
|
||||
py_newtuple(py_retval(), py_list_len(tmp));
|
||||
for(int i = 0; i < py_tuple_len(py_retval()); i++) {
|
||||
py_tuple_setitem(py_retval(), i, py_list_getitem(tmp, i));
|
||||
}
|
||||
py_pop();
|
||||
return true;
|
||||
@ -133,8 +133,8 @@ static bool tuple__contains__(int argc, py_Ref argv) {
|
||||
|
||||
static bool tuple__hash__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
int length = py_tuple__len(argv);
|
||||
py_TValue* data = py_tuple__data(argv);
|
||||
int length = py_tuple_len(argv);
|
||||
py_TValue* data = py_tuple_data(argv);
|
||||
uint64_t x = 1000003;
|
||||
for(int i = 0; i < length; i++) {
|
||||
py_i64 y;
|
||||
|
||||
@ -58,6 +58,12 @@ void py_setslot(py_Ref self, int i, py_Ref val) {
|
||||
PyObject__slots(self->_obj)[i] = *val;
|
||||
}
|
||||
|
||||
py_StackRef py_inspect_currentfunction(){
|
||||
Frame* frame = pk_current_vm->top_frame;
|
||||
if(!frame) return NULL;
|
||||
return frame->function;
|
||||
}
|
||||
|
||||
void py_assign(py_Ref dst, py_Ref src) { *dst = *src; }
|
||||
|
||||
/* Stack References */
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
a = {1, 2, 3}
|
||||
a |= {2, 3, 4}
|
||||
assert a == a
|
||||
assert a == {i for i in range(1, 3+1)}
|
||||
|
||||
a |= {2, 3, 4}
|
||||
assert a == {1, 2, 3, 4}
|
||||
|
||||
a = {1, 2, 3}
|
||||
@ -79,10 +81,10 @@ assert {1,2,3}.isdisjoint({4,5,6})
|
||||
assert not {1,2,3}.isdisjoint({2,3,4})
|
||||
|
||||
# unpacking builder
|
||||
a = {1, 2, 3}
|
||||
b = {*a, 4, 5, *a, *a}
|
||||
assert b == {1, 2, 3, 4, 5}
|
||||
# a = {1, 2, 3}
|
||||
# b = {*a, 4, 5, *a, *a}
|
||||
# assert b == {1, 2, 3, 4, 5}
|
||||
|
||||
a = set()
|
||||
b = {*a, 1, 2, 3, *a, *a}
|
||||
assert b == {1, 2, 3}
|
||||
# a = set()
|
||||
# b = {*a, 1, 2, 3, *a, *a}
|
||||
# assert b == {1, 2, 3}
|
||||
@ -13,7 +13,11 @@ assert getattr(1, '__add__')(2) == 3
|
||||
a = object()
|
||||
setattr(a, 'b', 1)
|
||||
assert a.b == 1
|
||||
assert hasattr(a, 'b')
|
||||
assert getattr(a, 'b') == 1
|
||||
assert getattr(a, 'c', ...) == ...
|
||||
delattr(a, 'b')
|
||||
assert not hasattr(a, 'b')
|
||||
|
||||
try:
|
||||
getattr(a, 'xxx')
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
# import re
|
||||
|
||||
# # test match, search, sub, split
|
||||
|
||||
# m = re.search('测试','123测试测试')
|
||||
# assert m.span() == (3,5)
|
||||
# assert m.group(0) == '测试'
|
||||
|
||||
# assert re.match('测试','123测试测试') is None
|
||||
# assert re.sub('测试','xxx','123测试12321测试') == '123xxx12321xxx'
|
||||
|
||||
# # this is different from cpython, the last empty string is not included
|
||||
# assert re.split('测试','测试123测试12321测试') == ['', '123', '12321']
|
||||
|
||||
# assert re.split(',','123,456,789,10') == ['123', '456', '789', '10']
|
||||
# assert re.split(',',',123,456,789,10') == ['', '123', '456', '789', '10']
|
||||
# assert re.split(',','123,456,789,10,') == ['123', '456', '789', '10']
|
||||
|
||||
# assert re.match('1','1') is not None
|
||||
Loading…
x
Reference in New Issue
Block a user