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:
K. Lange 2022-05-31 18:26:53 +09:00
parent 098b3168f3
commit 1ee63c15f6
9 changed files with 15 additions and 15 deletions

View File

@ -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

View File

@ -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;

View File

@ -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"

View File

@ -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__);

View File

@ -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__));

View File

@ -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__);

View File

@ -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__);

View File

@ -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;

View File

@ -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;