Compare commits

...

14 Commits

Author SHA1 Message Date
blueloveTH
65295f3e29 ... 2024-08-05 23:29:24 +08:00
blueloveTH
56097f6927 ... 2024-08-05 23:24:07 +08:00
blueloveTH
7ca97f03a7 ... 2024-08-05 22:36:26 +08:00
blueloveTH
ee29eadcd3 ... 2024-08-05 22:34:33 +08:00
blueloveTH
4254de48bf ... 2024-08-05 19:28:38 +08:00
blueloveTH
693026c6c4 ... 2024-08-05 19:25:57 +08:00
blueloveTH
33bea83e53 add docs for pocketpy.h 2024-08-05 19:20:40 +08:00
blueloveTH
26f53bf85d add setcomp 2024-08-05 17:48:48 +08:00
blueloveTH
f28335f1f7 add set 2024-08-05 17:48:06 +08:00
blueloveTH
9fbaca3b13 ... 2024-08-05 17:16:58 +08:00
blueloveTH
4e8920b280 ... 2024-08-05 17:11:53 +08:00
blueloveTH
0918256c90 ... 2024-08-05 17:06:21 +08:00
blueloveTH
90eb50a3a5 ... 2024-08-05 16:54:48 +08:00
blueloveTH
1735e0d3b8 ... 2024-08-05 16:53:02 +08:00
27 changed files with 640 additions and 457 deletions

View File

@ -7,12 +7,6 @@
extern "C" { extern "C" {
#endif #endif
#ifdef __cplusplus
#define PK_INLINE inline
#else
#define PK_INLINE static inline
#endif
#define PK_REGION(name) 1 #define PK_REGION(name) 1
#define PK_SLICE_LOOP(i, start, stop, step) \ #define PK_SLICE_LOOP(i, start, stop, step) \

View File

@ -38,38 +38,26 @@ typedef struct Frame {
struct Frame* f_back; struct Frame* f_back;
const Bytecode* ip; const Bytecode* ip;
const CodeObject* co; const CodeObject* co;
py_TValue module; // weak ref py_TValue module; // weak ref
PyObject* function; // a function object or NULL (global scope) py_StackRef function; // a function object or NULL (global scope)
py_TValue* p0; // unwinding base py_StackRef p0; // unwinding base
py_TValue* locals; // locals base py_StackRef locals; // locals base
const CodeObject* locals_co; const CodeObject* locals_co;
UnwindTarget* uw_list; UnwindTarget* uw_list;
} Frame; } Frame;
Frame* Frame__new(const CodeObject* co, Frame* Frame__new(const CodeObject* co,
py_TValue* module, py_TValue* module,
const py_TValue* function, py_StackRef function,
py_TValue* p0, py_StackRef p0,
py_TValue* locals, py_StackRef locals,
const CodeObject* locals_co); const CodeObject* locals_co);
void Frame__delete(Frame* self); void Frame__delete(Frame* self);
PK_INLINE int Frame__ip(const Frame* self) { return self->ip - (Bytecode*)self->co->codes.data; } int Frame__ip(const Frame* self);
int Frame__lineno(const Frame* self);
PK_INLINE int Frame__lineno(const Frame* self) { int Frame__iblock(const Frame* self);
int ip = Frame__ip(self); py_TValue* Frame__f_locals_try_get(Frame* self, py_Name name);
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);
}
py_TValue* Frame__f_closure_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*); int Frame__prepare_jump_exception_handler(Frame* self, ValueStack*);

View File

@ -51,6 +51,7 @@ extern py_GlobalRef py_None;
extern py_GlobalRef py_NIL; extern py_GlobalRef py_NIL;
/************* Global Setup *************/ /************* Global Setup *************/
/// Initialize pocketpy and the default VM. /// Initialize pocketpy and the default VM.
void py_initialize(); void py_initialize();
/// Finalize pocketpy. /// Finalize pocketpy.
@ -73,67 +74,102 @@ bool py_exec(const char* source,
py_Ref module) PY_RAISE; py_Ref module) PY_RAISE;
/************* Values Creation *************/ /************* 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. /// You should initialize all elements before using it.
void py_newtuple(py_Ref, int n); void py_newtuple(py_Ref, int n);
/// Create a list. /// Create an empty `list`.
void py_newlist(py_Ref); 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. /// You should initialize all elements before using it.
void py_newlistn(py_Ref, int n); void py_newlistn(py_Ref, int n);
/// Create an empty `dict`.
void py_newdict(py_Ref); 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); void py_newslice(py_Ref);
/// Create a `nativefunc` object.
void py_newnativefunc(py_Ref out, py_CFunction); void py_newnativefunc(py_Ref out, py_CFunction);
/// Create a `function` object.
py_Name py_Name
py_newfunction(py_Ref out, const char* sig, py_CFunction f, const char* docstring, int slots); 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); void py_newboundmethod(py_Ref out, py_Ref self, py_Ref func);
/************* Name Convertions *************/ /************* Name Convertions *************/
/// Convert a null-terminated string to a name.
py_Name py_name(const char*); py_Name py_name(const char*);
/// Convert a name to a null-terminated string.
const char* py_name2str(py_Name); const char* py_name2str(py_Name);
/// Convert a name to a `c11_sv`.
py_Name py_namev(c11_sv name); py_Name py_namev(c11_sv name);
/// Convert a `c11_sv` to a name.
c11_sv py_name2sv(py_Name); c11_sv py_name2sv(py_Name);
#define py_ismagicname(name) (name <= __missing__) #define py_ismagicname(name) (name <= __missing__)
/************* Meta Operations *************/ /************* Meta Operations *************/
/// Create a new type. /// Create a new type.
/// @param name name of the type. /// @param name name of the type.
/// @param base base type. /// @param base base type.
/// @param module module where the type is defined. Use NULL for built-in types. /// @param module module where the type is defined. Use `NULL` for built-in types.
/// @param dtor destructor function. Use NULL if not needed. /// @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*)); py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, void (*dtor)(void*));
/// Create a new object. /// Create a new object.
/// @param out output reference. /// @param out output reference.
/// @param type type of the object. /// @param type type of the object.
/// @param slots number of slots. Use -1 to create a `__dict__`. /// @param slots number of slots. Use -1 to create a `__dict__`.
/// @param udsize size of your userdata. 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); void* py_newobject(py_Ref out, py_Type type, int slots, int udsize);
/************* Type Cast *************/ /************* 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); void* py_touserdata(py_Ref);
#define py_isint(self) py_istype(self, tp_int) #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_isnil(self) py_istype(self, 0)
#define py_isnone(self) py_istype(self, tp_NoneType) #define py_isnone(self) py_istype(self, tp_NoneType)
/// Get the type of the object.
py_Type py_typeof(py_Ref self); py_Type py_typeof(py_Ref self);
/// Check if the object is exactly the given type.
bool py_istype(py_Ref, py_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); 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); bool py_issubclass(py_Type derived, py_Type base);
/// Search the magic method from the given type to the base type. /// 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); py_GlobalRef py_tpfindmagic(py_Type, py_Name name);
/// Search the name from the given type to the base type. /// 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); py_GlobalRef py_tpfindname(py_Type, py_Name name);
/// Get the type object of the given type. /// Get the type object of the given type.
py_GlobalRef py_tpobject(py_Type 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); const char* py_tpname(py_Type type);
/// Call a type to create a new instance. /// Call a type to create a new instance.
bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE; bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE;
/// 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); py_GlobalRef py_tpmagic(py_Type type, py_Name name);
/// Check if the object is an instance of the given type. /// Check if the object is an instance of the given type.
/// Raise `TypeError` if the check fails.
bool py_checktype(py_Ref self, py_Type type) PY_RAISE; bool py_checktype(py_Ref self, py_Type type) PY_RAISE;
#define py_checkint(self) py_checktype(self, tp_int) #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) #define py_checkstr(self) py_checktype(self, tp_str)
/************* References *************/ /************* References *************/
/// Get the reference to the i-th register. /// Get the i-th register.
/// All registers are located in a contiguous memory. /// All registers are located in a contiguous memory.
py_GlobalRef py_getreg(int i); 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); void py_setreg(int i, py_Ref val);
/// Equivalent to `*dst = *src`. /// Equivalent to `*dst = *src`.
void py_assign(py_Ref dst, py_Ref 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(); py_GlobalRef py_retval();
/// Get the reference of the object's `__dict__`. /// Get an item from the object's `__dict__`.
/// The object must have a `__dict__`. /// Return `NULL` if not found.
/// Returns a reference to the value or NULL if not found.
py_ObjectRef py_getdict(py_Ref self, py_Name name); 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); 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); 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); py_ObjectRef py_emplacedict(py_Ref self, py_Name name);
/// Get the reference of the i-th slot of the object. /// Get the i-th slot of the object.
/// The object must have slots and `i` must be in range. /// The object must have slots and `i` must be in valid range.
py_ObjectRef py_getslot(py_Ref self, int i); 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); 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 *************/ /************* 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); 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); 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); 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); 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)) #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_offset(p, i) ((py_Ref)((char*)p + ((i) << 4)))
#define py_arg(i) py_offset(argv, i) #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; 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; 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; bool py_delitem(py_Ref self, py_Ref key) PY_RAISE;
/// Perform a binary operation on the stack. /// 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 result will be set to `py_retval()`.
/// The stack remains unchanged after the operation.
bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) PY_RAISE; bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) PY_RAISE;
#define py_binaryadd(lhs, rhs) py_binaryop(lhs, rhs, __add__, __radd__) #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) #define py_binarymatmul(lhs, rhs) py_binaryop(lhs, rhs, __matmul__, 0)
/************* Stack Operations *************/ /************* 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); py_StackRef py_peek(int i);
/// Push the object to the stack. /// Push the object to the stack.
void py_push(py_Ref src); void py_push(py_Ref src);
/// Push a nil object to the stack. /// Push a `nil` object to the stack.
void py_pushnil(); void py_pushnil();
/// Pop an object from the stack. /// Pop an object from the stack.
void py_pop(); void py_pop();
/// Shrink the stack by n. /// Shrink the stack by n.
void py_shrink(int 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(); py_StackRef py_pushtmp();
/// Gets the unbound method of the object. /// Get the unbound method of the object.
/// Assumes the object is located at the top of the stack. /// Assume the object is located at the top of the stack.
/// If returns true: [self] -> [unbound, self] /// If return true: `[self] -> [unbound, self]`.
/// If returns false: [self] -> [self] (no change) /// If return false: `[self] -> [self]` (no change).
bool py_pushmethod(py_Name name); bool py_pushmethod(py_Name name);
/// A stack operation that calls a function. /// Call a callable object.
/// It assumes `argc + kwargc` arguments are already pushed to the stack. /// Assume `argc + kwargc` arguments are already pushed to the stack.
/// The result will be set to `py_retval()`. /// The result will be set to `py_retval()`.
/// The stack size will be reduced by `argc + kwargc`. /// The stack size will be reduced by `argc + kwargc`.
bool py_vectorcall(uint16_t argc, uint16_t kwargc) PY_RAISE; bool py_vectorcall(uint16_t argc, uint16_t kwargc) PY_RAISE;
/************* Modules *************/ /************* Modules *************/
/// Create a new module.
py_TmpRef py_newmodule(const char* path); py_TmpRef py_newmodule(const char* path);
/// Get a module by path.
py_TmpRef py_getmodule(const char* path); py_TmpRef py_getmodule(const char* path);
/// Import a module. /// Import a module.
@ -280,23 +361,24 @@ py_TmpRef py_getmodule(const char* path);
int py_import(const char* path) PY_RAISE; int py_import(const char* path) PY_RAISE;
/************* Errors *************/ /************* 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; 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; bool py_raise(py_Ref) PY_RAISE;
/// Print the current exception. /// Print the current exception.
void py_printexc(); 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(); char* py_formatexc();
/// Check if an exception is raised. /// Check if an exception is raised.
bool py_checkexc(); bool py_checkexc();
/// Check if the exception is an instance of the given type. /// Check if the exception is an instance of the given type.
bool py_matchexc(py_Type type); bool py_matchexc(py_Type type);
/// Clear the current exception. /// Clear the current exception.
/// @param p0 the unwinding point. Use `NULL` if not needed.
void py_clearexc(py_StackRef p0); 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 NameError(n) py_exception(tp_NameError, "name '%n' is not defined", (n))
#define TypeError(...) py_exception(tp_TypeError, __VA_ARGS__) #define TypeError(...) py_exception(tp_TypeError, __VA_ARGS__)
#define RuntimeError(...) py_exception(tp_RuntimeError, __VA_ARGS__) #define RuntimeError(...) py_exception(tp_RuntimeError, __VA_ARGS__)
@ -313,14 +395,18 @@ bool StopIteration();
bool KeyError(py_Ref key) PY_RAISE; bool KeyError(py_Ref key) PY_RAISE;
/************* Operators *************/ /************* 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)`. /// Python equivalent to `bool(val)`.
/// Returns 1 if `val` is truthy, otherwise 0. /// 1: true, 0: false, -1: error
/// Returns -1 if an error occurred.
int py_bool(py_Ref val) PY_RAISE; 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_eq(lhs, rhs) py_binaryop(lhs, rhs, __eq__, __eq__)
#define py_ne(lhs, rhs) py_binaryop(lhs, rhs, __ne__, __ne__) #define py_ne(lhs, rhs) py_binaryop(lhs, rhs, __ne__, __ne__)
#define py_lt(lhs, rhs) py_binaryop(lhs, rhs, __lt__, __gt__) #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_gt(lhs, rhs) py_binaryop(lhs, rhs, __gt__, __lt__)
#define py_ge(lhs, rhs) py_binaryop(lhs, rhs, __ge__, __le__) #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; bool py_hash(py_Ref, py_i64* out) PY_RAISE;
/// Get the iterator of the object. /// Get the iterator of the object.
bool py_iter(py_Ref) PY_RAISE; bool py_iter(py_Ref) PY_RAISE;
@ -341,40 +428,41 @@ bool py_isidentical(py_Ref, py_Ref);
/// The result will be set to `py_retval()`. /// The result will be set to `py_retval()`.
/// The stack remains unchanged after the operation. /// The stack remains unchanged after the operation.
bool py_call(py_Ref f, int argc, py_Ref argv) PY_RAISE; bool py_call(py_Ref f, int argc, py_Ref argv) PY_RAISE;
/// 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; bool py_str(py_Ref val) PY_RAISE;
/// Python equivalent to `repr(val)`.
bool py_repr(py_Ref val) PY_RAISE; bool py_repr(py_Ref val) PY_RAISE;
/// Python equivalent to `len(val)`.
bool py_len(py_Ref val) PY_RAISE; bool py_len(py_Ref val) PY_RAISE;
/************* Unchecked Functions *************/ /************* 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_ObjectRef py_tuple_data(py_Ref self);
py_TmpRef py_list__getitem(py_Ref self, int i); py_ObjectRef py_tuple_getitem(py_Ref self, int i);
void py_list__setitem(py_Ref self, int i, py_Ref val); void py_tuple_setitem(py_Ref self, int i, py_Ref val);
void py_list__delitem(py_Ref self, int i); int py_tuple_len(py_Ref self);
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; py_TmpRef py_list_data(py_Ref self);
void py_dict__setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE; py_TmpRef py_list_getitem(py_Ref self, int i);
void py_dict__delitem(py_Ref self, py_Ref key) PY_RAISE; void py_list_setitem(py_Ref self, int i, py_Ref val);
bool py_dict__contains(py_Ref self, py_Ref key); void py_list_delitem(py_Ref self, int i);
int py_dict__len(py_Ref self); int py_list_len(py_Ref self);
bool py_dict__apply(py_Ref self, bool (*f)(py_Ref key, py_Ref val, void* ctx), void* ctx); 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 *************/ /************* Others *************/
/// An utility function to read a line from stdin for REPL.
int py_replinput(char* buf, int max_size); int py_replinput(char* buf, int max_size);
/// Python favored string formatting. (just put here, not for users) /// Python favored string formatting. (just put here, not for users)
@ -415,8 +503,8 @@ enum py_PredefinedTypes {
tp_function, tp_function,
tp_nativefunc, tp_nativefunc,
tp_boundmethod, tp_boundmethod,
tp_super, // 1 slot + py_Type tp_super, // 1 slot + py_Type
tp_BaseException, tp_BaseException, // 2 slots (arg + inner exc)
tp_Exception, tp_Exception,
tp_bytes, tp_bytes,
tp_mappingproxy, tp_mappingproxy,

View File

@ -2262,7 +2262,7 @@ static Error* read_literal(Compiler* self, py_Ref out) {
consume(TK_RPAREN); consume(TK_RPAREN);
py_newtuple(out, count); py_newtuple(out, count);
for(int i = 0; i < count; i++) { for(int i = 0; i < count; i++) {
py_tuple__setitem(out, i, &cpnts[i]); py_tuple_setitem(out, i, &cpnts[i]);
} }
return NULL; 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_(ctx(), OP_PUSH_EXCEPTION, BC_NOARG, BC_KEEPLINE);
Ctx__emit_store_name(ctx(), name_scope(self), as_name, BC_KEEPLINE); Ctx__emit_store_name(ctx(), name_scope(self), as_name, BC_KEEPLINE);
} }
check(compile_block_body(self, compile_stmt));
// pop the exception // pop the exception
Ctx__emit_(ctx(), OP_POP_EXCEPTION, BC_NOARG, BC_KEEPLINE); 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); patches[patches_length++] = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
Ctx__patch_jump(ctx(), patch); Ctx__patch_jump(ctx(), patch);
} while(curr()->type == TK_EXCEPT); } while(curr()->type == TK_EXCEPT);

