This commit is contained in:
blueloveTH 2024-08-11 12:10:56 +08:00
parent 0e7936341b
commit 145782b789
7 changed files with 55 additions and 48 deletions

View File

@ -489,12 +489,18 @@ void py_list_append(py_Ref self, py_Ref val);
void py_list_clear(py_Ref self);
void py_list_insert(py_Ref self, int i, py_Ref val);
py_TmpRef py_dict_getitem(py_Ref self, py_Ref key) PY_RAISE;
void py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
void py_dict_delitem(py_Ref self, py_Ref key) PY_RAISE;
bool py_dict_contains(py_Ref self, py_Ref key) PY_RAISE;
int py_dict_len(py_Ref self);
/// -1: error, 0: not found, 1: found
int py_dict_getitem(py_Ref self, py_Ref key) PY_RAISE;
/// true: success, false: error
bool py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
/// -1: error, 0: not found, 1: found (and deleted)
int py_dict_delitem(py_Ref self, py_Ref key) PY_RAISE;
/// -1: error, 0: not found, 1: found
int py_dict_contains(py_Ref self, py_Ref key) PY_RAISE;
/// true: success, false: error
bool py_dict_apply(py_Ref self, bool (*f)(py_Ref key, py_Ref val, void* ctx), void* ctx) PY_RAISE;
/// noexcept
int py_dict_len(py_Ref self);
/************* Others *************/

View File

@ -87,14 +87,9 @@ FrameResult VM__run_top_frame(VM* self) {
__NEXT_STEP:
byte = *frame->ip;
#if PK_DEBUG
pk_print_stack(self, frame, byte);
// #if PK_DEBUG
// if(py_checkexc()) {
// py_printexc();
// c11__abort("unhandled exception!");
// }
// #endif
#endif
switch((Opcode)byte.op) {
case OP_NO_OP: DISPATCH();
@ -506,8 +501,8 @@ FrameResult VM__run_top_frame(VM* self) {
py_Ref tmp = py_pushtmp();
py_newdict(tmp);
for(int i = 0; i < byte.arg * 2; i += 2) {
py_dict_setitem(tmp, begin + i, begin + i + 1);
if(py_checkexc()) goto __ERROR;
bool ok = py_dict_setitem(tmp, begin + i, begin + i + 1);
if(!ok) goto __ERROR;
}
SP() = begin;
PUSH(tmp);
@ -760,8 +755,8 @@ FrameResult VM__run_top_frame(VM* self) {
}
case OP_DICT_ADD: {
// [dict, iter, key, value]
py_dict_setitem(FOURTH(), SECOND(), TOP());
if(py_checkexc()) goto __ERROR;
bool ok = py_dict_setitem(FOURTH(), SECOND(), TOP());
if(!ok) goto __ERROR;
STACK_SHRINK(2);
DISPATCH();
}
@ -917,6 +912,7 @@ FrameResult VM__run_top_frame(VM* self) {
}
case OP_END_CLASS: {
// [cls or decorated]
// TODO: if __eq__ is defined, check __ne__ and provide a default implementation
py_Name name = byte.arg;
// set into f_globals
py_setdict(frame->module, name, TOP());

View File

@ -389,9 +389,9 @@ static bool
py_Ref tmp = py_pushtmp();
c11_sv key_sv = py_name2sv(key);
py_newstrn(tmp, key_sv.data, key_sv.size);
py_dict_setitem(&buffer[decl->starred_kwarg], tmp, &p1[2 * j + 1]);
bool ok = py_dict_setitem(&buffer[decl->starred_kwarg], tmp, &p1[2 * j + 1]);
py_pop();
if(py_checkexc()) return false;
if(!ok) return false;
}
}
}

View File

@ -104,6 +104,7 @@ bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) {
c11__abort(
"py_CFunction returns nothing! Did you forget to call `py_newnone(py_retval())`?");
}
// if(py_checkexc()) { c11__abort("py_CFunction returns `true` but an exception is set!"); }
return true;
}
#endif

View File

