diff --git a/src/builtins.c b/src/builtins.c index cc98707..f2e3c2c 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -177,6 +177,29 @@ KRK_Method(object,__setattr__) { return krk_instanceSetAttribute_wrapper(argv[0], AS_STRING(argv[1]), argv[2]); } +KRK_StaticMethod(object,__new__) { + KrkClass * _class = NULL; + + /* We don't actually care, but we want to accept them anyway */ + int _argc = 0; + const KrkValue * _args = NULL; + + if (!krk_parseArgs("O!*~", (const char*[]){"cls"}, vm.baseClasses->typeClass, &_class, &_argc, &_args)) { + return NONE_VAL(); + } + + if (_argc && _class->_init == vm.baseClasses->objectClass->_init) { + return krk_runtimeError(vm.exceptions->typeError, "%S() takes no arguments", _class->name); + } + + return OBJECT_VAL(krk_newInstance(_class)); +} + +KRK_Method(object,__init__) { + return argv[0]; +} + + /** * object.__str__() / object.__repr__() * @@ -1229,7 +1252,9 @@ void _createAndBind_builtins(void) { BIND_METHOD(object,__hash__); BIND_METHOD(object,__eq__); BIND_METHOD(object,__format__); - BIND_METHOD(object,__setattr__)->obj.flags = KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD; + BIND_STATICMETHOD(object,__setattr__); + BIND_STATICMETHOD(object,__new__); + BIND_METHOD(object,__init__); krk_defineNative(&object->methods, "__repr__", FUNC_NAME(object,__str__)); krk_finalizeClass(object); KRK_DOC(object, diff --git a/src/compiler.c b/src/compiler.c index 6a996ec..9ddb794 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -1606,20 +1606,22 @@ static void classBody(struct GlobalState * state, size_t blockWidth) { consume(TOKEN_IDENTIFIER, "Expected method name after 'def'"); size_t ind = identifierConstant(state, &state->parser.previous); - if (state->parser.previous.length == 8 && memcmp(state->parser.previous.start, "__init__", 8) == 0) { - if (type == TYPE_COROUTINE_METHOD) { - error("'%s' can not be a coroutine","__init__"); - return; + static struct CompilerSpecialMethod { const char * name; int type; } compilerSpecialMethods[] = { + {"__init__", TYPE_INIT}, + {"__class_getitem__", TYPE_CLASSMETHOD}, + {"__new__", TYPE_STATIC}, + {"__prepare__", TYPE_CLASSMETHOD}, + {NULL,0} + }; + + for (struct CompilerSpecialMethod * method = compilerSpecialMethods; method->name; method++) { + if (state->parser.previous.length == strlen(method->name) && memcmp(state->parser.previous.start, method->name, strlen(method->name)) == 0) { + if (type == TYPE_COROUTINE_METHOD) { + error("'%s' can not be a coroutine",method->name); + return; + } + type = method->type; } - type = TYPE_INIT; - } else if (state->parser.previous.length == 17 && memcmp(state->parser.previous.start, "__class_getitem__", 17) == 0) { - if (type == TYPE_COROUTINE_METHOD) { - error("'%s' can not be a coroutine","__class_getitem__"); - return; - } - /* This magic method is implicitly always a class method, - * so mark it as such so we don't do implicit self for it. */ - type = TYPE_CLASSMETHOD; } function(state, type, blockWidth); diff --git a/src/kuroko/object.h b/src/kuroko/object.h index 933b9ba..e7db518 100644 --- a/src/kuroko/object.h +++ b/src/kuroko/object.h @@ -238,6 +238,7 @@ typedef struct KrkClass { KrkObj * _pos; KrkObj * _setattr; KrkObj * _format; + KrkObj * _new; size_t cacheIndex; } KrkClass; diff --git a/src/kuroko/util.h b/src/kuroko/util.h index 5c3e93e..e84d740 100644 --- a/src/kuroko/util.h +++ b/src/kuroko/util.h @@ -93,6 +93,20 @@ #define BIND_PROP(klass,method) krk_defineNativeProperty(&klass->methods, #method, _ ## klass ## _ ## method) #define BIND_FUNC(module,func) krk_defineNative(&module->fields, #func, _krk_ ## func) +static inline KrkNative * krk_defineNativeStaticMethod(KrkTable * table, const char * name, NativeFn function) { + KrkNative * out = krk_defineNative(table,name,function); + out->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD; + return out; +} +#define BIND_STATICMETHOD(klass,method) krk_defineNativeStaticMethod(&klass->methods, #method, _ ## klass ## _ ## method) + +static inline KrkNative * krk_deifneNativeClassMethod(KrkTable * table, const char * name, NativeFn function) { + KrkNative * out = krk_defineNative(table,name,function); + out->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_CLASS_METHOD; + return out; +} +#define BIND_CLASSMETHOD(klass,method) krk_defineNativeClassMethod(&klass->methods, #method, _ ## klass ## _ ## method) + #define KRK_Method_internal_name(klass, name) \ _krk_method_ ## klass ## _ ## name #define KRK_Method_internal_sig(klass, name) \ @@ -120,6 +134,16 @@ } \ KRK_Function_internal_sig(name) +#define KRK_StaticMethod_internal_sig(klass, name) \ + static inline KrkValue KRK_Method_internal_name(klass, name) (const char * _method_name, int argc, const KrkValue argv[], int hasKw) +#define KRK_StaticMethod(klass, name) \ + KRK_StaticMethod_internal_sig(klass, name); \ + FUNC_SIG(klass, name) { \ + static const char * _method_name = # name; \ + return KRK_Method_internal_name(klass,name)(_method_name,argc,argv,hasKw); \ + } \ + KRK_StaticMethod_internal_sig(klass,name) + /** * @brief Inline flexible string array. */ diff --git a/src/methods.h b/src/methods.h index 28b59e6..5778289 100644 --- a/src/methods.h +++ b/src/methods.h @@ -47,6 +47,7 @@ CACHED_METHOD(SETNAME, "__set_name__", _set_name) CACHED_METHOD(POS, "__pos__", _pos) CACHED_METHOD(SETATTR, "__setattr__", _setattr) CACHED_METHOD(FORMAT, "__format__", _format) +CACHED_METHOD(NEW, "__new__", _new) /* These are not methods */ SPECIAL_ATTRS(CLASS, "__class__") diff --git a/src/obj_base.c b/src/obj_base.c index 33ade57..3356e63 100644 --- a/src/obj_base.c +++ b/src/obj_base.c @@ -90,10 +90,58 @@ KRK_Method(type,__getitem__) { return krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not subscriptable", "type"); } +KRK_Method(type,__call__) { + if (self == vm.baseClasses->typeClass) { + if (argc == 2) { + return OBJECT_VAL(krk_getType(argv[1])); + } + return krk_runtimeError(vm.exceptions->attributeError, "TODO type(...)"); + } + + if (!self->_new) { + return krk_runtimeError(vm.exceptions->typeError, "%S() can not be built", self->name); + } + + /* Push args */ + int argCount = argc; + for (int i = 0; i < argc; ++i) { + krk_push(argv[i]); + } + + if (hasKw) { + argCount += 3; + krk_push(KWARGS_VAL(KWARGS_DICT)); + krk_push(argv[argc]); + krk_push(KWARGS_VAL(1)); + } + + krk_push(krk_callDirect(self->_new, argCount)); + + /* Exception here */ + if (unlikely(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) return NONE_VAL(); + + if (krk_isInstanceOf(krk_peek(0), self) && likely(self->_init != NULL)) { + for (int i = 0; i < argc - 1; ++i) { + krk_push(argv[i+1]); + } + + if (hasKw) { + krk_push(KWARGS_VAL(KWARGS_DICT)); + krk_push(argv[argc]); + krk_push(KWARGS_VAL(1)); + } + + return krk_callDirect(self->_init, argCount); + } + + return krk_pop(); +} + _noexport void _createAndBind_type(void) { KrkClass * type = ADD_BASE_CLASS(vm.baseClasses->typeClass, "type", vm.baseClasses->objectClass); type->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT; + type->allocSize = sizeof(KrkClass); BIND_PROP(type,__base__); BIND_PROP(type,__file__); @@ -104,6 +152,7 @@ void _createAndBind_type(void) { BIND_METHOD(type,__str__); BIND_METHOD(type,__subclasses__); BIND_METHOD(type,__getitem__); + BIND_METHOD(type,__call__); krk_defineNative(&type->methods,"__repr__",FUNC_NAME(type,__str__)); krk_finalizeClass(type); diff --git a/src/obj_bytes.c b/src/obj_bytes.c index 13a5469..486c16a 100644 --- a/src/obj_bytes.c +++ b/src/obj_bytes.c @@ -34,7 +34,7 @@ static int _bytes_callback(void * context, const KrkValue * values, size_t count return 0; } -KRK_Method(bytes,__init__) { +KRK_StaticMethod(bytes,__new__) { if (argc < 2) return OBJECT_VAL(krk_newBytes(0,NULL)); METHOD_TAKES_AT_MOST(1); @@ -420,7 +420,7 @@ _noexport void _createAndBind_bytesClass(void) { KrkClass * bytes = ADD_BASE_CLASS(vm.baseClasses->bytesClass, "bytes", vm.baseClasses->objectClass); bytes->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT; - KRK_DOC(BIND_METHOD(bytes,__init__), + KRK_DOC(BIND_STATICMETHOD(bytes,__new__), "@brief An array of bytes.\n" "@arguments iter=None\n\n" "Creates a new @ref bytes object. If @p iter is provided, it should be a @ref tuple or @ref list " diff --git a/src/obj_function.c b/src/obj_function.c index 0f51d23..95d9125 100644 --- a/src/obj_function.c +++ b/src/obj_function.c @@ -46,8 +46,7 @@ static KrkTuple * functionArgs(KrkCodeObject * _self) { #define CURRENT_NAME self #define CURRENT_CTYPE KrkValue -FUNC_SIG(function,__init__) { - static __attribute__ ((unused)) const char* _method_name = "__init__"; +KRK_StaticMethod(function,__new__) { METHOD_TAKES_EXACTLY(3); CHECK_ARG(1,codeobject,KrkCodeObject*,code); @@ -191,7 +190,7 @@ KRK_Method(function,__code__) { #undef CURRENT_CTYPE #define CURRENT_CTYPE KrkCodeObject* -FUNC_SIG(codeobject,__init__) { +KRK_StaticMethod(codeobject,__new__) { return krk_runtimeError(vm.exceptions->typeError, "codeobject object is not instantiable"); } @@ -294,9 +293,8 @@ KRK_Method(codeobject,__args__) { /* __init__ here will be called with a dummy instance as argv[0]; avoid * complications with method argument checking by not using KRK_METHOD. */ -FUNC_SIG(method,__init__) { - static __attribute__ ((unused)) const char* _method_name = "__init__"; - METHOD_TAKES_EXACTLY(2); +KRK_StaticMethod(method,__new__) { + FUNCTION_TAKES_EXACTLY(3); if (!IS_OBJECT(argv[1])) return krk_runtimeError(vm.exceptions->typeError, "first argument must be a heap object"); return OBJECT_VAL(krk_newBoundMethod(argv[2],AS_OBJECT(argv[1]))); } @@ -388,7 +386,7 @@ _noexport void _createAndBind_functionClass(void) { KrkClass * codeobject = ADD_BASE_CLASS(vm.baseClasses->codeobjectClass, "codeobject", vm.baseClasses->objectClass); codeobject->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT; - BIND_METHOD(codeobject,__init__); + BIND_STATICMETHOD(codeobject,__new__); BIND_METHOD(codeobject,__str__); BIND_METHOD(codeobject,_ip_to_line); BIND_PROP(codeobject,__constants__); @@ -405,7 +403,7 @@ void _createAndBind_functionClass(void) { KrkClass * function = ADD_BASE_CLASS(vm.baseClasses->functionClass, "function", vm.baseClasses->objectClass); function->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT; - BIND_METHOD(function,__init__); + BIND_STATICMETHOD(function,__new__); BIND_METHOD(function,__str__); BIND_METHOD(function,_ip_to_line); BIND_PROP(function,__doc__); @@ -422,9 +420,9 @@ void _createAndBind_functionClass(void) { KrkClass * method = ADD_BASE_CLASS(vm.baseClasses->methodClass, "method", vm.baseClasses->objectClass); method->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT; + BIND_STATICMETHOD(method,__new__); BIND_METHOD(method,__str__); BIND_METHOD(method,_ip_to_line); - BIND_METHOD(method,__init__); BIND_PROP(method,__doc__); BIND_PROP(method,__name__); BIND_PROP(method,__qualname__); diff --git a/src/obj_numeric.c b/src/obj_numeric.c index c94e35a..7bc5b77 100644 --- a/src/obj_numeric.c +++ b/src/obj_numeric.c @@ -16,8 +16,7 @@ extern KrkValue krk_int_from_float(double val); -FUNC_SIG(int,__init__) { - static __attribute__ ((unused)) const char* _method_name = "__init__"; +KRK_StaticMethod(int,__new__) { METHOD_TAKES_AT_MOST(2); if (argc < 2) return INTEGER_VAL(0); if (IS_BOOLEAN(argv[1])) return INTEGER_VAL(AS_INTEGER(argv[1])); @@ -567,9 +566,8 @@ KRK_Method(int,__pos__) { } \ } while (0) -FUNC_SIG(float,__init__) { - static __attribute__ ((unused)) const char* _method_name = "__init__"; - METHOD_TAKES_AT_MOST(1); +KRK_StaticMethod(float,__new__) { + FUNCTION_TAKES_AT_MOST(2); if (argc < 2) return FLOATING_VAL(0.0); if (IS_FLOATING(argv[1])) return argv[1]; if (IS_INTEGER(argv[1])) return FLOATING_VAL(AS_INTEGER(argv[1])); @@ -703,9 +701,8 @@ KRK_Method(float,__pos__) { #undef CURRENT_CTYPE #define CURRENT_CTYPE krk_integer_type -FUNC_SIG(bool,__init__) { - static __attribute__ ((unused)) const char* _method_name = "__init__"; - METHOD_TAKES_AT_MOST(1); +KRK_StaticMethod(bool,__new__) { + FUNCTION_TAKES_AT_MOST(2); if (argc < 2) return BOOLEAN_VAL(0); return BOOLEAN_VAL(!krk_isFalsey(argv[1])); } @@ -714,7 +711,7 @@ KRK_Method(bool,__str__) { return OBJECT_VAL((self ? S("True") : S("False"))); } -FUNC_SIG(NoneType,__init__) { +KRK_StaticMethod(NoneType,__new__) { if (argc > 1) return krk_runtimeError(vm.exceptions->argumentError, "%s takes no arguments", "NoneType"); return NONE_VAL(); } @@ -736,7 +733,7 @@ KRK_Method(NoneType,__eq__) { #define IS_NotImplementedType(o) IS_NOTIMPL(o) #define AS_NotImplementedType(o) (1) -FUNC_SIG(NotImplementedType,__init__) { +KRK_StaticMethod(NotImplementedType,__new__) { if (argc > 1) return krk_runtimeError(vm.exceptions->argumentError, "%s takes no arguments", "NotImplementedType"); return NOTIMPL_VAL(); } @@ -756,8 +753,10 @@ KRK_Method(NotImplementedType,__eq__) { } #undef BIND_METHOD +#undef BIND_STATICMETHOD /* These class names conflict with C types, so we need to cheat a bit */ #define BIND_METHOD(klass,method) do { krk_defineNative(& _ ## klass->methods, #method, _ ## klass ## _ ## method); } while (0) +#define BIND_STATICMETHOD(klass,method) do { krk_defineNativeStaticMethod(& _ ## klass->methods, #method, _ ## klass ## _ ## method); } while (0) #define BIND_TRIPLET(klass,name) \ BIND_METHOD(klass,__ ## name ## __); \ BIND_METHOD(klass,__r ## name ## __); \ @@ -766,7 +765,7 @@ _noexport void _createAndBind_numericClasses(void) { KrkClass * _int = ADD_BASE_CLASS(vm.baseClasses->intClass, "int", vm.baseClasses->objectClass); _int->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT; - BIND_METHOD(int,__init__); + BIND_STATICMETHOD(int,__new__); BIND_METHOD(int,__str__); BIND_METHOD(int,__int__); BIND_METHOD(int,__chr__); @@ -807,7 +806,7 @@ void _createAndBind_numericClasses(void) { KrkClass * _float = ADD_BASE_CLASS(vm.baseClasses->floatClass, "float", vm.baseClasses->objectClass); _float->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT; - BIND_METHOD(float,__init__); + BIND_STATICMETHOD(float,__new__); BIND_METHOD(float,__int__); BIND_METHOD(float,__float__); BIND_METHOD(float,__str__); @@ -831,7 +830,7 @@ void _createAndBind_numericClasses(void) { KrkClass * _bool = ADD_BASE_CLASS(vm.baseClasses->boolClass, "bool", vm.baseClasses->intClass); _bool->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT; - BIND_METHOD(bool,__init__); + BIND_STATICMETHOD(bool,__new__); BIND_METHOD(bool,__str__); krk_defineNative(&_bool->methods, "__repr__", FUNC_NAME(bool,__str__)); krk_finalizeClass(_bool); @@ -839,7 +838,7 @@ void _createAndBind_numericClasses(void) { KrkClass * _NoneType = ADD_BASE_CLASS(vm.baseClasses->noneTypeClass, "NoneType", vm.baseClasses->objectClass); _NoneType->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT; - BIND_METHOD(NoneType, __init__); + BIND_STATICMETHOD(NoneType, __new__); BIND_METHOD(NoneType, __str__); BIND_METHOD(NoneType, __hash__); BIND_METHOD(NoneType, __eq__); @@ -848,7 +847,7 @@ void _createAndBind_numericClasses(void) { KrkClass * _NotImplementedType = ADD_BASE_CLASS(vm.baseClasses->notImplClass, "NotImplementedType", vm.baseClasses->objectClass); _NotImplementedType->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT; - BIND_METHOD(NotImplementedType, __init__); + BIND_STATICMETHOD(NotImplementedType, __new__); BIND_METHOD(NotImplementedType, __str__); BIND_METHOD(NotImplementedType, __hash__); BIND_METHOD(NotImplementedType, __eq__); diff --git a/src/obj_str.c b/src/obj_str.c index 9db5f8c..d1bf5c3 100644 --- a/src/obj_str.c +++ b/src/obj_str.c @@ -27,12 +27,12 @@ KRK_Method(str,__ord__) { return INTEGER_VAL(krk_unicodeCodepoint(self,0)); } -KRK_Method(str,__init__) { +KRK_StaticMethod(str,__new__) { /* Ignore argument which would have been an instance */ if (argc < 2) { return OBJECT_VAL(S("")); } - METHOD_TAKES_AT_MOST(1); + FUNCTION_TAKES_AT_MOST(2); if (IS_STRING(argv[1])) return argv[1]; /* strings are immutable, so we can just return the arg */ /* Find the type of arg */ krk_push(argv[1]); @@ -1237,7 +1237,7 @@ _noexport void _createAndBind_strClass(void) { KrkClass * str = ADD_BASE_CLASS(vm.baseClasses->strClass, "str", vm.baseClasses->objectClass); str->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT; - BIND_METHOD(str,__init__); + BIND_STATICMETHOD(str,__new__); BIND_METHOD(str,__iter__); BIND_METHOD(str,__ord__); BIND_METHOD(str,__int__); diff --git a/src/obj_tuple.c b/src/obj_tuple.c index 9c88d53..031db80 100644 --- a/src/obj_tuple.c +++ b/src/obj_tuple.c @@ -24,21 +24,16 @@ static int _tuple_init_callback(void * context, const KrkValue * values, size_t return 0; } -static KrkValue _tuple_init(int argc, const KrkValue argv[], int hasKw) { +KRK_StaticMethod(tuple,__new__) { + METHOD_TAKES_AT_MOST(1); if (argc == 1) { return OBJECT_VAL(krk_newTuple(0)); - } else if (argc == 2) { - /* Expand argument as an iterable. */ - krk_push(OBJECT_VAL(krk_newTuple(0))); - KrkValueArray * positionals = &AS_TUPLE(krk_peek(0))->values; - KrkValue other = argv[1]; - krk_unpackIterable(other, positionals, _tuple_init_callback); - return krk_pop(); - } else { - return krk_runtimeError(vm.exceptions->argumentError, - "%s() takes %s %d argument%s (%d given)", - "tuple","at most",1,"",argc-1); } + krk_push(OBJECT_VAL(krk_newTuple(0))); + KrkValueArray * positionals = &AS_TUPLE(krk_peek(0))->values; + KrkValue other = argv[1]; + krk_unpackIterable(other, positionals, _tuple_init_callback); + return krk_pop(); } /* tuple creator */ @@ -273,6 +268,7 @@ _noexport void _createAndBind_tupleClass(void) { KrkClass * tuple = ADD_BASE_CLASS(vm.baseClasses->tupleClass, "tuple", vm.baseClasses->objectClass); tuple->obj.flags |= KRK_OBJ_FLAGS_NO_INHERIT; + BIND_STATICMETHOD(tuple,__new__); BIND_METHOD(tuple,__repr__); BIND_METHOD(tuple,__getitem__); BIND_METHOD(tuple,__len__); @@ -286,7 +282,6 @@ void _createAndBind_tupleClass(void) { BIND_METHOD(tuple,__hash__); BIND_METHOD(tuple,__add__); BIND_METHOD(tuple,__mul__); - krk_defineNative(&tuple->methods, "__init__", _tuple_init); krk_defineNative(&tuple->methods, "__str__", FUNC_NAME(tuple,__repr__)); krk_finalizeClass(tuple); diff --git a/src/sys.c b/src/sys.c index cca991e..cc85997 100644 --- a/src/sys.c +++ b/src/sys.c @@ -4,12 +4,12 @@ #include #define KRK_VERSION_MAJOR 1 -#define KRK_VERSION_MINOR 3 -#define KRK_VERSION_PATCH 1 -#define KRK_VERSION_LEVEL 0xF -#define KRK_VERSION_SERIAL 0x0 +#define KRK_VERSION_MINOR 4 +#define KRK_VERSION_PATCH 0 +#define KRK_VERSION_LEVEL 0xa +#define KRK_VERSION_SERIAL 0x1 -#define KRK_VERSION_EXTRA_BASE "" +#define KRK_VERSION_EXTRA_BASE "a1" #ifndef STATIC_ONLY #define KRK_VERSION_EXTRA KRK_VERSION_EXTRA_BASE diff --git a/src/vm.c b/src/vm.c index b17876f..da42774 100644 --- a/src/vm.c +++ b/src/vm.c @@ -250,7 +250,7 @@ void krk_finalizeClass(KrkClass * _class) { if (krk_tableGet(&_base->methods, vm.specialMethodNames[entry->index], &tmp)) break; _base = _base->base; } - if (_base && (IS_CLOSURE(tmp) || IS_NATIVE(tmp)) && !(AS_OBJECT(tmp)->flags & KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD)) { + if (_base && (IS_CLOSURE(tmp) || IS_NATIVE(tmp)) && (!(AS_OBJECT(tmp)->flags & KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD) || entry->index == METHOD_NEW)) { *entry->method = AS_OBJECT(tmp); } } @@ -768,38 +768,6 @@ int krk_callValue(KrkValue callee, int argCount, int returnDepth) { switch (OBJECT_TYPE(callee)) { case KRK_OBJ_CLOSURE: return _callManaged(AS_CLOSURE(callee), argCount, returnDepth); case KRK_OBJ_NATIVE: return _callNative(AS_NATIVE(callee), argCount, returnDepth); - case KRK_OBJ_INSTANCE: { - KrkClass * _class = AS_INSTANCE(callee)->_class; - if (likely(_class->_call != NULL)) { - if (unlikely(returnDepth == 0)) _rotate(argCount); - krk_currentThread.stackTop[-argCount - 1] = callee; - argCount++; - returnDepth = returnDepth ? (returnDepth - 1) : 0; - return (_class->_call->type == KRK_OBJ_CLOSURE) ? _callManaged((KrkClosure*)_class->_call, argCount, returnDepth) : _callNative((KrkNative*)_class->_call, argCount, returnDepth); - } else { - krk_runtimeError(vm.exceptions->typeError, "'%T' object is not callable", callee); - return 0; - } - } - case KRK_OBJ_CLASS: { - KrkClass * _class = AS_CLASS(callee); - KrkInstance * newInstance = krk_newInstance(_class); - if (likely(_class->_init != NULL)) { - if (unlikely(returnDepth == 0)) _rotate(argCount); - krk_currentThread.stackTop[-argCount - 1] = OBJECT_VAL(newInstance); - callee = OBJECT_VAL(_class->_init); - argCount++; - returnDepth = returnDepth ? (returnDepth - 1) : 0; - goto _innerObject; - } else if (unlikely(argCount != 0)) { - krk_runtimeError(vm.exceptions->typeError, "%S() takes no arguments (%d given)", - _class->name, argCount); - return 0; - } - krk_currentThread.stackTop -= argCount + returnDepth; - krk_push(OBJECT_VAL(newInstance)); - return 2; - } case KRK_OBJ_BOUND_METHOD: { KrkBoundMethod * bound = AS_BOUND_METHOD(callee); if (unlikely(!bound->method)) { @@ -813,8 +781,19 @@ int krk_callValue(KrkValue callee, int argCount, int returnDepth) { returnDepth = returnDepth ? (returnDepth - 1) : 0; goto _innerObject; } - default: - break; + default: { + KrkClass * _class = krk_getType(callee); + if (likely(_class->_call != NULL)) { + if (unlikely(returnDepth == 0)) _rotate(argCount); + krk_currentThread.stackTop[-argCount - 1] = callee; + argCount++; + returnDepth = returnDepth ? (returnDepth - 1) : 0; + return (_class->_call->type == KRK_OBJ_CLOSURE) ? _callManaged((KrkClosure*)_class->_call, argCount, returnDepth) : _callNative((KrkNative*)_class->_call, argCount, returnDepth); + } else { + krk_runtimeError(vm.exceptions->typeError, "'%T' object is not callable", callee); + return 0; + } + } } } krk_runtimeError(vm.exceptions->typeError, "'%T' object is not callable", callee); @@ -2778,6 +2757,9 @@ _finishReturn: (void)0; if (AS_STRING(name) == S("__class_getitem__") && IS_CLOSURE(method)) { AS_CLOSURE(method)->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_CLASS_METHOD; } + if (AS_STRING(name) == S("__new__") && IS_CLOSURE(method)) { + AS_CLOSURE(method)->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_STATIC_METHOD; + } krk_pop(); break; } diff --git a/test/testAttributePacking.krk.expect b/test/testAttributePacking.krk.expect index 0215bde..45c5625 100644 --- a/test/testAttributePacking.krk.expect +++ b/test/testAttributePacking.krk.expect @@ -1,4 +1,4 @@ -['__class__', '__dir__', '__eq__', '__format__', '__hash__', '__repr__', '__setattr__', '__str__', 'longList', 'ofAttributes', 'onThatObject', 'thatWeWantToSet'] +['__class__', '__dir__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__', 'longList', 'ofAttributes', 'onThatObject', 'thatWeWantToSet'] 1 2 3 diff --git a/test/testDel.krk.expect b/test/testDel.krk.expect index 22bc1db..639d3b4 100644 --- a/test/testDel.krk.expect +++ b/test/testDel.krk.expect @@ -7,10 +7,10 @@ False [1, 3, 4, 5] [1, 3, 4] list index out of range: 3 -['__class__', '__dir__', '__eq__', '__format__', '__hash__', '__repr__', '__setattr__', '__str__', 'baz', 'qux'] +['__class__', '__dir__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__', 'baz', 'qux'] 42 -['__class__', '__dir__', '__eq__', '__format__', '__hash__', '__repr__', '__setattr__', '__str__', 'qux'] +['__class__', '__dir__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__', 'qux'] hi 'object' object has no attribute 'baz' -['__class__', '__dir__', '__eq__', '__format__', '__hash__', '__repr__', '__setattr__', '__str__'] +['__class__', '__dir__', '__eq__', '__format__', '__hash__', '__init__', '__new__', '__repr__', '__setattr__', '__str__'] 'object' object has no attribute 'bar' diff --git a/test/testGetattrDir.krk.expect b/test/testGetattrDir.krk.expect index 6eae899..23fbbf6 100644 --- a/test/testGetattrDir.krk.expect +++ b/test/testGetattrDir.krk.expect @@ -1,3 +1,3 @@ -['__class__', '__dir__', '__eq__', '__format__', '__func__', '__getattr__', '__hash__', '__init__', '__module__', '__qualname__', '__repr__', '__setattr__', '__str__', '_dict'] +['__class__', '__dir__', '__eq__', '__format__', '__func__', '__getattr__', '__hash__', '__init__', '__module__', '__new__', '__qualname__', '__repr__', '__setattr__', '__str__', '_dict'] 1 -['__class__', '__dir__', '__eq__', '__format__', '__func__', '__hash__', '__module__', '__qualname__', '__repr__', '__setattr__', '__str__', 'butts'] +['__class__', '__dir__', '__eq__', '__format__', '__func__', '__hash__', '__init__', '__module__', '__new__', '__qualname__', '__repr__', '__setattr__', '__str__', 'butts'] diff --git a/test/testImplicitObjectBase.krk.expect b/test/testImplicitObjectBase.krk.expect index 3454412..e69de29 100644 --- a/test/testImplicitObjectBase.krk.expect +++ b/test/testImplicitObjectBase.krk.expect @@ -1,2 +0,0 @@ -'object' object has no attribute '__init__' -'object' object has no attribute '__init__' diff --git a/test/testSubclassPropertySuperCall.krk.expect b/test/testSubclassPropertySuperCall.krk.expect index e6bca56..60e7b61 100644 --- a/test/testSubclassPropertySuperCall.krk.expect +++ b/test/testSubclassPropertySuperCall.krk.expect @@ -1,6 +1,6 @@ True True -['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__get__', '__hash__', '__init__', '__module__', '__name__', '__repr__', '__set__', '__setattr__', '__str__', 'fget', 'setter'] +['__class__', '__dir__', '__doc__', '__eq__', '__format__', '__get__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__repr__', '__set__', '__setattr__', '__str__', 'fget', 'setter'] p retrieved from A {'a': 45} calling property from subclass