View File

@ -54,7 +54,7 @@ static bool format_object(py_Ref obj, c11_sv spec);
#define vectorcall_opcall(argc, kwargc) \ #define vectorcall_opcall(argc, kwargc) \
do { \ do { \
FrameResult res = VM__vectorcall(self, (argc), (kwargc), true); \ FrameResult res = VM__vectorcall(self, (argc), (kwargc), true); \
switch(res) { \ switch(res) { \
case RES_RETURN: PUSH(&self->last_retval); break; \ case RES_RETURN: PUSH(&self->last_retval); break; \
case RES_CALL: frame = self->top_frame; goto __NEXT_FRAME; \ 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->type == tp_nativefunc) {
if(!magic->_cfunc(2, SECOND())) goto __ERROR; if(!magic->_cfunc(2, SECOND())) goto __ERROR;
POP(); POP();
*TOP() = self->last_retval;
} else { } else {
INSERT_THIRD(); // [?, a, b] INSERT_THIRD(); // [?, a, b]
*THIRD() = *magic; // [__getitem__, a, b] *THIRD() = *magic; // [__getitem__, a, b]
if(!py_vectorcall(1, 0)) goto __ERROR; if(!py_vectorcall(1, 0)) goto __ERROR;
} }
*TOP() = self->last_retval;
DISPATCH(); DISPATCH();
} }
TypeError("'%t' object is not subscriptable", SECOND()->type); 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] py_newint(SP()++, 0); // [complex, NULL, 0]
*SP()++ = tmp; // [complex, NULL, 0, x] *SP()++ = tmp; // [complex, NULL, 0, x]
if(!py_vectorcall(2, 0)) goto __ERROR; if(!py_vectorcall(2, 0)) goto __ERROR;
PUSH(py_retval());
DISPATCH(); DISPATCH();
} }
case OP_BUILD_BYTES: { case OP_BUILD_BYTES: {
@ -437,7 +438,7 @@ FrameResult VM__run_top_frame(VM* self) {
py_newtuple(&tmp, byte.arg); py_newtuple(&tmp, byte.arg);
py_TValue* begin = SP() - byte.arg; py_TValue* begin = SP() - byte.arg;
for(int i = 0; i < byte.arg; i++) { for(int i = 0; i < byte.arg; i++) {
py_tuple__setitem(&tmp, i, begin + i); py_tuple_setitem(&tmp, i, begin + i);
} }
SP() = begin; SP() = begin;
PUSH(&tmp); PUSH(&tmp);
@ -448,7 +449,7 @@ FrameResult VM__run_top_frame(VM* self) {
py_newlistn(&tmp, byte.arg); py_newlistn(&tmp, byte.arg);
py_TValue* begin = SP() - byte.arg; py_TValue* begin = SP() - byte.arg;
for(int i = 0; i < byte.arg; i++) { for(int i = 0; i < byte.arg; i++) {
py_list__setitem(&tmp, i, begin + i); py_list_setitem(&tmp, i, begin + i);
} }
SP() = begin; SP() = begin;
PUSH(&tmp); PUSH(&tmp);
@ -459,7 +460,7 @@ FrameResult VM__run_top_frame(VM* self) {
py_Ref tmp = py_pushtmp(); py_Ref tmp = py_pushtmp();
py_newdict(tmp); py_newdict(tmp);
for(int i = 0; i < byte.arg * 2; i += 2) { 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; if(py_checkexc()) goto __ERROR;
} }
SP() = begin; SP() = begin;
@ -476,7 +477,12 @@ FrameResult VM__run_top_frame(VM* self) {
py_push(py_retval()); // empty set py_push(py_retval()); // empty set
py_Name id_add = py_name("add"); py_Name id_add = py_name("add");
for(int i = 0; i < byte.arg; i++) { 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(); py_TValue tmp = *TOP();
SP() = begin; SP() = begin;
@ -529,14 +535,14 @@ FrameResult VM__run_top_frame(VM* self) {
if(magic->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
if(!magic->_cfunc(2, SECOND())) goto __ERROR; if(!magic->_cfunc(2, SECOND())) goto __ERROR;
POP(); POP();
*TOP() = self->last_retval;
} else { } else {
INSERT_THIRD(); // [?, b, a] INSERT_THIRD(); // [?, b, a]
*THIRD() = *magic; // [__contains__, a, b] *THIRD() = *magic; // [__contains__, a, b]
if(!py_vectorcall(1, 0)) goto __ERROR; if(!py_vectorcall(1, 0)) goto __ERROR;
} }
bool res = py_tobool(TOP()); bool res = py_tobool(py_retval());
if(byte.arg) py_newbool(TOP(), !res); if(byte.arg) res = !res;
py_newbool(SP()++, res);
DISPATCH(); DISPATCH();
} }
TypeError("'%t' type does not support '__contains__'", SECOND()->type); 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); py_TValue* kwargs = py_getslot(&curr[1], 0);
if(kwargs->type == tp_dict) { if(kwargs->type == tp_dict) {
py_TValue* p = buf + n; 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; n = p - buf;
kwargc += py_dict__len(kwargs) - 1; kwargc += py_dict_len(kwargs) - 1;
} else { } else {
TypeError("**kwargs must be a dict, got '%t'", kwargs->type); TypeError("**kwargs must be a dict, got '%t'", kwargs->type);
goto __ERROR; goto __ERROR;
@ -700,18 +706,26 @@ FrameResult VM__run_top_frame(VM* self) {
///////// /////////
case OP_LIST_APPEND: { case OP_LIST_APPEND: {
// [list, iter, value] // [list, iter, value]
py_list__append(THIRD(), TOP()); py_list_append(THIRD(), TOP());
POP(); POP();
DISPATCH(); DISPATCH();
} }
case OP_DICT_ADD: { case OP_DICT_ADD: {
// [dict, iter, key, value] // [dict, iter, key, value]
py_dict__setitem(FOURTH(), SECOND(), TOP()); py_dict_setitem(FOURTH(), SECOND(), TOP());
if(py_checkexc()) goto __ERROR; if(py_checkexc()) goto __ERROR;
STACK_SHRINK(2); STACK_SHRINK(2);
DISPATCH(); DISPATCH();
} }
case OP_SET_ADD: { 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(); DISPATCH();
} }
///////// /////////
@ -824,7 +838,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
py_newlistn(SP()++, exceed); py_newlistn(SP()++, exceed);
for(int i = 0; i < exceed; i++) { 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(); DISPATCH();
} }

View File

@ -36,9 +36,9 @@ void UnwindTarget__delete(UnwindTarget* self) { free(self); }
Frame* Frame__new(const CodeObject* co, Frame* Frame__new(const CodeObject* co,
py_TValue* module, py_TValue* module,
const py_TValue* function, py_StackRef function,
py_TValue* p0, py_StackRef p0,
py_TValue* locals, py_StackRef locals,
const CodeObject* locals_co) { const CodeObject* locals_co) {
static_assert(sizeof(Frame) <= kPoolFrameBlockSize, "!(sizeof(Frame) <= kPoolFrameBlockSize)"); static_assert(sizeof(Frame) <= kPoolFrameBlockSize, "!(sizeof(Frame) <= kPoolFrameBlockSize)");
Frame* self = PoolFrame_alloc(); Frame* self = PoolFrame_alloc();
@ -46,7 +46,7 @@ Frame* Frame__new(const CodeObject* co,
self->ip = (Bytecode*)co->codes.data - 1; self->ip = (Bytecode*)co->codes.data - 1;
self->co = co; self->co = co;
self->module = *module; self->module = *module;
self->function = function ? function->_obj : NULL; self->function = function;
self->p0 = p0; self->p0 = p0;
self->locals = locals; self->locals = locals;
self->locals_co = locals_co; 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) { py_TValue* Frame__f_closure_try_get(Frame* self, py_Name name) {
if(self->function == NULL) return NULL; if(self->function == NULL) return NULL;
Function* ud = PyObject__userdata(self->function); Function* ud = py_touserdata(self->function);
if(ud->closure == NULL) return NULL; if(ud->closure == NULL) return NULL;
return NameDict__try_get(ud->closure, name); 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);
}

View File

@ -135,8 +135,8 @@ void VM__ctor(VM* self) {
// inject some builtin expections // inject some builtin expections
#define INJECT_BUILTIN_EXC(name) \ #define INJECT_BUILTIN_EXC(name) \
do { \ do { \
py_Type type = pk_newtype(#name, tp_Exception, &self->builtins, NULL, false, true); \ py_Type type = pk_newtype(#name, tp_Exception, &self->builtins, NULL, false, true); \
py_setdict(&self->builtins, py_name(#name), py_tpobject(type)); \ py_setdict(&self->builtins, py_name(#name), py_tpobject(type)); \
validate(tp_##name, type); \ validate(tp_##name, type); \
} while(0) } while(0)
@ -167,9 +167,8 @@ void VM__ctor(VM* self) {
tp_BaseException, tp_Exception, tp_StopIteration, tp_SyntaxError}; tp_BaseException, tp_Exception, tp_StopIteration, tp_SyntaxError};
for(int i = 0; i < c11__count_array(public_types); i++) { 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, public_types[i]);
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, t); py_setdict(&self->builtins, ti->name, &ti->self);
py_setdict(&self->builtins, ti->name, py_tpobject(t));
} }
py_newnotimplemented(py_emplacedict(&self->builtins, py_name("NotImplemented"))); 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_math();
pk__add_module_dis(); 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__"); self->main = *py_newmodule("__main__");
} }
@ -320,7 +328,7 @@ static bool
py_Ref vargs = &buffer[decl->starred_arg]; py_Ref vargs = &buffer[decl->starred_arg];
py_newtuple(vargs, exceed_argc); py_newtuple(vargs, exceed_argc);
for(int j = 0; j < exceed_argc; j++) { for(int j = 0; j < exceed_argc; j++) {
py_tuple__setitem(vargs, j, t++); py_tuple_setitem(vargs, j, t++);
} }
} else { } else {
// kwdefaults override // kwdefaults override
@ -353,7 +361,7 @@ static bool
py_Ref tmp = py_pushtmp(); py_Ref tmp = py_pushtmp();
c11_sv key_sv = py_name2sv(key); c11_sv key_sv = py_name2sv(key);
py_newstrn(tmp, key_sv.data, key_sv.size); 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(); py_pop();
if(py_checkexc()) return false; if(py_checkexc()) return false;
} }
@ -551,7 +559,6 @@ void ManagedHeap__mark(ManagedHeap* self) {
// mark frame // mark frame
for(Frame* frame = vm->top_frame; frame; frame = frame->f_back) { for(Frame* frame = vm->top_frame; frame; frame = frame->f_back) {
mark_value(&frame->module); mark_value(&frame->module);
if(frame->function) mark_object(frame->function);
} }
// mark vm's registers // mark vm's registers
mark_value(&vm->last_retval); mark_value(&vm->last_retval);
@ -563,7 +570,7 @@ void ManagedHeap__mark(ManagedHeap* self) {
void pk_print_stack(VM* self, Frame* frame, Bytecode byte) { void pk_print_stack(VM* self, Frame* frame, Bytecode byte) {
return; return;
if(frame == NULL) return; if(frame == NULL || py_isnil(&self->main)) return;
py_TValue* sp = self->stack.sp; py_TValue* sp = self->stack.sp;
c11_sbuf buf; 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_bool: c11_sbuf__write_cstr(&buf, p->_bool ? "True" : "False"); break;
case tp_NoneType: c11_sbuf__write_cstr(&buf, "None"); break; case tp_NoneType: c11_sbuf__write_cstr(&buf, "None"); break;
case tp_list: { case tp_list: {
pk_sprintf(&buf, "list(%d)", py_list__len(p)); pk_sprintf(&buf, "list(%d)", py_list_len(p));
break; break;
} }
case tp_tuple: { case tp_tuple: {
pk_sprintf(&buf, "tuple(%d)", py_tuple__len(p)); pk_sprintf(&buf, "tuple(%d)", py_tuple_len(p));
break; break;
} }
case tp_function: { case tp_function: {

View File

@ -37,8 +37,8 @@ static bool math_fsum(int argc, py_Ref argv) {
py_Ref list = py_arg(0); py_Ref list = py_arg(0);
double sum = 0; double sum = 0;
double c = 0; double c = 0;
for(int i = 0; i < py_list__len(list); i++) { for(int i = 0; i < py_list_len(list); i++) {
py_Ref item = py_list__getitem(list, i); py_Ref item = py_list_getitem(list, i);
double x; double x;
if(!py_castfloat(item, &x)) return false; if(!py_castfloat(item, &x)) return false;
double y = x - c; double y = x - c;
@ -136,8 +136,8 @@ static bool math_modf(int argc, py_Ref argv) {
double i; double i;
double f = modf(py_tofloat(py_arg(0)), &i); double f = modf(py_tofloat(py_arg(0)), &i);
py_newtuple(py_retval(), 2); py_newtuple(py_retval(), 2);
py_Ref _0 = py_tuple__getitem(py_retval(), 0); py_Ref _0 = py_tuple_getitem(py_retval(), 0);
py_Ref _1 = py_tuple__getitem(py_retval(), 1); py_Ref _1 = py_tuple_getitem(py_retval(), 1);
py_newfloat(_0, f); py_newfloat(_0, f);
py_newfloat(_1, i); py_newfloat(_1, i);
return true; 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("pi")), 3.1415926535897932384);
py_newfloat(py_emplacedict(mod, py_name("e")), 2.7182818284590452354); 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("inf")), INFINITY);
py_newfloat(py_emplacedict(mod, py_name("nan")), 0.0 / 0.0); py_newfloat(py_emplacedict(mod, py_name("nan")), NAN);
py_bindfunc(mod, "ceil", math_ceil); py_bindfunc(mod, "ceil", math_ceil);
py_bindfunc(mod, "fabs", math_fabs); py_bindfunc(mod, "fabs", math_fabs);

View File

@ -31,13 +31,13 @@ static bool os_chdir(int argc, py_Ref argv) {
PY_CHECK_ARG_TYPE(0, tp_str); PY_CHECK_ARG_TYPE(0, tp_str);
const char* path = py_tostr(py_arg(0)); const char* path = py_tostr(py_arg(0));
int code = platform_chdir(path); 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; return true;
} }
static bool os_getcwd(int argc, py_Ref argv) { static bool os_getcwd(int argc, py_Ref argv) {
char buf[1024]; 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); py_newstr(py_retval(), buf);
return true; return true;
} }

View File

@ -101,9 +101,9 @@ FuncDecl_ FuncDecl__build(c11_sv name,
} }
if(starred_arg.size) { FuncDecl__add_starred_arg(decl, py_namev(starred_arg)); } if(starred_arg.size) { FuncDecl__add_starred_arg(decl, py_namev(starred_arg)); }
assert(py_istype(kwdefaults, tp_tuple)); 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++) { 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)); if(starred_kwarg.size) FuncDecl__add_starred_kwarg(decl, py_namev(starred_kwarg));
decl->docstring = docstring; decl->docstring = docstring;

View File

@ -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) { bool py_vectorcall(uint16_t argc, uint16_t kwargc) {
VM* vm = pk_current_vm; VM* vm = pk_current_vm;
return VM__vectorcall(vm, argc, kwargc, false) != RES_ERROR; return VM__vectorcall(vm, argc, kwargc, false) != RES_ERROR;

View File

@ -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); PY_CHECK_ARGC(1);
return py_repr(argv); 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; int code = 0;
if(argc > 1) return TypeError("exit() takes at most 1 argument"); if(argc > 1) return TypeError("exit() takes at most 1 argument");
if(argc == 1) { if(argc == 1) {
@ -165,20 +165,20 @@ static bool builtins__exit(int argc, py_Ref argv) {
return false; return false;
} }
static bool builtins__len(int argc, py_Ref argv) { static bool builtins_len(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
return py_len(argv); 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); PY_CHECK_ARGC(1);
// convert _0 to list object // convert _0 to list object
if(!py_tpcall(tp_list, 1, argv)) return false; if(!py_tpcall(tp_list, 1, argv)) return false;
py_list__reverse(py_retval()); py_list_reverse(py_retval());
return true; 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_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_int); PY_CHECK_ARG_TYPE(0, tp_int);
@ -208,12 +208,12 @@ static bool builtins__hex(int argc, py_Ref argv) {
return true; return true;
} }
static bool builtins__iter(int argc, py_Ref argv) { static bool builtins_iter(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
return py_iter(argv); 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); PY_CHECK_ARGC(1);
int res = py_next(argv); int res = py_next(argv);
if(res == -1) return false; if(res == -1) return false;
@ -221,7 +221,7 @@ static bool builtins__next(int argc, py_Ref argv) {
return py_exception(tp_StopIteration, ""); 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); PY_CHECK_ARGC(3);
// convert _0 to list object // convert _0 to list object
if(!py_tpcall(tp_list, 1, py_arg(0))) return false; 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; 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_CHECK_ARGC(1);
py_i64 val; py_i64 val;
if(!py_hash(argv, &val)) return false; if(!py_hash(argv, &val)) return false;
@ -246,12 +246,12 @@ static bool builtins__hash(int argc, py_Ref argv) {
return true; return true;
} }
static bool builtins__abs(int argc, py_Ref argv) { static bool builtins_abs(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
return pk_callmagic(__abs__, 1, argv); 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); PY_CHECK_ARGC(1);
if(!py_iter(py_arg(0))) return false; if(!py_iter(py_arg(0))) return false;
@ -288,7 +288,7 @@ static bool builtins__sum(int argc, py_Ref argv) {
return true; return true;
} }
static bool builtins__print(int argc, py_Ref argv) { static bool builtins_print(int argc, py_Ref argv) {
int length; int length;
py_TValue* args = pk_arrayview(argv, &length); py_TValue* args = pk_arrayview(argv, &length);
assert(args != NULL); assert(args != NULL);
@ -314,24 +314,24 @@ static bool NoneType__repr__(int argc, py_Ref argv) {
return true; 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_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str); PY_CHECK_ARG_TYPE(0, tp_str);
return py_exec(py_tostr(argv), "<exec>", EXEC_MODE, NULL); 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_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str); PY_CHECK_ARG_TYPE(0, tp_str);
return py_exec(py_tostr(argv), "<eval>", EVAL_MODE, NULL); 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); PY_CHECK_ARGC(2);
if(py_istuple(py_arg(1))) { 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++) { 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_checktype(item, tp_type)) return false;
if(py_isinstance(py_arg(0), py_totype(item))) { if(py_isinstance(py_arg(0), py_totype(item))) {
py_newbool(py_retval(), true); py_newbool(py_retval(), true);
@ -347,7 +347,7 @@ static bool builtins__isinstance(int argc, py_Ref argv) {
return true; return true;
} }
static bool builtins__issubclass(int argc, py_Ref argv) { static bool builtins_issubclass(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
if(!py_checktype(py_arg(0), tp_type)) return false; if(!py_checktype(py_arg(0), tp_type)) return false;
if(!py_checktype(py_arg(1), 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; 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_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1))); py_Name name = py_namev(py_tosv(py_arg(1)));
if(argc == 2) { if(argc == 2) {
@ -365,7 +365,8 @@ static bool builtins__getattr(int argc, py_Ref argv) {
bool ok = py_getattr(py_arg(0), name); bool ok = py_getattr(py_arg(0), name);
if(!ok && py_matchexc(tp_AttributeError)) { if(!ok && py_matchexc(tp_AttributeError)) {
py_clearexc(p0); py_clearexc(p0);
return py_arg(2); // default value py_assign(py_retval(), py_arg(2));
return true; // default value
} }
return ok; return ok;
} else { } else {
@ -374,29 +375,64 @@ static bool builtins__getattr(int argc, py_Ref argv) {
return true; 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_TValue pk_builtins__register() {
py_Ref builtins = py_newmodule("builtins"); py_Ref builtins = py_newmodule("builtins");
py_bindfunc(builtins, "repr", builtins__repr); py_bindfunc(builtins, "repr", builtins_repr);
py_bindfunc(builtins, "exit", builtins__exit); py_bindfunc(builtins, "exit", builtins_exit);
py_bindfunc(builtins, "len", builtins__len); py_bindfunc(builtins, "len", builtins_len);
py_bindfunc(builtins, "reversed", builtins__reversed); py_bindfunc(builtins, "reversed", builtins_reversed);
py_bindfunc(builtins, "hex", builtins__hex); py_bindfunc(builtins, "hex", builtins_hex);
py_bindfunc(builtins, "iter", builtins__iter); py_bindfunc(builtins, "iter", builtins_iter);
py_bindfunc(builtins, "next", builtins__next); py_bindfunc(builtins, "next", builtins_next);
py_bindfunc(builtins, "hash", builtins__hash); py_bindfunc(builtins, "hash", builtins_hash);
py_bindfunc(builtins, "abs", builtins__abs); py_bindfunc(builtins, "abs", builtins_abs);
py_bindfunc(builtins, "sum", builtins__sum); py_bindfunc(builtins, "sum", builtins_sum);
py_bindfunc(builtins, "exec", builtins__exec); py_bindfunc(builtins, "exec", builtins_exec);
py_bindfunc(builtins, "eval", builtins__eval); py_bindfunc(builtins, "eval", builtins_eval);
py_bind(builtins, "print(*args, sep=' ', end='\\n')", builtins__print); py_bind(builtins, "print(*args, sep=' ', end='\\n')", builtins_print);
py_bind(builtins, "sorted(iterable, key=None, reverse=False)", builtins__sorted); py_bind(builtins, "sorted(iterable, key=None, reverse=False)", builtins_sorted);
py_bindfunc(builtins, "isinstance", builtins__isinstance); py_bindfunc(builtins, "isinstance", builtins_isinstance);
py_bindfunc(builtins, "issubclass", builtins__issubclass); 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__ // None __repr__
py_bindmagic(tp_NoneType, __repr__, NoneType__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) { c11__foreach(NameDict_KV, ud->closure, it) {
// printf("%s -> %s\n", py_name2str(it->key), py_tpname(it->value.type)); // printf("%s -> %s\n", py_name2str(it->key), py_tpname(it->value.type));
py_newstr(r0, py_name2str(it->key)); py_newstr(r0, py_name2str(it->key));
py_dict__setitem(retval, r0, &it->value); py_dict_setitem(retval, r0, &it->value);
if(py_checkexc()) { if(py_checkexc()) {
py_shrink(2); py_shrink(2);
return false; return false;
@ -435,7 +471,7 @@ py_Type pk_function__register() {
return type; 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_CHECK_ARGC(1);
py_newstr(py_retval(), "<nativefunc object>"); py_newstr(py_retval(), "<nativefunc object>");
return true; return true;
@ -443,7 +479,7 @@ static bool nativefunc__repr(int argc, py_Ref argv) {
py_Type pk_nativefunc__register() { py_Type pk_nativefunc__register() {
py_Type type = pk_newtype("nativefunc", tp_object, NULL, NULL, false, true); 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; return type;
} }
@ -455,8 +491,7 @@ static bool super__new__(int argc, py_Ref argv) {
if(argc == 1) { if(argc == 1) {
// super() // super()
if(frame->function) { if(frame->function) {
// class_arg = PK_OBJ_GET(Function, frame->_callable)._class; Function* func = py_touserdata(frame->function);
Function* func = PyObject__userdata(frame->function);
*class_arg = *(py_Type*)PyObject__userdata(func->clazz); *class_arg = *(py_Type*)PyObject__userdata(func->clazz);
if(frame->locals_co->nlocals > 0) self_arg = &frame->locals[0]; if(frame->locals_co->nlocals > 0) self_arg = &frame->locals[0];
} }

View File

@ -13,11 +13,11 @@ typedef struct array_iterator {
py_TValue* pk_arrayview(py_Ref self, int* length) { py_TValue* pk_arrayview(py_Ref self, int* length) {
if(self->type == tp_list) { if(self->type == tp_list) {
*length = py_list__len(self); *length = py_list_len(self);
return py_list__data(self); return py_list_data(self);
} }
if(self->type == tp_tuple) { if(self->type == tp_tuple) {
*length = py_tuple__len(self); *length = py_tuple_len(self);
return PyObject__slots(self->_obj); return PyObject__slots(self->_obj);
} }
return NULL; return NULL;

View File

@ -35,6 +35,7 @@ static void Dict__ctor(Dict* self, int capacity) {
self->indices = malloc(self->capacity * sizeof(DictIndex)); self->indices = malloc(self->capacity * sizeof(DictIndex));
memset(self->indices, -1, self->capacity * sizeof(DictIndex)); memset(self->indices, -1, self->capacity * sizeof(DictIndex));
c11_vector__ctor(&self->entries, sizeof(DictEntry)); c11_vector__ctor(&self->entries, sizeof(DictEntry));
c11_vector__reserve(&self->entries, capacity);
} }
static void Dict__dtor(Dict* self) { 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); PY_CHECK_ARG_TYPE(1, tp_list);
Dict* self = py_touserdata(argv); Dict* self = py_touserdata(argv);
py_Ref list = py_arg(1); py_Ref list = py_arg(1);
for(int i = 0; i < py_list__len(list); i++) { for(int i = 0; i < py_list_len(list); i++) {
py_Ref tuple = py_list__getitem(list, i); py_Ref tuple = py_list_getitem(list, i);
if(!py_istuple(tuple) || py_tuple__len(tuple) != 2) { if(!py_istuple(tuple) || py_tuple_len(tuple) != 2) {
return TypeError("dict.__init__() argument must be a list of tuple-2"); return TypeError("dict.__init__() argument must be a list of tuple-2");
} }
py_Ref key = py_tuple__getitem(tuple, 0); py_Ref key = py_tuple_getitem(tuple, 0);
py_Ref val = py_tuple__getitem(tuple, 1); py_Ref val = py_tuple_getitem(tuple, 1);
if(!Dict__set(self, key, val)) return false; if(!Dict__set(self, key, val)) return false;
} }
return true; return true;
@ -335,14 +336,14 @@ static bool dict__ne__(int argc, py_Ref argv) {
return true; return true;
} }
static bool dict__clear(int argc, py_Ref argv) { static bool dict_clear(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv); Dict* self = py_touserdata(argv);
Dict__clear(self); Dict__clear(self);
return true; return true;
} }
static bool dict__copy(int argc, py_Ref argv) { static bool dict_copy(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv); Dict* self = py_touserdata(argv);
Dict* new_dict = py_newobject(py_retval(), tp_dict, 0, sizeof(Dict)); 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; 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_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_dict); PY_CHECK_ARG_TYPE(1, tp_dict);
Dict* self = py_touserdata(argv); Dict* self = py_touserdata(argv);
@ -368,7 +369,7 @@ static bool dict__update(int argc, py_Ref argv) {
return true; 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); Dict* self = py_touserdata(argv);
if(argc > 3) return TypeError("get() takes at most 3 arguments (%d given)", argc); 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; 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; 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); Dict* self = py_touserdata(argv);
if(argc < 2 || argc > 3) return TypeError("pop() takes 2 or 3 arguments (%d given)", argc); 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; 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; return true;
} }
static bool dict__items(int argc, py_Ref argv) { static bool dict_items(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv); Dict* self = py_touserdata(argv);
DictIterator* ud = py_newobject(py_retval(), tp_dict_items, 1, sizeof(DictIterator)); 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; return true;
} }
static bool dict__keys(int argc, py_Ref argv) { static bool dict_keys(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv); Dict* self = py_touserdata(argv);
py_newtuple(py_retval(), self->length); py_newtuple(py_retval(), self->length);
@ -406,13 +407,13 @@ static bool dict__keys(int argc, py_Ref argv) {
while(1) { while(1) {
DictEntry* entry = DictIterator__next(&iter); DictEntry* entry = DictIterator__next(&iter);
if(!entry) break; if(!entry) break;
py_tuple__setitem(py_retval(), i++, &entry->key); py_tuple_setitem(py_retval(), i++, &entry->key);
} }
assert(i == self->length); assert(i == self->length);
return true; return true;
} }
static bool dict__values(int argc, py_Ref argv) { static bool dict_values(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv); Dict* self = py_touserdata(argv);
py_newtuple(py_retval(), self->length); py_newtuple(py_retval(), self->length);
@ -422,7 +423,7 @@ static bool dict__values(int argc, py_Ref argv) {
while(1) { while(1) {
DictEntry* entry = DictIterator__next(&iter); DictEntry* entry = DictIterator__next(&iter);
if(!entry) break; if(!entry) break;
py_tuple__setitem(py_retval(), i++, &entry->val); py_tuple_setitem(py_retval(), i++, &entry->val);
} }
assert(i == self->length); assert(i == self->length);
return true; return true;
@ -442,14 +443,14 @@ py_Type pk_dict__register() {
py_bindmagic(type, __eq__, dict__eq__); py_bindmagic(type, __eq__, dict__eq__);
py_bindmagic(type, __ne__, dict__ne__); py_bindmagic(type, __ne__, dict__ne__);
py_bindmethod(type, "clear", dict__clear); py_bindmethod(type, "clear", dict_clear);
py_bindmethod(type, "copy", dict__copy); py_bindmethod(type, "copy", dict_copy);
py_bindmethod(type, "update", dict__update); py_bindmethod(type, "update", dict_update);
py_bindmethod(type, "get", dict__get); py_bindmethod(type, "get", dict_get);
py_bindmethod(type, "pop", dict__pop); py_bindmethod(type, "pop", dict_pop);
py_bindmethod(type, "items", dict__items); py_bindmethod(type, "items", dict_items);
py_bindmethod(type, "keys", dict__keys); py_bindmethod(type, "keys", dict_keys);
py_bindmethod(type, "values", dict__values); py_bindmethod(type, "values", dict_values);
py_setdict(py_tpobject(type), __hash__, py_None); py_setdict(py_tpobject(type), __hash__, py_None);
return type; return type;
@ -468,8 +469,8 @@ static bool dict_items__next__(int argc, py_Ref argv) {
DictEntry* entry = (DictIterator__next(iter)); DictEntry* entry = (DictIterator__next(iter));
if(entry) { if(entry) {
py_newtuple(py_retval(), 2); py_newtuple(py_retval(), 2);
py_tuple__setitem(py_retval(), 0, &entry->key); py_tuple_setitem(py_retval(), 0, &entry->key);
py_tuple__setitem(py_retval(), 1, &entry->val); py_tuple_setitem(py_retval(), 1, &entry->val);
return true; return true;
} }
return StopIteration(); return StopIteration();
@ -489,7 +490,7 @@ void py_newdict(py_Ref out) {
Dict__ctor(ud, 8); 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)); assert(py_isdict(self));
Dict* ud = py_touserdata(self); Dict* ud = py_touserdata(self);
DictEntry* entry; DictEntry* entry;
@ -498,19 +499,19 @@ py_Ref py_dict__getitem(py_Ref self, py_Ref key) {
return NULL; 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)); assert(py_isdict(self));
Dict* ud = py_touserdata(self); Dict* ud = py_touserdata(self);
Dict__pop(ud, key); 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)); assert(py_isdict(self));
Dict* ud = py_touserdata(self); Dict* ud = py_touserdata(self);
Dict__set(ud, key, val); 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)); assert(py_isdict(self));
Dict* ud = py_touserdata(self); Dict* ud = py_touserdata(self);
DictEntry* entry; DictEntry* entry;
@ -518,13 +519,13 @@ bool py_dict__contains(py_Ref self, py_Ref key) {
return ok && entry != NULL; return ok && entry != NULL;
} }
int py_dict__len(py_Ref self) { int py_dict_len(py_Ref self) {
assert(py_isdict(self)); assert(py_isdict(self));
Dict* ud = py_touserdata(self); Dict* ud = py_touserdata(self);
return ud->length; 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); Dict* ud = py_touserdata(self);
for(int i = 0; i < ud->entries.count; i++) { for(int i = 0; i < ud->entries.count; i++) {
DictEntry* entry = c11__at(DictEntry, &ud->entries, i); DictEntry* entry = c11__at(DictEntry, &ud->entries, i);

View File

@ -52,8 +52,10 @@ static void BaseException__dtor(void* ud) {
static bool _py_BaseException__new__(int argc, py_Ref argv) { static bool _py_BaseException__new__(int argc, py_Ref argv) {
py_Type cls = py_totype(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)); 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->lineno_backup = -1;
ud->code_backup = NULL; ud->code_backup = NULL;
return true; return true;
@ -138,35 +140,46 @@ void py_printexc() {
free(msg); 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() { char* py_formatexc() {
VM* vm = pk_current_vm; VM* vm = pk_current_vm;
if(py_isnil(&vm->curr_exception)) return NULL; if(py_isnil(&vm->curr_exception)) return NULL;
c11_sbuf ss; c11_sbuf ss;
c11_sbuf__ctor(&ss); c11_sbuf__ctor(&ss);
if(true) { c11_sbuf__write_cstr(&ss, "Traceback (most recent call last):\n"); } py_Ref inner = py_getslot(&vm->curr_exception, 1);
if(py_isnil(inner)) {
BaseException* ud = py_touserdata(&vm->curr_exception); c11_sbuf__write_exc(&ss, &vm->curr_exception);
} else {
for(int i = ud->stacktrace.count - 1; i >= 0; i--) { c11_sbuf__write_exc(&ss, inner);
BaseExceptionFrame* frame = c11__at(BaseExceptionFrame, &ud->stacktrace, i); c11_sbuf__write_cstr(&ss, "\n\nDuring handling of the above exception, another exception occurred:\n\n");
SourceData__snapshot(frame->src, c11_sbuf__write_exc(&ss, &vm->curr_exception);
&ss,
frame->lineno,
NULL,
frame->name ? frame->name->data : NULL);
c11_sbuf__write_char(&ss, '\n');
} }
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); c11_string* res = c11_sbuf__submit(&ss);
char* dup = malloc(res->size + 1); char* dup = malloc(res->size + 1);
memcpy(dup, res->data, res->size); 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) { bool py_raise(py_Ref exc) {
assert(py_isinstance(exc, tp_BaseException)); assert(py_isinstance(exc, tp_BaseException));
VM* vm = pk_current_vm; VM* vm = pk_current_vm;
if(!py_isnil(&vm->curr_exception)){
// inner exception
py_setslot(exc, 1, &vm->curr_exception);
}
vm->curr_exception = *exc; vm->curr_exception = *exc;
return false; return false;
} }

View File

@ -19,47 +19,47 @@ void py_newlistn(py_Ref out, int n) {
userdata->count = 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); List* userdata = py_touserdata(self);
return userdata->data; 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); List* userdata = py_touserdata(self);
return c11__at(py_TValue, userdata, i); 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); List* userdata = py_touserdata(self);
c11__setitem(py_TValue, userdata, i, *val); 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); List* userdata = py_touserdata(self);
c11_vector__erase(py_TValue, userdata, i); 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); List* userdata = py_touserdata(self);
return userdata->count; 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); List* userdata = py_touserdata(self);
c11_vector__push(py_TValue, userdata, *val); 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); List* userdata = py_touserdata(self);
c11_vector__clear(userdata); 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); List* userdata = py_touserdata(self);
c11_vector__insert(py_TValue, userdata, i, *val); 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); List* userdata = py_touserdata(self);
c11__reverse(py_TValue, userdata); 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) { static bool list__len__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); 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); py_newint(py_retval(), res);
return true; return true;
} }
@ -107,7 +107,7 @@ static bool list__new__(int argc, py_Ref argv) {
if(p) { if(p) {
py_newlistn(py_retval(), length); py_newlistn(py_retval(), length);
for(int i = 0; i < length; i++) { 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; return true;
} }
@ -125,7 +125,7 @@ static bool list__new__(int argc, py_Ref argv) {
return false; return false;
} }
if(!res) break; if(!res) break;
py_list__append(list, py_retval()); py_list_append(list, py_retval());
} }
*py_retval() = *list; *py_retval() = *list;
py_shrink(2); 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__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_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()); py_newnone(py_retval());
return true; return true;
} }
@ -243,7 +243,7 @@ static bool list__repr__(int argc, py_Ref argv) {
return true; return true;
} }
static bool list__extend(int argc, py_Ref argv) { static bool list_extend(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
List* self = py_touserdata(py_arg(0)); List* self = py_touserdata(py_arg(0));
PY_CHECK_ARG_TYPE(1, tp_list); PY_CHECK_ARG_TYPE(1, tp_list);
@ -253,11 +253,11 @@ static bool list__extend(int argc, py_Ref argv) {
return true; return true;
} }
static bool list__count(int argc, py_Ref argv) { static bool list_count(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
int count = 0; int count = 0;
for(int i = 0; i < py_list__len(py_arg(0)); i++) { 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)); int res = py_equal(py_list_getitem(py_arg(0), i), py_arg(1));
if(res == -1) return false; if(res == -1) return false;
if(res) count++; if(res) count++;
} }
@ -265,14 +265,14 @@ static bool list__count(int argc, py_Ref argv) {
return true; 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_CHECK_ARGC(1);
py_list__clear(py_arg(0)); py_list_clear(py_arg(0));
py_newnone(py_retval()); py_newnone(py_retval());
return true; 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_CHECK_ARGC(1);
py_newlist(py_retval()); py_newlist(py_retval());
List* self = py_touserdata(py_arg(0)); List* self = py_touserdata(py_arg(0));
@ -281,15 +281,15 @@ static bool list__copy(int argc, py_Ref argv) {
return true; 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"); if(argc > 3) return TypeError("index() takes at most 3 arguments");
int start = 0; int start = 0;
if(argc == 3) { if(argc == 3) {
PY_CHECK_ARG_TYPE(2, tp_int); PY_CHECK_ARG_TYPE(2, tp_int);
start = py_toint(py_arg(2)); start = py_toint(py_arg(2));
} }
for(int i = start; i < py_list__len(py_arg(0)); i++) { 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)); int res = py_equal(py_list_getitem(py_arg(0), i), py_arg(1));
if(res == -1) return false; if(res == -1) return false;
if(res) { if(res) {
py_newint(py_retval(), i); 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"); 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); PY_CHECK_ARGC(1);
List* self = py_touserdata(py_arg(0)); List* self = py_touserdata(py_arg(0));
c11__reverse(py_TValue, self); c11__reverse(py_TValue, self);
@ -307,13 +307,13 @@ static bool list__reverse(int argc, py_Ref argv) {
return true; return true;
} }
static bool list__remove(int argc, py_Ref argv) { static bool list_remove(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
for(int i = 0; i < py_list__len(py_arg(0)); i++) { 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)); int res = py_equal(py_list_getitem(py_arg(0), i), py_arg(1));
if(res == -1) return false; if(res == -1) return false;
if(res) { if(res) {
py_list__delitem(py_arg(0), i); py_list_delitem(py_arg(0), i);
py_newnone(py_retval()); py_newnone(py_retval());
return true; return true;
} }
@ -321,7 +321,7 @@ static bool list__remove(int argc, py_Ref argv) {
return ValueError("list.remove(x): x not in list"); 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; int index;
if(argc == 1) { if(argc == 1) {
index = -1; index = -1;
@ -339,7 +339,7 @@ static bool list__pop(int argc, py_Ref argv) {
return true; 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_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_int); PY_CHECK_ARG_TYPE(1, tp_int);
List* self = py_touserdata(py_arg(0)); 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) // 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)); List* self = py_touserdata(py_arg(0));
py_Ref key = py_arg(1); py_Ref key = py_arg(1);
@ -423,19 +423,19 @@ py_Type pk_list__register() {
py_bindmagic(type, __iter__, list__iter__); py_bindmagic(type, __iter__, list__iter__);
py_bindmagic(type, __contains__, list__contains__); py_bindmagic(type, __contains__, list__contains__);
py_bindmethod(type, "append", list__append); py_bindmethod(type, "append", list_append);
py_bindmethod(type, "extend", list__extend); py_bindmethod(type, "extend", list_extend);
py_bindmethod(type, "count", list__count); py_bindmethod(type, "count", list_count);
py_bindmethod(type, "clear", list__clear); py_bindmethod(type, "clear", list_clear);
py_bindmethod(type, "copy", list__copy); py_bindmethod(type, "copy", list_copy);
py_bindmethod(type, "index", list__index); py_bindmethod(type, "index", list_index);
py_bindmethod(type, "reverse", list__reverse); py_bindmethod(type, "reverse", list_reverse);
py_bindmethod(type, "remove", list__remove); py_bindmethod(type, "remove", list_remove);
py_bindmethod(type, "pop", list__pop); py_bindmethod(type, "pop", list_pop);
py_bindmethod(type, "insert", list__insert); py_bindmethod(type, "insert", list_insert);
py_bindmethod(type, "sort", list__sort); 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); py_setdict(py_tpobject(type), __hash__, py_None);
return type; return type;

View File

@ -5,7 +5,7 @@
#include <math.h> #include <math.h>
#define DEF_NUM_BINARY_OP(name, op, rint, rfloat) \ #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); \ PY_CHECK_ARGC(2); \
if(py_isint(&argv[1])) { \ if(py_isint(&argv[1])) { \
py_i64 lhs = py_toint(&argv[0]); \ py_i64 lhs = py_toint(&argv[0]); \
@ -20,7 +20,7 @@
} \ } \
return true; \ 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_CHECK_ARGC(2); \
py_f64 lhs = py_tofloat(&argv[0]); \ py_f64 lhs = py_tofloat(&argv[0]); \
py_f64 rhs; \ py_f64 rhs; \
@ -45,21 +45,21 @@ DEF_NUM_BINARY_OP(__ge__, >=, py_newbool, py_newbool)
#undef DEF_NUM_BINARY_OP #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_CHECK_ARGC(1);
py_i64 val = py_toint(&argv[0]); py_i64 val = py_toint(&argv[0]);
py_newint(py_retval(), -val); py_newint(py_retval(), -val);
return true; 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_CHECK_ARGC(1);
py_f64 val = py_tofloat(&argv[0]); py_f64 val = py_tofloat(&argv[0]);
py_newfloat(py_retval(), -val); py_newfloat(py_retval(), -val);
return true; 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_CHECK_ARGC(2);
py_i64 lhs = py_toint(&argv[0]); py_i64 lhs = py_toint(&argv[0]);
py_f64 rhs; py_f64 rhs;
@ -71,7 +71,7 @@ static bool _py_int__truediv__(int argc, py_Ref argv) {
return true; 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_CHECK_ARGC(2);
py_f64 lhs = py_tofloat(&argv[0]); py_f64 lhs = py_tofloat(&argv[0]);
py_f64 rhs; py_f64 rhs;
@ -85,7 +85,7 @@ static bool _py_float__truediv__(int argc, py_Ref argv) {
#define ZeroDivisionError(msg) false #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); PY_CHECK_ARGC(2);
if(py_isint(&argv[0]) && py_isint(&argv[1])) { if(py_isint(&argv[0]) && py_isint(&argv[1])) {
py_i64 lhs = py_toint(&argv[0]); py_i64 lhs = py_toint(&argv[0]);
@ -119,7 +119,7 @@ static bool _py_number__pow__(int argc, py_Ref argv) {
return true; 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_CHECK_ARGC(2);
py_i64 lhs = py_toint(&argv[0]); py_i64 lhs = py_toint(&argv[0]);
if(py_isint(&argv[1])) { if(py_isint(&argv[1])) {
@ -132,7 +132,7 @@ static bool _py_int__floordiv__(int argc, py_Ref argv) {
return true; 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_CHECK_ARGC(2);
py_i64 lhs = py_toint(&argv[0]); py_i64 lhs = py_toint(&argv[0]);
if(py_isint(&argv[1])) { if(py_isint(&argv[1])) {
@ -145,14 +145,14 @@ static bool _py_int__mod__(int argc, py_Ref argv) {
return true; 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_CHECK_ARGC(1);
py_i64 val = py_toint(&argv[0]); py_i64 val = py_toint(&argv[0]);
py_newint(py_retval(), ~val); py_newint(py_retval(), ~val);
return true; 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_CHECK_ARGC(1);
py_i64 x = py_toint(py_arg(0)); py_i64 x = py_toint(py_arg(0));
if(x < 0) x = -x; 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) \ #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_CHECK_ARGC(2); \
py_i64 lhs = py_toint(&argv[0]); \ py_i64 lhs = py_toint(&argv[0]); \
if(py_isint(&argv[1])) { \ if(py_isint(&argv[1])) { \
@ -186,7 +186,7 @@ DEF_INT_BITWISE_OP(__rshift__, >>)
#undef DEF_INT_BITWISE_OP #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_CHECK_ARGC(1);
py_i64 val = py_toint(&argv[0]); py_i64 val = py_toint(&argv[0]);
char buf[32]; char buf[32];
@ -195,7 +195,7 @@ static bool _py_int__repr__(int argc, py_Ref argv) {
return true; 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_CHECK_ARGC(1);
py_f64 val = py_tofloat(&argv[0]); py_f64 val = py_tofloat(&argv[0]);
c11_sbuf buf; c11_sbuf buf;
@ -223,7 +223,7 @@ static py_i64 c11_8bytes__hash(union c11_8bytes u) {
return u._i64; 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_CHECK_ARGC(1);
py_i64 val = py_toint(&argv[0]); py_i64 val = py_toint(&argv[0]);
union c11_8bytes u = {._i64 = val}; union c11_8bytes u = {._i64 = val};
@ -231,7 +231,7 @@ static bool _py_int__hash__(int argc, py_Ref argv) {
return true; 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_CHECK_ARGC(1);
py_f64 val = py_tofloat(&argv[0]); py_f64 val = py_tofloat(&argv[0]);
union c11_8bytes u = {._f64 = val}; union c11_8bytes u = {._f64 = val};
@ -239,21 +239,21 @@ static bool _py_float__hash__(int argc, py_Ref argv) {
return true; 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_CHECK_ARGC(1);
py_i64 val = py_toint(&argv[0]); py_i64 val = py_toint(&argv[0]);
py_newint(py_retval(), val < 0 ? -val : val); py_newint(py_retval(), val < 0 ? -val : val);
return true; 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_CHECK_ARGC(1);
py_f64 val = py_tofloat(&argv[0]); py_f64 val = py_tofloat(&argv[0]);
py_newfloat(py_retval(), val < 0 ? -val : val); py_newfloat(py_retval(), val < 0 ? -val : val);
return true; 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) { if(argc == 1 + 0) {
// int() == 0 // int() == 0
py_newint(py_retval(), 0); py_newint(py_retval(), 0);
@ -308,7 +308,7 @@ static bool _py_int__new__(int argc, py_Ref argv) {
return true; 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) { if(argc == 1 + 0) {
// float() == 0.0 // float() == 0.0
py_newfloat(py_retval(), 0.0); py_newfloat(py_retval(), 0.0);
@ -356,7 +356,7 @@ static bool _py_float__new__(int argc, py_Ref argv) {
} }
// tp_bool // tp_bool
static bool _py_bool__new__(int argc, py_Ref argv) { static bool bool__new__(int argc, py_Ref argv) {
assert(argc > 0); assert(argc > 0);
if(argc == 1){ if(argc == 1){
py_newbool(py_retval(), false); 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"); 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); PY_CHECK_ARGC(1);
bool res = py_tobool(argv); bool res = py_tobool(argv);
py_newint(py_retval(), res); py_newint(py_retval(), res);
return true; 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); PY_CHECK_ARGC(1);
bool res = py_tobool(argv); bool res = py_tobool(argv);
py_newstr(py_retval(), res ? "True" : "False"); py_newstr(py_retval(), res ? "True" : "False");
return true; 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); PY_CHECK_ARGC(2);
bool lhs = py_tobool(&argv[0]); bool lhs = py_tobool(&argv[0]);
if(argv[1].type == tp_bool) { if(argv[1].type == tp_bool) {
@ -397,7 +397,7 @@ static bool _py_bool__eq__(int argc, py_Ref argv) {
return true; 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); PY_CHECK_ARGC(2);
bool lhs = py_tobool(&argv[0]); bool lhs = py_tobool(&argv[0]);
if(argv[1].type == tp_bool) { if(argv[1].type == tp_bool) {
@ -411,74 +411,74 @@ static bool _py_bool__ne__(int argc, py_Ref argv) {
void pk_number__register() { void pk_number__register() {
/****** tp_int & tp_float ******/ /****** tp_int & tp_float ******/
py_bindmagic(tp_int, __add__, _py_int__add__); py_bindmagic(tp_int, __add__, int__add__);
py_bindmagic(tp_float, __add__, _py_float__add__); py_bindmagic(tp_float, __add__, float__add__);
py_bindmagic(tp_int, __sub__, _py_int__sub__); py_bindmagic(tp_int, __sub__, int__sub__);
py_bindmagic(tp_float, __sub__, _py_float__sub__); py_bindmagic(tp_float, __sub__, float__sub__);
py_bindmagic(tp_int, __mul__, _py_int__mul__); py_bindmagic(tp_int, __mul__, int__mul__);
py_bindmagic(tp_float, __mul__, _py_float__mul__); py_bindmagic(tp_float, __mul__, float__mul__);
py_bindmagic(tp_int, __eq__, _py_int__eq__); py_bindmagic(tp_int, __eq__, int__eq__);
py_bindmagic(tp_float, __eq__, _py_float__eq__); py_bindmagic(tp_float, __eq__, float__eq__);
py_bindmagic(tp_int, __ne__, _py_int__ne__); py_bindmagic(tp_int, __ne__, int__ne__);
py_bindmagic(tp_float, __ne__, _py_float__ne__); py_bindmagic(tp_float, __ne__, float__ne__);
py_bindmagic(tp_int, __lt__, _py_int__lt__); py_bindmagic(tp_int, __lt__, int__lt__);
py_bindmagic(tp_float, __lt__, _py_float__lt__); py_bindmagic(tp_float, __lt__, float__lt__);
py_bindmagic(tp_int, __le__, _py_int__le__); py_bindmagic(tp_int, __le__, int__le__);
py_bindmagic(tp_float, __le__, _py_float__le__); py_bindmagic(tp_float, __le__, float__le__);
py_bindmagic(tp_int, __gt__, _py_int__gt__); py_bindmagic(tp_int, __gt__, int__gt__);
py_bindmagic(tp_float, __gt__, _py_float__gt__); py_bindmagic(tp_float, __gt__, float__gt__);
py_bindmagic(tp_int, __ge__, _py_int__ge__); py_bindmagic(tp_int, __ge__, int__ge__);
py_bindmagic(tp_float, __ge__, _py_float__ge__); py_bindmagic(tp_float, __ge__, float__ge__);
// __neg__ // __neg__
py_bindmagic(tp_int, __neg__, _py_int__neg__); py_bindmagic(tp_int, __neg__, int__neg__);
py_bindmagic(tp_float, __neg__, _py_float__neg__); py_bindmagic(tp_float, __neg__, float__neg__);
// __repr__ // __repr__
py_bindmagic(tp_int, __repr__, _py_int__repr__); py_bindmagic(tp_int, __repr__, int__repr__);
py_bindmagic(tp_float, __repr__, _py_float__repr__); py_bindmagic(tp_float, __repr__, float__repr__);
// __hash__ // __hash__
py_bindmagic(tp_int, __hash__, _py_int__hash__); py_bindmagic(tp_int, __hash__, int__hash__);
py_bindmagic(tp_float, __hash__, _py_float__hash__); py_bindmagic(tp_float, __hash__, float__hash__);
// __abs__ // __abs__
py_bindmagic(tp_int, __abs__, _py_int__abs__); py_bindmagic(tp_int, __abs__, int__abs__);
py_bindmagic(tp_float, __abs__, _py_float__abs__); py_bindmagic(tp_float, __abs__, float__abs__);
// __new__ // __new__
py_bindmagic(tp_int, __new__, _py_int__new__); py_bindmagic(tp_int, __new__, int__new__);
py_bindmagic(tp_float, __new__, _py_float__new__); py_bindmagic(tp_float, __new__, float__new__);
// __truediv__ // __truediv__
py_bindmagic(tp_int, __truediv__, _py_int__truediv__); py_bindmagic(tp_int, __truediv__, int__truediv__);
py_bindmagic(tp_float, __truediv__, _py_float__truediv__); py_bindmagic(tp_float, __truediv__, float__truediv__);
// __pow__ // __pow__
py_bindmagic(tp_int, __pow__, _py_number__pow__); py_bindmagic(tp_int, __pow__, number__pow__);
py_bindmagic(tp_float, __pow__, _py_number__pow__); py_bindmagic(tp_float, __pow__, number__pow__);
// __floordiv__ & __mod__ // __floordiv__ & __mod__
py_bindmagic(tp_int, __floordiv__, _py_int__floordiv__); py_bindmagic(tp_int, __floordiv__, int__floordiv__);
py_bindmagic(tp_int, __mod__, _py_int__mod__); py_bindmagic(tp_int, __mod__, int__mod__);
// int.__invert__ & int.<BITWISE OP> // 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, __and__, int__and__);
py_bindmagic(tp_int, __or__, _py_int__or__); py_bindmagic(tp_int, __or__, int__or__);
py_bindmagic(tp_int, __xor__, _py_int__xor__); py_bindmagic(tp_int, __xor__, int__xor__);
py_bindmagic(tp_int, __lshift__, _py_int__lshift__); py_bindmagic(tp_int, __lshift__, int__lshift__);
py_bindmagic(tp_int, __rshift__, _py_int__rshift__); py_bindmagic(tp_int, __rshift__, int__rshift__);
// int.bit_length // int.bit_length
py_bindmethod(tp_int, "bit_length", _py_int__bit_length); py_bindmethod(tp_int, "bit_length", int_bit_length);
/* tp_bool */ /* tp_bool */
py_bindmagic(tp_bool, __new__, _py_bool__new__); py_bindmagic(tp_bool, __new__, bool__new__);
py_bindmagic(tp_bool, __hash__, _py_bool__hash__); py_bindmagic(tp_bool, __hash__, bool__hash__);
py_bindmagic(tp_bool, __repr__, _py_bool__repr__); py_bindmagic(tp_bool, __repr__, bool__repr__);
py_bindmagic(tp_bool, __eq__, _py_bool__eq__); py_bindmagic(tp_bool, __eq__, bool__eq__);
py_bindmagic(tp_bool, __ne__, _py_bool__ne__); py_bindmagic(tp_bool, __ne__, bool__ne__);
} }

View File

@ -64,7 +64,11 @@ static bool type__base__getter(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
py_Type type = py_totype(argv); py_Type type = py_totype(argv);
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type); 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; return true;
} }

View File

@ -71,7 +71,10 @@ int py_next(py_Ref val) {
VM* vm = pk_current_vm; VM* vm = pk_current_vm;
vm->is_stopiteration = false; vm->is_stopiteration = false;
py_Ref tmp = py_tpfindmagic(val->type, __next__); 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); py_StackRef p0 = py_peek(0);
if(py_call(tmp, 1, val)) return true; if(py_call(tmp, 1, val)) return true;
if(vm->curr_exception.type == tp_StopIteration) { if(vm->curr_exception.type == tp_StopIteration) {

View File

@ -42,10 +42,35 @@ static bool slice__repr__(int argc, py_Ref argv) {
return true; 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 pk_slice__register() {
py_Type type = pk_newtype("slice", tp_object, NULL, NULL, false, true); py_Type type = pk_newtype("slice", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __new__, slice__new__); py_bindmagic(type, __new__, slice__new__);
py_bindmagic(type, __repr__, slice__repr__); 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; return type;
} }

View File

@ -212,7 +212,7 @@ DEF_STR_CMP_OP(__ge__, c11_sv__cmp, res >= 0)
#undef DEF_STR_CMP_OP #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); PY_CHECK_ARGC(1);
c11_string* self = py_touserdata(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
int total_size = sizeof(c11_string) + self->size + 1; int total_size = sizeof(c11_string) + self->size + 1;
@ -227,7 +227,7 @@ static bool str__lower(int argc, py_Ref argv) {
return true; return true;
} }
static bool str__upper(int argc, py_Ref argv) { static bool str_upper(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
c11_string* self = py_touserdata(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
int total_size = sizeof(c11_string) + self->size + 1; int total_size = sizeof(c11_string) + self->size + 1;
@ -242,7 +242,7 @@ static bool str__upper(int argc, py_Ref argv) {
return true; return true;
} }
static bool str__startswith(int argc, py_Ref argv) { static bool str_startswith(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_string* self = py_touserdata(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
@ -251,7 +251,7 @@ static bool str__startswith(int argc, py_Ref argv) {
return true; return true;
} }
static bool str__endswith(int argc, py_Ref argv) { static bool str_endswith(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_string* self = py_touserdata(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
@ -260,7 +260,7 @@ static bool str__endswith(int argc, py_Ref argv) {
return true; return true;
} }
static bool str__join(int argc, py_Ref argv) { static bool str_join(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_sv self = c11_string__sv(py_touserdata(&argv[0])); c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
py_Ref _1 = py_arg(1); py_Ref _1 = py_arg(1);
@ -268,11 +268,11 @@ static bool str__join(int argc, py_Ref argv) {
py_TValue* p; py_TValue* p;
int length; int length;
if(py_istype(_1, tp_list)) { if(py_istype(_1, tp_list)) {
p = py_list__getitem(_1, 0); p = py_list_getitem(_1, 0);
length = py_list__len(_1); length = py_list_len(_1);
} else if(py_istype(_1, tp_tuple)) { } else if(py_istype(_1, tp_tuple)) {
p = py_tuple__getitem(_1, 0); p = py_tuple_getitem(_1, 0);
length = py_tuple__len(_1); length = py_tuple_len(_1);
} else { } else {
return TypeError("join() argument must be a list or tuple"); 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; return true;
} }
static bool str__replace(int argc, py_Ref argv) { static bool str_replace(int argc, py_Ref argv) {
PY_CHECK_ARGC(3); PY_CHECK_ARGC(3);
c11_string* self = py_touserdata(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
@ -306,7 +306,7 @@ static bool str__replace(int argc, py_Ref argv) {
return true; 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_sv self = c11_string__sv(py_touserdata(&argv[0]));
c11_vector res; c11_vector res;
if(argc > 2) return TypeError("split() takes at most 2 arguments"); 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); py_newlistn(py_retval(), res.count);
for(int i = 0; i < res.count; i++) { for(int i = 0; i < res.count; i++) {
c11_sv item = c11__getitem(c11_sv, &res, 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); c11_vector__dtor(&res);
return true; return true;
} }
static bool str__count(int argc, py_Ref argv) { static bool str_count(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
c11_string* self = py_touserdata(&argv[0]); c11_string* self = py_touserdata(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str); 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; 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); 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); 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); 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); PY_CHECK_ARGC(2);
c11_sv self = c11_string__sv(py_touserdata(&argv[0])); c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
PY_CHECK_ARG_TYPE(1, tp_int); 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; 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); 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); 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"); if(argc > 3) return TypeError("find() takes at most 3 arguments");
int start = 0; int start = 0;
if(argc == 3) { if(argc == 3) {
@ -446,8 +446,8 @@ static bool str__find(int argc, py_Ref argv) {
return true; return true;
} }
static bool str__index(int argc, py_Ref argv) { static bool str_index(int argc, py_Ref argv) {
bool ok = str__find(argc, argv); bool ok = str_find(argc, argv);
if(!ok) return false; if(!ok) return false;
if(py_toint(py_retval()) == -1) return ValueError("substring not found"); if(py_toint(py_retval()) == -1) return ValueError("substring not found");
return true; return true;
@ -476,22 +476,22 @@ py_Type pk_str__register() {
py_bindmagic(tp_str, __gt__, str__gt__); py_bindmagic(tp_str, __gt__, str__gt__);
py_bindmagic(tp_str, __ge__, str__ge__); py_bindmagic(tp_str, __ge__, str__ge__);
py_bindmethod(tp_str, "lower", str__lower); py_bindmethod(tp_str, "lower", str_lower);
py_bindmethod(tp_str, "upper", str__upper); py_bindmethod(tp_str, "upper", str_upper);
py_bindmethod(tp_str, "startswith", str__startswith); py_bindmethod(tp_str, "startswith", str_startswith);
py_bindmethod(tp_str, "endswith", str__endswith); py_bindmethod(tp_str, "endswith", str_endswith);
py_bindmethod(tp_str, "join", str__join); py_bindmethod(tp_str, "join", str_join);
py_bindmethod(tp_str, "replace", str__replace); py_bindmethod(tp_str, "replace", str_replace);
py_bindmethod(tp_str, "split", str__split); py_bindmethod(tp_str, "split", str_split);
py_bindmethod(tp_str, "count", str__count); py_bindmethod(tp_str, "count", str_count);
py_bindmethod(tp_str, "strip", str__strip); py_bindmethod(tp_str, "strip", str_strip);
py_bindmethod(tp_str, "lstrip", str__lstrip); py_bindmethod(tp_str, "lstrip", str_lstrip);
py_bindmethod(tp_str, "rstrip", str__rstrip); py_bindmethod(tp_str, "rstrip", str_rstrip);
py_bindmethod(tp_str, "zfill", str__zfill); py_bindmethod(tp_str, "zfill", str_zfill);
py_bindmethod(tp_str, "ljust", str__ljust); py_bindmethod(tp_str, "ljust", str_ljust);
py_bindmethod(tp_str, "rjust", str__rjust); py_bindmethod(tp_str, "rjust", str_rjust);
py_bindmethod(tp_str, "find", str__find); py_bindmethod(tp_str, "find", str_find);
py_bindmethod(tp_str, "index", str__index); py_bindmethod(tp_str, "index", str_index);
return type; return type;
} }

View File

@ -13,17 +13,17 @@ void py_newtuple(py_Ref out, int n) {
out->_obj = obj; 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) { 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; return true;
} }
@ -31,7 +31,7 @@ static bool tuple__repr__(int argc, py_Ref argv) {
c11_sbuf buf; c11_sbuf buf;
c11_sbuf__ctor(&buf); c11_sbuf__ctor(&buf);
c11_sbuf__write_char(&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++) { for(int i = 0; i < length; i++) {
py_TValue* val = py_getslot(argv, i); py_TValue* val = py_getslot(argv, i);
bool ok = py_repr(val); bool ok = py_repr(val);
@ -58,10 +58,10 @@ static bool tuple__new__(int argc, py_Ref argv) {
if(!ok) return false; if(!ok) return false;
py_Ref tmp = py_pushtmp(); py_Ref tmp = py_pushtmp();
*tmp = *py_retval(); // backup the list *tmp = *py_retval(); // backup the list
int length = py_list__len(tmp); int length = py_list_len(tmp);
py_newtuple(py_retval(), length); py_newtuple(py_retval(), length);
for(int i = 0; i < py_tuple__len(py_retval()); i++) { for(int i = 0; i < py_tuple_len(py_retval()); i++) {
py_tuple__setitem(py_retval(), i, py_list__getitem(tmp, i)); py_tuple_setitem(py_retval(), i, py_list_getitem(tmp, i));
} }
py_pop(); py_pop();
return true; return true;
@ -71,7 +71,7 @@ static bool tuple__new__(int argc, py_Ref argv) {
static bool tuple__getitem__(int argc, py_Ref argv) { static bool tuple__getitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
int length = py_tuple__len(argv); int length = py_tuple_len(argv);
py_Ref _1 = py_arg(1); py_Ref _1 = py_arg(1);
if(_1->type == tp_int) { if(_1->type == tp_int) {
int index = py_toint(py_arg(1)); int index = py_toint(py_arg(1));
@ -84,11 +84,11 @@ static bool tuple__getitem__(int argc, py_Ref argv) {
if(!ok) return false; if(!ok) return false;
py_Ref tmp = py_pushtmp(); py_Ref tmp = py_pushtmp();
py_newlist(tmp); 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 // convert list to tuple
py_newtuple(py_retval(), py_list__len(tmp)); py_newtuple(py_retval(), py_list_len(tmp));
for(int i = 0; i < py_tuple__len(py_retval()); i++) { for(int i = 0; i < py_tuple_len(py_retval()); i++) {
py_tuple__setitem(py_retval(), i, py_list__getitem(tmp, i)); py_tuple_setitem(py_retval(), i, py_list_getitem(tmp, i));
} }
py_pop(); py_pop();
return true; return true;
@ -133,8 +133,8 @@ static bool tuple__contains__(int argc, py_Ref argv) {
static bool tuple__hash__(int argc, py_Ref argv) { static bool tuple__hash__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
int length = py_tuple__len(argv); int length = py_tuple_len(argv);
py_TValue* data = py_tuple__data(argv); py_TValue* data = py_tuple_data(argv);
uint64_t x = 1000003; uint64_t x = 1000003;
for(int i = 0; i < length; i++) { for(int i = 0; i < length; i++) {
py_i64 y; py_i64 y;

View File

@ -58,6 +58,12 @@ void py_setslot(py_Ref self, int i, py_Ref val) {
PyObject__slots(self->_obj)[i] = *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; } void py_assign(py_Ref dst, py_Ref src) { *dst = *src; }
/* Stack References */ /* Stack References */

View File

@ -1,6 +1,8 @@
a = {1, 2, 3} 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} assert a == {1, 2, 3, 4}
a = {1, 2, 3} 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}) assert not {1,2,3}.isdisjoint({2,3,4})
# unpacking builder # unpacking builder
a = {1, 2, 3} # a = {1, 2, 3}
b = {*a, 4, 5, *a, *a} # b = {*a, 4, 5, *a, *a}
assert b == {1, 2, 3, 4, 5} # assert b == {1, 2, 3, 4, 5}
a = set() # a = set()
b = {*a, 1, 2, 3, *a, *a} # b = {*a, 1, 2, 3, *a, *a}
assert b == {1, 2, 3} # assert b == {1, 2, 3}

View File

@ -13,7 +13,11 @@ assert getattr(1, '__add__')(2) == 3
a = object() a = object()
setattr(a, 'b', 1) setattr(a, 'b', 1)
assert a.b == 1 assert a.b == 1
assert hasattr(a, 'b')
assert getattr(a, 'b') == 1 assert getattr(a, 'b') == 1
assert getattr(a, 'c', ...) == ...
delattr(a, 'b')
assert not hasattr(a, 'b')
try: try:
getattr(a, 'xxx') getattr(a, 'xxx')

View File

@ -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