Use a flag to mark classes not subclassable
A KrkInstance should always have a valid and correct allocSize available from its class object, which for non-subclassable classes like the ones representing stack values should be the size of a normal instance, so that we can safely treat it as an instance until it can get garbage collected when it is allocated before the call to __init__ that replaces it with the right kind of object (or raises an exception).
This commit is contained in:
parent
098b3168f3
commit
1ee63c15f6
@ -61,6 +61,7 @@ typedef struct KrkObj {
|
||||
#define KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD 0x0002
|
||||
#define KRK_OBJ_FLAGS_FUNCTION_IS_DYNAMIC_PROPERTY 0x0004
|
||||
|
||||
#define KRK_OBJ_FLAGS_NO_INHERIT 0x0200
|
||||
#define KRK_OBJ_FLAGS_SECOND_CHANCE 0x0100
|
||||
#define KRK_OBJ_FLAGS_IS_MARKED 0x0010
|
||||
#define KRK_OBJ_FLAGS_IN_REPR 0x0020
|
||||
|
@ -79,7 +79,7 @@ static KrkValue _class_subclasses(int argc, const KrkValue argv[], int hasKw) {
|
||||
_noexport
|
||||
void _createAndBind_type(void) {
|
||||
ADD_BASE_CLASS(vm.baseClasses->typeClass, "type", vm.baseClasses->objectClass);
|
||||
vm.baseClasses->typeClass->allocSize = 0;
|
||||
vm.baseClasses->typeClass->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
|
||||
krk_defineNative(&vm.baseClasses->typeClass->methods, "__base__", krk_baseOfClass)->obj.flags = KRK_OBJ_FLAGS_FUNCTION_IS_DYNAMIC_PROPERTY;
|
||||
krk_defineNative(&vm.baseClasses->typeClass->methods, "__file__", krk_fileOfClass)->obj.flags = KRK_OBJ_FLAGS_FUNCTION_IS_DYNAMIC_PROPERTY;
|
||||
krk_defineNative(&vm.baseClasses->typeClass->methods, "__doc__", krk_docOfClass) ->obj.flags = KRK_OBJ_FLAGS_FUNCTION_IS_DYNAMIC_PROPERTY;
|
||||
|
@ -379,7 +379,7 @@ KRK_METHOD(bytearray,__iter__,{
|
||||
_noexport
|
||||
void _createAndBind_bytesClass(void) {
|
||||
KrkClass * bytes = ADD_BASE_CLASS(vm.baseClasses->bytesClass, "bytes", vm.baseClasses->objectClass);
|
||||
bytes->allocSize = 0; /* cannot subclass */
|
||||
bytes->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
|
||||
KRK_DOC(BIND_METHOD(bytes,__init__),
|
||||
"@brief An array of bytes.\n"
|
||||
"@arguments iter=None\n\n"
|
||||
|
@ -314,7 +314,7 @@ KRK_FUNC(classmethod,{
|
||||
_noexport
|
||||
void _createAndBind_functionClass(void) {
|
||||
KrkClass * codeobject = ADD_BASE_CLASS(vm.baseClasses->codeobjectClass, "codeobject", vm.baseClasses->objectClass);
|
||||
codeobject->allocSize = 0; /* cannot subclass */
|
||||
codeobject->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
|
||||
BIND_METHOD(codeobject,__init__);
|
||||
BIND_METHOD(codeobject,__str__);
|
||||
BIND_METHOD(codeobject,_ip_to_line);
|
||||
@ -325,7 +325,7 @@ void _createAndBind_functionClass(void) {
|
||||
krk_finalizeClass(codeobject);
|
||||
|
||||
KrkClass * function = ADD_BASE_CLASS(vm.baseClasses->functionClass, "function", vm.baseClasses->objectClass);
|
||||
function->allocSize = 0; /* cannot subclass */
|
||||
function->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
|
||||
BIND_METHOD(function,__init__);
|
||||
BIND_METHOD(function,__str__);
|
||||
BIND_METHOD(function,_ip_to_line);
|
||||
@ -341,7 +341,7 @@ void _createAndBind_functionClass(void) {
|
||||
krk_finalizeClass(function);
|
||||
|
||||
KrkClass * method = ADD_BASE_CLASS(vm.baseClasses->methodClass, "method", vm.baseClasses->objectClass);
|
||||
method->allocSize = 0; /* cannot subclass */
|
||||
method->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
|
||||
BIND_METHOD(method,__str__);
|
||||
BIND_METHOD(method,_ip_to_line);
|
||||
BIND_METHOD(method,__init__);
|
||||
|
@ -136,7 +136,7 @@ KRK_METHOD(NotImplementedType,__hash__,{
|
||||
_noexport
|
||||
void _createAndBind_numericClasses(void) {
|
||||
KrkClass * _int = ADD_BASE_CLASS(vm.baseClasses->intClass, "int", vm.baseClasses->objectClass);
|
||||
_int->allocSize = 0; /* cannot subclass */
|
||||
_int->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
|
||||
BIND_METHOD(int,__init__);
|
||||
BIND_METHOD(int,__str__);
|
||||
BIND_METHOD(int,__int__);
|
||||
@ -149,7 +149,7 @@ void _createAndBind_numericClasses(void) {
|
||||
KRK_DOC(_int, "Convert a number or string type to an integer representation.");
|
||||
|
||||
KrkClass * _float = ADD_BASE_CLASS(vm.baseClasses->floatClass, "float", vm.baseClasses->objectClass);
|
||||
_float->allocSize = 0; /* cannot subclass */
|
||||
_float->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
|
||||
BIND_METHOD(float,__init__);
|
||||
BIND_METHOD(float,__int__);
|
||||
BIND_METHOD(float,__float__);
|
||||
@ -161,7 +161,7 @@ void _createAndBind_numericClasses(void) {
|
||||
KRK_DOC(_float, "Convert a number or string type to a float representation.");
|
||||
|
||||
KrkClass * _bool = ADD_BASE_CLASS(vm.baseClasses->boolClass, "bool", vm.baseClasses->intClass);
|
||||
_bool->allocSize = 0; /* cannot subclass */
|
||||
_bool->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
|
||||
BIND_METHOD(bool,__init__);
|
||||
BIND_METHOD(bool,__str__);
|
||||
krk_defineNative(&_bool->methods, "__repr__", FUNC_NAME(bool,__str__));
|
||||
@ -169,14 +169,14 @@ void _createAndBind_numericClasses(void) {
|
||||
KRK_DOC(_bool, "Returns False if the argument is 'falsey', otherwise True.");
|
||||
|
||||
KrkClass * _NoneType = ADD_BASE_CLASS(vm.baseClasses->noneTypeClass, "NoneType", vm.baseClasses->objectClass);
|
||||
_NoneType->allocSize = 0; /* cannot subclass */
|
||||
_NoneType->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
|
||||
BIND_METHOD(NoneType, __str__);
|
||||
BIND_METHOD(NoneType, __hash__);
|
||||
krk_defineNative(&_NoneType->methods, "__repr__", FUNC_NAME(NoneType,__str__));
|
||||
krk_finalizeClass(_NoneType);
|
||||
|
||||
KrkClass * _NotImplementedType = ADD_BASE_CLASS(vm.baseClasses->notImplClass, "NotImplementedType", vm.baseClasses->objectClass);
|
||||
_NotImplementedType->allocSize = 0; /* cannot subclass */
|
||||
_NotImplementedType->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
|
||||
BIND_METHOD(NotImplementedType, __str__);
|
||||
BIND_METHOD(NotImplementedType, __hash__);
|
||||
krk_defineNative(&_NotImplementedType->methods, "__repr__", FUNC_NAME(NotImplementedType,__str__));
|
||||
|
@ -889,7 +889,7 @@ _corrupt:
|
||||
_noexport
|
||||
void _createAndBind_strClass(void) {
|
||||
KrkClass * str = ADD_BASE_CLASS(vm.baseClasses->strClass, "str", vm.baseClasses->objectClass);
|
||||
str->allocSize = 0; /* cannot subclass */
|
||||
str->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
|
||||
BIND_METHOD(str,__init__);
|
||||
BIND_METHOD(str,__iter__);
|
||||
BIND_METHOD(str,__ord__);
|
||||
|
@ -203,7 +203,7 @@ _unhashable:
|
||||
_noexport
|
||||
void _createAndBind_tupleClass(void) {
|
||||
KrkClass * tuple = ADD_BASE_CLASS(vm.baseClasses->tupleClass, "tuple", vm.baseClasses->objectClass);
|
||||
tuple->allocSize = 0; /* cannot subclass */
|
||||
tuple->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT;
|
||||
BIND_METHOD(tuple,__repr__);
|
||||
BIND_METHOD(tuple,__getitem__);
|
||||
BIND_METHOD(tuple,__len__);
|
||||
|
@ -324,8 +324,7 @@ KrkClass * krk_newClass(KrkString * name, KrkClass * baseClass) {
|
||||
}
|
||||
|
||||
KrkInstance * krk_newInstance(KrkClass * _class) {
|
||||
size_t allocSize = _class->allocSize ? _class->allocSize : sizeof(KrkInstance);
|
||||
KrkInstance * instance = (KrkInstance*)allocateObject(allocSize, KRK_OBJ_INSTANCE);
|
||||
KrkInstance * instance = (KrkInstance*)allocateObject(_class->allocSize, KRK_OBJ_INSTANCE);
|
||||
instance->_class = _class;
|
||||
krk_initTable(&instance->fields);
|
||||
return instance;
|
||||
|
2
src/vm.c
2
src/vm.c
@ -2590,7 +2590,7 @@ _finishReturn: (void)0;
|
||||
krk_typeName(superclass));
|
||||
goto _finishException;
|
||||
}
|
||||
if (AS_CLASS(superclass)->allocSize == 0) {
|
||||
if (AS_OBJECT(superclass)->flags & KRK_OBJ_FLAGS_NO_INHERIT) {
|
||||
krk_runtimeError(vm.exceptions->typeError, "'%s' can not be subclassed",
|
||||
AS_CLASS(superclass)->name->chars);
|
||||
goto _finishException;
|
||||
|
Loading…
Reference in New Issue
Block a user