mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
replace PyObject*
with PyVar
This commit is contained in:
parent
7fd4e3fdfb
commit
82d192e8da
@ -5,7 +5,7 @@ namespace pkpy{
|
||||
struct Array2d{
|
||||
PK_ALWAYS_PASS_BY_POINTER(Array2d)
|
||||
|
||||
PyObject** data;
|
||||
PyVar* data;
|
||||
int n_cols;
|
||||
int n_rows;
|
||||
int numel;
|
||||
@ -21,22 +21,22 @@ struct Array2d{
|
||||
this->n_cols = n_cols;
|
||||
this->n_rows = n_rows;
|
||||
this->numel = n_cols * n_rows;
|
||||
this->data = new PyObject*[numel];
|
||||
this->data = new PyVar[numel];
|
||||
}
|
||||
|
||||
bool is_valid(int col, int row) const{
|
||||
return 0 <= col && col < n_cols && 0 <= row && row < n_rows;
|
||||
}
|
||||
|
||||
PyObject* _get(int col, int row){
|
||||
PyVar _get(int col, int row){
|
||||
return data[row * n_cols + col];
|
||||
}
|
||||
|
||||
void _set(int col, int row, PyObject* value){
|
||||
void _set(int col, int row, PyVar value){
|
||||
data[row * n_cols + col] = value;
|
||||
}
|
||||
|
||||
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
||||
vm->bind(type, "__new__(cls, *args, **kwargs)", [](VM* vm, ArgsView args){
|
||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||
return vm->heap.gcnew<Array2d>(cls);
|
||||
@ -89,7 +89,7 @@ struct Array2d{
|
||||
int slice_height = stop_row - start_row; \
|
||||
if(slice_width <= 0 || slice_height <= 0) vm->ValueError("slice width and height must be positive");
|
||||
|
||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){
|
||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
||||
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
||||
const Tuple& xy = CAST(Tuple&, _1);
|
||||
i64 col, row;
|
||||
@ -102,7 +102,7 @@ struct Array2d{
|
||||
|
||||
if(is_type(xy[0], VM::tp_slice) && is_type(xy[1], VM::tp_slice)){
|
||||
HANDLE_SLICE();
|
||||
PyObject* new_array_obj = vm->new_user_object<Array2d>();
|
||||
PyVar new_array_obj = vm->new_user_object<Array2d>();
|
||||
Array2d& new_array = PK_OBJ_GET(Array2d, new_array_obj);
|
||||
new_array.init(stop_col - start_col, stop_row - start_row);
|
||||
for(int j = start_row; j < stop_row; j++){
|
||||
@ -116,7 +116,7 @@ struct Array2d{
|
||||
PK_UNREACHABLE();
|
||||
});
|
||||
|
||||
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1, PyObject* _2){
|
||||
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1, PyVar _2){
|
||||
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
||||
const Tuple& xy = CAST(Tuple&, _1);
|
||||
i64 col, row;
|
||||
@ -176,20 +176,20 @@ struct Array2d{
|
||||
return VAR(std::move(t));
|
||||
});
|
||||
|
||||
vm->bind__len__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){
|
||||
vm->bind__len__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){
|
||||
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
||||
return (i64)self.numel;
|
||||
});
|
||||
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> Str{
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> Str{
|
||||
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
||||
return _S("array2d(", self.n_cols, ", ", self.n_rows, ')');
|
||||
});
|
||||
|
||||
vm->bind(type, "map(self, f)", [](VM* vm, ArgsView args){
|
||||
Array2d& self = PK_OBJ_GET(Array2d, args[0]);
|
||||
PyObject* f = args[1];
|
||||
PyObject* new_array_obj = vm->new_user_object<Array2d>();
|
||||
PyVar f = args[1];
|
||||
PyVar new_array_obj = vm->new_user_object<Array2d>();
|
||||
Array2d& new_array = PK_OBJ_GET(Array2d, new_array_obj);
|
||||
new_array.init(self.n_cols, self.n_rows);
|
||||
for(int i = 0; i < new_array.numel; i++){
|
||||
@ -200,7 +200,7 @@ struct Array2d{
|
||||
|
||||
vm->bind(type, "copy(self)", [](VM* vm, ArgsView args){
|
||||
Array2d& self = PK_OBJ_GET(Array2d, args[0]);
|
||||
PyObject* new_array_obj = vm->new_user_object<Array2d>();
|
||||
PyVar new_array_obj = vm->new_user_object<Array2d>();
|
||||
Array2d& new_array = PK_OBJ_GET(Array2d, new_array_obj);
|
||||
new_array.init(self.n_cols, self.n_rows);
|
||||
for(int i = 0; i < new_array.numel; i++){
|
||||
@ -219,7 +219,7 @@ struct Array2d{
|
||||
|
||||
vm->bind(type, "apply_(self, f)", [](VM* vm, ArgsView args){
|
||||
Array2d& self = PK_OBJ_GET(Array2d, args[0]);
|
||||
PyObject* f = args[1];
|
||||
PyVar f = args[1];
|
||||
for(int i = 0; i < self.numel; i++){
|
||||
self.data[i] = vm->call(f, self.data[i]);
|
||||
}
|
||||
@ -250,7 +250,7 @@ struct Array2d{
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){
|
||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
||||
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
||||
if(!vm->is_user_type<Array2d>(_1)) return vm->NotImplemented;
|
||||
Array2d& other = PK_OBJ_GET(Array2d, _1);
|
||||
@ -263,10 +263,10 @@ struct Array2d{
|
||||
|
||||
vm->bind(type, "count_neighbors(self, value, neighborhood='Moore') -> array2d[int]", [](VM* vm, ArgsView args){
|
||||
Array2d& self = PK_OBJ_GET(Array2d, args[0]);
|
||||
PyObject* new_array_obj = vm->new_user_object<Array2d>();
|
||||
PyVar new_array_obj = vm->new_user_object<Array2d>();
|
||||
Array2d& new_array = PK_OBJ_GET(Array2d, new_array_obj);
|
||||
new_array.init(self.n_cols, self.n_rows);
|
||||
PyObject* value = args[1];
|
||||
PyVar value = args[1];
|
||||
const Str& neighborhood = CAST(Str&, args[2]);
|
||||
if(neighborhood == "Moore"){
|
||||
for(int j = 0; j < new_array.n_rows; j++){
|
||||
@ -302,7 +302,7 @@ struct Array2d{
|
||||
|
||||
vm->bind(type, "count(self, value) -> int", [](VM* vm, ArgsView args){
|
||||
Array2d& self = PK_OBJ_GET(Array2d, args[0]);
|
||||
PyObject* value = args[1];
|
||||
PyVar value = args[1];
|
||||
int count = 0;
|
||||
for(int i = 0; i < self.numel; i++) count += vm->py_eq(self.data[i], value);
|
||||
return VAR(count);
|
||||
@ -310,7 +310,7 @@ struct Array2d{
|
||||
|
||||
vm->bind(type, "find_bounding_rect(self, value)", [](VM* vm, ArgsView args){
|
||||
Array2d& self = PK_OBJ_GET(Array2d, args[0]);
|
||||
PyObject* value = args[1];
|
||||
PyVar value = args[1];
|
||||
int left = self.n_cols;
|
||||
int top = self.n_rows;
|
||||
int right = 0;
|
||||
@ -345,15 +345,15 @@ struct Array2d{
|
||||
struct Array2dIter{
|
||||
PK_ALWAYS_PASS_BY_POINTER(Array2dIter)
|
||||
|
||||
PyObject* ref;
|
||||
PyVar ref;
|
||||
int i;
|
||||
Array2dIter(PyObject* ref) : ref(ref), i(0) {}
|
||||
Array2dIter(PyVar ref) : ref(ref), i(0) {}
|
||||
|
||||
void _gc_mark() const{ PK_OBJ_MARK(ref); }
|
||||
|
||||
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) { return _0; });
|
||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> unsigned{
|
||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) { return _0; });
|
||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
|
||||
Array2dIter& self = PK_OBJ_GET(Array2dIter, _0);
|
||||
Array2d& a = PK_OBJ_GET(Array2d, self.ref);
|
||||
if(self.i == a.numel) return 0;
|
||||
@ -367,12 +367,12 @@ struct Array2dIter{
|
||||
};
|
||||
|
||||
void add_module_array2d(VM* vm){
|
||||
PyObject* mod = vm->new_module("array2d");
|
||||
PyVar mod = vm->new_module("array2d");
|
||||
|
||||
vm->register_user_class<Array2d>(mod, "array2d", VM::tp_object, true);
|
||||
vm->register_user_class<Array2dIter>(mod, "_array2d_iter");
|
||||
|
||||
vm->bind__iter__(vm->_tp_user<Array2d>(), [](VM* vm, PyObject* _0){
|
||||
vm->bind__iter__(vm->_tp_user<Array2d>(), [](VM* vm, PyVar _0){
|
||||
return vm->new_user_object<Array2dIter>(_0);
|
||||
});
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ base64_decode(const char *in, unsigned int inlen, unsigned char *out)
|
||||
}
|
||||
|
||||
void add_module_base64(VM* vm){
|
||||
PyObject* mod = vm->new_module("base64");
|
||||
PyVar mod = vm->new_module("base64");
|
||||
|
||||
// b64encode
|
||||
vm->bind_func(mod, "b64encode", 1, [](VM* vm, ArgsView args){
|
||||
|
282
src/ceval.cpp
282
src/ceval.cpp
@ -10,25 +10,25 @@ namespace pkpy{
|
||||
|
||||
#define PREDICT_INT_DIV_OP(op) \
|
||||
if(is_small_int(_0) && is_small_int(_1)){ \
|
||||
if(_1 == (PyObject*)0b10) ZeroDivisionError(); \
|
||||
if(_1 == (PyVar)0b10) ZeroDivisionError(); \
|
||||
TOP() = VAR((PK_BITS(_0)>>2) op (PK_BITS(_1)>>2)); \
|
||||
DISPATCH() \
|
||||
}
|
||||
|
||||
#define BINARY_F_COMPARE(func, op, rfunc) \
|
||||
PyObject* ret; \
|
||||
PyVar ret; \
|
||||
const PyTypeInfo* _ti = _tp_info(_0); \
|
||||
if(_ti->m##func){ \
|
||||
ret = _ti->m##func(this, _0, _1); \
|
||||
}else{ \
|
||||
PyObject* self; \
|
||||
PyObject* _2 = get_unbound_method(_0, func, &self, false); \
|
||||
PyVar self; \
|
||||
PyVar _2 = get_unbound_method(_0, func, &self, false); \
|
||||
if(_2 != nullptr) ret = call_method(self, _2, _1); \
|
||||
else ret = NotImplemented; \
|
||||
} \
|
||||
if(ret == NotImplemented){ \
|
||||
PyObject* self; \
|
||||
PyObject* _2 = get_unbound_method(_1, rfunc, &self, false); \
|
||||
PyVar self; \
|
||||
PyVar _2 = get_unbound_method(_1, rfunc, &self, false); \
|
||||
if(_2 != nullptr) ret = call_method(self, _2, _0); \
|
||||
else BinaryOptError(op, _0, _1); \
|
||||
if(ret == NotImplemented) BinaryOptError(op, _0, _1); \
|
||||
@ -36,12 +36,12 @@ namespace pkpy{
|
||||
|
||||
|
||||
void VM::__op_unpack_sequence(uint16_t arg){
|
||||
PyObject* _0 = POPX();
|
||||
PyVar _0 = POPX();
|
||||
if(is_type(_0, VM::tp_tuple)){
|
||||
// fast path for tuple
|
||||
Tuple& tuple = PK_OBJ_GET(Tuple, _0);
|
||||
if(tuple.size() == arg){
|
||||
for(PyObject* obj: tuple) PUSH(obj);
|
||||
for(PyVar obj: tuple) PUSH(obj);
|
||||
}else{
|
||||
ValueError(_S("expected ", (int)arg, " values to unpack, got ", (int)tuple.size()));
|
||||
}
|
||||
@ -50,7 +50,7 @@ void VM::__op_unpack_sequence(uint16_t arg){
|
||||
_0 = py_iter(_0);
|
||||
const PyTypeInfo* ti = _tp_info(_0);
|
||||
for(int i=0; i<arg; i++){
|
||||
PyObject* _1 = _py_next(ti, _0);
|
||||
PyVar _1 = _py_next(ti, _0);
|
||||
if(_1 == StopIteration) ValueError("not enough values to unpack");
|
||||
PUSH(_1);
|
||||
}
|
||||
@ -58,29 +58,29 @@ void VM::__op_unpack_sequence(uint16_t arg){
|
||||
}
|
||||
}
|
||||
|
||||
bool VM::py_lt(PyObject* _0, PyObject* _1){
|
||||
bool VM::py_lt(PyVar _0, PyVar _1){
|
||||
BINARY_F_COMPARE(__lt__, "<", __gt__);
|
||||
return ret == True;
|
||||
}
|
||||
|
||||
bool VM::py_le(PyObject* _0, PyObject* _1){
|
||||
bool VM::py_le(PyVar _0, PyVar _1){
|
||||
BINARY_F_COMPARE(__le__, "<=", __ge__);
|
||||
return ret == True;
|
||||
}
|
||||
|
||||
bool VM::py_gt(PyObject* _0, PyObject* _1){
|
||||
bool VM::py_gt(PyVar _0, PyVar _1){
|
||||
BINARY_F_COMPARE(__gt__, ">", __lt__);
|
||||
return ret == True;
|
||||
}
|
||||
|
||||
bool VM::py_ge(PyObject* _0, PyObject* _1){
|
||||
bool VM::py_ge(PyVar _0, PyVar _1){
|
||||
BINARY_F_COMPARE(__ge__, ">=", __le__);
|
||||
return ret == True;
|
||||
}
|
||||
|
||||
#undef BINARY_F_COMPARE
|
||||
|
||||
PyObject* VM::__run_top_frame(){
|
||||
PyVar VM::__run_top_frame(){
|
||||
Frame* frame = &callstack.top();
|
||||
const Frame* base_frame = frame;
|
||||
bool need_raise = false;
|
||||
@ -91,7 +91,7 @@ PyObject* VM::__run_top_frame(){
|
||||
/**********************************************************************/
|
||||
/* NOTE:
|
||||
* Be aware of accidental gc!
|
||||
* DO NOT leave any strong reference of PyObject* in the C stack
|
||||
* DO NOT leave any strong reference of PyVar in the C stack
|
||||
*/
|
||||
{
|
||||
|
||||
@ -128,7 +128,7 @@ __NEXT_STEP:;
|
||||
case OP_DUP_TOP: PUSH(TOP()); DISPATCH()
|
||||
case OP_ROT_TWO: std::swap(TOP(), SECOND()); DISPATCH()
|
||||
case OP_ROT_THREE:{
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _0 = TOP();
|
||||
TOP() = SECOND();
|
||||
SECOND() = THIRD();
|
||||
THIRD() = _0;
|
||||
@ -145,12 +145,12 @@ __NEXT_STEP:;
|
||||
case OP_LOAD_TRUE: PUSH(True); DISPATCH()
|
||||
case OP_LOAD_FALSE: PUSH(False); DISPATCH()
|
||||
/*****************************************/
|
||||
case OP_LOAD_SMALL_INT: PUSH((PyObject*)(uintptr_t)byte.arg); DISPATCH()
|
||||
case OP_LOAD_SMALL_INT: PUSH((PyVar)(uintptr_t)byte.arg); DISPATCH()
|
||||
/*****************************************/
|
||||
case OP_LOAD_ELLIPSIS: PUSH(Ellipsis); DISPATCH()
|
||||
case OP_LOAD_FUNCTION: {
|
||||
const FuncDecl_& decl = co->func_decls[byte.arg];
|
||||
PyObject* obj;
|
||||
PyVar obj;
|
||||
if(decl->nested){
|
||||
NameDict_ captured = frame->_locals.to_namedict();
|
||||
obj = VAR(Function(decl, frame->_module, nullptr, captured));
|
||||
@ -163,19 +163,19 @@ __NEXT_STEP:;
|
||||
case OP_LOAD_NULL: PUSH(PY_NULL); DISPATCH()
|
||||
/*****************************************/
|
||||
case OP_LOAD_FAST: {
|
||||
PyObject* _0 = frame->_locals[byte.arg];
|
||||
PyVar _0 = frame->_locals[byte.arg];
|
||||
if(_0 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
|
||||
PUSH(_0);
|
||||
} DISPATCH()
|
||||
case OP_LOAD_NAME: {
|
||||
StrName _name(byte.arg);
|
||||
PyObject** slot = frame->_locals.try_get_name(_name);
|
||||
PyVar* slot = frame->_locals.try_get_name(_name);
|
||||
if(slot != nullptr) {
|
||||
if(*slot == PY_NULL) vm->UnboundLocalError(_name);
|
||||
PUSH(*slot);
|
||||
DISPATCH()
|
||||
}
|
||||
PyObject* _0 = frame->f_closure_try_get(_name);
|
||||
PyVar _0 = frame->f_closure_try_get(_name);
|
||||
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
|
||||
_0 = frame->f_globals().try_get_likely_found(_name);
|
||||
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
|
||||
@ -185,7 +185,7 @@ __NEXT_STEP:;
|
||||
} DISPATCH()
|
||||
case OP_LOAD_NONLOCAL: {
|
||||
StrName _name(byte.arg);
|
||||
PyObject* _0 = frame->f_closure_try_get(_name);
|
||||
PyVar _0 = frame->f_closure_try_get(_name);
|
||||
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
|
||||
_0 = frame->f_globals().try_get_likely_found(_name);
|
||||
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
|
||||
@ -195,7 +195,7 @@ __NEXT_STEP:;
|
||||
} DISPATCH()
|
||||
case OP_LOAD_GLOBAL:{
|
||||
StrName _name(byte.arg);
|
||||
PyObject* _0 = frame->f_globals().try_get_likely_found(_name);
|
||||
PyVar _0 = frame->f_globals().try_get_likely_found(_name);
|
||||
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
|
||||
_0 = vm->builtins->attr().try_get_likely_found(_name);
|
||||
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
|
||||
@ -207,7 +207,7 @@ __NEXT_STEP:;
|
||||
case OP_LOAD_CLASS_GLOBAL:{
|
||||
PK_ASSERT(__curr_class != nullptr);
|
||||
StrName _name(byte.arg);
|
||||
PyObject* _0 = getattr(__curr_class, _name, false);
|
||||
PyVar _0 = getattr(__curr_class, _name, false);
|
||||
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
|
||||
// load global if attribute not found
|
||||
_0 = frame->f_globals().try_get_likely_found(_name);
|
||||
@ -217,13 +217,13 @@ __NEXT_STEP:;
|
||||
vm->NameError(_name);
|
||||
} DISPATCH()
|
||||
case OP_LOAD_METHOD:{
|
||||
PyObject* _0;
|
||||
PyVar _0;
|
||||
TOP() = get_unbound_method(TOP(), StrName(byte.arg), &_0, true, true);
|
||||
PUSH(_0);
|
||||
}DISPATCH()
|
||||
case OP_LOAD_SUBSCR:{
|
||||
PyObject* _1 = POPX(); // b
|
||||
PyObject* _0 = TOP(); // a
|
||||
PyVar _1 = POPX(); // b
|
||||
PyVar _0 = TOP(); // a
|
||||
auto _ti = _tp_info(_0);
|
||||
if(_ti->m__getitem__){
|
||||
TOP() = _ti->m__getitem__(this, _0, _1);
|
||||
@ -232,9 +232,9 @@ __NEXT_STEP:;
|
||||
}
|
||||
} DISPATCH()
|
||||
case OP_LOAD_SUBSCR_FAST:{
|
||||
PyObject* _1 = frame->_locals[byte.arg];
|
||||
PyVar _1 = frame->_locals[byte.arg];
|
||||
if(_1 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
|
||||
PyObject* _0 = TOP(); // a
|
||||
PyVar _0 = TOP(); // a
|
||||
auto _ti = _tp_info(_0);
|
||||
if(_ti->m__getitem__){
|
||||
TOP() = _ti->m__getitem__(this, _0, _1);
|
||||
@ -243,8 +243,8 @@ __NEXT_STEP:;
|
||||
}
|
||||
} DISPATCH()
|
||||
case OP_LOAD_SUBSCR_SMALL_INT:{
|
||||
PyObject* _1 = (PyObject*)(uintptr_t)byte.arg;
|
||||
PyObject* _0 = TOP(); // a
|
||||
PyVar _1 = (PyVar)(uintptr_t)byte.arg;
|
||||
PyVar _0 = TOP(); // a
|
||||
auto _ti = _tp_info(_0);
|
||||
if(_ti->m__getitem__){
|
||||
TOP() = _ti->m__getitem__(this, _0, _1);
|
||||
@ -257,9 +257,9 @@ __NEXT_STEP:;
|
||||
DISPATCH()
|
||||
case OP_STORE_NAME:{
|
||||
StrName _name(byte.arg);
|
||||
PyObject* _0 = POPX();
|
||||
PyVar _0 = POPX();
|
||||
if(frame->_callable != nullptr){
|
||||
PyObject** slot = frame->_locals.try_get_name(_name);
|
||||
PyVar* slot = frame->_locals.try_get_name(_name);
|
||||
if(slot != nullptr){
|
||||
*slot = _0; // store in locals if possible
|
||||
}else{
|
||||
@ -279,15 +279,15 @@ __NEXT_STEP:;
|
||||
frame->f_globals().set(StrName(byte.arg), POPX());
|
||||
DISPATCH()
|
||||
case OP_STORE_ATTR: {
|
||||
PyObject* _0 = TOP(); // a
|
||||
PyObject* _1 = SECOND(); // val
|
||||
PyVar _0 = TOP(); // a
|
||||
PyVar _1 = SECOND(); // val
|
||||
setattr(_0, StrName(byte.arg), _1);
|
||||
STACK_SHRINK(2);
|
||||
} DISPATCH()
|
||||
case OP_STORE_SUBSCR:{
|
||||
PyObject* _2 = POPX(); // b
|
||||
PyObject* _1 = POPX(); // a
|
||||
PyObject* _0 = POPX(); // val
|
||||
PyVar _2 = POPX(); // b
|
||||
PyVar _1 = POPX(); // a
|
||||
PyVar _0 = POPX(); // val
|
||||
auto _ti = _tp_info(_1);
|
||||
if(_ti->m__setitem__){
|
||||
_ti->m__setitem__(this, _1, _2, _0);
|
||||
@ -296,10 +296,10 @@ __NEXT_STEP:;
|
||||
}
|
||||
}DISPATCH()
|
||||
case OP_STORE_SUBSCR_FAST:{
|
||||
PyObject* _2 = frame->_locals[byte.arg]; // b
|
||||
PyVar _2 = frame->_locals[byte.arg]; // b
|
||||
if(_2 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
|
||||
PyObject* _1 = POPX(); // a
|
||||
PyObject* _0 = POPX(); // val
|
||||
PyVar _1 = POPX(); // a
|
||||
PyVar _0 = POPX(); // val
|
||||
auto _ti = _tp_info(_1);
|
||||
if(_ti->m__setitem__){
|
||||
_ti->m__setitem__(this, _1, _2, _0);
|
||||
@ -308,14 +308,14 @@ __NEXT_STEP:;
|
||||
}
|
||||
}DISPATCH()
|
||||
case OP_DELETE_FAST:{
|
||||
PyObject* _0 = frame->_locals[byte.arg];
|
||||
PyVar _0 = frame->_locals[byte.arg];
|
||||
if(_0 == PY_NULL) vm->UnboundLocalError(co->varnames[byte.arg]);
|
||||
frame->_locals[byte.arg] = PY_NULL;
|
||||
}DISPATCH()
|
||||
case OP_DELETE_NAME:{
|
||||
StrName _name(byte.arg);
|
||||
if(frame->_callable != nullptr){
|
||||
PyObject** slot = frame->_locals.try_get_name(_name);
|
||||
PyVar* slot = frame->_locals.try_get_name(_name);
|
||||
if(slot != nullptr){
|
||||
*slot = PY_NULL;
|
||||
}else{
|
||||
@ -337,12 +337,12 @@ __NEXT_STEP:;
|
||||
if(!frame->f_globals().del(_name)) vm->NameError(_name);
|
||||
}DISPATCH()
|
||||
case OP_DELETE_ATTR:{
|
||||
PyObject* _0 = POPX();
|
||||
PyVar _0 = POPX();
|
||||
delattr(_0, StrName(byte.arg));
|
||||
} DISPATCH()
|
||||
case OP_DELETE_SUBSCR:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = POPX();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = POPX();
|
||||
auto _ti = _tp_info(_0);
|
||||
if(_ti->m__delitem__){
|
||||
_ti->m__delitem__(this, _0, _1);
|
||||
@ -352,12 +352,12 @@ __NEXT_STEP:;
|
||||
}DISPATCH()
|
||||
/*****************************************/
|
||||
case OP_BUILD_LONG: {
|
||||
PyObject* _0 = builtins->attr().try_get_likely_found(pk_id_long);
|
||||
PyVar _0 = builtins->attr().try_get_likely_found(pk_id_long);
|
||||
if(_0 == nullptr) AttributeError(builtins, pk_id_long);
|
||||
TOP() = call(_0, TOP());
|
||||
} DISPATCH()
|
||||
case OP_BUILD_IMAG: {
|
||||
PyObject* _0 = builtins->attr().try_get_likely_found(pk_id_complex);
|
||||
PyVar _0 = builtins->attr().try_get_likely_found(pk_id_complex);
|
||||
if(_0 == nullptr) AttributeError(builtins, pk_id_long);
|
||||
TOP() = call(_0, VAR(0), TOP());
|
||||
} DISPATCH()
|
||||
@ -368,12 +368,12 @@ __NEXT_STEP:;
|
||||
TOP() = VAR(Bytes(p, s.size));
|
||||
} DISPATCH()
|
||||
case OP_BUILD_TUPLE:{
|
||||
PyObject* _0 = VAR(STACK_VIEW(byte.arg).to_tuple());
|
||||
PyVar _0 = VAR(STACK_VIEW(byte.arg).to_tuple());
|
||||
STACK_SHRINK(byte.arg);
|
||||
PUSH(_0);
|
||||
} DISPATCH()
|
||||
case OP_BUILD_LIST:{
|
||||
PyObject* _0 = VAR(STACK_VIEW(byte.arg).to_list());
|
||||
PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
|
||||
STACK_SHRINK(byte.arg);
|
||||
PUSH(_0);
|
||||
} DISPATCH()
|
||||
@ -382,27 +382,27 @@ __NEXT_STEP:;
|
||||
PUSH(VAR(Dict(this)));
|
||||
DISPATCH()
|
||||
}
|
||||
PyObject* _0 = VAR(STACK_VIEW(byte.arg).to_list());
|
||||
PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
|
||||
_0 = call(_t(tp_dict), _0);
|
||||
STACK_SHRINK(byte.arg);
|
||||
PUSH(_0);
|
||||
} DISPATCH()
|
||||
case OP_BUILD_SET:{
|
||||
PyObject* _0 = VAR(STACK_VIEW(byte.arg).to_list());
|
||||
PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
|
||||
_0 = call(builtins->attr(pk_id_set), _0);
|
||||
STACK_SHRINK(byte.arg);
|
||||
PUSH(_0);
|
||||
} DISPATCH()
|
||||
case OP_BUILD_SLICE:{
|
||||
PyObject* _2 = POPX(); // step
|
||||
PyObject* _1 = POPX(); // stop
|
||||
PyObject* _0 = POPX(); // start
|
||||
PyVar _2 = POPX(); // step
|
||||
PyVar _1 = POPX(); // stop
|
||||
PyVar _0 = POPX(); // start
|
||||
PUSH(VAR(Slice(_0, _1, _2)));
|
||||
} DISPATCH()
|
||||
case OP_BUILD_STRING: {
|
||||
SStream ss;
|
||||
ArgsView view = STACK_VIEW(byte.arg);
|
||||
for(PyObject* obj : view) ss << py_str(obj);
|
||||
for(PyVar obj : view) ss << py_str(obj);
|
||||
STACK_SHRINK(byte.arg);
|
||||
PUSH(VAR(ss.str()));
|
||||
} DISPATCH()
|
||||
@ -412,7 +412,7 @@ __NEXT_STEP:;
|
||||
List list;
|
||||
__unpack_as_list(STACK_VIEW(byte.arg), list);
|
||||
STACK_SHRINK(byte.arg);
|
||||
PyObject* _0 = VAR(Tuple(std::move(list)));
|
||||
PyVar _0 = VAR(Tuple(std::move(list)));
|
||||
PUSH(_0);
|
||||
} DISPATCH()
|
||||
case OP_BUILD_LIST_UNPACK: {
|
||||
@ -420,7 +420,7 @@ __NEXT_STEP:;
|
||||
List list;
|
||||
__unpack_as_list(STACK_VIEW(byte.arg), list);
|
||||
STACK_SHRINK(byte.arg);
|
||||
PyObject* _0 = VAR(std::move(list));
|
||||
PyVar _0 = VAR(std::move(list));
|
||||
PUSH(_0);
|
||||
} DISPATCH()
|
||||
case OP_BUILD_DICT_UNPACK: {
|
||||
@ -428,7 +428,7 @@ __NEXT_STEP:;
|
||||
Dict dict(this);
|
||||
__unpack_as_dict(STACK_VIEW(byte.arg), dict);
|
||||
STACK_SHRINK(byte.arg);
|
||||
PyObject* _0 = VAR(std::move(dict));
|
||||
PyVar _0 = VAR(std::move(dict));
|
||||
PUSH(_0);
|
||||
} DISPATCH()
|
||||
case OP_BUILD_SET_UNPACK: {
|
||||
@ -436,7 +436,7 @@ __NEXT_STEP:;
|
||||
List list;
|
||||
__unpack_as_list(STACK_VIEW(byte.arg), list);
|
||||
STACK_SHRINK(byte.arg);
|
||||
PyObject* _0 = VAR(std::move(list));
|
||||
PyVar _0 = VAR(std::move(list));
|
||||
_0 = call(builtins->attr(pk_id_set), _0);
|
||||
PUSH(_0);
|
||||
} DISPATCH()
|
||||
@ -446,152 +446,152 @@ __NEXT_STEP:;
|
||||
if(_ti->m##func){ \
|
||||
TOP() = _ti->m##func(this, _0, _1); \
|
||||
}else{ \
|
||||
PyObject* self; \
|
||||
PyObject* _2 = get_unbound_method(_0, func, &self, false); \
|
||||
PyVar self; \
|
||||
PyVar _2 = get_unbound_method(_0, func, &self, false); \
|
||||
if(_2 != nullptr) TOP() = call_method(self, _2, _1); \
|
||||
else TOP() = NotImplemented; \
|
||||
}
|
||||
|
||||
#define BINARY_OP_RSPECIAL(op, func) \
|
||||
if(TOP() == NotImplemented){ \
|
||||
PyObject* self; \
|
||||
PyObject* _2 = get_unbound_method(_1, func, &self, false); \
|
||||
PyVar self; \
|
||||
PyVar _2 = get_unbound_method(_1, func, &self, false); \
|
||||
if(_2 != nullptr) TOP() = call_method(self, _2, _0); \
|
||||
else BinaryOptError(op, _0, _1); \
|
||||
if(TOP() == NotImplemented) BinaryOptError(op, _0, _1); \
|
||||
}
|
||||
|
||||
case OP_BINARY_TRUEDIV:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__truediv__);
|
||||
if(TOP() == NotImplemented) BinaryOptError("/", _0, _1);
|
||||
} DISPATCH()
|
||||
case OP_BINARY_POW:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__pow__);
|
||||
if(TOP() == NotImplemented) BinaryOptError("**", _0, _1);
|
||||
} DISPATCH()
|
||||
case OP_BINARY_ADD:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_OP(+)
|
||||
const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__add__);
|
||||
BINARY_OP_RSPECIAL("+", __radd__);
|
||||
} DISPATCH()
|
||||
case OP_BINARY_SUB:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_OP(-)
|
||||
const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__sub__);
|
||||
BINARY_OP_RSPECIAL("-", __rsub__);
|
||||
} DISPATCH()
|
||||
case OP_BINARY_MUL:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_OP(*)
|
||||
const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__mul__);
|
||||
BINARY_OP_RSPECIAL("*", __rmul__);
|
||||
} DISPATCH()
|
||||
case OP_BINARY_FLOORDIV:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_DIV_OP(/)
|
||||
const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__floordiv__);
|
||||
if(TOP() == NotImplemented) BinaryOptError("//", _0, _1);
|
||||
} DISPATCH()
|
||||
case OP_BINARY_MOD:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_DIV_OP(%)
|
||||
const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__mod__);
|
||||
if(TOP() == NotImplemented) BinaryOptError("%", _0, _1);
|
||||
} DISPATCH()
|
||||
case OP_COMPARE_LT:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_OP(<)
|
||||
TOP() = VAR(py_lt(_0, _1));
|
||||
} DISPATCH()
|
||||
case OP_COMPARE_LE:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_OP(<=)
|
||||
TOP() = VAR(py_le(_0, _1));
|
||||
} DISPATCH()
|
||||
case OP_COMPARE_EQ:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
TOP() = VAR(py_eq(_0, _1));
|
||||
} DISPATCH()
|
||||
case OP_COMPARE_NE:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
TOP() = VAR(py_ne(_0, _1));
|
||||
} DISPATCH()
|
||||
case OP_COMPARE_GT:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_OP(>)
|
||||
TOP() = VAR(py_gt(_0, _1));
|
||||
} DISPATCH()
|
||||
case OP_COMPARE_GE:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_OP(>=)
|
||||
TOP() = VAR(py_ge(_0, _1));
|
||||
} DISPATCH()
|
||||
case OP_BITWISE_LSHIFT:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_OP(<<)
|
||||
const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__lshift__);
|
||||
if(TOP() == NotImplemented) BinaryOptError("<<", _0, _1);
|
||||
} DISPATCH()
|
||||
case OP_BITWISE_RSHIFT:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_OP(>>)
|
||||
const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__rshift__);
|
||||
if(TOP() == NotImplemented) BinaryOptError(">>", _0, _1);
|
||||
} DISPATCH()
|
||||
case OP_BITWISE_AND:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_OP(&)
|
||||
const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__and__);
|
||||
if(TOP() == NotImplemented) BinaryOptError("&", _0, _1);
|
||||
} DISPATCH()
|
||||
case OP_BITWISE_OR:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_OP(|)
|
||||
const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__or__);
|
||||
if(TOP() == NotImplemented) BinaryOptError("|", _0, _1);
|
||||
} DISPATCH()
|
||||
case OP_BITWISE_XOR:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
PREDICT_INT_OP(^)
|
||||
const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__xor__);
|
||||
if(TOP() == NotImplemented) BinaryOptError("^", _0, _1);
|
||||
} DISPATCH()
|
||||
case OP_BINARY_MATMUL:{
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _1 = POPX();
|
||||
PyVar _0 = TOP();
|
||||
const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__matmul__);
|
||||
if(TOP() == NotImplemented) BinaryOptError("@", _0, _1);
|
||||
@ -602,14 +602,14 @@ __NEXT_STEP:;
|
||||
#undef PREDICT_INT_OP
|
||||
|
||||
case OP_IS_OP:{
|
||||
PyObject* _1 = POPX(); // rhs
|
||||
PyObject* _0 = TOP(); // lhs
|
||||
PyVar _1 = POPX(); // rhs
|
||||
PyVar _0 = TOP(); // lhs
|
||||
TOP() = VAR(static_cast<bool>((_0==_1) ^ byte.arg));
|
||||
} DISPATCH()
|
||||
case OP_CONTAINS_OP:{
|
||||
// a in b -> b __contains__ a
|
||||
auto _ti = _tp_info(TOP());
|
||||
PyObject* _0;
|
||||
PyVar _0;
|
||||
if(_ti->m__contains__){
|
||||
_0 = _ti->m__contains__(this, TOP(), SECOND());
|
||||
}else{
|
||||
@ -662,7 +662,7 @@ __NEXT_STEP:;
|
||||
} DISPATCH()
|
||||
/*****************************************/
|
||||
case OP_FSTRING_EVAL:{
|
||||
PyObject* _0 = co->consts[byte.arg];
|
||||
PyVar _0 = co->consts[byte.arg];
|
||||
std::string_view string = CAST(Str&, _0).sv();
|
||||
auto it = __cached_codes.find(string);
|
||||
CodeObject_ code;
|
||||
@ -680,7 +680,7 @@ __NEXT_STEP:;
|
||||
DISPATCH()
|
||||
case OP_CALL:{
|
||||
if(heap._should_auto_collect()) heap._auto_collect();
|
||||
PyObject* _0 = vectorcall(
|
||||
PyVar _0 = vectorcall(
|
||||
byte.arg & 0xFF, // ARGC
|
||||
(byte.arg>>8) & 0xFF, // KWARGC
|
||||
true
|
||||
@ -693,15 +693,15 @@ __NEXT_STEP:;
|
||||
} DISPATCH()
|
||||
case OP_CALL_TP:{
|
||||
if(heap._should_auto_collect()) heap._auto_collect();
|
||||
PyObject* _0;
|
||||
PyObject* _1;
|
||||
PyObject* _2;
|
||||
PyVar _0;
|
||||
PyVar _1;
|
||||
PyVar _2;
|
||||
// [callable, <self>, args: tuple, kwargs: dict | NULL]
|
||||
if(byte.arg){
|
||||
_2 = POPX();
|
||||
_1 = POPX();
|
||||
for(PyObject* obj: _CAST(Tuple&, _1)) PUSH(obj);
|
||||
_CAST(Dict&, _2).apply([this](PyObject* k, PyObject* v){
|
||||
for(PyVar obj: _CAST(Tuple&, _1)) PUSH(obj);
|
||||
_CAST(Dict&, _2).apply([this](PyVar k, PyVar v){
|
||||
PUSH(VAR(StrName(CAST(Str&, k)).index));
|
||||
PUSH(v);
|
||||
});
|
||||
@ -713,7 +713,7 @@ __NEXT_STEP:;
|
||||
}else{
|
||||
// no **kwargs
|
||||
_1 = POPX();
|
||||
for(PyObject* obj: _CAST(Tuple&, _1)) PUSH(obj);
|
||||
for(PyVar obj: _CAST(Tuple&, _1)) PUSH(obj);
|
||||
_0 = vectorcall(
|
||||
_CAST(Tuple&, _1).size(), // ARGC
|
||||
0, // KWARGC
|
||||
@ -727,7 +727,7 @@ __NEXT_STEP:;
|
||||
PUSH(_0);
|
||||
} DISPATCH()
|
||||
case OP_RETURN_VALUE:{
|
||||
PyObject* _0 = byte.arg == BC_NOARG ? POPX() : None;
|
||||
PyVar _0 = byte.arg == BC_NOARG ? POPX() : None;
|
||||
__pop_frame();
|
||||
if(frame == base_frame){ // [ frameBase<- ]
|
||||
return _0;
|
||||
@ -741,16 +741,16 @@ __NEXT_STEP:;
|
||||
return PY_OP_YIELD;
|
||||
/*****************************************/
|
||||
case OP_LIST_APPEND:{
|
||||
PyObject* _0 = POPX();
|
||||
PyVar _0 = POPX();
|
||||
PK_OBJ_GET(List, SECOND()).push_back(_0);
|
||||
} DISPATCH()
|
||||
case OP_DICT_ADD: {
|
||||
PyObject* _0 = POPX();
|
||||
PyVar _0 = POPX();
|
||||
const Tuple& t = PK_OBJ_GET(Tuple, _0);
|
||||
PK_OBJ_GET(Dict, SECOND()).set(t[0], t[1]);
|
||||
} DISPATCH()
|
||||
case OP_SET_ADD:{
|
||||
PyObject* _0 = POPX();
|
||||
PyVar _0 = POPX();
|
||||
call_method(SECOND(), pk_id_add, _0);
|
||||
} DISPATCH()
|
||||
/*****************************************/
|
||||
@ -758,7 +758,7 @@ __NEXT_STEP:;
|
||||
TOP() = py_negate(TOP());
|
||||
DISPATCH()
|
||||
case OP_UNARY_NOT:{
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _0 = TOP();
|
||||
if(_0==True) TOP()=False;
|
||||
else if(_0==False) TOP()=True;
|
||||
else TOP() = VAR(!py_bool(_0));
|
||||
@ -767,7 +767,7 @@ __NEXT_STEP:;
|
||||
TOP() = VAR(StarWrapper(byte.arg, TOP()));
|
||||
DISPATCH()
|
||||
case OP_UNARY_INVERT:{
|
||||
PyObject* _0;
|
||||
PyVar _0;
|
||||
auto _ti = _tp_info(TOP());
|
||||
if(_ti->m__invert__) _0 = _ti->m__invert__(this, TOP());
|
||||
else _0 = call_method(TOP(), __invert__);
|
||||
@ -778,12 +778,12 @@ __NEXT_STEP:;
|
||||
TOP() = py_iter(TOP());
|
||||
DISPATCH()
|
||||
case OP_FOR_ITER:{
|
||||
PyObject* _0 = py_next(TOP());
|
||||
PyVar _0 = py_next(TOP());
|
||||
if(_0 == StopIteration) frame->loop_break(&s_data, co);
|
||||
else PUSH(_0);
|
||||
} DISPATCH()
|
||||
case OP_FOR_ITER_STORE_FAST:{
|
||||
PyObject* _0 = py_next(TOP());
|
||||
PyVar _0 = py_next(TOP());
|
||||
if(_0 == StopIteration){
|
||||
frame->loop_break(&s_data, co);
|
||||
}else{
|
||||
@ -791,7 +791,7 @@ __NEXT_STEP:;
|
||||
}
|
||||
} DISPATCH()
|
||||
case OP_FOR_ITER_STORE_GLOBAL:{
|
||||
PyObject* _0 = py_next(TOP());
|
||||
PyVar _0 = py_next(TOP());
|
||||
if(_0 == StopIteration){
|
||||
frame->loop_break(&s_data, co);
|
||||
}else{
|
||||
@ -799,7 +799,7 @@ __NEXT_STEP:;
|
||||
}
|
||||
} DISPATCH()
|
||||
case OP_FOR_ITER_YIELD_VALUE:{
|
||||
PyObject* _0 = py_next(TOP());
|
||||
PyVar _0 = py_next(TOP());
|
||||
if(_0 == StopIteration){
|
||||
frame->loop_break(&s_data, co);
|
||||
}else{
|
||||
@ -808,7 +808,7 @@ __NEXT_STEP:;
|
||||
}
|
||||
} DISPATCH()
|
||||
case OP_FOR_ITER_UNPACK:{
|
||||
PyObject* _0 = TOP();
|
||||
PyVar _0 = TOP();
|
||||
const PyTypeInfo* _ti = _tp_info(_0);
|
||||
if(_ti->m__next__){
|
||||
unsigned n = _ti->m__next__(this, _0);
|
||||
@ -837,17 +837,17 @@ __NEXT_STEP:;
|
||||
} DISPATCH()
|
||||
/*****************************************/
|
||||
case OP_IMPORT_PATH:{
|
||||
PyObject* _0 = co->consts[byte.arg];
|
||||
PyVar _0 = co->consts[byte.arg];
|
||||
PUSH(py_import(CAST(Str&, _0)));
|
||||
} DISPATCH()
|
||||
case OP_POP_IMPORT_STAR: {
|
||||
PyObject* _0 = POPX(); // pop the module
|
||||
PyObject* _1 = _0->attr().try_get(__all__);
|
||||
PyVar _0 = POPX(); // pop the module
|
||||
PyVar _1 = _0->attr().try_get(__all__);
|
||||
StrName _name;
|
||||
if(_1 != nullptr){
|
||||
for(PyObject* key: CAST(List&, _1)){
|
||||
for(PyVar key: CAST(List&, _1)){
|
||||
_name = StrName::get(CAST(Str&, key).sv());
|
||||
PyObject* value = _0->attr().try_get_likely_found(_name);
|
||||
PyVar value = _0->attr().try_get_likely_found(_name);
|
||||
if(value == nullptr){
|
||||
ImportError(_S("cannot import name ", _name.escape()));
|
||||
}else{
|
||||
@ -868,9 +868,9 @@ __NEXT_STEP:;
|
||||
} DISPATCH()
|
||||
case OP_UNPACK_EX: {
|
||||
auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!!
|
||||
PyObject* _0 = py_iter(POPX());
|
||||
PyVar _0 = py_iter(POPX());
|
||||
const PyTypeInfo* _ti = _tp_info(_0);
|
||||
PyObject* _1;
|
||||
PyVar _1;
|
||||
for(int i=0; i<byte.arg; i++){
|
||||
_1 = _py_next(_ti, _0);
|
||||
if(_1 == StopIteration) ValueError("not enough values to unpack");
|
||||
@ -887,7 +887,7 @@ __NEXT_STEP:;
|
||||
/*****************************************/
|
||||
case OP_BEGIN_CLASS:{
|
||||
StrName _name(byte.arg);
|
||||
PyObject* _0 = POPX(); // super
|
||||
PyVar _0 = POPX(); // super
|
||||
if(_0 == None) _0 = _t(tp_object);
|
||||
check_type(_0, tp_type);
|
||||
__curr_class = new_type_object(frame->_module, _name, PK_OBJ_GET(Type, _0));
|
||||
@ -907,7 +907,7 @@ __NEXT_STEP:;
|
||||
case OP_STORE_CLASS_ATTR:{
|
||||
PK_ASSERT(__curr_class != nullptr);
|
||||
StrName _name(byte.arg);
|
||||
PyObject* _0 = POPX();
|
||||
PyVar _0 = POPX();
|
||||
if(is_type(_0, tp_function)){
|
||||
PK_OBJ_GET(Function, _0)._class = __curr_class;
|
||||
}
|
||||
@ -935,9 +935,9 @@ __NEXT_STEP:;
|
||||
DISPATCH()
|
||||
/*****************************************/
|
||||
case OP_EXCEPTION_MATCH: {
|
||||
PyObject* assumed_type = POPX();
|
||||
PyVar assumed_type = POPX();
|
||||
check_type(assumed_type, tp_type);
|
||||
PyObject* e_obj = TOP();
|
||||
PyVar e_obj = TOP();
|
||||
bool ok = isinstance(e_obj, PK_OBJ_GET(Type, assumed_type));
|
||||
PUSH(VAR(ok));
|
||||
} DISPATCH()
|
||||
@ -963,30 +963,30 @@ __NEXT_STEP:;
|
||||
case OP_POP_EXCEPTION: __last_exception = POPX(); DISPATCH()
|
||||
/*****************************************/
|
||||
case OP_FORMAT_STRING: {
|
||||
PyObject* _0 = POPX();
|
||||
PyVar _0 = POPX();
|
||||
const Str& spec = CAST(Str&, co->consts[byte.arg]);
|
||||
PUSH(__format_object(_0, spec));
|
||||
} DISPATCH()
|
||||
/*****************************************/
|
||||
case OP_INC_FAST:{
|
||||
PyObject** p = &frame->_locals[byte.arg];
|
||||
PyVar* p = &frame->_locals[byte.arg];
|
||||
if(*p == PY_NULL) vm->NameError(co->varnames[byte.arg]);
|
||||
*p = VAR(CAST(i64, *p) + 1);
|
||||
} DISPATCH()
|
||||
case OP_DEC_FAST:{
|
||||
PyObject** p = &frame->_locals[byte.arg];
|
||||
PyVar* p = &frame->_locals[byte.arg];
|
||||
if(*p == PY_NULL) vm->NameError(co->varnames[byte.arg]);
|
||||
*p = VAR(CAST(i64, *p) - 1);
|
||||
} DISPATCH()
|
||||
case OP_INC_GLOBAL:{
|
||||
StrName _name(byte.arg);
|
||||
PyObject** p = frame->f_globals().try_get_2_likely_found(_name);
|
||||
PyVar* p = frame->f_globals().try_get_2_likely_found(_name);
|
||||
if(p == nullptr) vm->NameError(_name);
|
||||
*p = VAR(CAST(i64, *p) + 1);
|
||||
} DISPATCH()
|
||||
case OP_DEC_GLOBAL:{
|
||||
StrName _name(byte.arg);
|
||||
PyObject** p = frame->f_globals().try_get_2_likely_found(_name);
|
||||
PyVar* p = frame->f_globals().try_get_2_likely_found(_name);
|
||||
if(p == nullptr) vm->NameError(_name);
|
||||
*p = VAR(CAST(i64, *p) - 1);
|
||||
} DISPATCH()
|
||||
@ -998,7 +998,7 @@ __NEXT_STEP:;
|
||||
}catch(HandledException){
|
||||
continue;
|
||||
}catch(UnhandledException){
|
||||
PyObject* e_obj = POPX();
|
||||
PyVar e_obj = POPX();
|
||||
Exception& _e = PK_OBJ_GET(Exception, e_obj);
|
||||
bool is_base_frame_to_be_popped = frame == base_frame;
|
||||
__pop_frame();
|
||||
|
32
src/cffi.cpp
32
src/cffi.cpp
@ -2,25 +2,25 @@
|
||||
|
||||
namespace pkpy{
|
||||
|
||||
void VoidP::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||
void VoidP::_register(VM* vm, PyVar mod, PyVar type){
|
||||
vm->bind_func(type, __new__, 2, [](VM* vm, ArgsView args){
|
||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||
i64 addr = CAST(i64, args[1]);
|
||||
return vm->heap.gcnew<VoidP>(cls, reinterpret_cast<void*>(addr));
|
||||
});
|
||||
|
||||
vm->bind__hash__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
||||
vm->bind__hash__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj){
|
||||
VoidP& self = PK_OBJ_GET(VoidP, obj);
|
||||
return reinterpret_cast<i64>(self.ptr);
|
||||
});
|
||||
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj) -> Str{
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj) -> Str{
|
||||
VoidP& self = PK_OBJ_GET(VoidP, obj);
|
||||
return _S("<void* at ", self.hex(), ">");
|
||||
});
|
||||
|
||||
#define BIND_CMP(name, op) \
|
||||
vm->bind##name(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){ \
|
||||
vm->bind##name(PK_OBJ_GET(Type, type), [](VM* vm, PyVar lhs, PyVar rhs){ \
|
||||
if(!vm->isinstance(rhs, vm->_tp_user<VoidP>())) return vm->NotImplemented; \
|
||||
void* _0 = PK_OBJ_GET(VoidP, lhs).ptr; \
|
||||
void* _1 = PK_OBJ_GET(VoidP, rhs).ptr; \
|
||||
@ -37,7 +37,7 @@ namespace pkpy{
|
||||
}
|
||||
|
||||
|
||||
void Struct::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||
void Struct::_register(VM* vm, PyVar mod, PyVar type){
|
||||
vm->bind_func(type, __new__, 2, [](VM* vm, ArgsView args){
|
||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||
int size = CAST(int, args[1]);
|
||||
@ -72,7 +72,7 @@ namespace pkpy{
|
||||
return vm->new_user_object<Struct>(std::move(buffer));
|
||||
}, {}, BindType::STATICMETHOD);
|
||||
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj){
|
||||
Struct& self = _CAST(Struct&, obj);
|
||||
SStream ss;
|
||||
ss << "<struct object of " << self.size << " bytes>";
|
||||
@ -94,7 +94,7 @@ namespace pkpy{
|
||||
return vm->heap.gcnew<Struct>(vm->_tp(args[0]), self);
|
||||
});
|
||||
|
||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){
|
||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar lhs, PyVar rhs){
|
||||
Struct& self = _CAST(Struct&, lhs);
|
||||
if(!vm->is_user_type<Struct>(rhs)) return vm->NotImplemented;
|
||||
Struct& other = _CAST(Struct&, rhs);
|
||||
@ -134,7 +134,7 @@ namespace pkpy{
|
||||
}
|
||||
|
||||
void add_module_c(VM* vm){
|
||||
PyObject* mod = vm->new_module("c");
|
||||
PyVar mod = vm->new_module("c");
|
||||
|
||||
vm->bind_func(mod, "malloc", 1, [](VM* vm, ArgsView args){
|
||||
i64 size = CAST(i64, args[0]);
|
||||
@ -187,7 +187,7 @@ void add_module_c(VM* vm){
|
||||
return vm->heap.gcnew<VoidP>(args[0]->type, value);
|
||||
});
|
||||
|
||||
PyObject* type;
|
||||
PyVar type;
|
||||
Type type_t;
|
||||
|
||||
#define BIND_PRIMITIVE(T, CNAME) \
|
||||
@ -210,31 +210,31 @@ void add_module_c(VM* vm){
|
||||
*target = val; \
|
||||
return vm->None; \
|
||||
}); \
|
||||
vm->bind__getitem__(type_t, [](VM* vm, PyObject* obj, PyObject* index){ \
|
||||
vm->bind__getitem__(type_t, [](VM* vm, PyVar obj, PyVar index){ \
|
||||
VoidP& voidp = PK_OBJ_GET(VoidP, obj); \
|
||||
i64 offset = CAST(i64, index); \
|
||||
T* target = (T*)voidp.ptr; \
|
||||
return VAR(target[offset]); \
|
||||
}); \
|
||||
vm->bind__setitem__(type_t, [](VM* vm, PyObject* obj, PyObject* index, PyObject* value){ \
|
||||
vm->bind__setitem__(type_t, [](VM* vm, PyVar obj, PyVar index, PyVar value){ \
|
||||
VoidP& voidp = PK_OBJ_GET(VoidP, obj); \
|
||||
i64 offset = CAST(i64, index); \
|
||||
T* target = (T*)voidp.ptr; \
|
||||
target[offset] = CAST(T, value); \
|
||||
}); \
|
||||
vm->bind__add__(type_t, [](VM* vm, PyObject* lhs, PyObject* rhs){ \
|
||||
vm->bind__add__(type_t, [](VM* vm, PyVar lhs, PyVar rhs){ \
|
||||
VoidP& voidp = PK_OBJ_GET(VoidP, lhs); \
|
||||
i64 offset = CAST(i64, rhs); \
|
||||
T* target = (T*)voidp.ptr; \
|
||||
return vm->heap.gcnew<VoidP>(lhs->type, target + offset); \
|
||||
}); \
|
||||
vm->bind__sub__(type_t, [](VM* vm, PyObject* lhs, PyObject* rhs){ \
|
||||
vm->bind__sub__(type_t, [](VM* vm, PyVar lhs, PyVar rhs){ \
|
||||
VoidP& voidp = PK_OBJ_GET(VoidP, lhs); \
|
||||
i64 offset = CAST(i64, rhs); \
|
||||
T* target = (T*)voidp.ptr; \
|
||||
return vm->heap.gcnew<VoidP>(lhs->type, target - offset); \
|
||||
}); \
|
||||
vm->bind__repr__(type_t, [](VM* vm, PyObject* obj) -> Str{ \
|
||||
vm->bind__repr__(type_t, [](VM* vm, PyVar obj) -> Str{ \
|
||||
VoidP& self = _CAST(VoidP&, obj); \
|
||||
return _S("<", CNAME, "* at ", self.hex(), ">"); \
|
||||
}); \
|
||||
@ -255,7 +255,7 @@ void add_module_c(VM* vm){
|
||||
|
||||
#undef BIND_PRIMITIVE
|
||||
|
||||
PyObject* char_p_t = mod->attr("char_p");
|
||||
PyVar char_p_t = mod->attr("char_p");
|
||||
vm->bind(char_p_t, "read_string(self) -> str", [](VM* vm, ArgsView args){
|
||||
VoidP& voidp = PK_OBJ_GET(VoidP, args[0]);
|
||||
const char* target = (const char*)voidp.ptr;
|
||||
@ -272,7 +272,7 @@ void add_module_c(VM* vm){
|
||||
});
|
||||
}
|
||||
|
||||
PyObject* from_void_p(VM* vm, void* p){
|
||||
PyVar from_void_p(VM* vm, void* p){
|
||||
return vm->new_user_object<VoidP>(p);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ namespace pkpy{
|
||||
}
|
||||
|
||||
void CodeObject::_gc_mark() const {
|
||||
for(PyObject* v : consts) PK_OBJ_MARK(v);
|
||||
for(PyVar v : consts) PK_OBJ_MARK(v);
|
||||
for(auto& decl: func_decls) decl->_gc_mark();
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ namespace pkpy{
|
||||
void _obj_gc_mark() override {}
|
||||
};
|
||||
|
||||
PyObject* const PY_NULL = new PySignalObject();
|
||||
PyObject* const PY_OP_CALL = new PySignalObject();
|
||||
PyObject* const PY_OP_YIELD = new PySignalObject();
|
||||
PyVar const PY_NULL = new PySignalObject();
|
||||
PyVar const PY_OP_CALL = new PySignalObject();
|
||||
PyVar const PY_OP_YIELD = new PySignalObject();
|
||||
} // namespace pkpy
|
@ -67,7 +67,7 @@ namespace pkpy
|
||||
});
|
||||
// gets the item at the given index, if index is negative, it will be treated as index + len(deque)
|
||||
// if the index is out of range, IndexError will be thrown --> required for [] operator
|
||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0, PyObject* _1)
|
||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0, PyVar _1)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, _0);
|
||||
i64 index = CAST(i64, _1);
|
||||
@ -76,7 +76,7 @@ namespace pkpy
|
||||
});
|
||||
// sets the item at the given index, if index is negative, it will be treated as index + len(deque)
|
||||
// if the index is out of range, IndexError will be thrown --> required for [] operator
|
||||
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0, PyObject* _1, PyObject* _2)
|
||||
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0, PyVar _1, PyVar _2)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque&, _0);
|
||||
i64 index = CAST(i64, _1);
|
||||
@ -85,7 +85,7 @@ namespace pkpy
|
||||
});
|
||||
// erases the item at the given index, if index is negative, it will be treated as index + len(deque)
|
||||
// if the index is out of range, IndexError will be thrown --> required for [] operator
|
||||
vm->bind__delitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0, PyObject* _1)
|
||||
vm->bind__delitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0, PyVar _1)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque&, _0);
|
||||
i64 index = CAST(i64, _1);
|
||||
@ -93,19 +93,19 @@ namespace pkpy
|
||||
self.dequeItems.erase(self.dequeItems.begin() + index);
|
||||
});
|
||||
|
||||
vm->bind__len__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0)
|
||||
vm->bind__len__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque&, _0);
|
||||
return (i64)self.dequeItems.size();
|
||||
});
|
||||
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0)
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, _0);
|
||||
return vm->new_user_object<PyDequeIter>(_0, self.dequeItems.begin(), self.dequeItems.end());
|
||||
});
|
||||
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0) -> Str
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0) -> Str
|
||||
{
|
||||
if(vm->_repr_recursion_set.count(_0)) return "[...]";
|
||||
const PyDeque &self = _CAST(PyDeque&, _0);
|
||||
@ -123,7 +123,7 @@ namespace pkpy
|
||||
});
|
||||
|
||||
// enables comparison between two deques, == and != are supported
|
||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0, PyObject* _1)
|
||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0, PyVar _1)
|
||||
{
|
||||
const PyDeque &self = _CAST(PyDeque&, _0);
|
||||
if(!vm->is_user_type<PyDeque>(_0)) return vm->NotImplemented;
|
||||
@ -444,7 +444,7 @@ namespace pkpy
|
||||
/// @param back if true, pop from the back of the deque
|
||||
/// @param item if front and back is not set, remove the first occurrence of item from the deque
|
||||
/// @param vm is needed for the py_eq
|
||||
/// @return PyObject* if front or back is set, this is a pop operation and we return a PyObject*, if front and back are not set, this is a remove operation and we return the removed item or nullptr
|
||||
/// @return PyVar if front or back is set, this is a pop operation and we return a PyVar, if front and back are not set, this is a remove operation and we return the removed item or nullptr
|
||||
PyObject *PyDeque::popObj(bool front, bool back, PyObject *item, VM *vm)
|
||||
{
|
||||
// error handling
|
||||
@ -452,7 +452,7 @@ namespace pkpy
|
||||
throw std::runtime_error("both front and back are set"); // this should never happen
|
||||
if (front || back)
|
||||
{
|
||||
// front or back is set, we don't care about item, this is a pop operation and we return a PyObject*
|
||||
// front or back is set, we don't care about item, this is a pop operation and we return a PyVar
|
||||
if (this->dequeItems.empty())
|
||||
throw std::runtime_error("pop from an empty deque"); // shouldn't happen
|
||||
PyObject *obj;
|
||||
|
@ -1124,7 +1124,7 @@ __EAT_DOTS_END:
|
||||
break;
|
||||
case 2: {
|
||||
consume(TK("="));
|
||||
PyObject* value = read_literal();
|
||||
PyVar value = read_literal();
|
||||
if(value == nullptr){
|
||||
SyntaxError(Str("default argument must be a literal"));
|
||||
}
|
||||
@ -1153,7 +1153,7 @@ __EAT_DOTS_END:
|
||||
|
||||
decl->docstring = nullptr;
|
||||
if(decl->code->codes.size()>=2 && decl->code->codes[0].op == OP_LOAD_CONST && decl->code->codes[1].op == OP_POP_TOP){
|
||||
PyObject* c = decl->code->consts[decl->code->codes[0].arg];
|
||||
PyVar c = decl->code->consts[decl->code->codes[0].arg];
|
||||
if(is_type(c, vm->tp_str)){
|
||||
decl->code->codes[0].op = OP_NO_OP;
|
||||
decl->code->codes[1].op = OP_NO_OP;
|
||||
@ -1173,8 +1173,8 @@ __EAT_DOTS_END:
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* Compiler::to_object(const TokenValue& value){
|
||||
PyObject* obj = nullptr;
|
||||
PyVar Compiler::to_object(const TokenValue& value){
|
||||
PyVar obj = nullptr;
|
||||
if(std::holds_alternative<i64>(value)){
|
||||
obj = VAR(std::get<i64>(value));
|
||||
}
|
||||
@ -1188,12 +1188,12 @@ __EAT_DOTS_END:
|
||||
return obj;
|
||||
}
|
||||
|
||||
PyObject* Compiler::read_literal(){
|
||||
PyVar Compiler::read_literal(){
|
||||
advance();
|
||||
switch(prev().type){
|
||||
case TK("-"): {
|
||||
consume(TK("@num"));
|
||||
PyObject* val = to_object(prev().value);
|
||||
PyVar val = to_object(prev().value);
|
||||
return vm->py_negate(val);
|
||||
}
|
||||
case TK("@num"): return to_object(prev().value);
|
||||
@ -1373,7 +1373,7 @@ __EAT_DOTS_END:
|
||||
|
||||
// TODO: refactor this
|
||||
void Lexer::throw_err(StrName type, Str msg, int lineno, const char* cursor){
|
||||
PyObject* e_obj = vm->call(vm->builtins->attr(type), VAR(msg));
|
||||
PyVar e_obj = vm->call(vm->builtins->attr(type), VAR(msg));
|
||||
Exception& e = PK_OBJ_GET(Exception, e_obj);
|
||||
e.st_push(src, lineno, cursor, "");
|
||||
throw e;
|
||||
|
@ -3,7 +3,7 @@
|
||||
namespace pkpy{
|
||||
|
||||
void add_module_csv(VM *vm){
|
||||
PyObject* mod = vm->new_module("csv");
|
||||
PyVar mod = vm->new_module("csv");
|
||||
|
||||
vm->bind(mod, "reader(csvfile: list[str]) -> list[list]", [](VM* vm, ArgsView args){
|
||||
const List& csvfile = CAST(List&, args[0]);
|
||||
@ -67,8 +67,8 @@ __NEXT_LINE:
|
||||
});
|
||||
|
||||
vm->bind(mod, "DictReader(csvfile: list[str]) -> list[dict]", [](VM* vm, ArgsView args){
|
||||
PyObject* csv_reader = vm->_modules["csv"]->attr("reader");
|
||||
PyObject* ret_obj = vm->call(csv_reader, args[0]);
|
||||
PyVar csv_reader = vm->_modules["csv"]->attr("reader");
|
||||
PyVar ret_obj = vm->call(csv_reader, args[0]);
|
||||
const List& ret = CAST(List&, ret_obj);
|
||||
if(ret.size() == 0){
|
||||
vm->ValueError("empty csvfile");
|
||||
|
@ -4,11 +4,11 @@ namespace pkpy{
|
||||
|
||||
static void patch__init__(VM* vm, Type cls){
|
||||
vm->bind(vm->_t(cls), "__init__(self, *args, **kwargs)", [](VM* vm, ArgsView _view){
|
||||
PyObject* self = _view[0];
|
||||
PyVar self = _view[0];
|
||||
const Tuple& args = CAST(Tuple&, _view[1]);
|
||||
const Dict& kwargs_ = CAST(Dict&, _view[2]);
|
||||
NameDict kwargs;
|
||||
kwargs_.apply([&](PyObject* k, PyObject* v){
|
||||
kwargs_.apply([&](PyVar k, PyVar v){
|
||||
kwargs.set(CAST(Str&, k), v);
|
||||
});
|
||||
|
||||
@ -45,7 +45,7 @@ static void patch__init__(VM* vm, Type cls){
|
||||
}
|
||||
|
||||
static void patch__repr__(VM* vm, Type cls){
|
||||
vm->bind__repr__(cls, [](VM* vm, PyObject* _0) -> Str{
|
||||
vm->bind__repr__(cls, [](VM* vm, PyVar _0) -> Str{
|
||||
const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0)];
|
||||
const auto& fields = cls_info->annotated_fields;
|
||||
const NameDict& obj_d = _0->attr();
|
||||
@ -63,13 +63,13 @@ static void patch__repr__(VM* vm, Type cls){
|
||||
}
|
||||
|
||||
static void patch__eq__(VM* vm, Type cls){
|
||||
vm->bind__eq__(cls, [](VM* vm, PyObject* _0, PyObject* _1){
|
||||
vm->bind__eq__(cls, [](VM* vm, PyVar _0, PyVar _1){
|
||||
if(vm->_tp(_0) != vm->_tp(_1)) return vm->NotImplemented;
|
||||
const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0)];
|
||||
const auto& fields = cls_info->annotated_fields;
|
||||
for(StrName field: fields){
|
||||
PyObject* lhs = _0->attr(field);
|
||||
PyObject* rhs = _1->attr(field);
|
||||
PyVar lhs = _0->attr(field);
|
||||
PyVar rhs = _1->attr(field);
|
||||
if(vm->py_ne(lhs, rhs)) return vm->False;
|
||||
}
|
||||
return vm->True;
|
||||
@ -77,7 +77,7 @@ static void patch__eq__(VM* vm, Type cls){
|
||||
}
|
||||
|
||||
void add_module_dataclasses(VM* vm){
|
||||
PyObject* mod = vm->new_module("dataclasses");
|
||||
PyVar mod = vm->new_module("dataclasses");
|
||||
|
||||
vm->bind_func(mod, "dataclass", 1, [](VM* vm, ArgsView args){
|
||||
vm->check_type(args[0], VM::tp_type);
|
||||
|
12
src/dict.cpp
12
src/dict.cpp
@ -39,7 +39,7 @@ namespace pkpy{
|
||||
memcpy(_nodes, other._nodes, _capacity * sizeof(ItemNode));
|
||||
}
|
||||
|
||||
void Dict::set(PyObject* key, PyObject* val){
|
||||
void Dict::set(PyVar key, PyVar val){
|
||||
// do possible rehash
|
||||
if(_size+1 > _critical_size) _rehash();
|
||||
bool ok; int i;
|
||||
@ -89,20 +89,20 @@ namespace pkpy{
|
||||
}
|
||||
|
||||
|
||||
PyObject* Dict::try_get(PyObject* key) const{
|
||||
PyVar Dict::try_get(PyVar key) const{
|
||||
bool ok; int i;
|
||||
_probe_0(key, ok, i);
|
||||
if(!ok) return nullptr;
|
||||
return _items[i].second;
|
||||
}
|
||||
|
||||
bool Dict::contains(PyObject* key) const{
|
||||
bool Dict::contains(PyVar key) const{
|
||||
bool ok; int i;
|
||||
_probe_0(key, ok, i);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool Dict::erase(PyObject* key){
|
||||
bool Dict::erase(PyVar key){
|
||||
bool ok; int i;
|
||||
_probe_0(key, ok, i);
|
||||
if(!ok) return false;
|
||||
@ -131,7 +131,7 @@ namespace pkpy{
|
||||
}
|
||||
|
||||
void Dict::update(const Dict& other){
|
||||
other.apply([&](PyObject* k, PyObject* v){ set(k, v); });
|
||||
other.apply([&](PyVar k, PyVar v){ set(k, v); });
|
||||
}
|
||||
|
||||
Tuple Dict::keys() const{
|
||||
@ -173,7 +173,7 @@ namespace pkpy{
|
||||
}
|
||||
|
||||
void Dict::_gc_mark() const{
|
||||
apply([](PyObject* k, PyObject* v){
|
||||
apply([](PyVar k, PyVar v){
|
||||
PK_OBJ_MARK(k);
|
||||
PK_OBJ_MARK(v);
|
||||
});
|
||||
|
@ -206,7 +206,7 @@ static double easeInOutBounce( double x ) {
|
||||
}
|
||||
|
||||
void add_module_easing(VM* vm){
|
||||
PyObject* mod = vm->new_module("easing");
|
||||
PyVar mod = vm->new_module("easing");
|
||||
|
||||
#define EASE(name) \
|
||||
vm->bind_func(mod, #name, 1, [](VM* vm, ArgsView args){ \
|
||||
|
@ -131,7 +131,7 @@ namespace pkpy{
|
||||
}
|
||||
}
|
||||
|
||||
int CodeEmitContext::add_const(PyObject* v){
|
||||
int CodeEmitContext::add_const(PyVar v){
|
||||
if(is_type(v, vm->tp_str)){
|
||||
// warning: should use add_const_string() instead
|
||||
return add_const_string(PK_OBJ_GET(Str, v).sv());
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "pocketpy/frame.h"
|
||||
|
||||
namespace pkpy{
|
||||
PyObject** FastLocals::try_get_name(StrName name){
|
||||
PyVar* FastLocals::try_get_name(StrName name){
|
||||
int index = co->varnames_inv.try_get(name);
|
||||
if(index == -1) return nullptr;
|
||||
return &a[index];
|
||||
@ -10,13 +10,13 @@ namespace pkpy{
|
||||
NameDict_ FastLocals::to_namedict(){
|
||||
NameDict_ dict = std::make_shared<NameDict>();
|
||||
co->varnames_inv.apply([&](StrName name, int index){
|
||||
PyObject* value = a[index];
|
||||
PyVar value = a[index];
|
||||
if(value != PY_NULL) dict->set(name, value);
|
||||
});
|
||||
return dict;
|
||||
}
|
||||
|
||||
PyObject* Frame::f_closure_try_get(StrName name){
|
||||
PyVar Frame::f_closure_try_get(StrName name){
|
||||
if(_callable == nullptr) return nullptr;
|
||||
Function& fn = PK_OBJ_GET(Function, _callable);
|
||||
if(fn._closure == nullptr) return nullptr;
|
||||
@ -31,7 +31,7 @@ namespace pkpy{
|
||||
block = co->blocks[block].parent;
|
||||
}
|
||||
if(block < 0) return false;
|
||||
PyObject* obj = _s->popx(); // pop exception object
|
||||
PyVar obj = _s->popx(); // pop exception object
|
||||
// get the stack size of the try block
|
||||
int _stack_size = co->blocks[block].base_stack_size;
|
||||
if(stack_size(_s) < _stack_size) throw std::runtime_error(_S("invalid state: ", stack_size(_s), '<', _stack_size).str());
|
||||
|
10
src/gc.cpp
10
src/gc.cpp
@ -3,8 +3,8 @@
|
||||
namespace pkpy{
|
||||
|
||||
int ManagedHeap::sweep(){
|
||||
std::vector<PyObject*> alive;
|
||||
for(PyObject* obj: gen){
|
||||
std::vector<PyVar> alive;
|
||||
for(PyVar obj: gen){
|
||||
if(obj->gc_marked){
|
||||
obj->gc_marked = false;
|
||||
alive.push_back(obj);
|
||||
@ -19,7 +19,7 @@ namespace pkpy{
|
||||
}
|
||||
|
||||
// clear _no_gc marked flag
|
||||
for(PyObject* obj: _no_gc) obj->gc_marked = false;
|
||||
for(PyVar obj: _no_gc) obj->gc_marked = false;
|
||||
|
||||
int freed = gen.size() - alive.size();
|
||||
|
||||
@ -55,8 +55,8 @@ namespace pkpy{
|
||||
}
|
||||
|
||||
ManagedHeap::~ManagedHeap(){
|
||||
for(PyObject* obj: _no_gc) { obj->~PyObject(); pool64_dealloc(obj); }
|
||||
for(PyObject* obj: gen) { obj->~PyObject(); pool64_dealloc(obj); }
|
||||
for(PyVar obj: _no_gc) { obj->~PyObject(); pool64_dealloc(obj); }
|
||||
for(PyVar obj: gen) { obj->~PyObject(); pool64_dealloc(obj); }
|
||||
}
|
||||
|
||||
|
||||
|
10
src/io.cpp
10
src/io.cpp
@ -15,7 +15,7 @@ struct FileIO {
|
||||
|
||||
FileIO(VM* vm, const Str& file, const Str& mode);
|
||||
void close();
|
||||
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
||||
};
|
||||
|
||||
static FILE* io_fopen(const char* name, const char* mode){
|
||||
@ -53,7 +53,7 @@ unsigned char* _default_import_handler(const char* name, int* out_size){
|
||||
return buffer;
|
||||
};
|
||||
|
||||
void FileIO::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||
void FileIO::_register(VM* vm, PyVar mod, PyVar type){
|
||||
vm->bind_func(type, __new__, 3, [](VM* vm, ArgsView args){
|
||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||
return vm->heap.gcnew<FileIO>(cls, vm,
|
||||
@ -138,7 +138,7 @@ void FileIO::close(){
|
||||
}
|
||||
|
||||
void add_module_io(VM* vm){
|
||||
PyObject* mod = vm->new_module("io");
|
||||
PyVar mod = vm->new_module("io");
|
||||
vm->register_user_class<FileIO>(mod, "FileIO");
|
||||
|
||||
mod->attr().set("SEEK_SET", VAR(SEEK_SET));
|
||||
@ -153,8 +153,8 @@ void add_module_io(VM* vm){
|
||||
}
|
||||
|
||||
void add_module_os(VM* vm){
|
||||
PyObject* mod = vm->new_module("os");
|
||||
PyObject* path_obj = vm->heap.gcnew<DummyInstance>(vm->tp_object);
|
||||
PyVar mod = vm->new_module("os");
|
||||
PyVar path_obj = vm->heap.gcnew<DummyInstance>(vm->tp_object);
|
||||
mod->attr().set("path", path_obj);
|
||||
|
||||
// Working directory is shared by all VMs!!
|
||||
|
40
src/iter.cpp
40
src/iter.cpp
@ -2,9 +2,9 @@
|
||||
|
||||
namespace pkpy{
|
||||
|
||||
void RangeIter::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; });
|
||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> unsigned{
|
||||
void RangeIter::_register(VM* vm, PyVar mod, PyVar type){
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
|
||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
|
||||
RangeIter& self = PK_OBJ_GET(RangeIter, _0);
|
||||
if(self.r.step > 0){
|
||||
if(self.current >= self.r.stop) return 0;
|
||||
@ -17,9 +17,9 @@ namespace pkpy{
|
||||
});
|
||||
}
|
||||
|
||||
void ArrayIter::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; });
|
||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> unsigned{
|
||||
void ArrayIter::_register(VM* vm, PyVar mod, PyVar type){
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
|
||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
|
||||
ArrayIter& self = _CAST(ArrayIter&, _0);
|
||||
if(self.current == self.end) return 0;
|
||||
vm->s_data.push(*self.current++);
|
||||
@ -27,9 +27,9 @@ namespace pkpy{
|
||||
});
|
||||
}
|
||||
|
||||
void StringIter::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; });
|
||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> unsigned{
|
||||
void StringIter::_register(VM* vm, PyVar mod, PyVar type){
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
|
||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
|
||||
StringIter& self = _CAST(StringIter&, _0);
|
||||
Str& s = PK_OBJ_GET(Str, self.ref);
|
||||
if(self.i == s.size) return 0;
|
||||
@ -41,17 +41,17 @@ namespace pkpy{
|
||||
});
|
||||
}
|
||||
|
||||
PyObject* Generator::next(VM* vm){
|
||||
PyVar Generator::next(VM* vm){
|
||||
if(state == 2) return vm->StopIteration;
|
||||
// reset frame._sp_base
|
||||
frame._sp_base = vm->s_data._sp;
|
||||
frame._locals.a = vm->s_data._sp;
|
||||
// restore the context
|
||||
for(PyObject* obj: s_backup) vm->s_data.push(obj);
|
||||
for(PyVar obj: s_backup) vm->s_data.push(obj);
|
||||
s_backup.clear();
|
||||
vm->callstack.emplace(std::move(frame));
|
||||
|
||||
PyObject* ret;
|
||||
PyVar ret;
|
||||
try{
|
||||
ret = vm->__run_top_frame();
|
||||
}catch(...){
|
||||
@ -63,7 +63,7 @@ namespace pkpy{
|
||||
// backup the context
|
||||
frame = std::move(vm->callstack.top());
|
||||
ret = vm->s_data.popx();
|
||||
for(PyObject* obj: frame.stack_view(&vm->s_data)) s_backup.push_back(obj);
|
||||
for(PyVar obj: frame.stack_view(&vm->s_data)) s_backup.push_back(obj);
|
||||
vm->__pop_frame();
|
||||
state = 1;
|
||||
if(ret == vm->StopIteration) state = 2;
|
||||
@ -74,11 +74,11 @@ namespace pkpy{
|
||||
}
|
||||
}
|
||||
|
||||
void Generator::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; });
|
||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> unsigned{
|
||||
void Generator::_register(VM* vm, PyVar mod, PyVar type){
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
|
||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
|
||||
Generator& self = _CAST(Generator&, _0);
|
||||
PyObject* retval = self.next(vm);
|
||||
PyVar retval = self.next(vm);
|
||||
if(retval == vm->StopIteration) return 0;
|
||||
vm->s_data.push(retval);
|
||||
return 1;
|
||||
@ -86,8 +86,8 @@ namespace pkpy{
|
||||
}
|
||||
|
||||
void DictItemsIter::_register(VM *vm, PyObject *mod, PyObject *type){
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){ return _0; });
|
||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> unsigned{
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
|
||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
|
||||
DictItemsIter& self = _CAST(DictItemsIter&, _0);
|
||||
Dict& d = PK_OBJ_GET(Dict, self.ref);
|
||||
if(self.i == -1) return 0;
|
||||
@ -98,7 +98,7 @@ namespace pkpy{
|
||||
});
|
||||
}
|
||||
|
||||
PyObject* VM::__py_generator(Frame&& frame, ArgsView buffer){
|
||||
PyVar VM::__py_generator(Frame&& frame, ArgsView buffer){
|
||||
return vm->new_user_object<Generator>(std::move(frame), buffer);
|
||||
}
|
||||
|
||||
|
@ -3,14 +3,14 @@
|
||||
namespace pkpy{
|
||||
|
||||
#define BIND_VEC_VEC_OP(D, name, op) \
|
||||
vm->bind##name(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){ \
|
||||
vm->bind##name(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
|
||||
Vec##D& self = _CAST(Vec##D&, _0); \
|
||||
Vec##D& other = CAST(Vec##D&, _1); \
|
||||
return VAR(self op other); \
|
||||
});
|
||||
|
||||
#define BIND_VEC_FLOAT_OP(D, name, op) \
|
||||
vm->bind##name(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){ \
|
||||
vm->bind##name(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
|
||||
Vec##D& self = _CAST(Vec##D&, _0); \
|
||||
f64 other = CAST(f64, _1); \
|
||||
return VAR(self op other); \
|
||||
@ -30,7 +30,7 @@ namespace pkpy{
|
||||
});
|
||||
|
||||
#define BIND_VEC_MUL_OP(D) \
|
||||
vm->bind__mul__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){ \
|
||||
vm->bind__mul__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
|
||||
Vec##D& self = _CAST(Vec##D&, _0); \
|
||||
if(vm->is_user_type<Vec##D>(_1)){ \
|
||||
Vec##D& other = _CAST(Vec##D&, _1); \
|
||||
@ -44,14 +44,14 @@ namespace pkpy{
|
||||
f64 other = CAST(f64, args[1]); \
|
||||
return VAR(self * other); \
|
||||
}); \
|
||||
vm->bind__truediv__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){ \
|
||||
vm->bind__truediv__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
|
||||
Vec##D& self = _CAST(Vec##D&, _0); \
|
||||
f64 other = CAST(f64, _1); \
|
||||
return VAR(self / other); \
|
||||
});
|
||||
|
||||
#define BIND_VEC_GETITEM(D) \
|
||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj, PyObject* index){ \
|
||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj, PyVar index){ \
|
||||
Vec##D& self = _CAST(Vec##D&, obj); \
|
||||
i64 i = CAST(i64, index); \
|
||||
if(i < 0 || i >= D) vm->IndexError("index out of range"); \
|
||||
@ -114,7 +114,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
return Vec2(output_x, output_y);
|
||||
}
|
||||
|
||||
void Vec2::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||
void Vec2::_register(VM* vm, PyVar mod, PyVar type){
|
||||
PY_STRUCT_LIKE(Vec2)
|
||||
|
||||
type->attr().set("ZERO", vm->new_user_object<Vec2>(0, 0));
|
||||
@ -149,7 +149,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
return VAR(val);
|
||||
}, {}, BindType::STATICMETHOD);
|
||||
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj) -> Str{
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj) -> Str{
|
||||
Vec2 self = _CAST(Vec2&, obj);
|
||||
SStream ss;
|
||||
ss.setprecision(3);
|
||||
@ -187,7 +187,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
BIND_VEC_GETITEM(2)
|
||||
}
|
||||
|
||||
void Vec3::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||
void Vec3::_register(VM* vm, PyVar mod, PyVar type){
|
||||
PY_STRUCT_LIKE(Vec3)
|
||||
|
||||
type->attr().set("ZERO", vm->new_user_object<Vec3>(0, 0, 0));
|
||||
@ -200,7 +200,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
return vm->heap.gcnew<Vec3>(PK_OBJ_GET(Type, args[0]), x, y, z);
|
||||
});
|
||||
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj) -> Str{
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj) -> Str{
|
||||
Vec3 self = _CAST(Vec3&, obj);
|
||||
SStream ss;
|
||||
ss.setprecision(3);
|
||||
@ -225,7 +225,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
BIND_VEC_GETITEM(3)
|
||||
}
|
||||
|
||||
void Vec4::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||
void Vec4::_register(VM* vm, PyVar mod, PyVar type){
|
||||
PY_STRUCT_LIKE(Vec4)
|
||||
|
||||
type->attr().set("ZERO", vm->new_user_object<Vec4>(0, 0, 0, 0));
|
||||
@ -239,7 +239,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
return vm->heap.gcnew<Vec4>(PK_OBJ_GET(Type, args[0]), x, y, z, w);
|
||||
});
|
||||
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj) -> Str{
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj) -> Str{
|
||||
Vec4 self = _CAST(Vec4&, obj);
|
||||
SStream ss;
|
||||
ss.setprecision(3);
|
||||
@ -270,7 +270,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
#undef BIND_VEC_FUNCTION_1
|
||||
#undef BIND_VEC_GETITEM
|
||||
|
||||
void Mat3x3::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||
void Mat3x3::_register(VM* vm, PyVar mod, PyVar type){
|
||||
PY_STRUCT_LIKE(Mat3x3)
|
||||
|
||||
vm->bind_func(type, __new__, -1, [](VM* vm, ArgsView args){
|
||||
@ -298,7 +298,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj) -> Str{
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj) -> Str{
|
||||
const Mat3x3& self = _CAST(Mat3x3&, obj);
|
||||
SStream ss;
|
||||
ss.setprecision(3);
|
||||
@ -308,7 +308,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
return ss.str();
|
||||
});
|
||||
|
||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj, PyObject* index){
|
||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj, PyVar index){
|
||||
Mat3x3& self = _CAST(Mat3x3&, obj);
|
||||
Tuple& t = CAST(Tuple&, index);
|
||||
if(t.size() != 2){
|
||||
@ -322,7 +322,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
return VAR(self.m[i][j]);
|
||||
});
|
||||
|
||||
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj, PyObject* index, PyObject* value){
|
||||
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj, PyVar index, PyVar value){
|
||||
Mat3x3& self = _CAST(Mat3x3&, obj);
|
||||
const Tuple& t = CAST(Tuple&, index);
|
||||
if(t.size() != 2){
|
||||
@ -346,19 +346,19 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
vm->bind_field(type, "_32", &Mat3x3::_32);
|
||||
vm->bind_field(type, "_33", &Mat3x3::_33);
|
||||
|
||||
vm->bind__add__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){
|
||||
vm->bind__add__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
||||
Mat3x3& self = _CAST(Mat3x3&, _0);
|
||||
Mat3x3& other = CAST(Mat3x3&, _1);
|
||||
return vm->new_user_object<Mat3x3>(self + other);
|
||||
});
|
||||
|
||||
vm->bind__sub__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){
|
||||
vm->bind__sub__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
||||
Mat3x3& self = _CAST(Mat3x3&, _0);
|
||||
Mat3x3& other = CAST(Mat3x3&, _1);
|
||||
return vm->new_user_object<Mat3x3>(self - other);
|
||||
});
|
||||
|
||||
vm->bind__mul__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){
|
||||
vm->bind__mul__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
||||
Mat3x3& self = _CAST(Mat3x3&, _0);
|
||||
f64 other = CAST_F(_1);
|
||||
return vm->new_user_object<Mat3x3>(self * other);
|
||||
@ -370,13 +370,13 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
return vm->new_user_object<Mat3x3>(self * other);
|
||||
});
|
||||
|
||||
vm->bind__truediv__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){
|
||||
vm->bind__truediv__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
||||
Mat3x3& self = _CAST(Mat3x3&, _0);
|
||||
f64 other = CAST_F(_1);
|
||||
return vm->new_user_object<Mat3x3>(self / other);
|
||||
});
|
||||
|
||||
vm->bind__matmul__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){
|
||||
vm->bind__matmul__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
||||
Mat3x3& self = _CAST(Mat3x3&, _0);
|
||||
if(vm->is_user_type<Mat3x3>(_1)){
|
||||
const Mat3x3& other = _CAST(Mat3x3&, _1);
|
||||
@ -411,7 +411,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
return vm->new_user_object<Mat3x3>(self.transpose());
|
||||
});
|
||||
|
||||
vm->bind__invert__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
||||
vm->bind__invert__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj){
|
||||
Mat3x3& self = _CAST(Mat3x3&, obj);
|
||||
Mat3x3 ret;
|
||||
if(!self.inverse(ret)) vm->ValueError("matrix is not invertible");
|
||||
@ -548,14 +548,14 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
||||
|
||||
|
||||
void add_module_linalg(VM* vm){
|
||||
PyObject* linalg = vm->new_module("linalg");
|
||||
PyVar linalg = vm->new_module("linalg");
|
||||
|
||||
vm->register_user_class<Vec2>(linalg, "vec2", VM::tp_object, true);
|
||||
vm->register_user_class<Vec3>(linalg, "vec3", VM::tp_object, true);
|
||||
vm->register_user_class<Vec4>(linalg, "vec4", VM::tp_object, true);
|
||||
vm->register_user_class<Mat3x3>(linalg, "mat3x3", VM::tp_object, true);
|
||||
|
||||
PyObject* float_p = vm->_modules["c"]->attr("float_p");
|
||||
PyVar float_p = vm->_modules["c"]->attr("float_p");
|
||||
linalg->attr().set("vec2_p", float_p);
|
||||
linalg->attr().set("vec3_p", float_p);
|
||||
linalg->attr().set("vec4_p", float_p);
|
||||
|
@ -26,7 +26,7 @@ struct PyStructTime{
|
||||
tm_isdst = tm->tm_isdst;
|
||||
}
|
||||
|
||||
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
||||
PY_READONLY_FIELD(PyStructTime, "tm_year", tm_year);
|
||||
PY_READONLY_FIELD(PyStructTime, "tm_mon", tm_mon);
|
||||
PY_READONLY_FIELD(PyStructTime, "tm_mday", tm_mday);
|
||||
@ -40,7 +40,7 @@ struct PyStructTime{
|
||||
};
|
||||
|
||||
void add_module_time(VM* vm){
|
||||
PyObject* mod = vm->new_module("time");
|
||||
PyVar mod = vm->new_module("time");
|
||||
vm->register_user_class<PyStructTime>(mod, "struct_time");
|
||||
|
||||
vm->bind_func(mod, "time", 0, [](VM* vm, ArgsView args) {
|
||||
@ -67,12 +67,12 @@ void add_module_time(VM* vm){
|
||||
}
|
||||
|
||||
void add_module_sys(VM* vm){
|
||||
PyObject* mod = vm->new_module("sys");
|
||||
PyVar mod = vm->new_module("sys");
|
||||
vm->setattr(mod, "version", VAR(PK_VERSION));
|
||||
vm->setattr(mod, "platform", VAR(kPlatformStrings[PK_SYS_PLATFORM]));
|
||||
|
||||
PyObject* stdout_ = vm->heap.gcnew<DummyInstance>(vm->tp_object);
|
||||
PyObject* stderr_ = vm->heap.gcnew<DummyInstance>(vm->tp_object);
|
||||
PyVar stdout_ = vm->heap.gcnew<DummyInstance>(vm->tp_object);
|
||||
PyVar stderr_ = vm->heap.gcnew<DummyInstance>(vm->tp_object);
|
||||
vm->setattr(mod, "stdout", stdout_);
|
||||
vm->setattr(mod, "stderr", stderr_);
|
||||
|
||||
@ -90,7 +90,7 @@ void add_module_sys(VM* vm){
|
||||
}
|
||||
|
||||
void add_module_json(VM* vm){
|
||||
PyObject* mod = vm->new_module("json");
|
||||
PyVar mod = vm->new_module("json");
|
||||
vm->bind_func(mod, "loads", 1, [](VM* vm, ArgsView args) {
|
||||
std::string_view sv;
|
||||
if(is_type(args[0], vm->tp_bytes)){
|
||||
@ -109,7 +109,7 @@ void add_module_json(VM* vm){
|
||||
|
||||
// https://docs.python.org/3.5/library/math.html
|
||||
void add_module_math(VM* vm){
|
||||
PyObject* mod = vm->new_module("math");
|
||||
PyVar mod = vm->new_module("math");
|
||||
mod->attr().set("pi", VAR(3.1415926535897932384));
|
||||
mod->attr().set("e" , VAR(2.7182818284590452354));
|
||||
mod->attr().set("inf", VAR(std::numeric_limits<double>::infinity()));
|
||||
@ -122,7 +122,7 @@ void add_module_math(VM* vm){
|
||||
List& list = CAST(List&, args[0]);
|
||||
double sum = 0;
|
||||
double c = 0;
|
||||
for(PyObject* arg : list){
|
||||
for(PyVar arg : list){
|
||||
double x = CAST_F(arg);
|
||||
double y = x - c;
|
||||
double t = sum + y;
|
||||
@ -196,7 +196,7 @@ void add_module_math(VM* vm){
|
||||
}
|
||||
|
||||
void add_module_traceback(VM* vm){
|
||||
PyObject* mod = vm->new_module("traceback");
|
||||
PyVar mod = vm->new_module("traceback");
|
||||
vm->bind_func(mod, "print_exc", 0, [](VM* vm, ArgsView args) {
|
||||
if(vm->__last_exception==nullptr) vm->ValueError("no exception");
|
||||
Exception& e = _CAST(Exception&, vm->__last_exception);
|
||||
@ -212,16 +212,16 @@ void add_module_traceback(VM* vm){
|
||||
}
|
||||
|
||||
void add_module_dis(VM* vm){
|
||||
PyObject* mod = vm->new_module("dis");
|
||||
PyVar mod = vm->new_module("dis");
|
||||
|
||||
vm->bind_func(mod, "dis", 1, [](VM* vm, ArgsView args) {
|
||||
CodeObject_ code;
|
||||
PyObject* obj = args[0];
|
||||
PyVar obj = args[0];
|
||||
if(is_type(obj, vm->tp_str)){
|
||||
const Str& source = CAST(Str, obj);
|
||||
code = vm->compile(source, "<dis>", EXEC_MODE);
|
||||
}
|
||||
PyObject* f = obj;
|
||||
PyVar f = obj;
|
||||
if(is_type(f, vm->tp_bound_method)) f = CAST(BoundMethod, obj).func;
|
||||
code = CAST(Function&, f).decl->code;
|
||||
vm->stdout_write(vm->disassemble(code));
|
||||
@ -230,15 +230,15 @@ void add_module_dis(VM* vm){
|
||||
}
|
||||
|
||||
void add_module_gc(VM* vm){
|
||||
PyObject* mod = vm->new_module("gc");
|
||||
PyVar mod = vm->new_module("gc");
|
||||
vm->bind_func(mod, "collect", 0, PK_LAMBDA(VAR(vm->heap.collect())));
|
||||
}
|
||||
|
||||
void add_module_enum(VM* vm){
|
||||
PyObject* mod = vm->new_module("enum");
|
||||
PyVar mod = vm->new_module("enum");
|
||||
CodeObject_ code = vm->compile(kPythonLibs__enum, "enum.py", EXEC_MODE);
|
||||
vm->_exec(code, mod);
|
||||
PyObject* Enum = mod->attr("Enum");
|
||||
PyVar Enum = mod->attr("Enum");
|
||||
vm->_all_types[PK_OBJ_GET(Type, Enum).index].on_end_subclass = \
|
||||
[](VM* vm, PyTypeInfo* new_ti){
|
||||
new_ti->subclass_enabled = false; // Enum class cannot be subclassed twice
|
||||
@ -253,14 +253,14 @@ void add_module_enum(VM* vm){
|
||||
}
|
||||
|
||||
void add_module___builtins(VM* vm){
|
||||
PyObject* mod = vm->new_module("__builtins");
|
||||
PyVar mod = vm->new_module("__builtins");
|
||||
|
||||
vm->bind_func(mod, "next", 1, [](VM* vm, ArgsView args){
|
||||
return vm->py_next(args[0]);
|
||||
});
|
||||
|
||||
vm->bind_func(mod, "_enable_instance_dict", 1, [](VM* vm, ArgsView args){
|
||||
PyObject* self = args[0];
|
||||
PyVar self = args[0];
|
||||
if(is_tagged(self)) vm->TypeError("object: tagged object cannot enable instance dict");
|
||||
if(self->is_attr_valid()) vm->RuntimeError("object: instance dict is already enabled");
|
||||
self->_enable_instance_dict();
|
||||
@ -284,7 +284,7 @@ struct _LpGuard{
|
||||
struct LineProfilerW{
|
||||
LineProfiler profiler;
|
||||
|
||||
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
||||
vm->bind_func(type, __new__, 1, [](VM* vm, ArgsView args){
|
||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||
return vm->heap.gcnew<LineProfilerW>(cls);
|
||||
@ -300,13 +300,13 @@ struct LineProfilerW{
|
||||
|
||||
vm->bind(type, "runcall(self, func, *args)", [](VM* vm, ArgsView view){
|
||||
LineProfilerW& self = PK_OBJ_GET(LineProfilerW, view[0]);
|
||||
PyObject* func = view[1];
|
||||
PyVar func = view[1];
|
||||
const Tuple& args = CAST(Tuple&, view[2]);
|
||||
vm->s_data.push(func);
|
||||
vm->s_data.push(PY_NULL);
|
||||
for(PyObject* arg : args) vm->s_data.push(arg);
|
||||
for(PyVar arg : args) vm->s_data.push(arg);
|
||||
_LpGuard guard(&self, vm);
|
||||
PyObject* ret = vm->vectorcall(args.size());
|
||||
PyVar ret = vm->vectorcall(args.size());
|
||||
return ret;
|
||||
});
|
||||
|
||||
@ -333,7 +333,7 @@ _LpGuard::~_LpGuard(){
|
||||
}
|
||||
|
||||
void add_module_line_profiler(VM *vm){
|
||||
PyObject* mod = vm->new_module("line_profiler");
|
||||
PyVar mod = vm->new_module("line_profiler");
|
||||
vm->register_user_class<LineProfilerW>(mod, "LineProfiler");
|
||||
}
|
||||
#else
|
||||
|
240
src/pocketpy.cpp
240
src/pocketpy.cpp
@ -7,7 +7,7 @@ void add_module_cjson(VM* vm);
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
PyObject* PyArrayGetItem(VM* vm, PyObject* _0, PyObject* _1){
|
||||
PyVar PyArrayGetItem(VM* vm, PyVar _0, PyVar _1){
|
||||
static_assert(std::is_same_v<T, List> || std::is_same_v<T, Tuple>);
|
||||
const T& self = _CAST(T&, _0);
|
||||
i64 index;
|
||||
@ -29,13 +29,13 @@ PyObject* PyArrayGetItem(VM* vm, PyObject* _0, PyObject* _1){
|
||||
|
||||
void __init_builtins(VM* _vm) {
|
||||
#define BIND_NUM_ARITH_OPT(name, op) \
|
||||
_vm->bind##name(VM::tp_int, [](VM* vm, PyObject* lhs, PyObject* rhs) { \
|
||||
_vm->bind##name(VM::tp_int, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
||||
i64 val; \
|
||||
if(try_cast_int(rhs, &val)) return VAR(_CAST(i64, lhs) op val); \
|
||||
if(is_float(rhs)) return VAR(_CAST(i64, lhs) op _CAST(f64, rhs)); \
|
||||
return vm->NotImplemented; \
|
||||
}); \
|
||||
_vm->bind##name(VM::tp_float, [](VM* vm, PyObject* lhs, PyObject* rhs) { \
|
||||
_vm->bind##name(VM::tp_float, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
||||
i64 val; \
|
||||
if(try_cast_int(rhs, &val)) return VAR(_CAST(f64, lhs) op val); \
|
||||
if(is_float(rhs)) return VAR(_CAST(f64, lhs) op _CAST(f64, rhs)); \
|
||||
@ -49,13 +49,13 @@ void __init_builtins(VM* _vm) {
|
||||
#undef BIND_NUM_ARITH_OPT
|
||||
|
||||
#define BIND_NUM_LOGICAL_OPT(name, op) \
|
||||
_vm->bind##name(VM::tp_int, [](VM* vm, PyObject* lhs, PyObject* rhs) { \
|
||||
_vm->bind##name(VM::tp_int, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
||||
i64 val; \
|
||||
if(try_cast_int(rhs, &val)) return VAR(_CAST(i64, lhs) op val); \
|
||||
if(is_float(rhs)) return VAR(_CAST(i64, lhs) op _CAST(f64, rhs)); \
|
||||
return vm->NotImplemented; \
|
||||
}); \
|
||||
_vm->bind##name(VM::tp_float, [](VM* vm, PyObject* lhs, PyObject* rhs) { \
|
||||
_vm->bind##name(VM::tp_float, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
||||
i64 val; \
|
||||
if(try_cast_int(rhs, &val)) return VAR(_CAST(f64, lhs) op val); \
|
||||
if(is_float(rhs)) return VAR(_CAST(f64, lhs) op _CAST(f64, rhs)); \
|
||||
@ -80,8 +80,8 @@ void __init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_vm->bind_func(_vm->builtins, "super", -1, [](VM* vm, ArgsView args) {
|
||||
PyObject* class_arg = nullptr;
|
||||
PyObject* self_arg = nullptr;
|
||||
PyVar class_arg = nullptr;
|
||||
PyVar self_arg = nullptr;
|
||||
if(args.size() == 2){
|
||||
class_arg = args[0];
|
||||
self_arg = args[1];
|
||||
@ -108,13 +108,13 @@ void __init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_vm->bind_func(_vm->builtins, "staticmethod", 1, [](VM* vm, ArgsView args) {
|
||||
PyObject* func = args[0];
|
||||
PyVar func = args[0];
|
||||
vm->check_type(func, vm->tp_function);
|
||||
return vm->heap.gcnew<StaticMethod>(vm->tp_staticmethod, args[0]);
|
||||
});
|
||||
|
||||
_vm->bind_func(_vm->builtins, "classmethod", 1, [](VM* vm, ArgsView args) {
|
||||
PyObject* func = args[0];
|
||||
PyVar func = args[0];
|
||||
vm->check_type(func, vm->tp_function);
|
||||
return vm->heap.gcnew<ClassMethod>(vm->tp_classmethod, args[0]);
|
||||
});
|
||||
@ -122,7 +122,7 @@ void __init_builtins(VM* _vm) {
|
||||
_vm->bind_func(_vm->builtins, "isinstance", 2, [](VM* vm, ArgsView args) {
|
||||
if(is_type(args[1], vm->tp_tuple)){
|
||||
Tuple& types = _CAST(Tuple&, args[1]);
|
||||
for(PyObject* type : types){
|
||||
for(PyVar type : types){
|
||||
vm->check_type(type, vm->tp_type);
|
||||
if(vm->isinstance(args[0], PK_OBJ_GET(Type, type))) return vm->True;
|
||||
}
|
||||
@ -140,7 +140,7 @@ void __init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_vm->bind_func(_vm->builtins, "globals", 0, [](VM* vm, ArgsView args) {
|
||||
PyObject* mod = vm->callstack.top()._module;
|
||||
PyVar mod = vm->callstack.top()._module;
|
||||
return VAR(MappingProxy(mod));
|
||||
});
|
||||
|
||||
@ -171,7 +171,7 @@ void __init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_vm->bind_func(_vm->builtins, "id", 1, [](VM* vm, ArgsView args) {
|
||||
PyObject* obj = args[0];
|
||||
PyVar obj = args[0];
|
||||
if(is_tagged(obj)) return vm->None;
|
||||
return VAR(PK_BITS(obj));
|
||||
});
|
||||
@ -267,7 +267,7 @@ void __init_builtins(VM* _vm) {
|
||||
_vm->bind_func(_vm->builtins, "getattr", -1, [](VM* vm, ArgsView args) {
|
||||
if(args.size()!=2 && args.size()!=3) vm->TypeError("getattr() takes 2 or 3 arguments");
|
||||
StrName name = CAST(Str&, args[1]);
|
||||
PyObject* val = vm->getattr(args[0], name, false);
|
||||
PyVar val = vm->getattr(args[0], name, false);
|
||||
if(val == nullptr){
|
||||
if(args.size()==2) vm->AttributeError(args[0], name);
|
||||
return args[2];
|
||||
@ -291,7 +291,7 @@ void __init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_vm->bind_func(_vm->builtins, "next", 1, [](VM* vm, ArgsView args) {
|
||||
PyObject* retval = vm->py_next(args[0]);
|
||||
PyVar retval = vm->py_next(args[0]);
|
||||
if(retval == vm->StopIteration) vm->_error(vm->call(vm->StopIteration));
|
||||
return retval;
|
||||
});
|
||||
@ -327,7 +327,7 @@ void __init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
// tp_object
|
||||
_vm->bind__repr__(VM::tp_object, [](VM* vm, PyObject* obj) -> Str{
|
||||
_vm->bind__repr__(VM::tp_object, [](VM* vm, PyVar obj) -> Str{
|
||||
if(is_tagged(obj)) PK_FATAL_ERROR();
|
||||
SStream ss;
|
||||
ss << "<" << _type_name(vm, vm->_tp(obj)) << " object at ";
|
||||
@ -336,7 +336,7 @@ void __init_builtins(VM* _vm) {
|
||||
return ss.str();
|
||||
});
|
||||
|
||||
_vm->bind__eq__(VM::tp_object, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__eq__(VM::tp_object, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
return VAR(_0 == _1);
|
||||
});
|
||||
|
||||
@ -363,24 +363,24 @@ void __init_builtins(VM* _vm) {
|
||||
return VAR(r);
|
||||
});
|
||||
|
||||
_vm->bind__iter__(VM::tp_range, [](VM* vm, PyObject* obj) { return vm->new_user_object<RangeIter>(PK_OBJ_GET(Range, obj)); });
|
||||
_vm->bind__iter__(VM::tp_range, [](VM* vm, PyVar obj) { return vm->new_user_object<RangeIter>(PK_OBJ_GET(Range, obj)); });
|
||||
|
||||
// tp_nonetype
|
||||
_vm->bind__repr__(_vm->_tp(_vm->None), [](VM* vm, PyObject* _0) -> Str {
|
||||
_vm->bind__repr__(_vm->_tp(_vm->None), [](VM* vm, PyVar _0) -> Str {
|
||||
return "None";
|
||||
});
|
||||
|
||||
// tp_float / tp_float
|
||||
_vm->bind__truediv__(VM::tp_float, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__truediv__(VM::tp_float, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
f64 value = CAST_F(_1);
|
||||
return VAR(_CAST(f64, _0) / value);
|
||||
});
|
||||
_vm->bind__truediv__(VM::tp_int, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__truediv__(VM::tp_int, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
f64 value = CAST_F(_1);
|
||||
return VAR(_CAST(i64, _0) / value);
|
||||
});
|
||||
|
||||
auto py_number_pow = [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
auto py_number_pow = [](VM* vm, PyVar _0, PyVar _1) {
|
||||
i64 lhs, rhs;
|
||||
if(try_cast_int(_0, &lhs) && try_cast_int(_1, &rhs)){
|
||||
if(rhs < 0) {
|
||||
@ -439,13 +439,13 @@ void __init_builtins(VM* _vm) {
|
||||
return VAR(val);
|
||||
});
|
||||
|
||||
_vm->bind__floordiv__(VM::tp_int, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__floordiv__(VM::tp_int, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
i64 rhs = CAST(i64, _1);
|
||||
if(rhs == 0) vm->ZeroDivisionError();
|
||||
return VAR(_CAST(i64, _0) / rhs);
|
||||
});
|
||||
|
||||
_vm->bind__mod__(VM::tp_int, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__mod__(VM::tp_int, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
i64 rhs = CAST(i64, _1);
|
||||
if(rhs == 0) vm->ZeroDivisionError();
|
||||
return VAR(_CAST(i64, _0) % rhs);
|
||||
@ -459,15 +459,15 @@ void __init_builtins(VM* _vm) {
|
||||
return VAR(bits);
|
||||
});
|
||||
|
||||
_vm->bind__repr__(VM::tp_int, [](VM* vm, PyObject* obj) -> Str{
|
||||
_vm->bind__repr__(VM::tp_int, [](VM* vm, PyVar obj) -> Str{
|
||||
return std::to_string(_CAST(i64, obj));
|
||||
});
|
||||
_vm->bind__neg__(VM::tp_int, [](VM* vm, PyObject* obj) { return VAR(-_CAST(i64, obj)); });
|
||||
_vm->bind__hash__(VM::tp_int, [](VM* vm, PyObject* obj) { return _CAST(i64, obj); });
|
||||
_vm->bind__invert__(VM::tp_int, [](VM* vm, PyObject* obj) { return VAR(~_CAST(i64, obj)); });
|
||||
_vm->bind__neg__(VM::tp_int, [](VM* vm, PyVar obj) { return VAR(-_CAST(i64, obj)); });
|
||||
_vm->bind__hash__(VM::tp_int, [](VM* vm, PyVar obj) { return _CAST(i64, obj); });
|
||||
_vm->bind__invert__(VM::tp_int, [](VM* vm, PyVar obj) { return VAR(~_CAST(i64, obj)); });
|
||||
|
||||
#define INT_BITWISE_OP(name, op) \
|
||||
_vm->bind##name(VM::tp_int, [](VM* vm, PyObject* lhs, PyObject* rhs) { \
|
||||
_vm->bind##name(VM::tp_int, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
||||
return VAR(_CAST(i64, lhs) op CAST(i64, rhs)); \
|
||||
});
|
||||
|
||||
@ -511,14 +511,14 @@ void __init_builtins(VM* _vm) {
|
||||
return VAR(float_out);
|
||||
});
|
||||
|
||||
_vm->bind__hash__(VM::tp_float, [](VM* vm, PyObject* _0) {
|
||||
_vm->bind__hash__(VM::tp_float, [](VM* vm, PyVar _0) {
|
||||
f64 val = _CAST(f64, _0);
|
||||
return (i64)std::hash<f64>()(val);
|
||||
});
|
||||
|
||||
_vm->bind__neg__(VM::tp_float, [](VM* vm, PyObject* _0) { return VAR(-_CAST(f64, _0)); });
|
||||
_vm->bind__neg__(VM::tp_float, [](VM* vm, PyVar _0) { return VAR(-_CAST(f64, _0)); });
|
||||
|
||||
_vm->bind__repr__(VM::tp_float, [](VM* vm, PyObject* _0) -> Str {
|
||||
_vm->bind__repr__(VM::tp_float, [](VM* vm, PyVar _0) -> Str {
|
||||
f64 val = _CAST(f64, _0);
|
||||
SStream ss;
|
||||
ss << val;
|
||||
@ -532,17 +532,17 @@ void __init_builtins(VM* _vm) {
|
||||
return VAR(vm->py_str(args[1]));
|
||||
});
|
||||
|
||||
_vm->bind__hash__(VM::tp_str, [](VM* vm, PyObject* _0) {
|
||||
_vm->bind__hash__(VM::tp_str, [](VM* vm, PyVar _0) {
|
||||
return (i64)_CAST(Str&, _0).hash();
|
||||
});
|
||||
|
||||
_vm->bind__add__(VM::tp_str, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__add__(VM::tp_str, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
return VAR(_CAST(Str&, _0) + CAST(Str&, _1));
|
||||
});
|
||||
_vm->bind__len__(VM::tp_str, [](VM* vm, PyObject* _0) {
|
||||
_vm->bind__len__(VM::tp_str, [](VM* vm, PyVar _0) {
|
||||
return (i64)_CAST(Str&, _0).u8_length();
|
||||
});
|
||||
_vm->bind__mul__(VM::tp_str, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__mul__(VM::tp_str, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
const Str& self = _CAST(Str&, _0);
|
||||
i64 n = CAST(i64, _1);
|
||||
SStream ss;
|
||||
@ -556,20 +556,20 @@ void __init_builtins(VM* _vm) {
|
||||
for(i64 i = 0; i < n; i++) ss << self.sv();
|
||||
return VAR(ss.str());
|
||||
});
|
||||
_vm->bind__contains__(VM::tp_str, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__contains__(VM::tp_str, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
const Str& self = _CAST(Str&, _0);
|
||||
return VAR(self.index(CAST(Str&, _1)) != -1);
|
||||
});
|
||||
|
||||
_vm->bind_func(VM::tp_str, __str__, 1, [](VM* vm, ArgsView args) { return args[0]; });
|
||||
_vm->bind__iter__(VM::tp_str, [](VM* vm, PyObject* _0) { return vm->new_user_object<StringIter>(_0); });
|
||||
_vm->bind__repr__(VM::tp_str, [](VM* vm, PyObject* _0) -> Str {
|
||||
_vm->bind__iter__(VM::tp_str, [](VM* vm, PyVar _0) { return vm->new_user_object<StringIter>(_0); });
|
||||
_vm->bind__repr__(VM::tp_str, [](VM* vm, PyVar _0) -> Str {
|
||||
const Str& self = _CAST(Str&, _0);
|
||||
return self.escape();
|
||||
});
|
||||
|
||||
#define BIND_CMP_STR(name, op) \
|
||||
_vm->bind##name(VM::tp_str, [](VM* vm, PyObject* lhs, PyObject* rhs) { \
|
||||
_vm->bind##name(VM::tp_str, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
||||
if(!is_type(rhs, vm->tp_str)) return vm->NotImplemented; \
|
||||
return VAR(_CAST(Str&, lhs) op _CAST(Str&, rhs)); \
|
||||
});
|
||||
@ -581,7 +581,7 @@ void __init_builtins(VM* _vm) {
|
||||
BIND_CMP_STR(__ge__, >=)
|
||||
#undef BIND_CMP_STR
|
||||
|
||||
_vm->bind__getitem__(VM::tp_str, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__getitem__(VM::tp_str, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
const Str& self = PK_OBJ_GET(Str, _0);
|
||||
if(is_type(_1, vm->tp_slice)){
|
||||
const Slice& s = _CAST(Slice&, _1);
|
||||
@ -677,9 +677,9 @@ void __init_builtins(VM* _vm) {
|
||||
auto _lock = vm->heap.gc_scope_lock();
|
||||
const Str& self = _CAST(Str&, args[0]);
|
||||
SStream ss;
|
||||
PyObject* it = vm->py_iter(args[1]); // strong ref
|
||||
PyVar it = vm->py_iter(args[1]); // strong ref
|
||||
const PyTypeInfo* info = vm->_tp_info(args[1]);
|
||||
PyObject* obj = vm->_py_next(info, it);
|
||||
PyVar obj = vm->_py_next(info, it);
|
||||
while(obj != vm->StopIteration){
|
||||
if(!ss.empty()) ss << self;
|
||||
ss << CAST(Str&, obj);
|
||||
@ -771,13 +771,13 @@ void __init_builtins(VM* _vm) {
|
||||
// tp_list / tp_tuple
|
||||
_vm->bind(_vm->_t(VM::tp_list), "sort(self, key=None, reverse=False)", [](VM* vm, ArgsView args) {
|
||||
List& self = _CAST(List&, args[0]);
|
||||
PyObject* key = args[1];
|
||||
PyVar key = args[1];
|
||||
if(key == vm->None){
|
||||
std::stable_sort(self.begin(), self.end(), [vm](PyObject* a, PyObject* b){
|
||||
std::stable_sort(self.begin(), self.end(), [vm](PyVar a, PyVar b){
|
||||
return vm->py_lt(a, b);
|
||||
});
|
||||
}else{
|
||||
std::stable_sort(self.begin(), self.end(), [vm, key](PyObject* a, PyObject* b){
|
||||
std::stable_sort(self.begin(), self.end(), [vm, key](PyVar a, PyVar b){
|
||||
return vm->py_lt(vm->call(key, a), vm->call(key, b));
|
||||
});
|
||||
}
|
||||
@ -786,7 +786,7 @@ void __init_builtins(VM* _vm) {
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bind__repr__(VM::tp_list, [](VM* vm, PyObject* _0) -> Str{
|
||||
_vm->bind__repr__(VM::tp_list, [](VM* vm, PyVar _0) -> Str{
|
||||
if(vm->_repr_recursion_set.count(_0)) return "[...]";
|
||||
List& iterable = _CAST(List&, _0);
|
||||
SStream ss;
|
||||
@ -801,7 +801,7 @@ void __init_builtins(VM* _vm) {
|
||||
return ss.str();
|
||||
});
|
||||
|
||||
_vm->bind__repr__(VM::tp_tuple, [](VM* vm, PyObject* _0) -> Str{
|
||||
_vm->bind__repr__(VM::tp_tuple, [](VM* vm, PyVar _0) -> Str{
|
||||
Tuple& iterable = _CAST(Tuple&, _0);
|
||||
SStream ss;
|
||||
ss << '(';
|
||||
@ -825,20 +825,20 @@ void __init_builtins(VM* _vm) {
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bind__contains__(VM::tp_list, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__contains__(VM::tp_list, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
List& self = _CAST(List&, _0);
|
||||
for(PyObject* i: self) if(vm->py_eq(i, _1)) return vm->True;
|
||||
for(PyVar i: self) if(vm->py_eq(i, _1)) return vm->True;
|
||||
return vm->False;
|
||||
});
|
||||
|
||||
_vm->bind_func(VM::tp_list, "count", 2, [](VM* vm, ArgsView args) {
|
||||
List& self = _CAST(List&, args[0]);
|
||||
int count = 0;
|
||||
for(PyObject* i: self) if(vm->py_eq(i, args[1])) count++;
|
||||
for(PyVar i: self) if(vm->py_eq(i, args[1])) count++;
|
||||
return VAR(count);
|
||||
});
|
||||
|
||||
_vm->bind__eq__(VM::tp_list, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__eq__(VM::tp_list, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
List& a = _CAST(List&, _0);
|
||||
if(!is_type(_1, vm->tp_list)) return vm->NotImplemented;
|
||||
List& b = _CAST(List&, _1);
|
||||
@ -851,7 +851,7 @@ void __init_builtins(VM* _vm) {
|
||||
|
||||
_vm->bind(_vm->_t(VM::tp_list), "index(self, value, __start=0)", [](VM* vm, ArgsView args) {
|
||||
List& self = _CAST(List&, args[0]);
|
||||
PyObject* obj = args[1];
|
||||
PyVar obj = args[1];
|
||||
int start = CAST(int, args[2]);
|
||||
for(int i=start; i<self.size(); i++){
|
||||
if(vm->py_eq(self[i], obj)) return VAR(i);
|
||||
@ -862,7 +862,7 @@ void __init_builtins(VM* _vm) {
|
||||
|
||||
_vm->bind_func(VM::tp_list, "remove", 2, [](VM* vm, ArgsView args) {
|
||||
List& self = _CAST(List&, args[0]);
|
||||
PyObject* obj = args[1];
|
||||
PyVar obj = args[1];
|
||||
for(int i=0; i<self.size(); i++){
|
||||
if(vm->py_eq(self[i], obj)){
|
||||
self.erase(i);
|
||||
@ -882,7 +882,7 @@ void __init_builtins(VM* _vm) {
|
||||
if(args.size() == 1+1){
|
||||
i64 index = CAST(i64, args[1]);
|
||||
index = vm->normalized_index(index, self.size());
|
||||
PyObject* ret = self[index];
|
||||
PyVar ret = self[index];
|
||||
self.erase(index);
|
||||
return ret;
|
||||
}
|
||||
@ -899,9 +899,9 @@ void __init_builtins(VM* _vm) {
|
||||
_vm->bind_func(VM::tp_list, "extend", 2, [](VM* vm, ArgsView args) {
|
||||
auto _lock = vm->heap.gc_scope_lock();
|
||||
List& self = _CAST(List&, args[0]);
|
||||
PyObject* it = vm->py_iter(args[1]); // strong ref
|
||||
PyVar it = vm->py_iter(args[1]); // strong ref
|
||||
const PyTypeInfo* info = vm->_tp_info(args[1]);
|
||||
PyObject* obj = vm->_py_next(info, it);
|
||||
PyVar obj = vm->_py_next(info, it);
|
||||
while(obj != vm->StopIteration){
|
||||
self.push_back(obj);
|
||||
obj = vm->_py_next(info, it);
|
||||
@ -915,7 +915,7 @@ void __init_builtins(VM* _vm) {
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bind__mul__(VM::tp_list, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__mul__(VM::tp_list, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
const List& self = _CAST(List&, _0);
|
||||
if(!is_int(_1)) return vm->NotImplemented;
|
||||
int n = _CAST(int, _1);
|
||||
@ -952,7 +952,7 @@ void __init_builtins(VM* _vm) {
|
||||
_vm->bind_func(VM::tp_list, "copy", 1, PK_LAMBDA(VAR(_CAST(List, args[0]))));
|
||||
|
||||
#define BIND_RICH_CMP(name, op, _t, _T) \
|
||||
_vm->bind__##name##__(_vm->_t, [](VM* vm, PyObject* lhs, PyObject* rhs){ \
|
||||
_vm->bind__##name##__(_vm->_t, [](VM* vm, PyVar lhs, PyVar rhs){ \
|
||||
if(!is_type(rhs, vm->_t)) return vm->NotImplemented; \
|
||||
auto& a = _CAST(_T&, lhs); \
|
||||
auto& b = _CAST(_T&, rhs); \
|
||||
@ -975,7 +975,7 @@ void __init_builtins(VM* _vm) {
|
||||
|
||||
#undef BIND_RICH_CMP
|
||||
|
||||
_vm->bind__add__(VM::tp_list, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__add__(VM::tp_list, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
const List& self = _CAST(List&, _0);
|
||||
const List& other = CAST(List&, _1);
|
||||
List new_list(self); // copy construct
|
||||
@ -983,21 +983,21 @@ void __init_builtins(VM* _vm) {
|
||||
return VAR(std::move(new_list));
|
||||
});
|
||||
|
||||
_vm->bind__len__(VM::tp_list, [](VM* vm, PyObject* _0) {
|
||||
_vm->bind__len__(VM::tp_list, [](VM* vm, PyVar _0) {
|
||||
return (i64)_CAST(List&, _0).size();
|
||||
});
|
||||
_vm->bind__iter__(VM::tp_list, [](VM* vm, PyObject* _0) {
|
||||
_vm->bind__iter__(VM::tp_list, [](VM* vm, PyVar _0) {
|
||||
List& self = _CAST(List&, _0);
|
||||
return vm->new_user_object<ArrayIter>(_0, self.begin(), self.end());
|
||||
});
|
||||
_vm->bind__getitem__(VM::tp_list, PyArrayGetItem<List>);
|
||||
_vm->bind__setitem__(VM::tp_list, [](VM* vm, PyObject* _0, PyObject* _1, PyObject* _2){
|
||||
_vm->bind__setitem__(VM::tp_list, [](VM* vm, PyVar _0, PyVar _1, PyVar _2){
|
||||
List& self = _CAST(List&, _0);
|
||||
i64 i = CAST(i64, _1);
|
||||
i = vm->normalized_index(i, self.size());
|
||||
self[i] = _2;
|
||||
});
|
||||
_vm->bind__delitem__(VM::tp_list, [](VM* vm, PyObject* _0, PyObject* _1){
|
||||
_vm->bind__delitem__(VM::tp_list, [](VM* vm, PyVar _0, PyVar _1){
|
||||
List& self = _CAST(List&, _0);
|
||||
i64 i = CAST(i64, _1);
|
||||
i = vm->normalized_index(i, self.size());
|
||||
@ -1014,20 +1014,20 @@ void __init_builtins(VM* _vm) {
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bind__contains__(VM::tp_tuple, [](VM* vm, PyObject* obj, PyObject* item) {
|
||||
_vm->bind__contains__(VM::tp_tuple, [](VM* vm, PyVar obj, PyVar item) {
|
||||
Tuple& self = _CAST(Tuple&, obj);
|
||||
for(PyObject* i: self) if(vm->py_eq(i, item)) return vm->True;
|
||||
for(PyVar i: self) if(vm->py_eq(i, item)) return vm->True;
|
||||
return vm->False;
|
||||
});
|
||||
|
||||
_vm->bind_func(VM::tp_tuple, "count", 2, [](VM* vm, ArgsView args) {
|
||||
Tuple& self = _CAST(Tuple&, args[0]);
|
||||
int count = 0;
|
||||
for(PyObject* i: self) if(vm->py_eq(i, args[1])) count++;
|
||||
for(PyVar i: self) if(vm->py_eq(i, args[1])) count++;
|
||||
return VAR(count);
|
||||
});
|
||||
|
||||
_vm->bind__eq__(VM::tp_tuple, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__eq__(VM::tp_tuple, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
const Tuple& self = _CAST(Tuple&, _0);
|
||||
if(!is_type(_1, vm->tp_tuple)) return vm->NotImplemented;
|
||||
const Tuple& other = _CAST(Tuple&, _1);
|
||||
@ -1038,9 +1038,9 @@ void __init_builtins(VM* _vm) {
|
||||
return vm->True;
|
||||
});
|
||||
|
||||
_vm->bind__hash__(VM::tp_tuple, [](VM* vm, PyObject* _0) {
|
||||
_vm->bind__hash__(VM::tp_tuple, [](VM* vm, PyVar _0) {
|
||||
i64 x = 1000003;
|
||||
for (PyObject* item: _CAST(Tuple&, _0)) {
|
||||
for (PyVar item: _CAST(Tuple&, _0)) {
|
||||
i64 y = vm->py_hash(item);
|
||||
// recommended by Github Copilot
|
||||
x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2));
|
||||
@ -1048,45 +1048,45 @@ void __init_builtins(VM* _vm) {
|
||||
return x;
|
||||
});
|
||||
|
||||
_vm->bind__iter__(VM::tp_tuple, [](VM* vm, PyObject* _0) {
|
||||
_vm->bind__iter__(VM::tp_tuple, [](VM* vm, PyVar _0) {
|
||||
Tuple& self = _CAST(Tuple&, _0);
|
||||
return vm->new_user_object<ArrayIter>(_0, self.begin(), self.end());
|
||||
});
|
||||
_vm->bind__getitem__(VM::tp_tuple, PyArrayGetItem<Tuple>);
|
||||
_vm->bind__len__(VM::tp_tuple, [](VM* vm, PyObject* obj) {
|
||||
_vm->bind__len__(VM::tp_tuple, [](VM* vm, PyVar obj) {
|
||||
return (i64)_CAST(Tuple&, obj).size();
|
||||
});
|
||||
|
||||
// tp_bool
|
||||
_vm->bind_func(VM::tp_bool, __new__, 2, PK_LAMBDA(VAR(vm->py_bool(args[1]))));
|
||||
_vm->bind__hash__(VM::tp_bool, [](VM* vm, PyObject* _0) {
|
||||
_vm->bind__hash__(VM::tp_bool, [](VM* vm, PyVar _0) {
|
||||
return (i64)_CAST(bool, _0);
|
||||
});
|
||||
_vm->bind__repr__(VM::tp_bool, [](VM* vm, PyObject* _0) -> Str{
|
||||
_vm->bind__repr__(VM::tp_bool, [](VM* vm, PyVar _0) -> Str{
|
||||
bool val = _CAST(bool, _0);
|
||||
return val ? "True" : "False";
|
||||
});
|
||||
|
||||
_vm->bind__and__(VM::tp_bool, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__and__(VM::tp_bool, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
return VAR(_CAST(bool, _0) && CAST(bool, _1));
|
||||
});
|
||||
_vm->bind__or__(VM::tp_bool, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__or__(VM::tp_bool, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
return VAR(_CAST(bool, _0) || CAST(bool, _1));
|
||||
});
|
||||
_vm->bind__xor__(VM::tp_bool, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__xor__(VM::tp_bool, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
return VAR(_CAST(bool, _0) != CAST(bool, _1));
|
||||
});
|
||||
_vm->bind__eq__(VM::tp_bool, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__eq__(VM::tp_bool, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
if(is_type(_1, vm->tp_bool)) return VAR(_0 == _1);
|
||||
if(is_int(_1)) return VAR(_CAST(bool, _0) == (bool)CAST(i64, _1));
|
||||
return vm->NotImplemented;
|
||||
});
|
||||
|
||||
// tp_ellipsis / tp_NotImplementedType
|
||||
_vm->bind__repr__(_vm->_tp(_vm->Ellipsis), [](VM* vm, PyObject* _0) -> Str{
|
||||
_vm->bind__repr__(_vm->_tp(_vm->Ellipsis), [](VM* vm, PyVar _0) -> Str{
|
||||
return "...";
|
||||
});
|
||||
_vm->bind__repr__(_vm->_tp(_vm->NotImplemented), [](VM* vm, PyObject* _0) -> Str{
|
||||
_vm->bind__repr__(_vm->_tp(_vm->NotImplemented), [](VM* vm, PyVar _0) -> Str{
|
||||
return "NotImplemented";
|
||||
});
|
||||
|
||||
@ -1102,7 +1102,7 @@ void __init_builtins(VM* _vm) {
|
||||
return VAR(Bytes(buffer, list.size()));
|
||||
});
|
||||
|
||||
_vm->bind__getitem__(VM::tp_bytes, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__getitem__(VM::tp_bytes, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
const Bytes& self = PK_OBJ_GET(Bytes, _0);
|
||||
if(is_type(_1, vm->tp_slice)){
|
||||
const Slice& s = _CAST(Slice&, _1);
|
||||
@ -1120,7 +1120,7 @@ void __init_builtins(VM* _vm) {
|
||||
return VAR(self[i]);
|
||||
});
|
||||
|
||||
_vm->bind__add__(VM::tp_bytes, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__add__(VM::tp_bytes, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
const Bytes& a = _CAST(Bytes&, _0);
|
||||
const Bytes& b = CAST(Bytes&, _1);
|
||||
unsigned char *buffer = new unsigned char[a.size() + b.size()];
|
||||
@ -1129,13 +1129,13 @@ void __init_builtins(VM* _vm) {
|
||||
return VAR(Bytes(buffer, a.size() + b.size()));
|
||||
});
|
||||
|
||||
_vm->bind__hash__(VM::tp_bytes, [](VM* vm, PyObject* _0) {
|
||||
_vm->bind__hash__(VM::tp_bytes, [](VM* vm, PyVar _0) {
|
||||
const Bytes& self = _CAST(Bytes&, _0);
|
||||
std::string_view view((char*)self.data(), self.size());
|
||||
return (i64)std::hash<std::string_view>()(view);
|
||||
});
|
||||
|
||||
_vm->bind__repr__(VM::tp_bytes, [](VM* vm, PyObject* _0) -> Str {
|
||||
_vm->bind__repr__(VM::tp_bytes, [](VM* vm, PyVar _0) -> Str {
|
||||
const Bytes& self = _CAST(Bytes&, _0);
|
||||
SStream ss;
|
||||
ss << "b'";
|
||||
@ -1146,7 +1146,7 @@ void __init_builtins(VM* _vm) {
|
||||
ss << "'";
|
||||
return ss.str();
|
||||
});
|
||||
_vm->bind__len__(VM::tp_bytes, [](VM* vm, PyObject* _0) {
|
||||
_vm->bind__len__(VM::tp_bytes, [](VM* vm, PyVar _0) {
|
||||
return (i64)_CAST(Bytes&, _0).size();
|
||||
});
|
||||
|
||||
@ -1156,7 +1156,7 @@ void __init_builtins(VM* _vm) {
|
||||
return VAR(Str(self.str()));
|
||||
});
|
||||
|
||||
_vm->bind__eq__(VM::tp_bytes, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__eq__(VM::tp_bytes, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
if(!is_type(_1, vm->tp_bytes)) return vm->NotImplemented;
|
||||
return VAR(_CAST(Bytes&, _0) == _CAST(Bytes&, _1));
|
||||
});
|
||||
@ -1166,7 +1166,7 @@ void __init_builtins(VM* _vm) {
|
||||
return VAR(Slice(args[1], args[2], args[3]));
|
||||
});
|
||||
|
||||
_vm->bind__eq__(VM::tp_slice, [](VM* vm, PyObject* _0, PyObject* _1){
|
||||
_vm->bind__eq__(VM::tp_slice, [](VM* vm, PyVar _0, PyVar _1){
|
||||
const Slice& self = _CAST(Slice&, _0);
|
||||
if(!is_type(_1, vm->tp_slice)) return vm->NotImplemented;
|
||||
const Slice& other = _CAST(Slice&, _1);
|
||||
@ -1176,7 +1176,7 @@ void __init_builtins(VM* _vm) {
|
||||
return vm->True;
|
||||
});
|
||||
|
||||
_vm->bind__repr__(VM::tp_slice, [](VM* vm, PyObject* _0) -> Str {
|
||||
_vm->bind__repr__(VM::tp_slice, [](VM* vm, PyVar _0) -> Str {
|
||||
const Slice& self = _CAST(Slice&, _0);
|
||||
SStream ss;
|
||||
ss << "slice(";
|
||||
@ -1205,27 +1205,27 @@ void __init_builtins(VM* _vm) {
|
||||
MappingProxy& self = _CAST(MappingProxy&, args[0]);
|
||||
List items;
|
||||
for(auto [k, v] : self.attr().items()){
|
||||
PyObject* t = VAR(Tuple(VAR(k.sv()), v));
|
||||
PyVar t = VAR(Tuple(VAR(k.sv()), v));
|
||||
items.push_back(std::move(t));
|
||||
}
|
||||
return VAR(std::move(items));
|
||||
});
|
||||
|
||||
_vm->bind__len__(VM::tp_mappingproxy, [](VM* vm, PyObject* _0) {
|
||||
_vm->bind__len__(VM::tp_mappingproxy, [](VM* vm, PyVar _0) {
|
||||
return (i64)_CAST(MappingProxy&, _0).attr().size();
|
||||
});
|
||||
|
||||
_vm->bind__eq__(VM::tp_mappingproxy, [](VM* vm, PyObject* _0, PyObject* _1){
|
||||
_vm->bind__eq__(VM::tp_mappingproxy, [](VM* vm, PyVar _0, PyVar _1){
|
||||
const MappingProxy& a = _CAST(MappingProxy&, _0);
|
||||
if(!is_type(_1, VM::tp_mappingproxy)) return vm->NotImplemented;
|
||||
const MappingProxy& b = _CAST(MappingProxy&, _1);
|
||||
return VAR(a.obj == b.obj);
|
||||
});
|
||||
|
||||
_vm->bind__getitem__(VM::tp_mappingproxy, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__getitem__(VM::tp_mappingproxy, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
MappingProxy& self = _CAST(MappingProxy&, _0);
|
||||
StrName key = CAST(Str&, _1);
|
||||
PyObject* ret = self.attr().try_get_likely_found(key);
|
||||
PyVar ret = self.attr().try_get_likely_found(key);
|
||||
if(ret == nullptr) vm->KeyError(_1);
|
||||
return ret;
|
||||
});
|
||||
@ -1233,12 +1233,12 @@ void __init_builtins(VM* _vm) {
|
||||
_vm->bind(_vm->_t(VM::tp_mappingproxy), "get(self, key, default=None)", [](VM* vm, ArgsView args) {
|
||||
MappingProxy& self = _CAST(MappingProxy&, args[0]);
|
||||
StrName key = CAST(Str&, args[1]);
|
||||
PyObject* ret = self.attr().try_get(key);
|
||||
PyVar ret = self.attr().try_get(key);
|
||||
if(ret == nullptr) return args[2];
|
||||
return ret;
|
||||
});
|
||||
|
||||
_vm->bind__repr__(VM::tp_mappingproxy, [](VM* vm, PyObject* _0) -> Str{
|
||||
_vm->bind__repr__(VM::tp_mappingproxy, [](VM* vm, PyVar _0) -> Str{
|
||||
if(vm->_repr_recursion_set.count(_0)) return "{...}";
|
||||
MappingProxy& self = _CAST(MappingProxy&, _0);
|
||||
SStream ss;
|
||||
@ -1256,7 +1256,7 @@ void __init_builtins(VM* _vm) {
|
||||
return ss.str();
|
||||
});
|
||||
|
||||
_vm->bind__contains__(VM::tp_mappingproxy, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__contains__(VM::tp_mappingproxy, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
MappingProxy& self = _CAST(MappingProxy&, _0);
|
||||
return VAR(self.attr().contains(CAST(Str&, _1)));
|
||||
});
|
||||
@ -1279,7 +1279,7 @@ void __init_builtins(VM* _vm) {
|
||||
}
|
||||
if(is_type(args[1], vm->tp_list)){
|
||||
List& list = PK_OBJ_GET(List, args[1]);
|
||||
for(PyObject* item : list){
|
||||
for(PyVar item : list){
|
||||
Tuple& t = CAST(Tuple&, item);
|
||||
if(t.size() != 2){
|
||||
vm->ValueError("dict() takes a list of tuples (key, value)");
|
||||
@ -1295,17 +1295,17 @@ void __init_builtins(VM* _vm) {
|
||||
PK_UNREACHABLE()
|
||||
});
|
||||
|
||||
_vm->bind__len__(VM::tp_dict, [](VM* vm, PyObject* _0) {
|
||||
_vm->bind__len__(VM::tp_dict, [](VM* vm, PyVar _0) {
|
||||
return (i64)PK_OBJ_GET(Dict, _0).size();
|
||||
});
|
||||
|
||||
_vm->bind__getitem__(VM::tp_dict, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__getitem__(VM::tp_dict, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
Dict& self = PK_OBJ_GET(Dict, _0);
|
||||
PyObject* ret = self.try_get(_1);
|
||||
PyVar ret = self.try_get(_1);
|
||||
if(ret == nullptr){
|
||||
// try __missing__
|
||||
PyObject* self;
|
||||
PyObject* f_missing = vm->get_unbound_method(_0, __missing__, &self, false);
|
||||
PyVar self;
|
||||
PyVar f_missing = vm->get_unbound_method(_0, __missing__, &self, false);
|
||||
if(f_missing != nullptr){
|
||||
return vm->call_method(self, f_missing, _1);
|
||||
}
|
||||
@ -1314,12 +1314,12 @@ void __init_builtins(VM* _vm) {
|
||||
return ret;
|
||||
});
|
||||
|
||||
_vm->bind__setitem__(VM::tp_dict, [](VM* vm, PyObject* _0, PyObject* _1, PyObject* _2) {
|
||||
_vm->bind__setitem__(VM::tp_dict, [](VM* vm, PyVar _0, PyVar _1, PyVar _2) {
|
||||
Dict& self = _CAST(Dict&, _0);
|
||||
self.set(_1, _2);
|
||||
});
|
||||
|
||||
_vm->bind__delitem__(VM::tp_dict, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__delitem__(VM::tp_dict, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
Dict& self = _CAST(Dict&, _0);
|
||||
bool ok = self.erase(_1);
|
||||
if(!ok) vm->KeyError(_1);
|
||||
@ -1331,7 +1331,7 @@ void __init_builtins(VM* _vm) {
|
||||
return vm->None;
|
||||
}
|
||||
Dict& self = _CAST(Dict&, args[0]);
|
||||
PyObject* value = self.try_get(args[1]);
|
||||
PyVar value = self.try_get(args[1]);
|
||||
if(value == nullptr){
|
||||
if(args.size() == 2) vm->KeyError(args[1]);
|
||||
if(args.size() == 3){
|
||||
@ -1342,12 +1342,12 @@ void __init_builtins(VM* _vm) {
|
||||
return value;
|
||||
});
|
||||
|
||||
_vm->bind__contains__(VM::tp_dict, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__contains__(VM::tp_dict, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
Dict& self = _CAST(Dict&, _0);
|
||||
return VAR(self.contains(_1));
|
||||
});
|
||||
|
||||
_vm->bind__iter__(VM::tp_dict, [](VM* vm, PyObject* _0) {
|
||||
_vm->bind__iter__(VM::tp_dict, [](VM* vm, PyVar _0) {
|
||||
const Dict& self = _CAST(Dict&, _0);
|
||||
return vm->py_iter(VAR(self.keys()));
|
||||
});
|
||||
@ -1355,11 +1355,11 @@ void __init_builtins(VM* _vm) {
|
||||
_vm->bind_func(VM::tp_dict, "get", -1, [](VM* vm, ArgsView args) {
|
||||
Dict& self = _CAST(Dict&, args[0]);
|
||||
if(args.size() == 1+1){
|
||||
PyObject* ret = self.try_get(args[1]);
|
||||
PyVar ret = self.try_get(args[1]);
|
||||
if(ret != nullptr) return ret;
|
||||
return vm->None;
|
||||
}else if(args.size() == 1+2){
|
||||
PyObject* ret = self.try_get(args[1]);
|
||||
PyVar ret = self.try_get(args[1]);
|
||||
if(ret != nullptr) return ret;
|
||||
return args[2];
|
||||
}
|
||||
@ -1399,14 +1399,14 @@ void __init_builtins(VM* _vm) {
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bind__repr__(VM::tp_dict, [](VM* vm, PyObject* _0) -> Str{
|
||||
_vm->bind__repr__(VM::tp_dict, [](VM* vm, PyVar _0) -> Str{
|
||||
if(vm->_repr_recursion_set.count(_0)) return "{...}";
|
||||
Dict& self = _CAST(Dict&, _0);
|
||||
SStream ss;
|
||||
ss << "{";
|
||||
bool first = true;
|
||||
vm->_repr_recursion_set.insert(_0);
|
||||
self.apply([&](PyObject* k, PyObject* v){
|
||||
self.apply([&](PyVar k, PyVar v){
|
||||
if(!first) ss << ", ";
|
||||
first = false;
|
||||
ss << vm->py_repr(k) << ": " << vm->py_repr(v);
|
||||
@ -1416,7 +1416,7 @@ void __init_builtins(VM* _vm) {
|
||||
return ss.str();
|
||||
});
|
||||
|
||||
_vm->bind__eq__(VM::tp_dict, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||
_vm->bind__eq__(VM::tp_dict, [](VM* vm, PyVar _0, PyVar _1) {
|
||||
Dict& self = _CAST(Dict&, _0);
|
||||
if(!vm->isinstance(_1, vm->tp_dict)) return vm->NotImplemented;
|
||||
Dict& other = _CAST(Dict&, _1);
|
||||
@ -1424,14 +1424,14 @@ void __init_builtins(VM* _vm) {
|
||||
for(int i=0; i<self._capacity; i++){
|
||||
auto item = self._items[i];
|
||||
if(item.first == nullptr) continue;
|
||||
PyObject* value = other.try_get(item.first);
|
||||
PyVar value = other.try_get(item.first);
|
||||
if(value == nullptr) return vm->False;
|
||||
if(!vm->py_eq(item.second, value)) return vm->False;
|
||||
}
|
||||
return vm->True;
|
||||
});
|
||||
|
||||
_vm->bind__repr__(VM::tp_module, [](VM* vm, PyObject* _0) -> Str {
|
||||
_vm->bind__repr__(VM::tp_module, [](VM* vm, PyVar _0) -> Str {
|
||||
const Str& path = CAST(Str&, _0->attr(__path__));
|
||||
return _S("<module ", path.escape(), ">");
|
||||
});
|
||||
@ -1464,7 +1464,7 @@ void __init_builtins(VM* _vm) {
|
||||
_vm->bind_func(VM::tp_exception, __new__, -1, [](VM* vm, ArgsView args){
|
||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||
StrName cls_name = _type_name(vm, cls);
|
||||
PyObject* e_obj = vm->heap.gcnew<Exception>(cls, cls_name);
|
||||
PyVar e_obj = vm->heap.gcnew<Exception>(cls, cls_name);
|
||||
e_obj->_enable_instance_dict();
|
||||
PK_OBJ_GET(Exception, e_obj)._self = e_obj;
|
||||
return e_obj;
|
||||
@ -1480,12 +1480,12 @@ void __init_builtins(VM* _vm) {
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bind__repr__(VM::tp_exception, [](VM* vm, PyObject* _0) -> Str {
|
||||
_vm->bind__repr__(VM::tp_exception, [](VM* vm, PyVar _0) -> Str {
|
||||
Exception& self = _CAST(Exception&, _0);
|
||||
return _S(_type_name(vm, _0->type), '(', self.msg.escape(), ')');
|
||||
});
|
||||
|
||||
_vm->bind__str__(VM::tp_exception, [](VM* vm, PyObject* _0) -> Str{
|
||||
_vm->bind__str__(VM::tp_exception, [](VM* vm, PyVar _0) -> Str{
|
||||
Exception& self = _CAST(Exception&, _0);
|
||||
return self.msg;
|
||||
});
|
||||
@ -1502,7 +1502,7 @@ void VM::__post_init_builtin_types(){
|
||||
|
||||
bind_func(tp_module, __new__, -1, PK_ACTION(vm->NotImplementedError()));
|
||||
|
||||
_all_types[tp_module].m__getattr__ = [](VM* vm, PyObject* obj, StrName name) -> PyObject*{
|
||||
_all_types[tp_module].m__getattr__ = [](VM* vm, PyVar obj, StrName name) -> PyVar{
|
||||
const Str& path = CAST(Str&, obj->attr(__path__));
|
||||
return vm->py_import(_S(path, ".", name.sv()), false);
|
||||
};
|
||||
@ -1516,11 +1516,11 @@ void VM::__post_init_builtin_types(){
|
||||
});
|
||||
|
||||
// type
|
||||
bind__getitem__(tp_type, [](VM* vm, PyObject* self, PyObject* _){
|
||||
bind__getitem__(tp_type, [](VM* vm, PyVar self, PyVar _){
|
||||
return self; // for generics
|
||||
});
|
||||
|
||||
bind__repr__(tp_type, [](VM* vm, PyObject* self) -> Str{
|
||||
bind__repr__(tp_type, [](VM* vm, PyVar self) -> Str{
|
||||
SStream ss;
|
||||
const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, self)];
|
||||
ss << "<class '" << info.name << "'>";
|
||||
@ -1548,7 +1548,7 @@ void VM::__post_init_builtin_types(){
|
||||
return CAST(BoundMethod&, args[0]).func;
|
||||
});
|
||||
|
||||
bind__eq__(tp_bound_method, [](VM* vm, PyObject* lhs, PyObject* rhs){
|
||||
bind__eq__(tp_bound_method, [](VM* vm, PyVar lhs, PyVar rhs){
|
||||
if(!is_type(rhs, vm->tp_bound_method)) return vm->NotImplemented;
|
||||
const BoundMethod& _0 = PK_OBJ_GET(BoundMethod, lhs);
|
||||
const BoundMethod& _1 = PK_OBJ_GET(BoundMethod, rhs);
|
||||
|
@ -25,9 +25,9 @@ static int count_extra_elements(VM* vm, int n){
|
||||
return vm->s_data._sp - vm->__c.s_view.top().end();
|
||||
}
|
||||
|
||||
static PyObject* stack_item(VM* vm, int index){
|
||||
PyObject** begin;
|
||||
PyObject** end = vm->s_data.end();
|
||||
static PyVar stack_item(VM* vm, int index){
|
||||
PyVar* begin;
|
||||
PyVar* end = vm->s_data.end();
|
||||
if(vm->callstack.empty()){
|
||||
begin = vm->s_data.begin();
|
||||
}else{
|
||||
@ -48,7 +48,7 @@ static PyObject* stack_item(VM* vm, int index){
|
||||
vm->__c.error = e.self(); \
|
||||
return false; \
|
||||
} catch(const std::exception& re){ \
|
||||
PyObject* e_t = vm->_t(vm->tp_exception); \
|
||||
PyVar e_t = vm->_t(vm->tp_exception); \
|
||||
vm->__c.error = vm->call(e_t, VAR(re.what())); \
|
||||
return false; \
|
||||
}
|
||||
@ -64,7 +64,7 @@ void pkpy_delete_vm(pkpy_vm* vm){
|
||||
bool pkpy_exec(pkpy_vm* vm_handle, const char* source) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PyObject* res;
|
||||
PyVar res;
|
||||
PK_PROTECTED(
|
||||
CodeObject_ code = vm->compile(source, "main.py", EXEC_MODE);
|
||||
res = vm->_exec(code, vm->_main);
|
||||
@ -75,8 +75,8 @@ bool pkpy_exec(pkpy_vm* vm_handle, const char* source) {
|
||||
bool pkpy_exec_2(pkpy_vm* vm_handle, const char* source, const char* filename, int mode, const char* module){
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PyObject* res;
|
||||
PyObject* mod;
|
||||
PyVar res;
|
||||
PyVar mod;
|
||||
PK_PROTECTED(
|
||||
if(module == nullptr){
|
||||
mod = vm->_main;
|
||||
@ -98,7 +98,7 @@ bool pkpy_dup(pkpy_vm* vm_handle, int n){
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
PyObject* item = stack_item(vm, n);
|
||||
PyVar item = stack_item(vm, n);
|
||||
vm->s_data.push(item);
|
||||
)
|
||||
return true;
|
||||
@ -150,7 +150,7 @@ int pkpy_stack_size(pkpy_vm* vm_handle){
|
||||
bool pkpy_push_int(pkpy_vm* vm_handle, int value) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PyObject* res;
|
||||
PyVar res;
|
||||
PK_PROTECTED(
|
||||
// int may overflow so we should protect it
|
||||
res = py_var(vm, value);
|
||||
@ -171,7 +171,7 @@ bool pkpy_to_int(pkpy_vm* vm_handle, int i, int* out){
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
PyObject* item = stack_item(vm, i);
|
||||
PyVar item = stack_item(vm, i);
|
||||
*out = py_cast<int>(vm, item);
|
||||
)
|
||||
return true;
|
||||
@ -181,7 +181,7 @@ bool pkpy_to_int(pkpy_vm* vm_handle, int i, int* out){
|
||||
bool pkpy_push_float(pkpy_vm* vm_handle, double value) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PyObject* res = py_var(vm, value);
|
||||
PyVar res = py_var(vm, value);
|
||||
vm->s_data.push(res);
|
||||
return true;
|
||||
}
|
||||
@ -190,7 +190,7 @@ bool pkpy_is_float(pkpy_vm* vm_handle, int i){
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
PyObject* item = stack_item(vm, i);
|
||||
PyVar item = stack_item(vm, i);
|
||||
return is_float(item);
|
||||
)
|
||||
}
|
||||
@ -199,7 +199,7 @@ bool pkpy_to_float(pkpy_vm* vm_handle, int i, double* out){
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
PyObject* item = stack_item(vm, i);
|
||||
PyVar item = stack_item(vm, i);
|
||||
*out = py_cast<double>(vm, item);
|
||||
)
|
||||
return true;
|
||||
@ -217,7 +217,7 @@ bool pkpy_is_bool(pkpy_vm* vm_handle, int i){
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
PyObject* item = stack_item(vm, i);
|
||||
PyVar item = stack_item(vm, i);
|
||||
return is_type(item, vm->tp_bool);
|
||||
)
|
||||
}
|
||||
@ -226,7 +226,7 @@ bool pkpy_to_bool(pkpy_vm* vm_handle, int i, bool* out){
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
PyObject* item = stack_item(vm, i);
|
||||
PyVar item = stack_item(vm, i);
|
||||
*out = py_cast<bool>(vm, item);
|
||||
)
|
||||
return true;
|
||||
@ -236,7 +236,7 @@ bool pkpy_to_bool(pkpy_vm* vm_handle, int i, bool* out){
|
||||
bool pkpy_push_string(pkpy_vm* vm_handle, pkpy_CString value) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PyObject* res = py_var(vm, value);
|
||||
PyVar res = py_var(vm, value);
|
||||
vm->s_data.push(res);
|
||||
return true;
|
||||
}
|
||||
@ -245,7 +245,7 @@ bool pkpy_is_string(pkpy_vm* vm_handle, int i){
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
PyObject* item = stack_item(vm, i);
|
||||
PyVar item = stack_item(vm, i);
|
||||
return is_type(item, vm->tp_str);
|
||||
)
|
||||
}
|
||||
@ -254,7 +254,7 @@ bool pkpy_to_string(pkpy_vm* vm_handle, int i, pkpy_CString* out){
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
PyObject* item = stack_item(vm, i);
|
||||
PyVar item = stack_item(vm, i);
|
||||
const Str& s = py_cast<Str&>(vm, item);
|
||||
*out = s.c_str();
|
||||
)
|
||||
@ -265,7 +265,7 @@ bool pkpy_to_string(pkpy_vm* vm_handle, int i, pkpy_CString* out){
|
||||
bool pkpy_push_voidp(pkpy_vm* vm_handle, void* value) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PyObject* res = py_var(vm, value);
|
||||
PyVar res = py_var(vm, value);
|
||||
vm->s_data.push(res);
|
||||
return true;
|
||||
}
|
||||
@ -274,7 +274,7 @@ bool pkpy_is_voidp(pkpy_vm* vm_handle, int i){
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
PyObject* item = stack_item(vm, i);
|
||||
PyVar item = stack_item(vm, i);
|
||||
return vm->is_user_type<VoidP>(item);
|
||||
)
|
||||
}
|
||||
@ -283,7 +283,7 @@ bool pkpy_to_voidp(pkpy_vm* vm_handle, int i, void** out){
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
PyObject* item = stack_item(vm, i);
|
||||
PyVar item = stack_item(vm, i);
|
||||
VoidP& vp = py_cast<VoidP&>(vm, item);
|
||||
*out = vp.ptr;
|
||||
)
|
||||
@ -302,7 +302,7 @@ bool pkpy_is_none(pkpy_vm* vm_handle, int i){
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
PyObject* item = stack_item(vm, i);
|
||||
PyVar item = stack_item(vm, i);
|
||||
return item == vm->None;
|
||||
)
|
||||
}
|
||||
@ -331,9 +331,9 @@ struct TempViewPopper{
|
||||
};
|
||||
|
||||
// function
|
||||
static PyObject* c_function_wrapper(VM* vm, ArgsView args) {
|
||||
static PyVar c_function_wrapper(VM* vm, ArgsView args) {
|
||||
pkpy_CFunction f = lambda_get_userdata<pkpy_CFunction>(args.begin());
|
||||
PyObject** curr_sp = vm->s_data._sp;
|
||||
PyVar* curr_sp = vm->s_data._sp;
|
||||
|
||||
vm->__c.s_view.push(args);
|
||||
TempViewPopper _tvp(vm);
|
||||
@ -342,7 +342,7 @@ static PyObject* c_function_wrapper(VM* vm, ArgsView args) {
|
||||
|
||||
// propagate_if_errored
|
||||
if (vm->__c.error != nullptr){
|
||||
PyObject* e_obj = PK_OBJ_GET(Exception, vm->__c.error).self();
|
||||
PyVar e_obj = PK_OBJ_GET(Exception, vm->__c.error).self();
|
||||
vm->__c.error = nullptr;
|
||||
vm->_error(e_obj);
|
||||
return nullptr;
|
||||
@ -357,7 +357,7 @@ static PyObject* c_function_wrapper(VM* vm, ArgsView args) {
|
||||
bool pkpy_push_function(pkpy_vm* vm_handle, const char* sig, pkpy_CFunction f) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PyObject* f_obj;
|
||||
PyVar f_obj;
|
||||
PK_PROTECTED(
|
||||
f_obj = vm->bind(nullptr, sig, c_function_wrapper, f);
|
||||
)
|
||||
@ -370,7 +370,7 @@ bool pkpy_push_module(pkpy_vm* vm_handle, const char* name) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
PyObject* module = vm->new_module(name);
|
||||
PyVar module = vm->new_module(name);
|
||||
vm->s_data.push(module);
|
||||
)
|
||||
return true;
|
||||
@ -381,7 +381,7 @@ bool pkpy_getattr(pkpy_vm* vm_handle, pkpy_CName name) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_ASSERT_N_EXTRA_ELEMENTS(1)
|
||||
PyObject* o = vm->s_data.top();
|
||||
PyVar o = vm->s_data.top();
|
||||
o = vm->getattr(o, StrName(name), false);
|
||||
if(o == nullptr) return false;
|
||||
vm->s_data.top() = o;
|
||||
@ -392,8 +392,8 @@ bool pkpy_setattr(pkpy_vm* vm_handle, pkpy_CName name) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_ASSERT_N_EXTRA_ELEMENTS(2)
|
||||
PyObject* a = vm->s_data.top();
|
||||
PyObject* val = vm->s_data.second();
|
||||
PyVar a = vm->s_data.top();
|
||||
PyVar val = vm->s_data.second();
|
||||
PK_PROTECTED(
|
||||
vm->setattr(a, StrName(name), val);
|
||||
)
|
||||
@ -405,7 +405,7 @@ bool pkpy_setattr(pkpy_vm* vm_handle, pkpy_CName name) {
|
||||
bool pkpy_getglobal(pkpy_vm* vm_handle, pkpy_CName name) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PyObject* o = vm->_main->attr().try_get(StrName(name));
|
||||
PyVar o = vm->_main->attr().try_get(StrName(name));
|
||||
if (o == nullptr) {
|
||||
o = vm->builtins->attr().try_get(StrName(name));
|
||||
if (o == nullptr) return false;
|
||||
@ -427,7 +427,7 @@ bool pkpy_eval(pkpy_vm* vm_handle, const char* source) {
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_PROTECTED(
|
||||
CodeObject_ co = vm->compile(source, "<eval>", EVAL_MODE);
|
||||
PyObject* ret = vm->_exec(co, vm->_main);
|
||||
PyVar ret = vm->_exec(co, vm->_main);
|
||||
vm->s_data.push(ret);
|
||||
)
|
||||
return true;
|
||||
@ -439,9 +439,9 @@ bool pkpy_unpack_sequence(pkpy_vm* vm_handle, int n) {
|
||||
PK_ASSERT_N_EXTRA_ELEMENTS(1)
|
||||
auto _lock = vm->heap.gc_scope_lock();
|
||||
PK_PROTECTED(
|
||||
PyObject* _0 = vm->py_iter(vm->s_data.popx());
|
||||
PyVar _0 = vm->py_iter(vm->s_data.popx());
|
||||
for(int i=0; i<n; i++){
|
||||
PyObject* _1 = vm->py_next(_0);
|
||||
PyVar _1 = vm->py_next(_0);
|
||||
if(_1 == vm->StopIteration) vm->ValueError("not enough values to unpack");
|
||||
vm->s_data.push(_1);
|
||||
}
|
||||
@ -454,8 +454,8 @@ bool pkpy_get_unbound_method(pkpy_vm* vm_handle, pkpy_CName name){
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_ASSERT_N_EXTRA_ELEMENTS(1)
|
||||
PyObject* o = vm->s_data.top();
|
||||
PyObject* self;
|
||||
PyVar o = vm->s_data.top();
|
||||
PyVar self;
|
||||
PK_PROTECTED(
|
||||
o = vm->get_unbound_method(o, StrName(name), &self);
|
||||
)
|
||||
@ -469,7 +469,7 @@ bool pkpy_py_repr(pkpy_vm* vm_handle) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_ASSERT_N_EXTRA_ELEMENTS(1)
|
||||
PyObject* item = vm->s_data.top();
|
||||
PyVar item = vm->s_data.top();
|
||||
PK_PROTECTED(
|
||||
item = VAR(vm->py_repr(item));
|
||||
)
|
||||
@ -481,7 +481,7 @@ bool pkpy_py_str(pkpy_vm* vm_handle) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_ASSERT_N_EXTRA_ELEMENTS(1)
|
||||
PyObject* item = vm->s_data.top();
|
||||
PyVar item = vm->s_data.top();
|
||||
PK_PROTECTED(
|
||||
item = VAR(vm->py_str(item));
|
||||
)
|
||||
@ -493,7 +493,7 @@ bool pkpy_py_str(pkpy_vm* vm_handle) {
|
||||
bool pkpy_error(pkpy_vm* vm_handle, const char* name, pkpy_CString message) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PyObject* e_t = vm->_main->attr().try_get_likely_found(name);
|
||||
PyVar e_t = vm->_main->attr().try_get_likely_found(name);
|
||||
if(e_t == nullptr){
|
||||
e_t = vm->builtins->attr().try_get_likely_found(name);
|
||||
if(e_t == nullptr){
|
||||
@ -533,7 +533,7 @@ bool pkpy_vectorcall(pkpy_vm* vm_handle, int argc) {
|
||||
VM* vm = (VM*) vm_handle;
|
||||
PK_ASSERT_NO_ERROR()
|
||||
PK_ASSERT_N_EXTRA_ELEMENTS(argc + 2)
|
||||
PyObject* res;
|
||||
PyVar res;
|
||||
PK_PROTECTED(
|
||||
res = vm->vectorcall(argc);
|
||||
)
|
||||
|
@ -133,7 +133,7 @@ struct Random{
|
||||
gen.seed((uint32_t)count);
|
||||
}
|
||||
|
||||
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
||||
vm->bind_func(type, __new__, 1, [](VM* vm, ArgsView args){
|
||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||
return vm->heap.gcnew<Random>(cls);
|
||||
@ -187,7 +187,7 @@ struct Random{
|
||||
vm->bind(type, "choices(self, population, weights=None, k=1)", [](VM* vm, ArgsView args) {
|
||||
Random& self = PK_OBJ_GET(Random, args[0]);
|
||||
ArgsView view = vm->cast_array_view(args[1]);
|
||||
PyObject** data = view.begin();
|
||||
PyVar* data = view.begin();
|
||||
int size = view.size();
|
||||
if(size == 0) vm->IndexError("cannot choose from an empty sequence");
|
||||
pod_vector<f64> cum_weights(size);
|
||||
@ -215,9 +215,9 @@ struct Random{
|
||||
};
|
||||
|
||||
void add_module_random(VM* vm){
|
||||
PyObject* mod = vm->new_module("random");
|
||||
PyVar mod = vm->new_module("random");
|
||||
vm->register_user_class<Random>(mod, "Random");
|
||||
PyObject* instance = vm->new_user_object<Random>();
|
||||
PyVar instance = vm->new_user_object<Random>();
|
||||
mod->attr().set("seed", vm->getattr(instance, "seed"));
|
||||
mod->attr().set("random", vm->getattr(instance, "random"));
|
||||
mod->attr().set("uniform", vm->getattr(instance, "uniform"));
|
||||
|
@ -6,7 +6,7 @@ Tuple::Tuple(int n){
|
||||
if(n <= 3){
|
||||
this->_args = _inlined;
|
||||
}else{
|
||||
this->_args = (PyObject**)pool64_alloc(n * sizeof(void*));
|
||||
this->_args = (PyVar*)pool64_alloc(n * sizeof(void*));
|
||||
}
|
||||
this->_size = n;
|
||||
}
|
||||
@ -33,18 +33,18 @@ Tuple::Tuple(List&& other) noexcept {
|
||||
other._data = nullptr;
|
||||
}
|
||||
|
||||
Tuple::Tuple(PyObject* _0, PyObject* _1): Tuple(2){
|
||||
Tuple::Tuple(PyVar _0, PyVar _1): Tuple(2){
|
||||
_args[0] = _0;
|
||||
_args[1] = _1;
|
||||
}
|
||||
|
||||
Tuple::Tuple(PyObject* _0, PyObject* _1, PyObject* _2): Tuple(3){
|
||||
Tuple::Tuple(PyVar _0, PyVar _1, PyVar _2): Tuple(3){
|
||||
_args[0] = _0;
|
||||
_args[1] = _1;
|
||||
_args[2] = _2;
|
||||
}
|
||||
|
||||
Tuple::Tuple(PyObject* _0, PyObject* _1, PyObject* _2, PyObject* _3): Tuple(4){
|
||||
Tuple::Tuple(PyVar _0, PyVar _1, PyVar _2, PyVar _3): Tuple(4){
|
||||
_args[0] = _0;
|
||||
_args[1] = _1;
|
||||
_args[2] = _2;
|
||||
|
270
src/vm.cpp
270
src/vm.cpp
@ -10,10 +10,10 @@ namespace pkpy{
|
||||
|
||||
struct JsonSerializer{
|
||||
VM* vm;
|
||||
PyObject* root;
|
||||
PyVar root;
|
||||
SStream ss;
|
||||
|
||||
JsonSerializer(VM* vm, PyObject* root) : vm(vm), root(root) {}
|
||||
JsonSerializer(VM* vm, PyVar root) : vm(vm), root(root) {}
|
||||
|
||||
template<typename T>
|
||||
void write_array(T& arr){
|
||||
@ -28,7 +28,7 @@ namespace pkpy{
|
||||
void write_dict(Dict& dict){
|
||||
ss << '{';
|
||||
bool first = true;
|
||||
dict.apply([&](PyObject* k, PyObject* v){
|
||||
dict.apply([&](PyVar k, PyVar v){
|
||||
if(!first) ss << ", ";
|
||||
first = false;
|
||||
if(!is_type(k, VM::tp_str)){
|
||||
@ -40,7 +40,7 @@ namespace pkpy{
|
||||
ss << '}';
|
||||
}
|
||||
|
||||
void write_object(PyObject* obj){
|
||||
void write_object(PyVar obj){
|
||||
Type obj_t = vm->_tp(obj);
|
||||
if(obj == vm->None){
|
||||
ss << "null";
|
||||
@ -84,13 +84,13 @@ namespace pkpy{
|
||||
__init_builtin_types();
|
||||
}
|
||||
|
||||
Str VM::py_str(PyObject* obj){
|
||||
Str VM::py_str(PyVar obj){
|
||||
const PyTypeInfo* ti = _tp_info(obj);
|
||||
if(ti->m__str__) return ti->m__str__(this, obj);
|
||||
PyObject* self;
|
||||
PyObject* f = get_unbound_method(obj, __str__, &self, false);
|
||||
PyVar self;
|
||||
PyVar f = get_unbound_method(obj, __str__, &self, false);
|
||||
if(self != PY_NULL){
|
||||
PyObject* retval = call_method(self, f);
|
||||
PyVar retval = call_method(self, f);
|
||||
if(!is_type(retval, tp_str)){
|
||||
throw std::runtime_error("object.__str__ must return str");
|
||||
}
|
||||
@ -99,32 +99,32 @@ namespace pkpy{
|
||||
return py_repr(obj);
|
||||
}
|
||||
|
||||
Str VM::py_repr(PyObject* obj){
|
||||
Str VM::py_repr(PyVar obj){
|
||||
const PyTypeInfo* ti = _tp_info(obj);
|
||||
if(ti->m__repr__) return ti->m__repr__(this, obj);
|
||||
PyObject* retval = call_method(obj, __repr__);
|
||||
PyVar retval = call_method(obj, __repr__);
|
||||
if(!is_type(retval, tp_str)){
|
||||
throw std::runtime_error("object.__repr__ must return str");
|
||||
}
|
||||
return PK_OBJ_GET(Str, retval);
|
||||
}
|
||||
|
||||
Str VM::py_json(PyObject* obj){
|
||||
Str VM::py_json(PyVar obj){
|
||||
auto j = JsonSerializer(this, obj);
|
||||
return j.serialize();
|
||||
}
|
||||
|
||||
PyObject* VM::py_iter(PyObject* obj){
|
||||
PyVar VM::py_iter(PyVar obj){
|
||||
const PyTypeInfo* ti = _tp_info(obj);
|
||||
if(ti->m__iter__) return ti->m__iter__(this, obj);
|
||||
PyObject* self;
|
||||
PyObject* iter_f = get_unbound_method(obj, __iter__, &self, false);
|
||||
PyVar self;
|
||||
PyVar iter_f = get_unbound_method(obj, __iter__, &self, false);
|
||||
if(self != PY_NULL) return call_method(self, iter_f);
|
||||
TypeError(_type_name(vm, _tp(obj)).escape() + " object is not iterable");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ArgsView VM::cast_array_view(PyObject* obj){
|
||||
ArgsView VM::cast_array_view(PyVar obj){
|
||||
if(is_type(obj, VM::tp_list)){
|
||||
List& list = PK_OBJ_GET(List, obj);
|
||||
return ArgsView(list.begin(), list.end());
|
||||
@ -137,14 +137,14 @@ namespace pkpy{
|
||||
}
|
||||
|
||||
void VM::set_main_argv(int argc, char** argv){
|
||||
PyObject* mod = vm->_modules["sys"];
|
||||
PyVar mod = vm->_modules["sys"];
|
||||
List argv_(argc);
|
||||
for(int i=0; i<argc; i++) argv_[i] = VAR(std::string_view(argv[i]));
|
||||
mod->attr().set("argv", VAR(std::move(argv_)));
|
||||
}
|
||||
|
||||
PyObject* VM::find_name_in_mro(Type cls, StrName name){
|
||||
PyObject* val;
|
||||
PyVar VM::find_name_in_mro(Type cls, StrName name){
|
||||
PyVar val;
|
||||
do{
|
||||
val = _t(cls)->attr().try_get(name);
|
||||
if(val != nullptr) return val;
|
||||
@ -154,7 +154,7 @@ namespace pkpy{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool VM::isinstance(PyObject* obj, Type base){
|
||||
bool VM::isinstance(PyVar obj, Type base){
|
||||
return issubclass(_tp(obj), base);
|
||||
}
|
||||
|
||||
@ -168,7 +168,7 @@ namespace pkpy{
|
||||
return false;
|
||||
}
|
||||
|
||||
PyObject* VM::exec(std::string_view source, Str filename, CompileMode mode, PyObject* _module){
|
||||
PyVar VM::exec(std::string_view source, Str filename, CompileMode mode, PyVar _module){
|
||||
if(_module == nullptr) _module = _main;
|
||||
try {
|
||||
#if PK_DEBUG_PRECOMPILED_EXEC == 1
|
||||
@ -197,16 +197,16 @@ namespace pkpy{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* VM::exec(std::string_view source){
|
||||
PyVar VM::exec(std::string_view source){
|
||||
return exec(source, "main.py", EXEC_MODE);
|
||||
}
|
||||
|
||||
PyObject* VM::eval(std::string_view source){
|
||||
PyVar VM::eval(std::string_view source){
|
||||
return exec(source, "<eval>", EVAL_MODE);
|
||||
}
|
||||
|
||||
PyObject* VM::new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled){
|
||||
PyObject* obj = heap._new<Type>(tp_type, Type(_all_types.size()));
|
||||
PyVar VM::new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled){
|
||||
PyVar obj = heap._new<Type>(tp_type, Type(_all_types.size()));
|
||||
const PyTypeInfo& base_info = _all_types[base];
|
||||
if(!base_info.subclass_enabled){
|
||||
Str error = _S("type ", base_info.name.escape(), " is not `subclass_enabled`");
|
||||
@ -223,10 +223,10 @@ namespace pkpy{
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool VM::py_eq(PyObject* lhs, PyObject* rhs){
|
||||
bool VM::py_eq(PyVar lhs, PyVar rhs){
|
||||
if(lhs == rhs) return true;
|
||||
const PyTypeInfo* ti = _tp_info(lhs);
|
||||
PyObject* res;
|
||||
PyVar res;
|
||||
if(ti->m__eq__){
|
||||
res = ti->m__eq__(this, lhs, rhs);
|
||||
if(res != vm->NotImplemented) return res == vm->True;
|
||||
@ -244,8 +244,8 @@ namespace pkpy{
|
||||
return false;
|
||||
}
|
||||
|
||||
PyObject* VM::py_op(std::string_view name){
|
||||
PyObject* func;
|
||||
PyVar VM::py_op(std::string_view name){
|
||||
PyVar func;
|
||||
auto it = __cached_op_funcs.find(name);
|
||||
if(it == __cached_op_funcs.end()){
|
||||
func = py_import("operator")->attr(StrName::get(name));
|
||||
@ -264,7 +264,7 @@ namespace pkpy{
|
||||
return index;
|
||||
}
|
||||
|
||||
PyObject* VM::_py_next(const PyTypeInfo* ti, PyObject* obj){
|
||||
PyVar VM::_py_next(const PyTypeInfo* ti, PyVar obj){
|
||||
if(ti->m__next__){
|
||||
unsigned n = ti->m__next__(this, obj);
|
||||
return __pack_next_retval(n);
|
||||
@ -272,12 +272,12 @@ namespace pkpy{
|
||||
return call_method(obj, __next__);
|
||||
}
|
||||
|
||||
PyObject* VM::py_next(PyObject* obj){
|
||||
PyVar VM::py_next(PyVar obj){
|
||||
const PyTypeInfo* ti = _tp_info(obj);
|
||||
return _py_next(ti, obj);
|
||||
}
|
||||
|
||||
bool VM::py_callable(PyObject* obj){
|
||||
bool VM::py_callable(PyVar obj){
|
||||
Type cls = vm->_tp(obj);
|
||||
switch(cls.index){
|
||||
case VM::tp_function.index: return vm->True;
|
||||
@ -288,13 +288,13 @@ namespace pkpy{
|
||||
return vm->find_name_in_mro(cls, __call__) != nullptr;
|
||||
}
|
||||
|
||||
PyObject* VM::__minmax_reduce(bool (VM::*op)(PyObject*, PyObject*), PyObject* args, PyObject* key){
|
||||
PyVar VM::__minmax_reduce(bool (VM::*op)(PyVar, PyVar), PyVar args, PyVar key){
|
||||
auto _lock = heap.gc_scope_lock();
|
||||
const Tuple& args_tuple = PK_OBJ_GET(Tuple, args); // from *args, it must be a tuple
|
||||
if(key==vm->None && args_tuple.size()==2){
|
||||
// fast path
|
||||
PyObject* a = args_tuple[0];
|
||||
PyObject* b = args_tuple[1];
|
||||
PyVar a = args_tuple[0];
|
||||
PyVar b = args_tuple[1];
|
||||
return (this->*op)(a, b) ? a : b;
|
||||
}
|
||||
|
||||
@ -308,7 +308,7 @@ namespace pkpy{
|
||||
}
|
||||
|
||||
if(view.empty()) ValueError("arg is an empty sequence");
|
||||
PyObject* res = view[0];
|
||||
PyVar res = view[0];
|
||||
|
||||
if(key == vm->None){
|
||||
for(int i=1; i<view.size(); i++){
|
||||
@ -317,15 +317,15 @@ namespace pkpy{
|
||||
}else{
|
||||
auto _lock = heap.gc_scope_lock();
|
||||
for(int i=1; i<view.size(); i++){
|
||||
PyObject* a = call(key, view[i]);
|
||||
PyObject* b = call(key, res);
|
||||
PyVar a = call(key, view[i]);
|
||||
PyVar b = call(key, res);
|
||||
if((this->*op)(a, b)) res = view[i];
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
PyObject* VM::py_import(Str path, bool throw_err){
|
||||
PyVar VM::py_import(Str path, bool throw_err){
|
||||
if(path.empty()) vm->ValueError("empty module name");
|
||||
static auto f_join = [](const pod_vector<std::string_view>& cpnts){
|
||||
SStream ss;
|
||||
@ -360,7 +360,7 @@ namespace pkpy{
|
||||
|
||||
// check existing module
|
||||
StrName name(path);
|
||||
PyObject* ext_mod = _modules.try_get(name);
|
||||
PyVar ext_mod = _modules.try_get(name);
|
||||
if(ext_mod != nullptr) return ext_mod;
|
||||
|
||||
pod_vector<std::string_view> path_cpnts = path.split('.');
|
||||
@ -398,7 +398,7 @@ namespace pkpy{
|
||||
|
||||
Str name_cpnt = path_cpnts.back();
|
||||
path_cpnts.pop_back();
|
||||
PyObject* new_mod = new_module(name_cpnt, f_join(path_cpnts));
|
||||
PyVar new_mod = new_module(name_cpnt, f_join(path_cpnts));
|
||||
_exec(code, new_mod);
|
||||
return new_mod;
|
||||
}
|
||||
@ -411,33 +411,33 @@ namespace pkpy{
|
||||
_lazy_modules.clear();
|
||||
}
|
||||
|
||||
PyObject* VM::py_negate(PyObject* obj){
|
||||
PyVar VM::py_negate(PyVar obj){
|
||||
const PyTypeInfo* ti = _tp_info(obj);
|
||||
if(ti->m__neg__) return ti->m__neg__(this, obj);
|
||||
return call_method(obj, __neg__);
|
||||
}
|
||||
|
||||
bool VM::py_bool(PyObject* obj){
|
||||
bool VM::py_bool(PyVar obj){
|
||||
if(obj == vm->True) return true;
|
||||
if(obj == vm->False) return false;
|
||||
if(obj == None) return false;
|
||||
if(is_int(obj)) return _CAST(i64, obj) != 0;
|
||||
if(is_float(obj)) return _CAST(f64, obj) != 0.0;
|
||||
PyObject* self;
|
||||
PyObject* len_f = get_unbound_method(obj, __len__, &self, false);
|
||||
PyVar self;
|
||||
PyVar len_f = get_unbound_method(obj, __len__, &self, false);
|
||||
if(self != PY_NULL){
|
||||
PyObject* ret = call_method(self, len_f);
|
||||
PyVar ret = call_method(self, len_f);
|
||||
return CAST(i64, ret) > 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
List VM::py_list(PyObject* it){
|
||||
List VM::py_list(PyVar it){
|
||||
auto _lock = heap.gc_scope_lock();
|
||||
it = py_iter(it);
|
||||
List list;
|
||||
const PyTypeInfo* info = _tp_info(it);
|
||||
PyObject* obj = _py_next(info, it);
|
||||
PyVar obj = _py_next(info, it);
|
||||
while(obj != StopIteration){
|
||||
list.push_back(obj);
|
||||
obj = _py_next(info, it);
|
||||
@ -489,15 +489,15 @@ void VM::parse_int_slice(const Slice& s, int length, int& start, int& stop, int&
|
||||
}
|
||||
}
|
||||
|
||||
i64 VM::py_hash(PyObject* obj){
|
||||
i64 VM::py_hash(PyVar obj){
|
||||
// https://docs.python.org/3.10/reference/datamodel.html#object.__hash__
|
||||
const PyTypeInfo* ti = _tp_info(obj);
|
||||
if(ti->m__hash__) return ti->m__hash__(this, obj);
|
||||
|
||||
PyObject* self;
|
||||
PyObject* f = get_unbound_method(obj, __hash__, &self, false);
|
||||
PyVar self;
|
||||
PyVar f = get_unbound_method(obj, __hash__, &self, false);
|
||||
if(f != nullptr){
|
||||
PyObject* ret = call_method(self, f);
|
||||
PyVar ret = call_method(self, f);
|
||||
return CAST(i64, ret);
|
||||
}
|
||||
// if it is trivial `object`, return PK_BITS
|
||||
@ -517,7 +517,7 @@ i64 VM::py_hash(PyObject* obj){
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* VM::__py_exec_internal(const CodeObject_& code, PyObject* globals, PyObject* locals){
|
||||
PyVar VM::__py_exec_internal(const CodeObject_& code, PyVar globals, PyVar locals){
|
||||
Frame* frame = &vm->callstack.top();
|
||||
|
||||
// fast path
|
||||
@ -527,7 +527,7 @@ PyObject* VM::__py_exec_internal(const CodeObject_& code, PyObject* globals, PyO
|
||||
|
||||
auto _lock = heap.gc_scope_lock(); // for safety
|
||||
|
||||
PyObject* globals_obj = nullptr;
|
||||
PyVar globals_obj = nullptr;
|
||||
Dict* globals_dict = nullptr;
|
||||
|
||||
NameDict_ locals_closure = nullptr;
|
||||
@ -544,13 +544,13 @@ PyObject* VM::__py_exec_internal(const CodeObject_& code, PyObject* globals, PyO
|
||||
globals_obj = heap.gcnew<DummyInstance>(VM::tp_object);
|
||||
globals_obj->_enable_instance_dict();
|
||||
globals_dict = &PK_OBJ_GET(Dict, globals);
|
||||
globals_dict->apply([&](PyObject* k, PyObject* v){
|
||||
globals_dict->apply([&](PyVar k, PyVar v){
|
||||
globals_obj->attr().set(CAST(Str&, k), v);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* retval = nullptr;
|
||||
PyVar retval = nullptr;
|
||||
|
||||
if(locals == vm->None){
|
||||
retval = vm->_exec(code, globals_obj); // only globals
|
||||
@ -558,40 +558,40 @@ PyObject* VM::__py_exec_internal(const CodeObject_& code, PyObject* globals, PyO
|
||||
check_compatible_type(locals, VM::tp_dict);
|
||||
locals_dict = &PK_OBJ_GET(Dict, locals);
|
||||
locals_closure = std::make_shared<NameDict>();
|
||||
locals_dict->apply([&](PyObject* k, PyObject* v){
|
||||
locals_dict->apply([&](PyVar k, PyVar v){
|
||||
locals_closure->set(CAST(Str&, k), v);
|
||||
});
|
||||
PyObject* _callable = VAR(Function(__dynamic_func_decl, globals_obj, nullptr, locals_closure));
|
||||
PyVar _callable = VAR(Function(__dynamic_func_decl, globals_obj, nullptr, locals_closure));
|
||||
retval = vm->_exec(code.get(), globals_obj, _callable, vm->s_data._sp);
|
||||
}
|
||||
|
||||
if(globals_dict){
|
||||
globals_dict->clear();
|
||||
globals_obj->attr().apply([&](StrName k, PyObject* v){
|
||||
globals_obj->attr().apply([&](StrName k, PyVar v){
|
||||
globals_dict->set(VAR(k.sv()), v);
|
||||
});
|
||||
}
|
||||
|
||||
if(locals_dict){
|
||||
locals_dict->clear();
|
||||
locals_closure->apply([&](StrName k, PyObject* v){
|
||||
locals_closure->apply([&](StrName k, PyVar v){
|
||||
locals_dict->set(VAR(k.sv()), v);
|
||||
});
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void VM::py_exec(std::string_view source, PyObject* globals, PyObject* locals){
|
||||
void VM::py_exec(std::string_view source, PyVar globals, PyVar locals){
|
||||
CodeObject_ code = vm->compile(source, "<exec>", EXEC_MODE, true);
|
||||
__py_exec_internal(code, globals, locals);
|
||||
}
|
||||
|
||||
PyObject* VM::py_eval(std::string_view source, PyObject* globals, PyObject* locals){
|
||||
PyVar VM::py_eval(std::string_view source, PyVar globals, PyVar locals){
|
||||
CodeObject_ code = vm->compile(source, "<eval>", EVAL_MODE, true);
|
||||
return __py_exec_internal(code, globals, locals);
|
||||
}
|
||||
|
||||
PyObject* VM::__format_object(PyObject* obj, Str spec){
|
||||
PyVar VM::__format_object(PyVar obj, Str spec){
|
||||
if(spec.empty()) return VAR(py_str(obj));
|
||||
char type;
|
||||
switch(spec.end()[-1]){
|
||||
@ -676,8 +676,8 @@ PyObject* VM::__format_object(PyObject* obj, Str spec){
|
||||
return VAR(ret);
|
||||
}
|
||||
|
||||
PyObject* VM::new_module(Str name, Str package) {
|
||||
PyObject* obj = heap._new<DummyModule>(tp_module);
|
||||
PyVar VM::new_module(Str name, Str package) {
|
||||
PyVar obj = heap._new<DummyModule>(tp_module);
|
||||
obj->attr().set(__name__, VAR(name));
|
||||
obj->attr().set(__package__, VAR(package));
|
||||
// convert to fullname
|
||||
@ -781,7 +781,7 @@ void VM::__log_s_data(const char* title) {
|
||||
if(callstack.empty()) return;
|
||||
SStream ss;
|
||||
if(title) ss << title << " | ";
|
||||
std::map<PyObject**, int> sp_bases;
|
||||
std::map<PyVar*, int> sp_bases;
|
||||
for(Frame& f: callstack.data()){
|
||||
if(f._sp_base == nullptr) PK_FATAL_ERROR();
|
||||
sp_bases[f._sp_base] += 1;
|
||||
@ -789,10 +789,10 @@ void VM::__log_s_data(const char* title) {
|
||||
Frame* frame = &callstack.top();
|
||||
int line = frame->co->lines[frame->_ip];
|
||||
ss << frame->co->name << ":" << line << " [";
|
||||
for(PyObject** p=s_data.begin(); p!=s_data.end(); p++){
|
||||
for(PyVar* p=s_data.begin(); p!=s_data.end(); p++){
|
||||
ss << std::string(sp_bases[p], '|');
|
||||
if(sp_bases[p] > 0) ss << " ";
|
||||
PyObject* obj = *p;
|
||||
PyVar obj = *p;
|
||||
if(obj == nullptr) ss << "(nil)";
|
||||
else if(obj == PY_NULL) ss << "NULL";
|
||||
else if(is_int(obj)) ss << CAST(i64, obj);
|
||||
@ -831,7 +831,7 @@ void VM::__init_builtin_types(){
|
||||
_all_types.push_back({heap._new<Type>(Type(1), Type(1)), Type(0), nullptr, "type", false});
|
||||
|
||||
auto _new_type = [this](const char* name, Type base=Type(0), bool subclass_enabled=false){
|
||||
PyObject* obj = new_type_object(nullptr, name, base, subclass_enabled);
|
||||
PyVar obj = new_type_object(nullptr, name, base, subclass_enabled);
|
||||
return PK_OBJ_GET(Type, obj);
|
||||
};
|
||||
|
||||
@ -900,14 +900,14 @@ void VM::__init_builtin_types(){
|
||||
|
||||
// `heap.gc_scope_lock();` needed before calling this function
|
||||
void VM::__unpack_as_list(ArgsView args, List& list){
|
||||
for(PyObject* obj: args){
|
||||
for(PyVar obj: args){
|
||||
if(is_type(obj, tp_star_wrapper)){
|
||||
const StarWrapper& w = _CAST(StarWrapper&, obj);
|
||||
// maybe this check should be done in the compile time
|
||||
if(w.level != 1) TypeError("expected level 1 star wrapper");
|
||||
PyObject* _0 = py_iter(w.obj);
|
||||
PyVar _0 = py_iter(w.obj);
|
||||
const PyTypeInfo* info = _tp_info(_0);
|
||||
PyObject* _1 = _py_next(info, _0);
|
||||
PyVar _1 = _py_next(info, _0);
|
||||
while(_1 != StopIteration){
|
||||
list.push_back(_1);
|
||||
_1 = _py_next(info, _0);
|
||||
@ -920,7 +920,7 @@ void VM::__unpack_as_list(ArgsView args, List& list){
|
||||
|
||||
// `heap.gc_scope_lock();` needed before calling this function
|
||||
void VM::__unpack_as_dict(ArgsView args, Dict& dict){
|
||||
for(PyObject* obj: args){
|
||||
for(PyVar obj: args){
|
||||
if(is_type(obj, tp_star_wrapper)){
|
||||
const StarWrapper& w = _CAST(StarWrapper&, obj);
|
||||
// maybe this check should be done in the compile time
|
||||
@ -936,7 +936,7 @@ void VM::__unpack_as_dict(ArgsView args, Dict& dict){
|
||||
}
|
||||
|
||||
|
||||
void VM::__prepare_py_call(PyObject** buffer, ArgsView args, ArgsView kwargs, const FuncDecl_& decl){
|
||||
void VM::__prepare_py_call(PyVar* buffer, ArgsView args, ArgsView kwargs, const FuncDecl_& decl){
|
||||
const CodeObject* co = decl->code.get();
|
||||
int co_nlocals = co->varnames.size();
|
||||
int decl_argc = decl->args.size();
|
||||
@ -969,7 +969,7 @@ void VM::__prepare_py_call(PyObject** buffer, ArgsView args, ArgsView kwargs, co
|
||||
if(i < args.size()) TypeError(_S("too many arguments", " (", decl->code->name, ')'));
|
||||
}
|
||||
|
||||
PyObject* vkwargs;
|
||||
PyVar vkwargs;
|
||||
if(decl->starred_kwarg != -1){
|
||||
vkwargs = VAR(Dict(this));
|
||||
buffer[decl->starred_kwarg] = vkwargs;
|
||||
@ -995,12 +995,12 @@ void VM::__prepare_py_call(PyObject** buffer, ArgsView args, ArgsView kwargs, co
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
PyObject** p1 = s_data._sp - KWARGC*2;
|
||||
PyObject** p0 = p1 - ARGC - 2;
|
||||
PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
PyVar* p1 = s_data._sp - KWARGC*2;
|
||||
PyVar* p0 = p1 - ARGC - 2;
|
||||
// [callable, <self>, args..., kwargs...]
|
||||
// ^p0 ^p1 ^_sp
|
||||
PyObject* callable = p1[-(ARGC + 2)];
|
||||
PyVar callable = p1[-(ARGC + 2)];
|
||||
Type callable_t = _tp(callable);
|
||||
|
||||
int method_call = p0[1] != PY_NULL;
|
||||
@ -1020,8 +1020,8 @@ PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
ArgsView args(p1 - ARGC - method_call, p1);
|
||||
ArgsView kwargs(p1, s_data._sp);
|
||||
|
||||
PyObject** _base = args.begin();
|
||||
PyObject* buffer[PK_MAX_CO_VARNAMES];
|
||||
PyVar* _base = args.begin();
|
||||
PyVar buffer[PK_MAX_CO_VARNAMES];
|
||||
|
||||
if(callable_t == tp_function){
|
||||
/*****************_py_call*****************/
|
||||
@ -1047,7 +1047,7 @@ PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
// ^p0 ^p1 ^_sp
|
||||
s_data.reset(_base + co_nlocals);
|
||||
// initialize local variables to PY_NULL
|
||||
for(PyObject** p=p1; p!=s_data._sp; p++) *p = PY_NULL;
|
||||
for(PyVar* p=p1; p!=s_data._sp; p++) *p = PY_NULL;
|
||||
break;
|
||||
case FuncType::EMPTY:
|
||||
if(args.size() != fn.decl->args.size()) TypeError(_S(co->name, "() takes ", fn.decl->args.size(), " positional arguments but ", args.size(), " were given"));
|
||||
@ -1072,7 +1072,7 @@ PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
|
||||
if(callable_t == tp_native_func){
|
||||
const auto& f = PK_OBJ_GET(NativeFunc, callable);
|
||||
PyObject* ret;
|
||||
PyVar ret;
|
||||
if(f.decl != nullptr){
|
||||
int co_nlocals = f.decl->code->varnames.size();
|
||||
__prepare_py_call(buffer, args, kwargs, f.decl);
|
||||
@ -1091,8 +1091,8 @@ PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
|
||||
if(callable_t == tp_type){
|
||||
// [type, NULL, args..., kwargs...]
|
||||
PyObject* new_f = find_name_in_mro(PK_OBJ_GET(Type, callable), __new__);
|
||||
PyObject* obj;
|
||||
PyVar new_f = find_name_in_mro(PK_OBJ_GET(Type, callable), __new__);
|
||||
PyVar obj;
|
||||
PK_DEBUG_ASSERT(new_f != nullptr && !method_call);
|
||||
if(new_f == __cached_object_new) {
|
||||
// fast path for object.__new__
|
||||
@ -1101,14 +1101,14 @@ PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
PUSH(new_f);
|
||||
PUSH(PY_NULL);
|
||||
PUSH(callable); // cls
|
||||
for(PyObject* o: args) PUSH(o);
|
||||
for(PyObject* o: kwargs) PUSH(o);
|
||||
for(PyVar o: args) PUSH(o);
|
||||
for(PyVar o: kwargs) PUSH(o);
|
||||
// if obj is not an instance of `cls`, the behavior is undefined
|
||||
obj = vectorcall(ARGC+1, KWARGC);
|
||||
}
|
||||
|
||||
// __init__
|
||||
PyObject* self;
|
||||
PyVar self;
|
||||
callable = get_unbound_method(obj, __init__, &self, false);
|
||||
if (callable != nullptr) {
|
||||
callable_t = _tp(callable);
|
||||
@ -1127,8 +1127,8 @@ PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
}
|
||||
|
||||
// handle `__call__` overload
|
||||
PyObject* self;
|
||||
PyObject* call_f = get_unbound_method(callable, __call__, &self, false);
|
||||
PyVar self;
|
||||
PyVar call_f = get_unbound_method(callable, __call__, &self, false);
|
||||
if(self != PY_NULL){
|
||||
p1[-(ARGC + 2)] = call_f;
|
||||
p1[-(ARGC + 1)] = self;
|
||||
@ -1147,7 +1147,7 @@ void VM::delattr(PyObject *_0, StrName _name){
|
||||
}
|
||||
|
||||
// https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
|
||||
PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){
|
||||
PyVar VM::getattr(PyVar obj, StrName name, bool throw_err){
|
||||
Type objtype(0);
|
||||
// handle super() proxy
|
||||
if(is_type(obj, tp_super)){
|
||||
@ -1157,7 +1157,7 @@ PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){
|
||||
}else{
|
||||
objtype = _tp(obj);
|
||||
}
|
||||
PyObject* cls_var = find_name_in_mro(objtype, name);
|
||||
PyVar cls_var = find_name_in_mro(objtype, name);
|
||||
if(cls_var != nullptr){
|
||||
// handle descriptor
|
||||
if(is_type(cls_var, tp_property)){
|
||||
@ -1167,7 +1167,7 @@ PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){
|
||||
}
|
||||
// handle instance __dict__
|
||||
if(!is_tagged(obj) && obj->is_attr_valid()){
|
||||
PyObject* val;
|
||||
PyVar val;
|
||||
if(obj->type == tp_type){
|
||||
val = find_name_in_mro(PK_OBJ_GET(Type, obj), name);
|
||||
if(val != nullptr){
|
||||
@ -1200,7 +1200,7 @@ PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){
|
||||
|
||||
const PyTypeInfo* ti = &_all_types[objtype];
|
||||
if(ti->m__getattr__){
|
||||
PyObject* ret = ti->m__getattr__(this, obj, name);
|
||||
PyVar ret = ti->m__getattr__(this, obj, name);
|
||||
if(ret) return ret;
|
||||
}
|
||||
|
||||
@ -1210,7 +1210,7 @@ PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){
|
||||
|
||||
// used by OP_LOAD_METHOD
|
||||
// try to load a unbound method (fallback to `getattr` if not found)
|
||||
PyObject* VM::get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err, bool fallback){
|
||||
PyVar VM::get_unbound_method(PyVar obj, StrName name, PyVar* self, bool throw_err, bool fallback){
|
||||
*self = PY_NULL;
|
||||
Type objtype(0);
|
||||
// handle super() proxy
|
||||
@ -1221,7 +1221,7 @@ PyObject* VM::get_unbound_method(PyObject* obj, StrName name, PyObject** self, b
|
||||
}else{
|
||||
objtype = _tp(obj);
|
||||
}
|
||||
PyObject* cls_var = find_name_in_mro(objtype, name);
|
||||
PyVar cls_var = find_name_in_mro(objtype, name);
|
||||
|
||||
if(fallback){
|
||||
if(cls_var != nullptr){
|
||||
@ -1233,7 +1233,7 @@ PyObject* VM::get_unbound_method(PyObject* obj, StrName name, PyObject** self, b
|
||||
}
|
||||
// handle instance __dict__
|
||||
if(!is_tagged(obj) && obj->is_attr_valid()){
|
||||
PyObject* val;
|
||||
PyVar val;
|
||||
if(obj->type == tp_type){
|
||||
val = find_name_in_mro(PK_OBJ_GET(Type, obj), name);
|
||||
if(val != nullptr){
|
||||
@ -1271,7 +1271,7 @@ PyObject* VM::get_unbound_method(PyObject* obj, StrName name, PyObject** self, b
|
||||
|
||||
const PyTypeInfo* ti = &_all_types[objtype];
|
||||
if(fallback && ti->m__getattr__){
|
||||
PyObject* ret = ti->m__getattr__(this, obj, name);
|
||||
PyVar ret = ti->m__getattr__(this, obj, name);
|
||||
if(ret) return ret;
|
||||
}
|
||||
|
||||
@ -1279,7 +1279,7 @@ PyObject* VM::get_unbound_method(PyObject* obj, StrName name, PyObject** self, b
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void VM::setattr(PyObject* obj, StrName name, PyObject* value){
|
||||
void VM::setattr(PyVar obj, StrName name, PyVar value){
|
||||
Type objtype(0);
|
||||
// handle super() proxy
|
||||
if(is_type(obj, tp_super)){
|
||||
@ -1289,7 +1289,7 @@ void VM::setattr(PyObject* obj, StrName name, PyObject* value){
|
||||
}else{
|
||||
objtype = _tp(obj);
|
||||
}
|
||||
PyObject* cls_var = find_name_in_mro(objtype, name);
|
||||
PyVar cls_var = find_name_in_mro(objtype, name);
|
||||
if(cls_var != nullptr){
|
||||
// handle descriptor
|
||||
if(is_type(cls_var, tp_property)){
|
||||
@ -1314,8 +1314,8 @@ void VM::setattr(PyObject* obj, StrName name, PyObject* value){
|
||||
obj->attr().set(name, value);
|
||||
}
|
||||
|
||||
PyObject* VM::bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, any userdata, BindType bt) {
|
||||
PyObject* nf = VAR(NativeFunc(fn, argc, std::move(userdata)));
|
||||
PyVar VM::bind_func(PyVar obj, StrName name, int argc, NativeFuncC fn, any userdata, BindType bt) {
|
||||
PyVar nf = VAR(NativeFunc(fn, argc, std::move(userdata)));
|
||||
switch(bt){
|
||||
case BindType::DEFAULT: break;
|
||||
case BindType::STATICMETHOD: nf = VAR(StaticMethod(nf)); break;
|
||||
@ -1325,11 +1325,11 @@ PyObject* VM::bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, a
|
||||
return nf;
|
||||
}
|
||||
|
||||
PyObject* VM::bind(PyObject* obj, const char* sig, NativeFuncC fn, any userdata, BindType bt){
|
||||
PyVar VM::bind(PyVar obj, const char* sig, NativeFuncC fn, any userdata, BindType bt){
|
||||
return bind(obj, sig, nullptr, fn, std::move(userdata), bt);
|
||||
}
|
||||
|
||||
PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, NativeFuncC fn, any userdata, BindType bt){
|
||||
PyVar VM::bind(PyVar obj, const char* sig, const char* docstring, NativeFuncC fn, any userdata, BindType bt){
|
||||
CodeObject_ co;
|
||||
try{
|
||||
// fn(a, b, *c, d=1) -> None
|
||||
@ -1342,7 +1342,7 @@ PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, Native
|
||||
}
|
||||
FuncDecl_ decl = co->func_decls[0];
|
||||
decl->docstring = docstring;
|
||||
PyObject* f_obj = VAR(NativeFunc(fn, decl, std::move(userdata)));
|
||||
PyVar f_obj = VAR(NativeFunc(fn, decl, std::move(userdata)));
|
||||
|
||||
switch(bt){
|
||||
case BindType::STATICMETHOD:
|
||||
@ -1358,29 +1358,29 @@ PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, Native
|
||||
return f_obj;
|
||||
}
|
||||
|
||||
PyObject* VM::bind_property(PyObject* obj, const char* name, NativeFuncC fget, NativeFuncC fset){
|
||||
PyVar VM::bind_property(PyVar obj, const char* name, NativeFuncC fget, NativeFuncC fset){
|
||||
PK_ASSERT(is_type(obj, tp_type));
|
||||
std::string_view name_sv(name); int pos = name_sv.find(':');
|
||||
if(pos > 0) name_sv = name_sv.substr(0, pos);
|
||||
PyObject* _0 = heap.gcnew<NativeFunc>(tp_native_func, fget, 1);
|
||||
PyObject* _1 = vm->None;
|
||||
PyVar _0 = heap.gcnew<NativeFunc>(tp_native_func, fget, 1);
|
||||
PyVar _1 = vm->None;
|
||||
if(fset != nullptr) _1 = heap.gcnew<NativeFunc>(tp_native_func, fset, 2);
|
||||
PyObject* prop = VAR(Property(_0, _1));
|
||||
PyVar prop = VAR(Property(_0, _1));
|
||||
obj->attr().set(StrName(name_sv), prop);
|
||||
return prop;
|
||||
}
|
||||
|
||||
void VM::__builtin_error(StrName type){ _error(call(builtins->attr(type))); }
|
||||
void VM::__builtin_error(StrName type, PyObject* arg){ _error(call(builtins->attr(type), arg)); }
|
||||
void VM::__builtin_error(StrName type, PyVar arg){ _error(call(builtins->attr(type), arg)); }
|
||||
void VM::__builtin_error(StrName type, const Str& msg){ __builtin_error(type, VAR(msg)); }
|
||||
|
||||
void VM::BinaryOptError(const char* op, PyObject* _0, PyObject* _1) {
|
||||
void VM::BinaryOptError(const char* op, PyVar _0, PyVar _1) {
|
||||
StrName name_0 = _type_name(vm, _tp(_0));
|
||||
StrName name_1 = _type_name(vm, _tp(_1));
|
||||
TypeError(_S("unsupported operand type(s) for ", op, ": ", name_0.escape(), " and ", name_1.escape()));
|
||||
}
|
||||
|
||||
void VM::AttributeError(PyObject* obj, StrName name){
|
||||
void VM::AttributeError(PyVar obj, StrName name){
|
||||
if(isinstance(obj, vm->tp_type)){
|
||||
__builtin_error("AttributeError", _S("type object ", _type_name(vm, PK_OBJ_GET(Type, obj)).escape(), " has no attribute ", name.escape()));
|
||||
}else{
|
||||
@ -1388,7 +1388,7 @@ void VM::AttributeError(PyObject* obj, StrName name){
|
||||
}
|
||||
}
|
||||
|
||||
void VM::_error(PyObject* e_obj){
|
||||
void VM::_error(PyVar e_obj){
|
||||
PK_ASSERT(isinstance(e_obj, tp_exception))
|
||||
Exception& e = PK_OBJ_GET(Exception, e_obj);
|
||||
if(callstack.empty()){
|
||||
@ -1420,9 +1420,9 @@ void VM::__raise_exc(bool re_raise){
|
||||
}
|
||||
|
||||
void ManagedHeap::mark() {
|
||||
for(PyObject* obj: _no_gc) PK_OBJ_MARK(obj);
|
||||
for(PyVar obj: _no_gc) PK_OBJ_MARK(obj);
|
||||
vm->callstack.apply([](Frame& frame){ frame._gc_mark(); });
|
||||
for(PyObject* obj: vm->s_data) PK_OBJ_MARK(obj);
|
||||
for(PyVar obj: vm->s_data) PK_OBJ_MARK(obj);
|
||||
for(auto [_, co]: vm->__cached_codes) co->_gc_mark();
|
||||
if(vm->__last_exception) PK_OBJ_MARK(vm->__last_exception);
|
||||
if(vm->__curr_class) PK_OBJ_MARK(vm->__curr_class);
|
||||
@ -1435,62 +1435,62 @@ StrName _type_name(VM *vm, Type type){
|
||||
}
|
||||
|
||||
void _gc_mark_namedict(NameDict* t){
|
||||
t->apply([](StrName name, PyObject* obj){
|
||||
t->apply([](StrName name, PyVar obj){
|
||||
PK_OBJ_MARK(obj);
|
||||
});
|
||||
}
|
||||
|
||||
void VM::bind__getitem__(Type type, PyObject* (*f)(VM*, PyObject*, PyObject*)){
|
||||
void VM::bind__getitem__(Type type, PyVar (*f)(VM*, PyVar, PyVar)){
|
||||
_all_types[type].m__getitem__ = f;
|
||||
bind_func(type, __getitem__, 2, [](VM* vm, ArgsView args){
|
||||
return lambda_get_userdata<PyObject*(*)(VM*, PyObject*, PyObject*)>(args.begin())(vm, args[0], args[1]);
|
||||
return lambda_get_userdata<PyVar(*)(VM*, PyVar, PyVar)>(args.begin())(vm, args[0], args[1]);
|
||||
}, f);
|
||||
}
|
||||
|
||||
void VM::bind__setitem__(Type type, void (*f)(VM*, PyObject*, PyObject*, PyObject*)){
|
||||
void VM::bind__setitem__(Type type, void (*f)(VM*, PyVar, PyVar, PyVar)){
|
||||
_all_types[type].m__setitem__ = f;
|
||||
bind_func(type, __setitem__, 3, [](VM* vm, ArgsView args){
|
||||
lambda_get_userdata<void(*)(VM* vm, PyObject*, PyObject*, PyObject*)>(args.begin())(vm, args[0], args[1], args[2]);
|
||||
lambda_get_userdata<void(*)(VM* vm, PyVar, PyVar, PyVar)>(args.begin())(vm, args[0], args[1], args[2]);
|
||||
return vm->None;
|
||||
}, f);
|
||||
}
|
||||
|
||||
void VM::bind__delitem__(Type type, void (*f)(VM*, PyObject*, PyObject*)){
|
||||
void VM::bind__delitem__(Type type, void (*f)(VM*, PyVar, PyVar)){
|
||||
_all_types[type].m__delitem__ = f;
|
||||
bind_func(type, __delitem__, 2, [](VM* vm, ArgsView args){
|
||||
lambda_get_userdata<void(*)(VM*, PyObject*, PyObject*)>(args.begin())(vm, args[0], args[1]);
|
||||
lambda_get_userdata<void(*)(VM*, PyVar, PyVar)>(args.begin())(vm, args[0], args[1]);
|
||||
return vm->None;
|
||||
}, f);
|
||||
}
|
||||
|
||||
PyObject* VM::__pack_next_retval(unsigned n){
|
||||
PyVar VM::__pack_next_retval(unsigned n){
|
||||
if(n == 0) return StopIteration;
|
||||
if(n == 1) return s_data.popx();
|
||||
PyObject* retval = VAR(s_data.view(n).to_tuple());
|
||||
PyVar retval = VAR(s_data.view(n).to_tuple());
|
||||
s_data._sp -= n;
|
||||
return retval;
|
||||
}
|
||||
|
||||
void VM::bind__next__(Type type, unsigned (*f)(VM*, PyObject*)){
|
||||
void VM::bind__next__(Type type, unsigned (*f)(VM*, PyVar)){
|
||||
_all_types[type].m__next__ = f;
|
||||
bind_func(type, __next__, 1, [](VM* vm, ArgsView args){
|
||||
int n = lambda_get_userdata<unsigned(*)(VM*, PyObject*)>(args.begin())(vm, args[0]);
|
||||
int n = lambda_get_userdata<unsigned(*)(VM*, PyVar)>(args.begin())(vm, args[0]);
|
||||
return vm->__pack_next_retval(n);
|
||||
}, f);
|
||||
}
|
||||
|
||||
void VM::bind__next__(Type type, PyObject* (*f)(VM*, PyObject*)){
|
||||
void VM::bind__next__(Type type, PyVar (*f)(VM*, PyVar)){
|
||||
bind_func(type, __next__, 1, [](VM* vm, ArgsView args){
|
||||
auto f = lambda_get_userdata<PyObject*(*)(VM*, PyObject*)>(args.begin());
|
||||
auto f = lambda_get_userdata<PyVar(*)(VM*, PyVar)>(args.begin());
|
||||
return f(vm, args[0]);
|
||||
}, f);
|
||||
}
|
||||
|
||||
#define BIND_UNARY_SPECIAL(name) \
|
||||
void VM::bind##name(Type type, PyObject* (*f)(VM*, PyObject*)){ \
|
||||
void VM::bind##name(Type type, PyVar (*f)(VM*, PyVar)){ \
|
||||
_all_types[type].m##name = f; \
|
||||
bind_func(type, name, 1, [](VM* vm, ArgsView args){ \
|
||||
return lambda_get_userdata<PyObject*(*)(VM*, PyObject*)>(args.begin())(vm, args[0]); \
|
||||
return lambda_get_userdata<PyVar(*)(VM*, PyVar)>(args.begin())(vm, args[0]); \
|
||||
}, f); \
|
||||
}
|
||||
BIND_UNARY_SPECIAL(__iter__)
|
||||
@ -1498,7 +1498,7 @@ void VM::bind__next__(Type type, PyObject* (*f)(VM*, PyObject*)){
|
||||
BIND_UNARY_SPECIAL(__invert__)
|
||||
#undef BIND_UNARY_SPECIAL
|
||||
|
||||
void VM::bind__str__(Type type, Str (*f)(VM*, PyObject*)){
|
||||
void VM::bind__str__(Type type, Str (*f)(VM*, PyVar)){
|
||||
_all_types[type].m__str__ = f;
|
||||
bind_func(type, __str__, 1, [](VM* vm, ArgsView args){
|
||||
Str s = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
|
||||
@ -1506,7 +1506,7 @@ void VM::bind__str__(Type type, Str (*f)(VM*, PyObject*)){
|
||||
}, f);
|
||||
}
|
||||
|
||||
void VM::bind__repr__(Type type, Str (*f)(VM*, PyObject*)){
|
||||
void VM::bind__repr__(Type type, Str (*f)(VM*, PyVar)){
|
||||
_all_types[type].m__repr__ = f;
|
||||
bind_func(type, __repr__, 1, [](VM* vm, ArgsView args){
|
||||
Str s = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
|
||||
@ -1514,7 +1514,7 @@ void VM::bind__repr__(Type type, Str (*f)(VM*, PyObject*)){
|
||||
}, f);
|
||||
}
|
||||
|
||||
void VM::bind__hash__(Type type, i64 (*f)(VM*, PyObject*)){
|
||||
void VM::bind__hash__(Type type, i64 (*f)(VM*, PyVar)){
|
||||
_all_types[type].m__hash__ = f;
|
||||
bind_func(type, __hash__, 1, [](VM* vm, ArgsView args){
|
||||
i64 ret = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
|
||||
@ -1522,7 +1522,7 @@ void VM::bind__hash__(Type type, i64 (*f)(VM*, PyObject*)){
|
||||
}, f);
|
||||
}
|
||||
|
||||
void VM::bind__len__(Type type, i64 (*f)(VM*, PyObject*)){
|
||||
void VM::bind__len__(Type type, i64 (*f)(VM*, PyVar)){
|
||||
_all_types[type].m__len__ = f;
|
||||
bind_func(type, __len__, 1, [](VM* vm, ArgsView args){
|
||||
i64 ret = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
|
||||
@ -1703,7 +1703,7 @@ void VM::__breakpoint(){
|
||||
if(line == "c" || line == "continue") break;
|
||||
if(line == "a" || line == "args"){
|
||||
int i = 0;
|
||||
for(PyObject* obj: frame_0->_locals){
|
||||
for(PyVar obj: frame_0->_locals){
|
||||
if(obj == PY_NULL) continue;
|
||||
StrName name = frame_0->co->varnames[i++];
|
||||
stdout_write(_S(name.sv(), " = ", vm->py_repr(obj), '\n'));
|
||||
@ -1749,7 +1749,7 @@ void VM::__breakpoint(){
|
||||
if(arg.empty()) continue; // ignore empty command
|
||||
if(cmd == "p" || cmd == "print"){
|
||||
CodeObject_ code = compile(arg, "<stdin>", EVAL_MODE, true);
|
||||
PyObject* retval = vm->_exec(code.get(), frame_0->_module, frame_0->_callable, frame_0->_locals);
|
||||
PyVar retval = vm->_exec(code.get(), frame_0->_module, frame_0->_callable, frame_0->_locals);
|
||||
stdout_write(vm->py_repr(retval));
|
||||
stdout_write("\n");
|
||||
}else if(cmd == "!"){
|
||||
|
Loading…
x
Reference in New Issue
Block a user