This commit is contained in:
blueloveTH 2024-06-30 22:44:51 +08:00
parent 7ed09f927d
commit 25ceed2703
14 changed files with 391 additions and 307 deletions

View File

@ -15,7 +15,8 @@ py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co,
pk_NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co); pk_NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co);
typedef struct ValueStack { typedef struct ValueStack {
// We allocate extra PK_VM_STACK_SIZE/128 places to keep `_sp` valid when `is_overflow() == true`. // We allocate extra PK_VM_STACK_SIZE/128 places to keep `_sp` valid when `is_overflow() ==
// true`.
py_TValue* sp; py_TValue* sp;
py_TValue* end; py_TValue* end;
py_TValue begin[PK_VM_STACK_SIZE + PK_VM_STACK_SIZE / 128]; py_TValue begin[PK_VM_STACK_SIZE + PK_VM_STACK_SIZE / 128];
@ -34,7 +35,7 @@ UnwindTarget* UnwindTarget__new(UnwindTarget* next, int iblock, int offset);
void UnwindTarget__delete(UnwindTarget* self); void UnwindTarget__delete(UnwindTarget* self);
typedef struct Frame { typedef struct Frame {
struct Frame* f_back; // TODO: set this struct Frame* f_back;
const Bytecode* ip; const Bytecode* ip;
const CodeObject* co; const CodeObject* co;
PyObject* module; PyObject* module;
@ -45,13 +46,15 @@ typedef struct Frame {
UnwindTarget* uw_list; UnwindTarget* uw_list;
} Frame; } Frame;
Frame* Frame__new(const CodeObject* co,
Frame* Frame__new(const CodeObject* co, const py_TValue* module, const py_TValue* function, py_TValue* p0, py_TValue* locals, const CodeObject* locals_co); const py_TValue* module,
const py_TValue* function,
py_TValue* p0,
py_TValue* locals,
const CodeObject* locals_co);
void Frame__delete(Frame* self); void Frame__delete(Frame* self);
PK_INLINE int Frame__ip(const Frame* self){ PK_INLINE int Frame__ip(const Frame* self) { return self->ip - (Bytecode*)self->co->codes.data; }
return self->ip - (Bytecode*)self->co->codes.data;
}
PK_INLINE int Frame__lineno(const Frame* self) { PK_INLINE int Frame__lineno(const Frame* self) {
int ip = Frame__ip(self); int ip = Frame__ip(self);
@ -63,9 +66,7 @@ PK_INLINE int Frame__iblock(const Frame* self){
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).iblock; return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).iblock;
} }
PK_INLINE pk_NameDict* Frame__f_globals(Frame* self){ PK_INLINE pk_NameDict* Frame__f_globals(Frame* self) { return PyObject__dict(self->module); }
return PyObject__dict(self->module);
}
PK_INLINE py_TValue* Frame__f_globals_try_get(Frame* self, py_Name name) { PK_INLINE py_TValue* Frame__f_globals_try_get(Frame* self, py_Name name) {
return pk_NameDict__try_get(Frame__f_globals(self), name); return pk_NameDict__try_get(Frame__f_globals(self), name);

View File

@ -21,21 +21,22 @@ typedef struct pk_TypeInfo{
c11_vector/*T=StrName*/ annotated_fields; c11_vector/*T=StrName*/ annotated_fields;
py_CFunction on_end_subclass; // backdoor for enum module
/* Magic Caches */ /* Magic Caches */
// unary operators py_TValue magic[64];
py_CFunction m__repr__, m__str__, m__hash__, m__len__; // // unary operators
py_CFunction m__iter__, m__next__, m__neg__, m__invert__; // py_CFunction m__repr__, m__str__, m__hash__, m__len__;
// binary operators // py_CFunction m__iter__, m__next__, m__neg__, m__invert__;
py_CFunction m__eq__, m__lt__, m__le__, m__gt__, m__ge__, m__contains__; // // binary operators
py_CFunction m__add__, m__sub__, m__mul__, m__truediv__, m__floordiv__; // py_CFunction m__eq__, m__lt__, m__le__, m__gt__, m__ge__, m__contains__;
py_CFunction m__mod__, m__pow__, m__matmul__; // py_CFunction m__add__, m__sub__, m__mul__, m__truediv__, m__floordiv__;
py_CFunction m__lshift__, m__rshift__, m__and__, m__xor__, m__or__; // py_CFunction m__mod__, m__pow__, m__matmul__;
// indexer // py_CFunction m__lshift__, m__rshift__, m__and__, m__xor__, m__or__;
py_CFunction m__getitem__, m__setitem__, m__delitem__; // // indexer
// attribute access (internal use only) // py_CFunction m__getitem__, m__setitem__, m__delitem__;
py_CFunction m__getattr__, m__setattr__, m__delattr__; // // attribute access (internal use only)
// backdoors // py_CFunction m__getattr__, m__setattr__, m__delattr__;
py_CFunction on_end_subclass; // for enum module
} pk_TypeInfo; } pk_TypeInfo;
void pk_TypeInfo__ctor(pk_TypeInfo* self, py_Name name, py_Type base, PyObject* obj, const py_TValue* module, bool subclass_enabled); void pk_TypeInfo__ctor(pk_TypeInfo* self, py_Name name, py_Type base, PyObject* obj, const py_TValue* module, bool subclass_enabled);
@ -91,6 +92,9 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self);
py_Type pk_VM__new_type(pk_VM* self, const char* name, py_Type base, const py_TValue* module, bool subclass_enabled); py_Type pk_VM__new_type(pk_VM* self, const char* name, py_Type base, const py_TValue* module, bool subclass_enabled);
// type registration
py_Type pk_list__register();
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -20,31 +20,34 @@ typedef struct py_TValue{
py_Type type; py_Type type;
bool is_ptr; bool is_ptr;
int extra; int extra;
union { union {
int64_t _i64; int64_t _i64;
double _f64; double _f64;
PyObject* _obj; PyObject* _obj;
void* _ptr; void* _ptr;
py_CFunction _cfunc;
// Vec2 // Vec2
}; };
} py_TValue; } py_TValue;
// 16 bytes to make py_arg() macro work // 16 bytes to make py_arg() macro work
static_assert(sizeof(py_CFunction) <= 8, "sizeof(py_CFunction) > 8");
static_assert(sizeof(py_TValue) == 16, "sizeof(py_TValue) != 16"); static_assert(sizeof(py_TValue) == 16, "sizeof(py_TValue) != 16");
/* predefined vars */ /* predefined vars */
static const py_Type tp_object = {1}, tp_type = {2}; const static py_Type tp_object = {1}, tp_type = {2};
static const py_Type tp_int = {3}, tp_float = {4}, tp_bool = {5}, tp_str = {6}; const static py_Type tp_int = {3}, tp_float = {4}, tp_bool = {5}, tp_str = {6};
static const py_Type tp_list = {7}, tp_tuple = {8}; const static py_Type tp_list = {7}, tp_tuple = {8};
static const py_Type tp_slice = {9}, tp_range = {10}, tp_module = {11}; const static py_Type tp_slice = {9}, tp_range = {10}, tp_module = {11};
static const py_Type tp_function = {12}, tp_nativefunc = {13}, tp_bound_method = {14}; const static py_Type tp_function = {12}, tp_nativefunc = {13}, tp_bound_method = {14};
static const py_Type tp_super = {15}, tp_exception = {16}, tp_bytes = {17}, tp_mappingproxy = {18}; const static py_Type tp_super = {15}, tp_exception = {16}, tp_bytes = {17}, tp_mappingproxy = {18};
static const py_Type tp_dict = {19}, tp_property = {20}, tp_star_wrapper = {21}; const static py_Type tp_dict = {19}, tp_property = {20}, tp_star_wrapper = {21};
static const py_Type tp_staticmethod = {22}, tp_classmethod = {23}; const static py_Type tp_staticmethod = {22}, tp_classmethod = {23};
static const py_Type tp_none_type = {24}, tp_not_implemented_type = {25}; const static py_Type tp_none_type = {24}, tp_not_implemented_type = {25};
static const py_Type tp_ellipsis = {26}; const static py_Type tp_ellipsis = {26};
static const py_Type tp_op_call = {27}, tp_op_yield = {28}; const static py_Type tp_op_call = {27}, tp_op_yield = {28};
static const py_Type tp_syntax_error = {29}, tp_stop_iteration = {30}; const static py_Type tp_syntax_error = {29}, tp_stop_iteration = {30};
extern py_TValue PY_NULL, PY_OP_CALL, PY_OP_YIELD; extern py_TValue PY_NULL, PY_OP_CALL, PY_OP_YIELD;

View File

@ -18,7 +18,8 @@ typedef struct py_Error {
/// Native function signature. /// Native function signature.
/// @param argc number of arguments. /// @param argc number of arguments.
/// @param argv array of arguments. Use `py_arg(i)` macro to get the i-th argument. /// @param argv array of arguments. Use `py_arg(i)` macro to get the i-th argument.
/// @param out output reference to the result. /// @param out output reference to the result. Please note that `out` could overlap with `argv`.
/// Always set `out` after using `argv`.
/// @return true if the function is successful. /// @return true if the function is successful.
typedef bool (*py_CFunction)(int argc, py_TValue* argv, py_TValue* out); typedef bool (*py_CFunction)(int argc, py_TValue* argv, py_TValue* out);
@ -74,13 +75,7 @@ void py_newfunction2(py_Ref out,
const char* docstring, const char* docstring,
const py_Ref upvalue); const py_Ref upvalue);
// old style argc-based function // old style argc-based function
void py_newnativefunc(py_Ref out, py_CFunction, int argc); void py_newnativefunc(py_Ref out, py_CFunction);
void py_newnativefunc2(py_Ref out,
py_CFunction,
int argc,
BindType bt,
const char* docstring,
const py_Ref upvalue);
void py_newnotimplemented(py_Ref out); void py_newnotimplemented(py_Ref out);
@ -110,7 +105,21 @@ bool py_istype(const py_Ref, py_Type);
// bool py_issubclass(py_Type derived, py_Type base); // bool py_issubclass(py_Type derived, py_Type base);
/************* References *************/ /************* References *************/
#define TypeError(x) false
#define py_arg(i) (py_Ref)((char*)argv + ((i) << 4)) #define py_arg(i) (py_Ref)((char*)argv + ((i) << 4))
#define py_checkargc(n) \
if(argc != n) return TypeError()
py_Ref py_tpmagic(py_Type type, py_Name name);
#define py_bindmagic(type, __magic__, f) py_newnativefunc(py_tpmagic((type), __magic__), (f))
// new style decl-based bindings
py_Ref py_bind(py_Ref obj, const char* sig, py_CFunction f);
py_Ref py_bind2(py_Ref obj, const char* sig, py_CFunction f, BindType bt, const char* docstring, const py_Ref upvalue);
// old style argc-based bindings
void py_bindmethod(py_Type type, const char* name, py_CFunction f);
void py_bindmethod2(py_Type type, const char* name, py_CFunction f, BindType bt);
void py_bindnativefunc(py_Ref obj, const char* name, py_CFunction f);
py_Ref py_reg(int i); py_Ref py_reg(int i);
@ -126,7 +135,11 @@ void py_setupvalue(py_Ref self, const py_Ref val);
/// Gets the attribute of the object. /// Gets the attribute of the object.
bool py_getattr(const py_Ref self, py_Name name, py_Ref out); bool py_getattr(const py_Ref self, py_Name name, py_Ref out);
/// Gets the unbound method of the object. /// Gets the unbound method of the object.
bool py_getunboundmethod(const py_Ref self, py_Name name, bool fallback, py_Ref out, py_Ref out_self); bool py_getunboundmethod(const py_Ref self,
py_Name name,
bool fallback,
py_Ref out,
py_Ref out_self);
/// Sets the attribute of the object. /// Sets the attribute of the object.
bool py_setattr(py_Ref self, py_Name name, const py_Ref val); bool py_setattr(py_Ref self, py_Name name, const py_Ref val);
/// Deletes the attribute of the object. /// Deletes the attribute of the object.
@ -177,21 +190,29 @@ int py_eq(const py_Ref, const py_Ref);
int py_le(const py_Ref, const py_Ref); int py_le(const py_Ref, const py_Ref);
bool py_hash(const py_Ref, int64_t* out); bool py_hash(const py_Ref, int64_t* out);
bool py_str(const py_Ref, py_Ref out);
bool py_repr(const py_Ref, py_Ref out);
/// A stack operation that calls a function. /// A stack operation that calls a function.
/// It consumes `argc + kwargc` arguments from the stack. /// It assumes `argc + kwargc` arguments are already pushed to the stack.
/// The result will be set to `vm->last_retval`. /// The result will be set to `vm->last_retval`.
int pk_vectorcall(int argc, int kwargc, bool op_call); /// The stack size will be reduced by `argc + kwargc`.
bool pk_vectorcall(int argc, int kwargc, bool op_call);
/// Call a function. /// Call a function.
/// It prepares the stack and then performs a `vectorcall(argc, 0, false)`. /// It prepares the stack and then performs a `vectorcall(argc, 0, false)`.
/// The result will be set to `vm->last_retval`. /// The result will be set to `vm->last_retval`.
/// The stack remains unchanged after the operation.
bool py_call(py_Ref f, int argc, py_Ref argv); bool py_call(py_Ref f, int argc, py_Ref argv);
/// Call a method. /// Call a non-magic method.
/// It prepares the stack and then performs a `vectorcall(argc+1, 0, false)`. /// It prepares the stack and then performs a `vectorcall(argc+1, 0, false)`.
/// The result will be set to `vm->last_retval`. /// The result will be set to `vm->last_retval`.
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv); /// The stack remains unchanged after the operation.
bool py_callmethod(py_Ref self, py_Name, int argc, py_Ref argv);
/// Call a magic method.
/// The result will be set to `vm->last_retval`.
/// The stack remains unchanged after the operation.
bool py_callmagic(py_Name name, int argc, py_Ref argv);
#define py_repr(self) py_callmagic(__repr__, 1, self)
#define py_str(self) py_callmagic(__str__, 1, self)
/// The return value of the most recent vectorcall. /// The return value of the most recent vectorcall.
py_Ref py_lastretval(); py_Ref py_lastretval();
@ -217,6 +238,15 @@ void py_list__insert(py_Ref self, int i, const py_Ref val);
typedef struct pk_TypeInfo pk_TypeInfo; typedef struct pk_TypeInfo pk_TypeInfo;
pk_TypeInfo* pk_tpinfo(const py_Ref self); pk_TypeInfo* pk_tpinfo(const py_Ref self);
/// Search the magic method from the given type to the base type.
/// Returns the reference or NULL if not found.
/// @lifespan: Permanent.
py_Ref py_tpfindmagic(py_Type, py_Name name);
/// Get the type object of the given type.
/// @lifespan: Permanent.
py_Ref py_tpobject(py_Type type);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -52,19 +52,7 @@ OPCODE(BUILD_SET)
OPCODE(BUILD_SLICE) OPCODE(BUILD_SLICE)
OPCODE(BUILD_STRING) OPCODE(BUILD_STRING)
/**************************/ /**************************/
OPCODE(BUILD_TUPLE_UNPACK) OPCODE(BINARY_OP)
OPCODE(BUILD_LIST_UNPACK)
OPCODE(BUILD_DICT_UNPACK)
OPCODE(BUILD_SET_UNPACK)
/**************************/
OPCODE(BINARY_TRUEDIV)
OPCODE(BINARY_POW)
OPCODE(BINARY_ADD)
OPCODE(BINARY_SUB)
OPCODE(BINARY_MUL)
OPCODE(BINARY_FLOORDIV)
OPCODE(BINARY_MOD)
OPCODE(COMPARE_LT) OPCODE(COMPARE_LT)
OPCODE(COMPARE_LE) OPCODE(COMPARE_LE)
@ -73,14 +61,6 @@ OPCODE(COMPARE_NE)
OPCODE(COMPARE_GT) OPCODE(COMPARE_GT)
OPCODE(COMPARE_GE) OPCODE(COMPARE_GE)
OPCODE(BITWISE_LSHIFT)
OPCODE(BITWISE_RSHIFT)
OPCODE(BITWISE_AND)
OPCODE(BITWISE_OR)
OPCODE(BITWISE_XOR)
OPCODE(BINARY_MATMUL)
OPCODE(IS_OP) OPCODE(IS_OP)
OPCODE(IS_NOT_OP) OPCODE(IS_NOT_OP)
OPCODE(IN_OP) OPCODE(IN_OP)
@ -101,7 +81,7 @@ OPCODE(GOTO)
OPCODE(FSTRING_EVAL) OPCODE(FSTRING_EVAL)
OPCODE(REPR) OPCODE(REPR)
OPCODE(CALL) OPCODE(CALL)
OPCODE(CALL_TP) OPCODE(CALL_VARGS)
OPCODE(RETURN_VALUE) OPCODE(RETURN_VALUE)
OPCODE(YIELD_VALUE) OPCODE(YIELD_VALUE)
/**************************/ /**************************/

