Support __set_name__

This commit is contained in:
K. Lange 2022-07-06 15:00:22 +09:00
parent 388a649ec9
commit 855d342a68
3 changed files with 48 additions and 0 deletions

View File

@ -234,6 +234,7 @@ typedef struct KrkClass {
KrkObj * _lt, * _gt, * _le, * _ge;
KrkObj * _invert, * _negate;
KrkObj * _set_name;
} KrkClass;
/**

View File

@ -42,6 +42,7 @@ CACHED_METHOD(LE, "__le__", _le)
CACHED_METHOD(GE, "__ge__", _ge)
CACHED_METHOD(INVERT, "__invert__", _invert)
CACHED_METHOD(NEGATE, "__neg__", _negate)
CACHED_METHOD(SETNAME, "__set_name__", _set_name)
/* These are not methods */
SPECIAL_ATTRS(CLASS, "__class__")

View File

@ -543,6 +543,50 @@ void krk_finalizeClass(KrkClass * _class) {
}
}
/**
* This should really be the default behavior of type.__new__?
*/
static void _callSetName(KrkClass * _class) {
KrkValue setnames = krk_list_of(0,NULL,0);
krk_push(setnames);
extern FUNC_SIG(list,append);
/* The semantics of this require that we first collect all of the relevant items... */
for (size_t i = 0; i < _class->methods.capacity; ++i) {
KrkTableEntry * entry = &_class->methods.entries[i];
if (!IS_KWARGS(entry->key)) {
KrkClass * type = krk_getType(entry->value);
if (type->_set_name) {
FUNC_NAME(list,append)(2,(KrkValue[]){setnames,entry->key},0);
FUNC_NAME(list,append)(2,(KrkValue[]){setnames,entry->value},0);
}
}
}
/* Then call __set_name__ on them */
for (size_t i = 0; i < AS_LIST(setnames)->count; i += 2) {
KrkValue name = AS_LIST(setnames)->values[i];
KrkValue value = AS_LIST(setnames)->values[i+1];
KrkClass * type = krk_getType(value);
if (type->_set_name) {
krk_push(value);
krk_push(OBJECT_VAL(_class));
krk_push(name);
krk_callDirect(type->_set_name, 3);
/* If any of these raises an exception, bail; CPython raises
* an outer exception, setting the cause, but I'm being lazy
* at the moment... */
if (unlikely(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) {
break;
}
}
}
/* List used to store name+value pairs */
krk_pop();
}
/**
* Maps values to their base classes.
* Internal version of type().
@ -2692,6 +2736,8 @@ _finishReturn: (void)0;
KrkClass * _class = AS_CLASS(krk_peek(0));
/* Store special methods for quick access */
krk_finalizeClass(_class);
/* Call __set_name__? */
_callSetName(_class);
break;
}
case OP_INHERIT: {