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" {
#endif
#ifdef __cplusplus
#define PK_INLINE inline
#else
#define PK_INLINE static inline
#endif
#define PK_REGION(name) 1
#define PK_SLICE_LOOP(i, start, stop, step) \

View File

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

View File

@ -51,6 +51,7 @@ extern py_GlobalRef py_None;
extern py_GlobalRef py_NIL;
/************* Global Setup *************/
/// Initialize pocketpy and the default VM.
void py_initialize();
/// Finalize pocketpy.
@ -73,67 +74,102 @@ bool py_exec(const char* source,
py_Ref module) PY_RAISE;
/************* Values Creation *************/
void py_newint(py_Ref, py_i64);
void py_newfloat(py_Ref, py_f64);
void py_newbool(py_Ref, bool);
void py_newstr(py_Ref, const char*);
void py_newstrn(py_Ref, const char*, int);
unsigned char* py_newbytes(py_Ref, int);
void py_newnone(py_Ref);
void py_newnotimplemented(py_Ref out);
void py_newellipsis(py_Ref out);
void py_newnil(py_Ref);
/// Create a tuple with n UNINITIALIZED elements.
/// Create an `int` object.
void py_newint(py_Ref, py_i64);
/// Create a `float` object.
void py_newfloat(py_Ref, py_f64);
/// Create a `bool` object.
void py_newbool(py_Ref, bool);
/// Create a `str` object from a null-terminated string (utf-8).
void py_newstr(py_Ref, const char*);
/// Create a `str` object from a char array (utf-8).
void py_newstrn(py_Ref, const char*, int);
/// Create a `bytes` object with `n` UNINITIALIZED bytes.
unsigned char* py_newbytes(py_Ref, int n);
/// Create a `None` object.
void py_newnone(py_Ref);
/// Create a `NotImplemented` object.
void py_newnotimplemented(py_Ref out);
/// Create a `...` object.
void py_newellipsis(py_Ref out);
/// Create a `nil` object. `nil` is an invalid representation of an object.
/// Don't use it unless you know what you are doing.
void py_newnil(py_Ref);
/// Create a `tuple` with `n` UNINITIALIZED elements.
/// You should initialize all elements before using it.
void py_newtuple(py_Ref, int n);
/// Create a list.
/// Create an empty `list`.
void py_newlist(py_Ref);
/// Create a list with n UNINITIALIZED elements.
/// Create a `list` with `n` UNINITIALIZED elements.
/// You should initialize all elements before using it.
void py_newlistn(py_Ref, int n);
/// Create an empty `dict`.
void py_newdict(py_Ref);
/// Create an UNINITIALIZED `slice` object.
/// You should use `py_setslot()` to set `start`, `stop`, and `step`.
void py_newslice(py_Ref);
/// Create a `nativefunc` object.
void py_newnativefunc(py_Ref out, py_CFunction);
/// Create a `function` object.
py_Name
py_newfunction(py_Ref out, const char* sig, py_CFunction f, const char* docstring, int slots);
/// Create a `boundmethod` object.
void py_newboundmethod(py_Ref out, py_Ref self, py_Ref func);
/************* Name Convertions *************/
/// Convert a null-terminated string to a name.
py_Name py_name(const char*);
/// Convert a name to a null-terminated string.
const char* py_name2str(py_Name);
/// Convert a name to a `c11_sv`.
py_Name py_namev(c11_sv name);
/// Convert a `c11_sv` to a name.
c11_sv py_name2sv(py_Name);
#define py_ismagicname(name) (name <= __missing__)
/************* Meta Operations *************/
/// Create a new type.
/// @param name name of the type.
/// @param base base type.
/// @param module module where the type is defined. Use NULL for built-in types.
/// @param dtor destructor function. Use NULL if not needed.
/// @param module module where the type is defined. Use `NULL` for built-in types.
/// @param dtor destructor function. Use `NULL` if not needed.
py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, void (*dtor)(void*));
/// Create a new object.
/// @param out output reference.
/// @param type type of the object.
/// @param slots number of slots. Use -1 to create a `__dict__`.
/// @param udsize size of your userdata. You can use `py_touserdata()` to get the pointer to it.
/// @param udsize size of your userdata.
/// @return pointer to the userdata.
void* py_newobject(py_Ref out, py_Type type, int slots, int udsize);
/************* Type Cast *************/
py_i64 py_toint(py_Ref);
py_f64 py_tofloat(py_Ref);
bool py_castfloat(py_Ref, py_f64* out) PY_RAISE;
bool py_tobool(py_Ref);
py_Type py_totype(py_Ref);
const char* py_tostr(py_Ref);
const char* py_tostrn(py_Ref, int* size);
c11_sv py_tosv(py_Ref);
unsigned char* py_tobytes(py_Ref, int* size);
/// Convert an `int` object in python to `int64_t`.
py_i64 py_toint(py_Ref);
/// Convert a `float` object in python to `double`.
py_f64 py_tofloat(py_Ref);
/// Cast a `int` or `float` object in python to `double`.
/// If successful, returns true and set the value to `out`.
/// Otherwise, return false and raise `TypeError`.
bool py_castfloat(py_Ref, py_f64* out) PY_RAISE;
/// Convert a `bool` object in python to `bool`.
bool py_tobool(py_Ref);
/// Convert a `type` object in python to `py_Type`.
py_Type py_totype(py_Ref);
/// Convert a `str` object in python to null-terminated string.
const char* py_tostr(py_Ref);
/// Convert a `str` object in python to char array.
const char* py_tostrn(py_Ref, int* size);
/// Convert a `str` object in python to `c11_sv`.
c11_sv py_tosv(py_Ref);
/// Convert a `bytes` object in python to char array.
unsigned char* py_tobytes(py_Ref, int* size);
/// Convert a user-defined object to its userdata.
void* py_touserdata(py_Ref);
#define py_isint(self) py_istype(self, tp_int)
@ -147,14 +183,20 @@ void* py_touserdata(py_Ref);
#define py_isnil(self) py_istype(self, 0)
#define py_isnone(self) py_istype(self, tp_NoneType)
/// Get the type of the object.
py_Type py_typeof(py_Ref self);
/// Check if the object is exactly the given type.
bool py_istype(py_Ref, py_Type);
/// Check if the object is an instance of the given type.
bool py_isinstance(py_Ref obj, py_Type type);
/// Check if the derived type is a subclass of the base type.
bool py_issubclass(py_Type derived, py_Type base);
/// Search the magic method from the given type to the base type.
/// Return `NULL` if not found.
py_GlobalRef py_tpfindmagic(py_Type, py_Name name);
/// Search the name from the given type to the base type.
/// Return `NULL` if not found.
py_GlobalRef py_tpfindname(py_Type, py_Name name);
/// Get the type object of the given type.
py_GlobalRef py_tpobject(py_Type type);
@ -162,10 +204,12 @@ py_GlobalRef py_tpobject(py_Type type);
const char* py_tpname(py_Type type);
/// Call a type to create a new instance.
bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE;
/// Find the magic method from the given type only.
/// Get the magic method from the given type only.
/// The returned reference is always valid. However, its value may be `nil`.
py_GlobalRef py_tpmagic(py_Type type, py_Name name);
/// Check if the object is an instance of the given type.
/// Raise `TypeError` if the check fails.
bool py_checktype(py_Ref self, py_Type type) PY_RAISE;
#define py_checkint(self) py_checktype(self, tp_int)
@ -174,36 +218,62 @@ bool py_checktype(py_Ref self, py_Type type) PY_RAISE;
#define py_checkstr(self) py_checktype(self, tp_str)
/************* References *************/
/// Get the reference to the i-th register.
/// Get the i-th register.
/// All registers are located in a contiguous memory.
py_GlobalRef py_getreg(int i);
/// Set the reference to the i-th register.
/// Set the i-th register.
void py_setreg(int i, py_Ref val);
/// Equivalent to `*dst = *src`.
void py_assign(py_Ref dst, py_Ref src);
/// The return value of the most recent call.
/// Get the last return value.
py_GlobalRef py_retval();
/// Get the reference of the object's `__dict__`.
/// The object must have a `__dict__`.
/// Returns a reference to the value or NULL if not found.
/// Get an item from the object's `__dict__`.
/// Return `NULL` if not found.
py_ObjectRef py_getdict(py_Ref self, py_Name name);
/// Set an item to the object's `__dict__`.
void py_setdict(py_Ref self, py_Name name, py_Ref val);
/// Delete an item from the object's `__dict__`.
/// Return `true` if the deletion is successful.
bool py_deldict(py_Ref self, py_Name name);
/// Prepare an insertion to the object's `__dict__`.
py_ObjectRef py_emplacedict(py_Ref self, py_Name name);
/// Get the reference of the i-th slot of the object.
/// The object must have slots and `i` must be in range.
/// Get the i-th slot of the object.
/// The object must have slots and `i` must be in valid range.
py_ObjectRef py_getslot(py_Ref self, int i);
/// Set the i-th slot of the object.
void py_setslot(py_Ref self, int i, py_Ref val);
/************* Inspection *************/
/// Get the current `function` object from the stack.
/// Return `NULL` if not available.
py_StackRef py_inspect_currentfunction();
/************* Bindings *************/
// new style decl-based bindings
/// Bind a function to the object via "decl-based" style.
/// @param obj the target object.
/// @param sig signature of the function. e.g. `add(x, y)`.
/// @param f function to bind.
void py_bind(py_Ref obj, const char* sig, py_CFunction f);
// old style argc-based bindings
/// Bind a method to type via "argc-based" style.
/// @param type the target type.
/// @param name name of the method.
/// @param f function to bind.
void py_bindmethod(py_Type type, const char* name, py_CFunction f);
/// Bind a function to the object via "argc-based" style.
/// @param obj the target object.
/// @param name name of the function.
/// @param f function to bind.
void py_bindfunc(py_Ref obj, const char* name, py_CFunction f);
/// Bind a property to type.
/// @param type the target type.
/// @param name name of the property.
/// @param getter getter function.
/// @param setter setter function. Use `NULL` if not needed.
void py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFunction setter);
#define py_bindmagic(type, __magic__, f) py_newnativefunc(py_tpmagic((type), __magic__), (f))
@ -216,18 +286,25 @@ void py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFu
#define py_offset(p, i) ((py_Ref)((char*)p + ((i) << 4)))
#define py_arg(i) py_offset(argv, i)
/************* Python Equivalents *************/
bool py_getattr(py_Ref self, py_Name name) PY_RAISE;
bool py_setattr(py_Ref self, py_Name name, py_Ref val) PY_RAISE;
bool py_delattr(py_Ref self, py_Name name) PY_RAISE;
/************* Python Equivalents *************/
/// Python equivalent to `getattr(self, name)`.
bool py_getattr(py_Ref self, py_Name name) PY_RAISE;
/// Python equivalent to `setattr(self, name, val)`.
bool py_setattr(py_Ref self, py_Name name, py_Ref val) PY_RAISE;
/// Python equivalent to `delattr(self, name)`.
bool py_delattr(py_Ref self, py_Name name) PY_RAISE;
/// Python equivalent to `self[key]`.
bool py_getitem(py_Ref self, py_Ref key) PY_RAISE;
/// Python equivalent to `self[key] = val`.
bool py_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
/// Python equivalent to `del self[key]`.
bool py_delitem(py_Ref self, py_Ref key) PY_RAISE;
/// Perform a binary operation on the stack.
/// It assumes `lhs` and `rhs` are already pushed to the stack.
/// The result will be set to `py_retval()`.
/// The stack remains unchanged after the operation.
bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) PY_RAISE;
#define py_binaryadd(lhs, rhs) py_binaryop(lhs, rhs, __add__, __radd__)
@ -246,32 +323,36 @@ bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) PY_RAISE;
#define py_binarymatmul(lhs, rhs) py_binaryop(lhs, rhs, __matmul__, 0)
/************* Stack Operations *************/
/// Return a reference to the i-th object from the top of the stack.
/// i should be negative, e.g. (-1) means TOS.
/// Get the i-th object from the top of the stack.
/// `i` should be negative, e.g. (-1) means TOS.
py_StackRef py_peek(int i);
/// Push the object to the stack.
void py_push(py_Ref src);
/// Push a nil object to the stack.
/// Push a `nil` object to the stack.
void py_pushnil();
/// Pop an object from the stack.
void py_pop();
/// Shrink the stack by n.
void py_shrink(int n);
/// Get a temporary variable from the stack and returns the reference to it.
/// Get a temporary variable from the stack.
py_StackRef py_pushtmp();
/// Gets the unbound method of the object.
/// Assumes the object is located at the top of the stack.
/// If returns true: [self] -> [unbound, self]
/// If returns false: [self] -> [self] (no change)
/// Get the unbound method of the object.
/// Assume the object is located at the top of the stack.
/// If return true: `[self] -> [unbound, self]`.
/// If return false: `[self] -> [self]` (no change).
bool py_pushmethod(py_Name name);
/// A stack operation that calls a function.
/// It assumes `argc + kwargc` arguments are already pushed to the stack.
/// Call a callable object.
/// Assume `argc + kwargc` arguments are already pushed to the stack.
/// The result will be set to `py_retval()`.
/// The stack size will be reduced by `argc + kwargc`.
bool py_vectorcall(uint16_t argc, uint16_t kwargc) PY_RAISE;
/************* Modules *************/
/// Create a new module.
py_TmpRef py_newmodule(const char* path);
/// Get a module by path.
py_TmpRef py_getmodule(const char* path);
/// Import a module.
@ -280,23 +361,24 @@ py_TmpRef py_getmodule(const char* path);
int py_import(const char* path) PY_RAISE;
/************* Errors *************/
/// Raise an exception by name and message. Always returns false.
/// Raise an exception by type and message. Always return false.
bool py_exception(py_Type type, const char* fmt, ...) PY_RAISE;
/// Raise an expection object. Always returns false.
/// Raise an expection object. Always return false.
bool py_raise(py_Ref) PY_RAISE;
/// Print the current exception.
void py_printexc();
/// Format the current exception.
/// Format the current exception and return a null-terminated string.
/// The result should be freed by the caller.
char* py_formatexc();
/// Check if an exception is raised.
bool py_checkexc();
/// Check if the exception is an instance of the given type.
bool py_matchexc(py_Type type);
/// Clear the current exception.
/// @param p0 the unwinding point. Use `NULL` if not needed.
void py_clearexc(py_StackRef p0);
#define IOError(...) py_exception(tp_IOError, __VA_ARGS__)
#define OSError(...) py_exception(tp_OSError, __VA_ARGS__)
#define NameError(n) py_exception(tp_NameError, "name '%n' is not defined", (n))
#define TypeError(...) py_exception(tp_TypeError, __VA_ARGS__)
#define RuntimeError(...) py_exception(tp_RuntimeError, __VA_ARGS__)
@ -313,14 +395,18 @@ bool StopIteration();
bool KeyError(py_Ref key) PY_RAISE;
/************* Operators *************/
int py_equal(py_Ref lhs, py_Ref rhs) PY_RAISE;
int py_less(py_Ref lhs, py_Ref rhs) PY_RAISE;
/// Equivalent to `bool(val)`.
/// Returns 1 if `val` is truthy, otherwise 0.
/// Returns -1 if an error occurred.
/// Python equivalent to `bool(val)`.
/// 1: true, 0: false, -1: error
int py_bool(py_Ref val) PY_RAISE;
/// Compare two objects.
/// 1: lhs == rhs, 0: lhs != rhs, -1: error
int py_equal(py_Ref lhs, py_Ref rhs) PY_RAISE;
/// Compare two objects.
/// 1: lhs < rhs, 0: lhs >= rhs, -1: error
int py_less(py_Ref lhs, py_Ref rhs) PY_RAISE;
#define py_eq(lhs, rhs) py_binaryop(lhs, rhs, __eq__, __eq__)
#define py_ne(lhs, rhs) py_binaryop(lhs, rhs, __ne__, __ne__)
#define py_lt(lhs, rhs) py_binaryop(lhs, rhs, __lt__, __gt__)
@ -328,6 +414,7 @@ int py_bool(py_Ref val) PY_RAISE;
#define py_gt(lhs, rhs) py_binaryop(lhs, rhs, __gt__, __lt__)
#define py_ge(lhs, rhs) py_binaryop(lhs, rhs, __ge__, __le__)
/// Get the hash value of the object.
bool py_hash(py_Ref, py_i64* out) PY_RAISE;
/// Get the iterator of the object.
bool py_iter(py_Ref) PY_RAISE;
@ -341,40 +428,41 @@ bool py_isidentical(py_Ref, py_Ref);
/// The result will be set to `py_retval()`.
/// The stack remains unchanged after the operation.
bool py_call(py_Ref f, int argc, py_Ref argv) PY_RAISE;
/// Call a non-magic method.
/// It prepares the stack and then performs a `vectorcall(argc+1, 0, false)`.
/// The result will be set to `py_retval()`.
/// The stack remains unchanged after the operation.
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) PY_RAISE;
/// Python equivalent to `str(val)`.
bool py_str(py_Ref val) PY_RAISE;
/// Python equivalent to `repr(val)`.
bool py_repr(py_Ref val) PY_RAISE;
/// Python equivalent to `len(val)`.
bool py_len(py_Ref val) PY_RAISE;
/************* Unchecked Functions *************/
py_ObjectRef py_tuple__data(py_Ref self);
py_ObjectRef py_tuple__getitem(py_Ref self, int i);
void py_tuple__setitem(py_Ref self, int i, py_Ref val);
int py_tuple__len(py_Ref self);
py_TmpRef py_list__data(py_Ref self);
py_TmpRef py_list__getitem(py_Ref self, int i);
void py_list__setitem(py_Ref self, int i, py_Ref val);
void py_list__delitem(py_Ref self, int i);
int py_list__len(py_Ref self);
void py_list__append(py_Ref self, py_Ref val);
void py_list__clear(py_Ref self);
void py_list__insert(py_Ref self, int i, py_Ref val);
void py_list__reverse(py_Ref self);
py_ObjectRef py_tuple_data(py_Ref self);
py_ObjectRef py_tuple_getitem(py_Ref self, int i);
void py_tuple_setitem(py_Ref self, int i, py_Ref val);
int py_tuple_len(py_Ref self);
py_TmpRef py_dict__getitem(py_Ref self, py_Ref key) PY_RAISE;
void py_dict__setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
void py_dict__delitem(py_Ref self, py_Ref key) PY_RAISE;
bool py_dict__contains(py_Ref self, py_Ref key);
int py_dict__len(py_Ref self);
bool py_dict__apply(py_Ref self, bool (*f)(py_Ref key, py_Ref val, void* ctx), void* ctx);
py_TmpRef py_list_data(py_Ref self);
py_TmpRef py_list_getitem(py_Ref self, int i);
void py_list_setitem(py_Ref self, int i, py_Ref val);
void py_list_delitem(py_Ref self, int i);
int py_list_len(py_Ref self);
void py_list_append(py_Ref self, py_Ref val);
void py_list_clear(py_Ref self);
void py_list_insert(py_Ref self, int i, py_Ref val);
void py_list_reverse(py_Ref self);
py_TmpRef py_dict_getitem(py_Ref self, py_Ref key) PY_RAISE;
void py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
void py_dict_delitem(py_Ref self, py_Ref key) PY_RAISE;
bool py_dict_contains(py_Ref self, py_Ref key) PY_RAISE;
int py_dict_len(py_Ref self);
bool py_dict_apply(py_Ref self, bool (*f)(py_Ref key, py_Ref val, void* ctx), void* ctx) PY_RAISE;
/************* Others *************/
/// An utility function to read a line from stdin for REPL.
int py_replinput(char* buf, int max_size);
/// Python favored string formatting. (just put here, not for users)
@ -415,8 +503,8 @@ enum py_PredefinedTypes {
tp_function,
tp_nativefunc,
tp_boundmethod,
tp_super, // 1 slot + py_Type
tp_BaseException,
tp_super, // 1 slot + py_Type
tp_BaseException, // 2 slots (arg + inner exc)
tp_Exception,
tp_bytes,
tp_mappingproxy,

View File

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

View File

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

View File

@ -36,9 +36,9 @@ void UnwindTarget__delete(UnwindTarget* self) { free(self); }
Frame* Frame__new(const CodeObject* co,
py_TValue* module,
const py_TValue* function,
py_TValue* p0,
py_TValue* locals,
py_StackRef function,
py_StackRef p0,
py_StackRef locals,
const CodeObject* locals_co) {
static_assert(sizeof(Frame) <= kPoolFrameBlockSize, "!(sizeof(Frame) <= kPoolFrameBlockSize)");
Frame* self = PoolFrame_alloc();
@ -46,7 +46,7 @@ Frame* Frame__new(const CodeObject* co,
self->ip = (Bytecode*)co->codes.data - 1;
self->co = co;
self->module = *module;
self->function = function ? function->_obj : NULL;
self->function = function;
self->p0 = p0;
self->locals = locals;
self->locals_co = locals_co;
@ -133,7 +133,23 @@ void Frame__set_unwind_target(Frame* self, py_TValue* sp) {
py_TValue* Frame__f_closure_try_get(Frame* self, py_Name name) {
if(self->function == NULL) return NULL;
Function* ud = PyObject__userdata(self->function);
Function* ud = py_touserdata(self->function);
if(ud->closure == NULL) return NULL;
return NameDict__try_get(ud->closure, name);
}
int Frame__ip(const Frame* self) { return self->ip - (Bytecode*)self->co->codes.data; }
int Frame__lineno(const Frame* self) {
int ip = Frame__ip(self);
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).lineno;
}
int Frame__iblock(const Frame* self) {
int ip = Frame__ip(self);
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).iblock;
}
py_TValue* Frame__f_locals_try_get(Frame* self, py_Name name) {
return FastLocals__try_get_by_name(self->locals, self->locals_co, name);
}

View File

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

View File

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

View File

@ -31,13 +31,13 @@ static bool os_chdir(int argc, py_Ref argv) {
PY_CHECK_ARG_TYPE(0, tp_str);
const char* path = py_tostr(py_arg(0));
int code = platform_chdir(path);
if(code != 0) return OSError("chdir() failed: %d", code);
if(code != 0) return py_exception(tp_OSError, "chdir() failed: %d", code);
return true;
}
static bool os_getcwd(int argc, py_Ref argv) {
char buf[1024];
if(!platform_getcwd(buf, sizeof(buf))) return OSError("getcwd() failed");
if(!platform_getcwd(buf, sizeof(buf))) return py_exception(tp_OSError, "getcwd() failed");
py_newstr(py_retval(), buf);
return true;
}

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)); }
assert(py_istype(kwdefaults, tp_tuple));
assert(py_tuple__len(kwdefaults) == kwargc);
assert(py_tuple_len(kwdefaults) == kwargc);
for(int i = 0; i < kwargc; i++) {
FuncDecl__add_kwarg(decl, py_namev(kwargs[i]), py_tuple__getitem(kwdefaults, i));
FuncDecl__add_kwarg(decl, py_namev(kwargs[i]), py_tuple_getitem(kwdefaults, i));
}
if(starred_kwarg.size) FuncDecl__add_starred_kwarg(decl, py_namev(starred_kwarg));
decl->docstring = docstring;

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