View File

@ -75,6 +75,11 @@ void pk_StrName__initialize(){
pk_id_set = pk_StrName__map("set"); pk_id_set = pk_StrName__map("set");
pk_id_long = pk_StrName__map("long"); pk_id_long = pk_StrName__map("long");
pk_id_complex = pk_StrName__map("complex"); pk_id_complex = pk_StrName__map("complex");
// // print all names
// for(int i = 0; i < _interned.count; i++) {
// printf("%d: %s\n", i+1, c11__getitem(char*, &_r_interned, i));
// }
} }
void pk_StrName__finalize() { void pk_StrName__finalize() {
@ -99,9 +104,7 @@ uint16_t pk_StrName__map2(c11_string name){
uint16_t index = c11_smallmap_s2n__get(&_interned, name, 0); uint16_t index = c11_smallmap_s2n__get(&_interned, name, 0);
if(index != 0) return index; if(index != 0) return index;
// generate new index // generate new index
if(_interned.count > 65530){ if(_interned.count > 65530) { PK_FATAL_ERROR("StrName index overflow\n"); }
PK_FATAL_ERROR("StrName index overflow\n");
}
// NOTE: we must allocate the string in the heap so iterators are not invalidated // NOTE: we must allocate the string in the heap so iterators are not invalidated
char* p = malloc(name.size + 1); char* p = malloc(name.size + 1);
memcpy(p, name.data, name.size); memcpy(p, name.data, name.size);
@ -125,8 +128,6 @@ c11_string pk_StrName__rmap2(uint16_t index){
return (c11_string){p, strlen(p)}; return (c11_string){p, strlen(p)};
} }
// unary operators // unary operators
uint16_t __repr__; uint16_t __repr__;
uint16_t __str__; uint16_t __str__;

View File

@ -898,15 +898,18 @@ static void BinaryExpr__emit_(Expr* self_, Ctx* ctx) {
} }
vtemit_(self->rhs, ctx); vtemit_(self->rhs, ctx);
Opcode opcode;
Opcode opcode = OP_BINARY_OP;
uint16_t arg = BC_NOARG;
switch(self->op) { switch(self->op) {
case TK_ADD: opcode = OP_BINARY_ADD; break; case TK_ADD: arg = __add__ | (__radd__ << 8); break;
case TK_SUB: opcode = OP_BINARY_SUB; break; case TK_SUB: arg = __sub__ | (__rsub__ << 8); break;
case TK_MUL: opcode = OP_BINARY_MUL; break; case TK_MUL: arg = __mul__ | (__rmul__ << 8); break;
case TK_DIV: opcode = OP_BINARY_TRUEDIV; break; case TK_DIV: arg = __truediv__; break;
case TK_FLOORDIV: opcode = OP_BINARY_FLOORDIV; break; case TK_FLOORDIV: arg = __floordiv__; break;
case TK_MOD: opcode = OP_BINARY_MOD; break; case TK_MOD: arg = __mod__; break;
case TK_POW: opcode = OP_BINARY_POW; break; case TK_POW: arg = __pow__; break;
case TK_LT: opcode = OP_COMPARE_LT; break; case TK_LT: opcode = OP_COMPARE_LT; break;
case TK_LE: opcode = OP_COMPARE_LE; break; case TK_LE: opcode = OP_COMPARE_LE; break;
@ -920,17 +923,16 @@ static void BinaryExpr__emit_(Expr* self_, Ctx* ctx) {
case TK_IS: opcode = OP_IS_OP; break; case TK_IS: opcode = OP_IS_OP; break;
case TK_IS_NOT: opcode = OP_IS_NOT_OP; break; case TK_IS_NOT: opcode = OP_IS_NOT_OP; break;
case TK_LSHIFT: opcode = OP_BITWISE_LSHIFT; break; case TK_LSHIFT: arg = __lshift__; break;
case TK_RSHIFT: opcode = OP_BITWISE_RSHIFT; break; case TK_RSHIFT: arg = __rshift__; break;
case TK_AND: opcode = OP_BITWISE_AND; break; case TK_AND: arg = __and__; break;
case TK_OR: opcode = OP_BITWISE_OR; break; case TK_OR: arg = __or__; break;
case TK_XOR: opcode = OP_BITWISE_XOR; break; case TK_XOR: arg = __xor__; break;
case TK_DECORATOR: arg = __matmul__; break;
case TK_DECORATOR: opcode = OP_BINARY_MATMUL; break;
default: assert(false); default: assert(false);
} }
Ctx__emit_(ctx, opcode, BC_NOARG, self->line); Ctx__emit_(ctx, opcode, arg, self->line);
c11__foreach(int, &jmps, i) { Ctx__patch_jump(ctx, *i); } c11__foreach(int, &jmps, i) { Ctx__patch_jump(ctx, *i); }
} }
@ -1137,8 +1139,8 @@ void CallExpr__dtor(Expr* self_) {
void CallExpr__emit_(Expr* self_, Ctx* ctx) { void CallExpr__emit_(Expr* self_, Ctx* ctx) {
CallExpr* self = (CallExpr*)self_; CallExpr* self = (CallExpr*)self_;
bool vargs = false; bool vargs = false; // whether there is *args as input
bool vkwargs = false; bool vkwargs = false; // whether there is **kwargs as input
c11__foreach(Expr*, &self->args, e) { c11__foreach(Expr*, &self->args, e) {
if((*e)->vt->is_starred) vargs = true; if((*e)->vt->is_starred) vargs = true;
} }
@ -1147,7 +1149,6 @@ void CallExpr__emit_(Expr* self_, Ctx* ctx) {
} }
// if callable is a AttrExpr, we should try to use `fast_call` instead of use `boundmethod` // if callable is a AttrExpr, we should try to use `fast_call` instead of use `boundmethod`
// proxy
if(self->callable->vt->is_attrib) { if(self->callable->vt->is_attrib) {
AttribExpr* p = (AttribExpr*)self->callable; AttribExpr* p = (AttribExpr*)self->callable;
vtemit_(p->child, ctx); vtemit_(p->child, ctx);
@ -1157,41 +1158,22 @@ void CallExpr__emit_(Expr* self_, Ctx* ctx) {
Ctx__emit_(ctx, OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE); Ctx__emit_(ctx, OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
} }
c11__foreach(Expr*, &self->args, e) { vtemit_(*e, ctx); } Opcode opcode = OP_CALL;
if(vargs || vkwargs) { if(vargs || vkwargs) {
Ctx__emit_(ctx, OP_BUILD_TUPLE_UNPACK, (uint16_t)self->args.count, self->line); // in this case, there is at least one *args or **kwargs as StarredExpr
// OP_CALL_VARGS needs to unpack them via __vectorcall_buffer
opcode = OP_CALL_VARGS;
}
if(self->kwargs.count != 0) { c11__foreach(Expr*, &self->args, e) { vtemit_(*e, ctx); }
c11__foreach(CallExprKwArg, &self->kwargs, e) {
if(e->val->vt->is_starred) {
// **kwargs
StarredExpr* se = (StarredExpr*)e->val;
assert(se->level == 2 && e->key == 0);
vtemit_(e->val, ctx);
} else {
// k=v
int index = Ctx__add_const_string(ctx, pk_StrName__rmap2(e->key));
Ctx__emit_(ctx, OP_LOAD_CONST, index, self->line);
vtemit_(e->val, ctx);
Ctx__emit_(ctx, OP_BUILD_TUPLE, 2, self->line);
}
}
Ctx__emit_(ctx, OP_BUILD_DICT_UNPACK, self->kwargs.count, self->line);
Ctx__emit_(ctx, OP_CALL_TP, 1, self->line);
} else {
Ctx__emit_(ctx, OP_CALL_TP, 0, self->line);
}
} else {
// vectorcall protocol
c11__foreach(CallExprKwArg, &self->kwargs, e) { c11__foreach(CallExprKwArg, &self->kwargs, e) {
Ctx__emit_int(ctx, e->key, self->line); Ctx__emit_int(ctx, e->key, self->line);
vtemit_(e->val, ctx); vtemit_(e->val, ctx);
} }
int KWARGC = self->kwargs.count; int KWARGC = self->kwargs.count;
int ARGC = self->args.count; int ARGC = self->args.count;
Ctx__emit_(ctx, OP_CALL, (KWARGC << 8) | ARGC, self->line); assert(KWARGC < 256 && ARGC < 256);
} Ctx__emit_(ctx, opcode, (KWARGC << 8) | ARGC, self->line);
} }
CallExpr* CallExpr__new(int line, Expr* callable) { CallExpr* CallExpr__new(int line, Expr* callable) {

View File

@ -9,6 +9,7 @@ int UnboundLocalError(py_Name name) { return -1; }
int NameError(py_Name name) { return -1; } int NameError(py_Name name) { return -1; }
#define AttributeError(obj, name) #define AttributeError(obj, name)
#define BinaryOptError(op)
#define DISPATCH() \ #define DISPATCH() \
do { \ do { \
@ -38,6 +39,13 @@ int NameError(py_Name name) { return -1; }
#define POPX() (*--self->stack.sp) #define POPX() (*--self->stack.sp)
#define SP() (self->stack.sp) #define SP() (self->stack.sp)
// [a, b] -> [?, a, b]
#define INSERT_THIRD() \
do { \
PUSH(TOP()); \
*SECOND() = *THIRD(); \
} while(0)
#define vectorcall_opcall(n) \ #define vectorcall_opcall(n) \
do { \ do { \
pk_FrameResult res = pk_vectorcall(n, 0, true); \ pk_FrameResult res = pk_vectorcall(n, 0, true); \
@ -104,8 +112,9 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
} }
case OP_PRINT_EXPR: case OP_PRINT_EXPR:
if(TOP()->type != tp_none_type) { if(TOP()->type != tp_none_type) {
py_TValue tmp; bool ok = py_repr(TOP());
if(py_repr(TOP(), &tmp)) self->_stdout("%s\n", py_tostr(&tmp)); if(!ok) goto __ERROR;
self->_stdout("%s\n", py_tostr(&self->last_retval));
} }
POP(); POP();
DISPATCH(); DISPATCH();
@ -247,20 +256,22 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
} }
case OP_LOAD_SUBSCR: { case OP_LOAD_SUBSCR: {
// [a, b] -> a[b] // [a, b] -> a[b]
pk_TypeInfo* ti = pk_tpinfo(SECOND()); py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__);
if(ti->m__getitem__) { if(magic) {
if(!ti->m__getitem__(2, SECOND(), SECOND())) goto __ERROR; if(magic->type == tp_nativefunc) {
} else { bool ok = magic->_cfunc(2, SECOND(), SECOND());
// [a, b] -> [?, a, b]
PUSH(TOP()); // [a, b, b]
*SECOND() = *THIRD(); // [a, a, b]
bool ok = py_getunboundmethod(SECOND(), __getitem__, false, THIRD(), SECOND());
// [__getitem__, self, b]
if(!ok) goto __ERROR; if(!ok) goto __ERROR;
POP();
} else {
INSERT_THIRD(); // [?, a, b]
*THIRD() = *magic; // [__getitem__, a, b]
vectorcall_opcall(2); vectorcall_opcall(2);
} }
DISPATCH(); DISPATCH();
} }
TypeError();
goto __ERROR;
}
case OP_STORE_FAST: frame->locals[byte.arg] = POPX(); DISPATCH(); case OP_STORE_FAST: frame->locals[byte.arg] = POPX(); DISPATCH();
case OP_STORE_NAME: { case OP_STORE_NAME: {
py_Name _name = byte.arg; py_Name _name = byte.arg;
@ -296,20 +307,24 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
} }
case OP_STORE_SUBSCR: { case OP_STORE_SUBSCR: {
// [val, a, b] -> a[b] = val // [val, a, b] -> a[b] = val
pk_TypeInfo* ti = pk_tpinfo(SECOND());
PUSH(THIRD()); // [val, a, b, val] PUSH(THIRD()); // [val, a, b, val]
if(ti->m__setitem__) { py_Ref magic = py_tpfindmagic(SECOND()->type, __setitem__);
if(!ti->m__setitem__(3, THIRD(), FOURTH())) goto __ERROR; if(magic) {
STACK_SHRINK(3); // [retval] if(magic->type == tp_nativefunc) {
} else { bool ok = magic->_cfunc(3, THIRD(), FOURTH());
bool ok = py_getunboundmethod(THIRD(), __setitem__, false, FOURTH(), THIRD());
if(!ok) goto __ERROR; if(!ok) goto __ERROR;
// [__setitem__, self, b, val] STACK_SHRINK(4);
} else {
INSERT_THIRD(); // [?, a, b]
*FOURTH() = *magic; // [__selitem__, a, b, val]
vectorcall_opcall(3); vectorcall_opcall(3);
POP(); // discard retval POP(); // discard retval
} }
DISPATCH(); DISPATCH();
} }
TypeError();
goto __ERROR;
}
case OP_DELETE_FAST: { case OP_DELETE_FAST: {
py_Ref tmp = &frame->locals[byte.arg]; py_Ref tmp = &frame->locals[byte.arg];
if(py_isnull(tmp)) { if(py_isnull(tmp)) {
@ -362,22 +377,23 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
case OP_DELETE_SUBSCR: { case OP_DELETE_SUBSCR: {
// [a, b] -> del a[b] // [a, b] -> del a[b]
pk_TypeInfo* ti = pk_tpinfo(SECOND()); py_Ref magic = py_tpfindmagic(SECOND()->type, __delitem__);
if(ti->m__delitem__) { if(magic) {
if(!ti->m__delitem__(2, SECOND(), SECOND())) goto __ERROR; if(magic->type == tp_nativefunc) {
POP(); bool ok = magic->_cfunc(2, SECOND(), SECOND());
} else {
PUSH(TOP()); // [a, b, b]
*SECOND() = *THIRD(); // [a, a, b]
bool ok = py_getunboundmethod(SECOND(), __delitem__, false, THIRD(), SECOND());
// [__delitem__, self, b]
if(!ok) goto __ERROR; if(!ok) goto __ERROR;
STACK_SHRINK(2);
} else {
INSERT_THIRD(); // [?, a, b]
*THIRD() = *magic; // [__delitem__, a, b]
vectorcall_opcall(2); vectorcall_opcall(2);
POP(); // discard retval POP(); // discard retval
} }
DISPATCH(); DISPATCH();
} }
TypeError();
goto __ERROR;
}
/*****************************************/ /*****************************************/
case OP_BUILD_LONG: { case OP_BUILD_LONG: {
@ -398,7 +414,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
py_newnull(SP()++); // [complex, NULL] py_newnull(SP()++); // [complex, NULL]
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]
vectorcall_opcall(2); // [complex(x, 0)] vectorcall_opcall(2); // [complex(x)]
DISPATCH(); DISPATCH();
} }
case OP_BUILD_BYTES: { case OP_BUILD_BYTES: {
@ -462,20 +478,77 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
} }
case OP_BUILD_STRING: { case OP_BUILD_STRING: {
py_TValue* begin = SP() - byte.arg; py_TValue* begin = SP() - byte.arg;
py_Ref tmp = py_pushtmp();
pk_SStream ss; pk_SStream ss;
pk_SStream__ctor(&ss); pk_SStream__ctor(&ss);
for(int i = 0; i < byte.arg; i++) { for(int i = 0; i < byte.arg; i++) {
if(!py_str(begin + i, tmp)) goto __ERROR; if(!py_str(begin + i)) goto __ERROR;
py_Str* item = py_touserdata(tmp); py_Str* item = py_touserdata(&self->last_retval);
pk_SStream__write_Str(&ss, item); pk_SStream__write_Str(&ss, item);
} }
SP() = begin; SP() = begin;
py_newStr_(tmp, pk_SStream__submit(&ss)); py_newStr_(SP()++, pk_SStream__submit(&ss));
PUSH(tmp);
DISPATCH(); DISPATCH();
} }
/*****************************/ /*****************************/
case OP_BINARY_OP: {
py_Name op = byte.arg & 0xFF;
// [a, b]
py_Ref _0 = py_tpfindmagic(SECOND()->type, op);
py_Ref _1;
py_TValue tmp;
if(_0) {
if(_0->type == tp_nativefunc) {
bool ok = _0->_cfunc(2, SECOND(), &tmp);
if(!ok) goto __ERROR;
if(tmp.type != tp_not_implemented_type) {
POP();
*TOP() = tmp;
DISPATCH();
}
} else {
// standard call
bool ok = py_call(_0, 2, SECOND());
if(!ok) goto __ERROR;
if(self->last_retval.type != tp_not_implemented_type) {
POP();
*TOP() = self->last_retval;
DISPATCH();
}
}
}
// try reverse operation
op = byte.arg >> 8;
if(op) {
// [a, b] -> [b, a]
tmp = *TOP();
*TOP() = *SECOND();
*SECOND() = tmp;
_1 = py_tpfindmagic(SECOND()->type, op);
if(_1) {
if(_1->type == tp_nativefunc) {
bool ok = _1->_cfunc(2, SECOND(), &tmp);
if(!ok) goto __ERROR;
if(tmp.type != tp_not_implemented_type) {
POP();
*TOP() = tmp;
DISPATCH();
}
} else {
// standard call
bool ok = py_call(_1, 2, SECOND());
if(!ok) goto __ERROR;
if(self->last_retval.type != tp_not_implemented_type) {
POP();
*TOP() = self->last_retval;
DISPATCH();
}
}
}
}
BinaryOptError(byte.arg);
goto __ERROR;
}
case OP_RETURN_VALUE: { case OP_RETURN_VALUE: {
self->last_retval = byte.arg == BC_NOARG ? POPX() : self->None; self->last_retval = byte.arg == BC_NOARG ? POPX() : self->None;
pk_VM__pop_frame(self); pk_VM__pop_frame(self);

View File

@ -41,6 +41,7 @@
#define DEF_NUM_BINARY_OP(name, op) \ #define DEF_NUM_BINARY_OP(name, op) \
static bool _py_int##name(int argc, py_Ref argv, py_Ref out) { \ static bool _py_int##name(int argc, py_Ref argv, py_Ref out) { \
py_checkargc(2); \
if(py_isint(&argv[1])) { \ if(py_isint(&argv[1])) { \
int64_t lhs = py_toint(&argv[0]); \ int64_t lhs = py_toint(&argv[0]); \
int64_t rhs = py_toint(&argv[1]); \ int64_t rhs = py_toint(&argv[1]); \
@ -55,6 +56,7 @@
return true; \ return true; \
} \ } \
static bool _py_float##name(int argc, py_Ref argv, py_Ref out) { \ static bool _py_float##name(int argc, py_Ref argv, py_Ref out) { \
py_checkargc(2); \
double lhs = py_tofloat(&argv[0]); \ double lhs = py_tofloat(&argv[0]); \
double rhs; \ double rhs; \
if(py_castfloat(&argv[1], &rhs)) { \ if(py_castfloat(&argv[1], &rhs)) { \
@ -78,18 +80,21 @@ DEF_NUM_BINARY_OP(__ge__, >=)
#undef DEF_NUM_BINARY_OP #undef DEF_NUM_BINARY_OP
static bool _py_int__neg__(int argc, py_Ref argv, py_Ref out) { static bool _py_int__neg__(int argc, py_Ref argv, py_Ref out) {
py_checkargc(1);
int64_t val = py_toint(&argv[0]); int64_t val = py_toint(&argv[0]);
py_newint(out, -val); py_newint(out, -val);
return true; return true;
} }
static bool _py_float__neg__(int argc, py_Ref argv, py_Ref out) { static bool _py_float__neg__(int argc, py_Ref argv, py_Ref out) {
py_checkargc(1);
double val = py_tofloat(&argv[0]); double val = py_tofloat(&argv[0]);
py_newfloat(out, -val); py_newfloat(out, -val);
return true; return true;
} }
static bool _py_int__truediv__(int argc, py_Ref argv, py_Ref out) { static bool _py_int__truediv__(int argc, py_Ref argv, py_Ref out) {
py_checkargc(2);
int64_t lhs = py_toint(&argv[0]); int64_t lhs = py_toint(&argv[0]);
double rhs; double rhs;
if(py_castfloat(&argv[1], &rhs)) { if(py_castfloat(&argv[1], &rhs)) {
@ -101,6 +106,7 @@ static bool _py_int__truediv__(int argc, py_Ref argv, py_Ref out) {
} }
static bool _py_float__truediv__(int argc, py_Ref argv, py_Ref out) { static bool _py_float__truediv__(int argc, py_Ref argv, py_Ref out) {
py_checkargc(2);
double lhs = py_tofloat(&argv[0]); double lhs = py_tofloat(&argv[0]);
double rhs; double rhs;
if(py_castfloat(&argv[1], &rhs)) { if(py_castfloat(&argv[1], &rhs)) {
@ -114,6 +120,7 @@ static bool _py_float__truediv__(int argc, py_Ref argv, py_Ref out) {
#define ZeroDivisionError(msg) false #define ZeroDivisionError(msg) false
static bool _py_number__pow__(int argc, py_Ref argv, py_Ref out) { static bool _py_number__pow__(int argc, py_Ref argv, py_Ref out) {
py_checkargc(2);
if(py_isint(&argv[0]) && py_isint(&argv[1])) { if(py_isint(&argv[0]) && py_isint(&argv[1])) {
int64_t lhs = py_toint(&argv[0]); int64_t lhs = py_toint(&argv[0]);
int64_t rhs = py_toint(&argv[1]); int64_t rhs = py_toint(&argv[1]);
@ -145,6 +152,7 @@ static bool _py_number__pow__(int argc, py_Ref argv, py_Ref out) {
} }
static bool _py_int__floordiv__(int argc, py_Ref argv, py_Ref out) { static bool _py_int__floordiv__(int argc, py_Ref argv, py_Ref out) {
py_checkargc(2);
int64_t lhs = py_toint(&argv[0]); int64_t lhs = py_toint(&argv[0]);
if(py_isint(&argv[1])) { if(py_isint(&argv[1])) {
int64_t rhs = py_toint(&argv[1]); int64_t rhs = py_toint(&argv[1]);
@ -157,6 +165,7 @@ static bool _py_int__floordiv__(int argc, py_Ref argv, py_Ref out) {
} }
static bool _py_int__mod__(int argc, py_Ref argv, py_Ref out) { static bool _py_int__mod__(int argc, py_Ref argv, py_Ref out) {
py_checkargc(2);
int64_t lhs = py_toint(&argv[0]); int64_t lhs = py_toint(&argv[0]);
if(py_isint(&argv[1])) { if(py_isint(&argv[1])) {
int64_t rhs = py_toint(&argv[1]); int64_t rhs = py_toint(&argv[1]);
@ -169,12 +178,14 @@ static bool _py_int__mod__(int argc, py_Ref argv, py_Ref out) {
} }
static bool _py_int__invert__(int argc, py_Ref argv, py_Ref out) { static bool _py_int__invert__(int argc, py_Ref argv, py_Ref out) {
py_checkargc(1);
int64_t val = py_toint(&argv[0]); int64_t val = py_toint(&argv[0]);
py_newint(out, ~val); py_newint(out, ~val);
return true; return true;
} }
static bool _py_int__bit_length(int argc, py_Ref argv, py_Ref out) { static bool _py_int__bit_length(int argc, py_Ref argv, py_Ref out) {
py_checkargc(1);
int64_t x = py_toint(py_arg(0)); int64_t x = py_toint(py_arg(0));
if(x < 0) x = -x; if(x < 0) x = -x;
int bits = 0; int bits = 0;
@ -188,6 +199,7 @@ static bool _py_int__bit_length(int argc, py_Ref argv, py_Ref out) {
#define DEF_INT_BITWISE_OP(name, op) \ #define DEF_INT_BITWISE_OP(name, op) \
static bool _py_int##name(int argc, py_Ref argv, py_Ref out) { \ static bool _py_int##name(int argc, py_Ref argv, py_Ref out) { \
py_checkargc(2); \
int64_t lhs = py_toint(&argv[0]); \ int64_t lhs = py_toint(&argv[0]); \
if(py_isint(&argv[1])) { \ if(py_isint(&argv[1])) { \
int64_t rhs = py_toint(&argv[1]); \ int64_t rhs = py_toint(&argv[1]); \
@ -208,81 +220,53 @@ DEF_INT_BITWISE_OP(__rshift__, >>)
void pk_VM__init_builtins(pk_VM* self) { void pk_VM__init_builtins(pk_VM* self) {
/****** tp_int & tp_float ******/ /****** tp_int & tp_float ******/
py_Ref tmp = py_pushtmp(); py_bindmagic(tp_int, __add__, _py_int__add__);
py_Ref int_type = py_pushtmp(); py_bindmagic(tp_float, __add__, _py_float__add__);
*int_type = *py_getdict(&self->builtins, py_name("int")); py_bindmagic(tp_int, __sub__, _py_int__sub__);
py_Ref float_type = py_pushtmp(); py_bindmagic(tp_float, __sub__, _py_float__sub__);
*float_type = *py_getdict(&self->builtins, py_name("float")); py_bindmagic(tp_int, __mul__, _py_int__mul__);
py_bindmagic(tp_float, __mul__, _py_float__mul__);
#define BIND_INT_BINARY_OP(name) \ py_bindmagic(tp_int, __eq__, _py_int__eq__);
py_newnativefunc(tmp, _py_int##name, 2); \ py_bindmagic(tp_float, __eq__, _py_float__eq__);
py_setdict(int_type, name, tmp); py_bindmagic(tp_int, __lt__, _py_int__lt__);
py_bindmagic(tp_float, __lt__, _py_float__lt__);
#define BIND_FLOAT_BINARY_OP(name) \ py_bindmagic(tp_int, __le__, _py_int__le__);
py_newnativefunc(tmp, _py_float##name, 2); \ py_bindmagic(tp_float, __le__, _py_float__le__);
py_setdict(float_type, name, tmp); py_bindmagic(tp_int, __gt__, _py_int__gt__);
py_bindmagic(tp_float, __gt__, _py_float__gt__);
BIND_INT_BINARY_OP(__add__); py_bindmagic(tp_int, __ge__, _py_int__ge__);
BIND_FLOAT_BINARY_OP(__add__); py_bindmagic(tp_float, __ge__, _py_float__ge__);
BIND_INT_BINARY_OP(__sub__);
BIND_FLOAT_BINARY_OP(__sub__);
BIND_INT_BINARY_OP(__mul__);
BIND_FLOAT_BINARY_OP(__mul__);
BIND_INT_BINARY_OP(__eq__);
BIND_FLOAT_BINARY_OP(__eq__);
BIND_INT_BINARY_OP(__lt__);
BIND_FLOAT_BINARY_OP(__lt__);
BIND_INT_BINARY_OP(__le__);
BIND_FLOAT_BINARY_OP(__le__);
BIND_INT_BINARY_OP(__gt__);
BIND_FLOAT_BINARY_OP(__gt__);
BIND_INT_BINARY_OP(__ge__);
BIND_FLOAT_BINARY_OP(__ge__);
// __neg__ // __neg__
py_newnativefunc(tmp, _py_int__neg__, 1); py_bindmagic(tp_int, __neg__, _py_int__neg__);
py_setdict(int_type, __neg__, tmp); py_bindmagic(tp_float, __neg__, _py_float__neg__);
py_newnativefunc(tmp, _py_float__neg__, 1);
py_setdict(float_type, __neg__, tmp);
// TODO: __repr__, __new__, __hash__ // TODO: __repr__, __new__, __hash__
// __truediv__ // __truediv__
py_newnativefunc(tmp, _py_int__truediv__, 2); py_bindmagic(tp_int, __truediv__, _py_int__truediv__);
py_setdict(int_type, __truediv__, tmp); py_bindmagic(tp_float, __truediv__, _py_float__truediv__);
py_newnativefunc(tmp, _py_float__truediv__, 2);
py_setdict(float_type, __truediv__, tmp);
// __pow__ // __pow__
py_newnativefunc(tmp, _py_number__pow__, 2); py_bindmagic(tp_int, __pow__, _py_number__pow__);
py_setdict(int_type, __pow__, tmp); py_bindmagic(tp_float, __pow__, _py_number__pow__);
py_setdict(float_type, __pow__, tmp);
// __floordiv__ & __mod__ // __floordiv__ & __mod__
py_newnativefunc(tmp, _py_int__floordiv__, 2); py_bindmagic(tp_int, __floordiv__, _py_int__floordiv__);
py_setdict(int_type, __floordiv__, tmp); py_bindmagic(tp_int, __mod__, _py_int__mod__);
py_newnativefunc(tmp, _py_int__mod__, 2);
py_setdict(int_type, __mod__, tmp);
// int.__invert__ & int.<BITWISE OP> // int.__invert__ & int.<BITWISE OP>
py_newnativefunc(tmp, _py_int__invert__, 1); py_bindmagic(tp_int, __invert__, _py_int__invert__);
py_setdict(int_type, __invert__, tmp);
BIND_INT_BINARY_OP(__and__); py_bindmagic(tp_int, __and__, _py_int__and__);
BIND_INT_BINARY_OP(__or__); py_bindmagic(tp_int, __or__, _py_int__or__);
BIND_INT_BINARY_OP(__xor__); py_bindmagic(tp_int, __xor__, _py_int__xor__);
BIND_INT_BINARY_OP(__lshift__); py_bindmagic(tp_int, __lshift__, _py_int__lshift__);
BIND_INT_BINARY_OP(__rshift__); py_bindmagic(tp_int, __rshift__, _py_int__rshift__);
// int.bit_length // int.bit_length
py_newnativefunc(tmp, _py_int__bit_length, 1); py_bindmethod(tp_int, "bit_length", _py_int__bit_length);
py_setdict(int_type, py_name("bit_length"), tmp);
#undef BIND_INT_BINARY_OP
#undef BIND_FLOAT_BINARY_OP
py_poptmp(3);
// py_Ref builtins = py_getmodule("builtins"); // py_Ref builtins = py_getmodule("builtins");
// py_newfunction(py_reg(0), _py_print, // py_newfunction(py_reg(0), _py_print,

View File

@ -108,10 +108,7 @@ void pk_VM__ctor(pk_VM* self) {
validate(tp_bool, pk_VM__new_type(self, "bool", tp_object, NULL, false)); validate(tp_bool, pk_VM__new_type(self, "bool", tp_object, NULL, false));
validate(tp_str, pk_VM__new_type(self, "str", tp_object, NULL, false)); validate(tp_str, pk_VM__new_type(self, "str", tp_object, NULL, false));
validate(tp_list, pk_VM__new_type(self, "list", tp_object, NULL, false)); validate(tp_list, pk_list__register());
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, tp_list);
ti->dtor = (void (*)(void*))c11_vector__dtor;
validate(tp_tuple, pk_VM__new_type(self, "tuple", tp_object, NULL, false)); validate(tp_tuple, pk_VM__new_type(self, "tuple", tp_object, NULL, false));
validate(tp_slice, pk_VM__new_type(self, "slice", tp_object, NULL, false)); validate(tp_slice, pk_VM__new_type(self, "slice", tp_object, NULL, false));

View File

@ -6,6 +6,14 @@
typedef c11_vector List; typedef c11_vector List;
py_Type pk_list__register() {
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "list", tp_object, NULL, false);
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &vm->types, type);
ti->dtor = (void (*)(void*))c11_vector__dtor;
return type;
}
void py_newlist(py_Ref out) { void py_newlist(py_Ref out) {
pk_VM* vm = pk_current_vm; pk_VM* vm = pk_current_vm;
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_list, 0, sizeof(List)); PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_list, 0, sizeof(List));

View File

@ -7,19 +7,6 @@ int py_le(const py_Ref lhs, const py_Ref rhs) { return 0; }
bool py_hash(const py_Ref val, int64_t* out) { return 0; } bool py_hash(const py_Ref val, int64_t* out) { return 0; }
bool py_str(const py_Ref val, py_Ref out) { return 0; }
bool py_repr(const py_Ref val, py_Ref out) {
const pk_TypeInfo* ti = pk_tpinfo(val);
if(ti->m__repr__) return ti->m__repr__(1, val, out);
bool ok = py_callmethod(val, __repr__, 0, NULL);
if(ok) {
*out = pk_current_vm->last_retval;
return true;
}
return false;
}
bool py_getattr(const py_Ref self, py_Name name, py_Ref out) { return true; } bool py_getattr(const py_Ref self, py_Name name, py_Ref out) { return true; }
bool py_setattr(py_Ref self, py_Name name, const py_Ref val) { return -1; } bool py_setattr(py_Ref self, py_Name name, const py_Ref val) { return -1; }

View File

@ -79,16 +79,25 @@ void py_newfunction2(py_Ref out,
const char* docstring, const char* docstring,
const py_Ref upvalue) {} const py_Ref upvalue) {}
void py_newnativefunc(py_Ref out, py_CFunction f, int argc) { void py_newnativefunc(py_Ref out, py_CFunction f) {
py_newnativefunc2(out, f, argc, BindType_FUNCTION, NULL, NULL);
} }
void py_newnativefunc2(py_Ref out, void py_bindmethod(py_Type type, const char *name, py_CFunction f){
py_CFunction f, py_bindmethod2(type, name, f, BindType_FUNCTION);
int argc, }
BindType bt,
const char* docstring, void py_bindmethod2(py_Type type, const char *name, py_CFunction f, BindType bt){
const py_Ref upvalue) {} py_TValue tmp;
py_newnativefunc(&tmp, f);
py_setdict(py_tpobject(type), py_name(name), &tmp);
}
void py_bindnativefunc(py_Ref obj, const char *name, py_CFunction f){
py_TValue tmp;
py_newnativefunc(&tmp, f);
py_setdict(obj, py_name(name), &tmp);
}
void py_newnotimplemented(py_Ref out) { void py_newnotimplemented(py_Ref out) {
pk_VM* vm = pk_current_vm; pk_VM* vm = pk_current_vm;

View File

@ -47,23 +47,19 @@ int py_eval(const char* source, py_Ref out) {
PK_UNREACHABLE(); PK_UNREACHABLE();
} }
bool py_call(py_Ref f, int argc, py_Ref argv){ bool py_call(py_Ref f, int argc, py_Ref argv) { return -1; }
return -1;
}
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv){ bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; }
return -1;
}
int pk_vectorcall(int argc, int kwargc, bool op_call){ bool pk_vectorcall(int argc, int kwargc, bool op_call) { return -1; }
return -1;
}
py_Ref py_lastretval(){ py_Ref py_lastretval() { return &pk_current_vm->last_retval; }
return &pk_current_vm->last_retval;
}
bool py_getunboundmethod(const py_Ref self, py_Name name, bool fallback, py_Ref out, py_Ref out_self){ bool py_getunboundmethod(const py_Ref self,
py_Name name,
bool fallback,
py_Ref out,
py_Ref out_self) {
return -1; return -1;
} }
@ -72,3 +68,32 @@ pk_TypeInfo* pk_tpinfo(const py_Ref self){
return c11__at(pk_TypeInfo, &vm->types, self->type); return c11__at(pk_TypeInfo, &vm->types, self->type);
} }
py_Ref py_tpfindmagic(py_Type t, py_Name name) {
assert(name < 64);
pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
do {
py_Ref f = &types[t].magic[name];
if(!py_isnull(f)) return f;
t = types[t].base;
} while(t);
return NULL;
}
py_Ref py_tpmagic(py_Type type, py_Name name) {
assert(name < 64);
pk_VM* vm = pk_current_vm;
return &c11__at(pk_TypeInfo, &vm->types, type)->magic[name];
}
py_Ref py_tpobject(py_Type type) {
pk_VM* vm = pk_current_vm;
return &c11__at(pk_TypeInfo, &vm->types, type)->self;
}
bool py_callmagic(py_Name name, int argc, py_Ref argv) {
assert(argc >= 1);
py_Ref tmp = py_tpfindmagic(argv->type, name);
if(!tmp) return TypeError(name);
if(tmp->type == tp_nativefunc) { return tmp->_cfunc(argc, argv, &pk_current_vm->last_retval); }
return py_call(tmp, argc, argv);
}