initial support for __new__
This commit is contained in:
parent
eef955935d
commit
f9df8b22ef
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -238,6 +238,7 @@ typedef struct KrkClass {
|
||||
KrkObj * _pos;
|
||||
KrkObj * _setattr;
|
||||
KrkObj * _format;
|
||||
KrkObj * _new;
|
||||
|
||||
size_t cacheIndex;
|
||||
} KrkClass;
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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__")
|
||||
|
@ -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);
|
||||
|
@ -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 "
|
||||
|
@ -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__);
|
||||
|
@ -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__);
|
||||
|
@ -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__);
|
||||
|
@ -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);
|
||||
|
||||
|
10
src/sys.c
10
src/sys.c
@ -4,12 +4,12 @@
|
||||
#include <kuroko/util.h>
|
||||
|
||||
#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
|
||||
|
52
src/vm.c
52
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
@ -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']
|
||||
|
@ -1,2 +0,0 @@
|
||||
'object' object has no attribute '__init__'
|
||||
'object' object has no attribute '__init__'
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user