@ -617,11 +617,8 @@ static bool function__closure__getter(int argc, py_Ref argv) {
c11__foreach(NameDict_KV, ud->closure, it) {
// printf("%s -> %s\n", py_name2str(it->key), py_tpname(it->value.type));
py_newstr(r0, py_name2str(it->key));
py_dict_setitem(retval, r0, &it->value);
if(py_checkexc()) {
py_shrink(2);
return false;
}
bool ok = py_dict_setitem(retval, r0, &it->value);
if(!ok) return false;
}
py_assign(py_retval(), retval);
py_shrink(2);

View File

@ -164,12 +164,10 @@ static bool Dict__set(Dict* self, py_TValue* key, py_TValue* val) {
}
/// Delete an entry from the dict.
/// If the key is found, `py_retval()` is set to the value.
/// If the key is not found, `py_retval()` is set to `nil`.
/// Returns false on error.
static bool Dict__pop(Dict* self, py_Ref key) {
/// -1: error, 0: not found, 1: found and deleted
static int Dict__pop(Dict* self, py_Ref key) {
py_i64 hash;
if(!py_hash(key, &hash)) return false;
if(!py_hash(key, &hash)) return -1;
int idx = hash & (self->capacity - 1);
for(int i = 0; i < PK_DICT_MAX_COLLISION; i++) {
int idx2 = self->indices[idx]._[i];
@ -182,12 +180,11 @@ static bool Dict__pop(Dict* self, py_Ref key) {
self->indices[idx]._[i] = -1;
self->length--;
if(self->length < self->entries.count / 2) Dict__compact_entries(self);
return true;
return 1;
}
if(res == -1) return false; // error
if(res == -1) return -1; // error
}
py_newnil(py_retval());
return true;
return 0;
}
static void DictIterator__ctor(DictIterator* self, Dict* dict) {
@ -262,8 +259,13 @@ static bool dict__setitem__(int argc, py_Ref argv) {
static bool dict__delitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
Dict* self = py_touserdata(argv);
if(!Dict__pop(self, py_arg(1))) return false;
int res = Dict__pop(self, py_arg(1));
if(res == 1) {
py_newnone(py_retval());
return true;
}
if(res == 0) return KeyError(py_arg(1));
return false;
}
static bool dict__contains__(int argc, py_Ref argv) {
@ -396,10 +398,11 @@ static bool dict_get(int argc, py_Ref argv) {
static bool dict_pop(int argc, py_Ref argv) {
Dict* self = py_touserdata(argv);
if(argc < 2 || argc > 3) return TypeError("pop() takes 2 or 3 arguments (%d given)", argc);
if(argc < 2 || argc > 3) return TypeError("pop() takes 1 or 2 arguments (%d given)", argc - 1);
py_Ref default_val = argc == 3 ? py_arg(2) : py_None;
if(!Dict__pop(self, py_arg(1))) return false;
if(py_isnil(py_retval())) *py_retval() = *default_val;
int res = Dict__pop(self, py_arg(1));
if(res == -1) return false;
if(res == 0) { py_assign(py_retval(), default_val); }
return true;
}
@ -506,33 +509,37 @@ py_Type pk_dict_items__register() {
//////////////////////////
py_Ref py_dict_getitem(py_Ref self, py_Ref key) {
int py_dict_getitem(py_Ref self, py_Ref key) {
assert(py_isdict(self));
Dict* ud = py_touserdata(self);
DictEntry* entry;
if(!Dict__try_get(ud, key, &entry)) return NULL;
if(entry) return &entry->val;
return NULL;
if(!Dict__try_get(ud, key, &entry)) return -1;
if(entry) {
py_assign(py_retval(), &entry->val);
return 1;
}
return 0;
}
void py_dict_delitem(py_Ref self, py_Ref key) {
int py_dict_delitem(py_Ref self, py_Ref key) {
assert(py_isdict(self));
Dict* ud = py_touserdata(self);
Dict__pop(ud, key);
return Dict__pop(ud, key);
}
void py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) {
bool py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) {
assert(py_isdict(self));
Dict* ud = py_touserdata(self);
Dict__set(ud, key, val);
return Dict__set(ud, key, val);
}
bool py_dict_contains(py_Ref self, py_Ref key) {
int py_dict_contains(py_Ref self, py_Ref key) {
assert(py_isdict(self));
Dict* ud = py_touserdata(self);
DictEntry* entry;
bool ok = Dict__try_get(ud, key, &entry);
return ok && entry != NULL;
if(!ok) return -1;
return entry ? 1 : 0;
}
int py_dict_len(py_Ref self) {

View File

@ -66,7 +66,7 @@ static bool _py_BaseException__init__(int argc, py_Ref argv) {
py_setslot(py_arg(0), 0, py_arg(1));
return true;
}
return TypeError("__init__() takes at most 2 arguments but %d were given", argc);
return TypeError("__init__() takes at most 1 arguments but %d were given", argc - 1);
}
static bool _py_BaseException__repr__(int argc, py_Ref argv) {