View File

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

View File

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

View File

@ -52,8 +52,10 @@ static void BaseException__dtor(void* ud) {
static bool _py_BaseException__new__(int argc, py_Ref argv) {
py_Type cls = py_totype(argv);
BaseException* ud = py_newobject(py_retval(), cls, 1, sizeof(BaseException));
BaseException* ud = py_newobject(py_retval(), cls, 2, sizeof(BaseException));
c11_vector__ctor(&ud->stacktrace, sizeof(BaseExceptionFrame));
py_setslot(py_retval(), 0, py_NIL);
py_setslot(py_retval(), 1, py_NIL);
ud->lineno_backup = -1;
ud->code_backup = NULL;
return true;
@ -138,35 +140,46 @@ void py_printexc() {
free(msg);
}
static void c11_sbuf__write_exc(c11_sbuf* self, py_Ref exc){
if(true) { c11_sbuf__write_cstr(self, "Traceback (most recent call last):\n"); }
BaseException* ud = py_touserdata(exc);
for(int i = ud->stacktrace.count - 1; i >= 0; i--) {
BaseExceptionFrame* frame = c11__at(BaseExceptionFrame, &ud->stacktrace, i);
SourceData__snapshot(frame->src,
self,
frame->lineno,
NULL,
frame->name ? frame->name->data : NULL);
c11_sbuf__write_char(self, '\n');
}
const char* name = py_tpname(exc->type);
bool ok = py_str(exc);
if(!ok) c11__abort("py_printexc(): failed to convert exception to string");
const char* message = py_tostr(py_retval());
c11_sbuf__write_cstr(self, name);
c11_sbuf__write_cstr(self, ": ");
c11_sbuf__write_cstr(self, message);
}
char* py_formatexc() {
VM* vm = pk_current_vm;
if(py_isnil(&vm->curr_exception)) return NULL;
c11_sbuf ss;
c11_sbuf__ctor(&ss);
if(true) { c11_sbuf__write_cstr(&ss, "Traceback (most recent call last):\n"); }
BaseException* ud = py_touserdata(&vm->curr_exception);
for(int i = ud->stacktrace.count - 1; i >= 0; i--) {
BaseExceptionFrame* frame = c11__at(BaseExceptionFrame, &ud->stacktrace, i);
SourceData__snapshot(frame->src,
&ss,
frame->lineno,
NULL,
frame->name ? frame->name->data : NULL);
c11_sbuf__write_char(&ss, '\n');
py_Ref inner = py_getslot(&vm->curr_exception, 1);
if(py_isnil(inner)) {
c11_sbuf__write_exc(&ss, &vm->curr_exception);
} else {
c11_sbuf__write_exc(&ss, inner);
c11_sbuf__write_cstr(&ss, "\n\nDuring handling of the above exception, another exception occurred:\n\n");
c11_sbuf__write_exc(&ss, &vm->curr_exception);
}
const char* name = py_tpname(vm->curr_exception.type);
bool ok = py_str(&vm->curr_exception);
if(!ok) c11__abort("py_printexc(): failed to convert exception to string");
const char* message = py_tostr(py_retval());
c11_sbuf__write_cstr(&ss, name);
c11_sbuf__write_cstr(&ss, ": ");
c11_sbuf__write_cstr(&ss, message);
c11_string* res = c11_sbuf__submit(&ss);
char* dup = malloc(res->size + 1);
memcpy(dup, res->data, res->size);
@ -196,6 +209,10 @@ bool py_exception(py_Type type, const char* fmt, ...) {
bool py_raise(py_Ref exc) {
assert(py_isinstance(exc, tp_BaseException));
VM* vm = pk_current_vm;
if(!py_isnil(&vm->curr_exception)){
// inner exception
py_setslot(exc, 1, &vm->curr_exception);
}
vm->curr_exception = *exc;
return false;
}

View File

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

View File

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

View File

@ -64,7 +64,11 @@ static bool type__base__getter(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_Type type = py_totype(argv);
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
py_assign(py_retval(), py_tpobject(ti->base));
if(ti->base){
py_assign(py_retval(), py_tpobject(ti->base));
}else{
py_newnone(py_retval());
}
return true;
}

View File

@ -71,7 +71,10 @@ int py_next(py_Ref val) {
VM* vm = pk_current_vm;
vm->is_stopiteration = false;
py_Ref tmp = py_tpfindmagic(val->type, __next__);
if(!tmp) return TypeError("'%t' object is not an iterator", val->type);
if(!tmp) {
TypeError("'%t' object is not an iterator", val->type);
return -1;
}
py_StackRef p0 = py_peek(0);
if(py_call(tmp, 1, val)) return true;
if(vm->curr_exception.type == tp_StopIteration) {

View File

@ -42,10 +42,35 @@ static bool slice__repr__(int argc, py_Ref argv) {
return true;
}
static bool slice_start__getter(int argc, py_Ref argv) {
py_Ref self = py_arg(0);
py_TValue* val = py_getslot(self, 0);
py_assign(py_retval(), val);
return true;
}
static bool slice_stop__getter(int argc, py_Ref argv) {
py_Ref self = py_arg(0);
py_TValue* val = py_getslot(self, 1);
py_assign(py_retval(), val);
return true;
}
static bool slice_step__getter(int argc, py_Ref argv) {
py_Ref self = py_arg(0);
py_TValue* val = py_getslot(self, 2);
py_assign(py_retval(), val);
return true;
}
py_Type pk_slice__register() {
py_Type type = pk_newtype("slice", tp_object, NULL, NULL, false, true);
py_bindmagic(type, __new__, slice__new__);
py_bindmagic(type, __repr__, slice__repr__);
py_bindproperty(type, "start", slice_start__getter, NULL);
py_bindproperty(type, "stop", slice_stop__getter, NULL);
py_bindproperty(type, "step", slice_step__getter, NULL);
return type;
}

View File

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

View File

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

View File

@ -58,6 +58,12 @@ void py_setslot(py_Ref self, int i, py_Ref val) {
PyObject__slots(self->_obj)[i] = *val;
}
py_StackRef py_inspect_currentfunction(){
Frame* frame = pk_current_vm->top_frame;
if(!frame) return NULL;
return frame->function;
}
void py_assign(py_Ref dst, py_Ref src) { *dst = *src; }
/* Stack References */

View File

@ -1,6 +1,8 @@
a = {1, 2, 3}
a |= {2, 3, 4}
assert a == a
assert a == {i for i in range(1, 3+1)}
a |= {2, 3, 4}
assert a == {1, 2, 3, 4}
a = {1, 2, 3}
@ -79,10 +81,10 @@ assert {1,2,3}.isdisjoint({4,5,6})
assert not {1,2,3}.isdisjoint({2,3,4})
# unpacking builder
a = {1, 2, 3}
b = {*a, 4, 5, *a, *a}
assert b == {1, 2, 3, 4, 5}
# a = {1, 2, 3}
# b = {*a, 4, 5, *a, *a}
# assert b == {1, 2, 3, 4, 5}
a = set()
b = {*a, 1, 2, 3, *a, *a}
assert b == {1, 2, 3}
# a = set()
# b = {*a, 1, 2, 3, *a, *a}
# assert b == {1, 2, 3}

View File

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

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