mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-19 19:10:17 +00:00
123 lines
4.1 KiB
C
123 lines
4.1 KiB
C
#include "pocketpy/interpreter/vm.h"
|
|
#include "pocketpy/objects/base.h"
|
|
#include "pocketpy/pocketpy.h"
|
|
|
|
bool py_isidentical(const py_Ref lhs, const py_Ref rhs) {
|
|
if(lhs->type != rhs->type) return false;
|
|
switch(lhs->type) {
|
|
case tp_int: return lhs->_i64 == rhs->_i64;
|
|
case tp_float: return lhs->_f64 == rhs->_f64;
|
|
case tp_bool: return lhs->_bool == rhs->_bool;
|
|
case tp_nativefunc: return lhs->_cfunc == rhs->_cfunc;
|
|
case tp_NoneType: return true;
|
|
case tp_NotImplementedType: return true;
|
|
case tp_ellipsis: return true;
|
|
// fallback to pointer comparison
|
|
default: return lhs->is_ptr && rhs->is_ptr && lhs->_obj == rhs->_obj;
|
|
}
|
|
}
|
|
|
|
int py_bool(const py_Ref val) {
|
|
switch(val->type) {
|
|
case tp_bool: return val->_bool;
|
|
case tp_int: return val->_i64 != 0;
|
|
case tp_float: return val->_f64 != 0;
|
|
case tp_NoneType: return 0;
|
|
default: {
|
|
py_Ref tmp = py_tpfindmagic(val->type, __bool__);
|
|
if(tmp) {
|
|
bool ok = py_call(tmp, 1, val);
|
|
if(!ok) return -1;
|
|
return py_tobool(py_retval());
|
|
} else {
|
|
tmp = py_tpfindmagic(val->type, __len__);
|
|
if(tmp) {
|
|
bool ok = py_call(tmp, 1, val);
|
|
if(!ok) return -1;
|
|
return py_toint(py_retval());
|
|
} else {
|
|
return 1; // True
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool py_hash(const py_Ref val, int64_t* out) {
|
|
py_Type t = val->type;
|
|
pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
|
|
do {
|
|
py_Ref _hash = &types[t].magic[__hash__];
|
|
if(py_isnone(_hash)) break;
|
|
py_Ref _eq = &types[t].magic[__eq__];
|
|
if(!py_isnil(_hash) && !py_isnil(_eq)) {
|
|
bool ok = py_call(_hash, 1, val);
|
|
if(!ok) return false;
|
|
*out = py_toint(py_retval());
|
|
return true;
|
|
}
|
|
t = types[t].base;
|
|
} while(t);
|
|
return TypeError("unhashable type: '%t'", val->type);
|
|
}
|
|
|
|
bool py_iter(const py_Ref val) {
|
|
py_Ref tmp = py_tpfindmagic(val->type, __iter__);
|
|
if(!tmp) return TypeError("'%t' object is not iterable", val->type);
|
|
return py_call(tmp, 1, val);
|
|
}
|
|
|
|
int py_next(const py_Ref val) {
|
|
pk_VM* vm = pk_current_vm;
|
|
vm->is_stopiteration = false;
|
|
py_Ref tmp = py_tpfindmagic(val->type, __next__);
|
|
if(!tmp) return TypeError("'%t' object is not an iterator", val->type);
|
|
bool ok = py_call(tmp, 1, val);
|
|
if(ok) return true;
|
|
return vm->is_stopiteration ? 0 : -1;
|
|
}
|
|
|
|
int py_getattr(const py_Ref self, py_Name name, py_Ref out) { return -1; }
|
|
|
|
bool py_setattr(py_Ref self, py_Name name, const py_Ref val) { return false; }
|
|
|
|
bool py_delattr(py_Ref self, py_Name name) { return false; }
|
|
|
|
bool py_getitem(const py_Ref self, const py_Ref key) {
|
|
py_push(self);
|
|
py_push(key);
|
|
bool ok = py_callmagic(__getitem__, 2, py_peek(-2));
|
|
py_shrink(2);
|
|
return ok;
|
|
}
|
|
|
|
bool py_setitem(py_Ref self, const py_Ref key, const py_Ref val) {
|
|
py_push(self);
|
|
py_push(key);
|
|
py_push(val);
|
|
bool ok = py_callmagic(__setitem__, 3, py_peek(-3));
|
|
py_shrink(3);
|
|
return ok;
|
|
}
|
|
|
|
bool py_delitem(py_Ref self, const py_Ref key) {
|
|
py_push(self);
|
|
py_push(key);
|
|
bool ok = py_callmagic(__delitem__, 2, py_peek(-2));
|
|
py_shrink(2);
|
|
return ok;
|
|
}
|
|
|
|
#define COMPARE_OP_IMPL(name, op, rop) \
|
|
int py_##name(const py_Ref lhs, const py_Ref rhs) { \
|
|
bool ok = py_binaryop(lhs, rhs, op, rop); \
|
|
if(!ok) return -1; \
|
|
return py_tobool(py_retval()); \
|
|
}
|
|
|
|
COMPARE_OP_IMPL(eq, __eq__, __eq__)
|
|
COMPARE_OP_IMPL(ne, __ne__, __ne__)
|
|
COMPARE_OP_IMPL(lt, __lt__, __gt__)
|
|
COMPARE_OP_IMPL(le, __le__, __ge__)
|
|
COMPARE_OP_IMPL(gt, __gt__, __lt__)
|
|
COMPARE_OP_IMPL(ge, __ge__, __le__) |