Cleanup common method invocation instructions
This commit is contained in:
parent
431d347568
commit
ff43e94054
@ -74,6 +74,15 @@ KRK_Method(type,__subclasses__) {
|
||||
return krk_pop();
|
||||
}
|
||||
|
||||
KRK_Method(type,__getitem__) {
|
||||
if (self->_classgetitem && argc == 2) {
|
||||
krk_push(argv[0]);
|
||||
krk_push(argv[1]);
|
||||
return krk_callDirect(self->_classgetitem, 2);
|
||||
}
|
||||
return krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not subscriptable", "type");
|
||||
}
|
||||
|
||||
_noexport
|
||||
void _createAndBind_type(void) {
|
||||
KrkClass * type = ADD_BASE_CLASS(vm.baseClasses->typeClass, "type", vm.baseClasses->objectClass);
|
||||
@ -87,6 +96,7 @@ void _createAndBind_type(void) {
|
||||
BIND_METHOD(type,__init__);
|
||||
BIND_METHOD(type,__str__);
|
||||
BIND_METHOD(type,__subclasses__);
|
||||
BIND_METHOD(type,__getitem__);
|
||||
krk_defineNative(&type->methods,"__repr__",FUNC_NAME(type,__str__));
|
||||
|
||||
krk_finalizeClass(type);
|
||||
|
58
src/vm.c
58
src/vm.c
@ -2603,6 +2603,16 @@ static inline int doFormatString(int options) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void commonMethodInvoke(size_t methodOffset, int args, const char * msgFormat) {
|
||||
KrkClass * type = krk_getType(krk_peek(args-1));
|
||||
KrkObj * method = *(KrkObj**)((char*)type + methodOffset);
|
||||
if (likely(method != NULL)) {
|
||||
krk_push(krk_callDirect(method, args));
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->attributeError, msgFormat, krk_typeName(krk_peek(args-1)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* VM main loop.
|
||||
@ -2773,59 +2783,25 @@ _finishReturn: (void)0;
|
||||
krk_pop();
|
||||
break;
|
||||
case OP_INVOKE_GETTER: {
|
||||
KrkClass * type = krk_getType(krk_peek(1));
|
||||
if (likely(type->_getter != NULL)) {
|
||||
krk_push(krk_callDirect(type->_getter, 2));
|
||||
} else if (IS_CLASS(krk_peek(1)) && AS_CLASS(krk_peek(1))->_classgetitem) {
|
||||
krk_push(krk_callDirect(AS_CLASS(krk_peek(1))->_classgetitem, 2));
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not subscriptable", krk_typeName(krk_peek(1)));
|
||||
}
|
||||
commonMethodInvoke(offsetof(KrkClass,_getter), 2, "'%s' object is not subscriptable");
|
||||
break;
|
||||
}
|
||||
case OP_INVOKE_SETTER: {
|
||||
KrkClass * type = krk_getType(krk_peek(2));
|
||||
if (likely(type->_setter != NULL)) {
|
||||
krk_push(krk_callDirect(type->_setter, 3));
|
||||
} else {
|
||||
if (type->_getter) {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not mutable", krk_typeName(krk_peek(2)));
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not subscriptable", krk_typeName(krk_peek(2)));
|
||||
}
|
||||
}
|
||||
commonMethodInvoke(offsetof(KrkClass,_setter), 3, "'%s' object doesn't support item assignment");
|
||||
break;
|
||||
}
|
||||
case OP_INVOKE_DELETE: {
|
||||
KrkClass * type = krk_getType(krk_peek(1));
|
||||
if (likely(type->_delitem != NULL)) {
|
||||
krk_callDirect(type->_delitem, 2);
|
||||
} else {
|
||||
if (type->_getter) {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not mutable", krk_typeName(krk_peek(1)));
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not subscriptable", krk_typeName(krk_peek(1)));
|
||||
}
|
||||
}
|
||||
commonMethodInvoke(offsetof(KrkClass,_delitem), 2, "'%s' object doesn't support item deletion");
|
||||
krk_pop(); /* unused result */
|
||||
break;
|
||||
}
|
||||
case OP_INVOKE_ITER: {
|
||||
KrkClass * type = krk_getType(krk_peek(0));
|
||||
if (likely(type->_iter != NULL)) {
|
||||
krk_push(krk_callDirect(type->_iter, 1));
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not iterable", krk_typeName(krk_peek(0)));
|
||||
}
|
||||
commonMethodInvoke(offsetof(KrkClass,_iter), 1, "'%s' object is not iterable");
|
||||
break;
|
||||
}
|
||||
case OP_INVOKE_CONTAINS: {
|
||||
KrkClass * type = krk_getType(krk_peek(0));
|
||||
if (likely(type->_contains != NULL)) {
|
||||
krk_swap(1);
|
||||
krk_push(krk_callDirect(type->_contains, 2));
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->attributeError, "'%s' object can not be tested for membership", krk_typeName(krk_peek(0)));
|
||||
}
|
||||
krk_swap(1); /* operands are backwards */
|
||||
commonMethodInvoke(offsetof(KrkClass,_contains), 2, "'%s' object can not be tested for membership");
|
||||
break;
|
||||
}
|
||||
case OP_INVOKE_AWAIT: {
|
||||
|
Loading…
Reference in New Issue
Block a user