Use a custom formatter for krk_runtimeError

This commit is contained in:
K. Lange 2022-07-27 21:42:37 +09:00
parent b9c8e36414
commit 26a31b713e
18 changed files with 260 additions and 130 deletions

View File

@ -49,7 +49,7 @@ static KrkValue myfunction(int argc, KrkValue argv[], int hasKw) {
int myarg;
if (argc != 1) return krk_runtimeError(vm.exceptions->argumentError, "myfunction() expects exactly 1 argument, %d given", argc);
if (!IS_INTEGER(argv[0])) return krk_runtimeError(vm.exceptions->typeError, "expected int, not '%s'", krk_typeName(argv[0]));
if (!IS_INTEGER(argv[0])) return krk_runtimeError(vm.exceptions->typeError, "expected int, not '%T'", argv[0]);
myarg = AS_INTEGER(argv[0]);

View File

@ -175,7 +175,7 @@ KRK_Method(object,__format__) {
if (!IS_STRING(argv[1])) return TYPE_ERROR(str,argv[1]);
if (AS_STRING(argv[1])->length != 0) return krk_runtimeError(vm.exceptions->typeError, "Unsupported format string");
KrkClass * type = krk_getType(argv[0]);
if (!type->_tostr) return krk_runtimeError(vm.exceptions->typeError, "'%s' can not be converted to str", krk_typeName(argv[0]));
if (!type->_tostr) return krk_runtimeError(vm.exceptions->typeError, "'%T' can not be converted to str", argv[0]);
krk_push(argv[0]);
return krk_callDirect(type->_tostr, 1);
}
@ -190,7 +190,7 @@ KRK_Function(len) {
if (IS_TUPLE(argv[0])) return INTEGER_VAL(AS_TUPLE(argv[0])->values.count);
KrkClass * type = krk_getType(argv[0]);
if (!type->_len) return krk_runtimeError(vm.exceptions->typeError, "object of type '%s' has no len()", krk_typeName(argv[0]));
if (!type->_len) return krk_runtimeError(vm.exceptions->typeError, "object of type '%T' has no len()", argv[0]);
krk_push(argv[0]);
return krk_callDirect(type->_len, 1);
@ -311,7 +311,7 @@ int krk_unpackIterable(KrkValue iterable, void * context, int callback(void *, c
} else {
KrkClass * type = krk_getType(iterable);
if (unlikely(!type->_iter)) {
krk_runtimeError(vm.exceptions->typeError, "'%s' object is not iterable", krk_typeName(iterable));
krk_runtimeError(vm.exceptions->typeError, "'%T' object is not iterable", iterable);
return 1;
}
@ -413,7 +413,7 @@ KRK_Method(map,__init__) {
for (int i = 2; i < argc; ++i) {
KrkClass * type = krk_getType(argv[i]);
if (!type->_iter) {
return krk_runtimeError(vm.exceptions->typeError, "'%s' object is not iterable", krk_typeName(argv[i]));
return krk_runtimeError(vm.exceptions->typeError, "'%T' object is not iterable", argv[i]);
}
krk_push(argv[i]);
KrkValue asIter = krk_callDirect(type->_iter, 1);
@ -477,7 +477,7 @@ KRK_Method(zip,__init__) {
for (int i = 1; i < argc; ++i) {
KrkClass * type = krk_getType(argv[i]);
if (!type->_iter) {
return krk_runtimeError(vm.exceptions->typeError, "'%s' object is not iterable", krk_typeName(argv[i]));
return krk_runtimeError(vm.exceptions->typeError, "'%T' object is not iterable", argv[i]);
}
krk_push(argv[i]);
KrkValue asIter = krk_callDirect(type->_iter, 1);
@ -527,7 +527,7 @@ KRK_Method(filter,__init__) {
krk_attachNamedValue(&self->fields, "_function", argv[1]);
KrkClass * type = krk_getType(argv[2]);
if (!type->_iter) {
return krk_runtimeError(vm.exceptions->typeError, "'%s' object is not iterable", krk_typeName(argv[2]));
return krk_runtimeError(vm.exceptions->typeError, "'%T' object is not iterable", argv[2]);
}
krk_push(argv[2]);
KrkValue asIter = krk_callDirect(type->_iter, 1);
@ -593,7 +593,7 @@ KRK_Method(enumerate,__init__) {
/* Attach iterator */
KrkClass * type = krk_getType(argv[1]);
if (!type->_iter) {
return krk_runtimeError(vm.exceptions->typeError, "'%s' object is not iterable", krk_typeName(argv[1]));
return krk_runtimeError(vm.exceptions->typeError, "'%T' object is not iterable", argv[1]);
}
krk_push(argv[1]);
KrkValue asIter = krk_callDirect(type->_iter, 1);
@ -724,12 +724,12 @@ KRK_Function(print) {
char * end = "\n"; size_t endLen = 1;
if (hasKw) {
if (krk_tableGet(AS_DICT(argv[argc]), OBJECT_VAL(S("sep")), &sepVal)) {
if (!IS_STRING(sepVal)) return krk_runtimeError(vm.exceptions->typeError, "'%s' should be a string, not '%s'", "sep", krk_typeName(sepVal));
if (!IS_STRING(sepVal)) return krk_runtimeError(vm.exceptions->typeError, "'%s' should be a string, not '%T'", "sep", sepVal);
sep = AS_CSTRING(sepVal);
sepLen = AS_STRING(sepVal)->length;
}
if (krk_tableGet(AS_DICT(argv[argc]), OBJECT_VAL(S("end")), &endVal)) {
if (!IS_STRING(endVal)) return krk_runtimeError(vm.exceptions->typeError, "'%s' should be a string, not '%s'", "end", krk_typeName(endVal));
if (!IS_STRING(endVal)) return krk_runtimeError(vm.exceptions->typeError, "'%s' should be a string, not '%T'", "end", endVal);
end = AS_CSTRING(endVal);
endLen = AS_STRING(endVal)->length;
}
@ -1037,7 +1037,7 @@ KRK_Method(property,__get__) {
KrkValue fget;
if (!krk_tableGet(&self->fields, OBJECT_VAL(S("fget")), &fget))
return krk_runtimeError(vm.exceptions->attributeError, "'%s' object has no attribute '%s'", "property", "fget");
return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", argv[0], "fget");
krk_push(fget);
krk_push(argv[1]);
@ -1068,7 +1068,7 @@ KRK_Method(property,__set__) {
KRK_Function(id) {
FUNCTION_TAKES_EXACTLY(1);
if (!IS_OBJECT(argv[0])) return krk_runtimeError(vm.exceptions->typeError, "'%s' has no identity", krk_typeName(argv[0]));
if (!IS_OBJECT(argv[0])) return krk_runtimeError(vm.exceptions->typeError, "'%T' has no identity", argv[0]);
return INTEGER_VAL((size_t)AS_OBJECT(argv[0]));
}
@ -1095,8 +1095,7 @@ KRK_Function(abs) {
return FLOATING_VAL(i >= 0 ? i : -i);
} else {
trySlowMethod(OBJECT_VAL(S("__abs__")));
return krk_runtimeError(vm.exceptions->typeError, "bad operand type for 'abs()': '%s'",
krk_typeName(argv[0]));
return krk_runtimeError(vm.exceptions->typeError, "bad operand type for 'abs()': '%T'", argv[0]);
}
}
@ -1107,7 +1106,7 @@ KRK_Function(format) {
KrkClass * type = krk_getType(argv[0]);
if (!type->_format) {
return krk_runtimeError(vm.exceptions->typeError, "'%s' has no __format__ method", krk_typeName(argv[0]));
return krk_runtimeError(vm.exceptions->typeError, "'%T' has no __format__ method", argv[0]);
}
krk_push(argv[0]);

View File

@ -603,7 +603,7 @@ KRK_Function(dis) {
krk_disassembleCodeObject(stdout, func, tmp);
free(tmp);
} else {
krk_runtimeError(vm.exceptions->typeError, "Can not disassemble built-in method of '%s'", krk_typeName(AS_BOUND_METHOD(argv[0])->receiver));
krk_runtimeError(vm.exceptions->typeError, "Can not disassemble built-in method of '%T'", AS_BOUND_METHOD(argv[0])->receiver);
}
} else if (IS_CLASS(argv[0])) {
KrkValue code;
@ -613,7 +613,7 @@ KRK_Function(dis) {
}
/* TODO Methods! */
} else {
krk_runtimeError(vm.exceptions->typeError, "Don't know how to disassemble '%s'", krk_typeName(argv[0]));
krk_runtimeError(vm.exceptions->typeError, "Don't know how to disassemble '%T'", argv[0]);
}
return NONE_VAL();

View File

@ -25,8 +25,8 @@
#define ADD_BASE_CLASS(obj, name, baseClass) krk_makeClass(vm.builtins, &obj, name, baseClass)
#define ATTRIBUTE_NOT_ASSIGNABLE() do { if (unlikely(argc != 1)) return krk_runtimeError(vm.exceptions->attributeError, "'%s' object has no attribute '%s'", \
krk_typeName(argv[0]), _method_name); } while (0)
#define ATTRIBUTE_NOT_ASSIGNABLE() do { if (unlikely(argc != 1)) return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", \
argv[0], _method_name); } while (0)
#define METHOD_TAKES_NONE() do { if (unlikely(argc != 1)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes no arguments (%d given)", \
_method_name, (argc-1)); } while (0)
@ -52,8 +52,8 @@
#define FUNCTION_TAKES_AT_MOST(n) do { if (unlikely(argc > n)) return krk_runtimeError(vm.exceptions->argumentError, "%s() takes %s %d argument%s (%d given)", \
_method_name, "at most", n, (n != 1) ? "s" : "", (argc)); } while (0)
#define TYPE_ERROR(expected,value) krk_runtimeError(vm.exceptions->typeError, "%s() expects %s, not '%s'", \
/* Function name */ _method_name, /* expected type */ #expected, krk_typeName(value))
#define TYPE_ERROR(expected,value) krk_runtimeError(vm.exceptions->typeError, "%s() expects %s, not '%T'", \
/* Function name */ _method_name, /* expected type */ #expected, value)
#define NOT_ENOUGH_ARGS(name) krk_runtimeError(vm.exceptions->argumentError, "Expected more args.")

View File

@ -472,12 +472,25 @@ extern void krk_attachNamedObject(KrkTable * table, const char name[], KrkObj *
* The created exception object is attached to the current thread state and
* the @c KRK_THREAD_HAS_EXCEPTION flag is set.
*
* If the format string is exactly "%V", the first format argument will
* be attached the exception as the 'msg' attribute.
*
* No field width or precisions are supported on any conversion specifiers.
*
* Standard conversion specifiers 'c', 's', 'd', 'u' are available, and the
* 'd' and 'u' specifiers may have length modifiers of l, L, or z.
*
* Additional format specifiers are as follows:
*
* %S - Accepts one KrkString* to be printed in its entirety.
* %R - Accepts one KrkValue and calls repr on it.
* %T - Accepts one KrkValue and emits the name of its type.
*
* @param type Class pointer for the exception type, eg. @c vm.exceptions->valueError
* @param fmt Format string.
* @return As a convenience to C extension authors, returns @c None
*/
extern KrkValue krk_runtimeError(KrkClass * type, const char * fmt, ...)
__attribute__((format (printf, 2, 3)));
extern KrkValue krk_runtimeError(KrkClass * type, const char * fmt, ...);
/**
* @brief Get a pointer to the current thread state.
@ -749,6 +762,9 @@ extern int krk_isFalsey(KrkValue value);
* This is a convenience function that works in essentially the
* same way as the OP_GET_PROPERTY instruction.
*
* @warning As this function takes a C string, it will not work with
* @warning attribute names that have nil bytes.
*
* @param value Value to examine.
* @param name C-string of the property name to query.
* @return The requested property, or None with an @ref AttributeError
@ -769,6 +785,9 @@ extern KrkValue krk_valueGetAttribute_default(KrkValue value, char * name, KrkVa
* This is a convenience function that works in essentially the
* same way as the OP_SET_PROPERTY instruction.
*
* @warning As this function takes a C string, it will not work with
* @warning attribute names that have nil bytes.
*
* @param owner The owner of the property to modify.
* @param name C-string of the property name to modify.
* @param to The value to assign.
@ -785,6 +804,9 @@ extern KrkValue krk_valueSetAttribute(KrkValue owner, char * name, KrkValue to);
* This is a convenience function that works in essentially the
* same way as the OP_DEL_PROPERTY instruction.
*
* @warning As this function takes a C string, it will not work with
* @warning attribute names that have nil bytes.
*
* @param owner The owner of the property to delete.
* @param name C-string of the property name to delete.
*/

View File

@ -34,7 +34,7 @@
} }
#define REAL_NUMBER_NOT(name, garbage) { \
krk_runtimeError(vm.exceptions->typeError, "%s() argument must be real number, not %s", #name, krk_typeName(garbage)); \
krk_runtimeError(vm.exceptions->typeError, "%s() argument must be real number, not '%T'", #name, garbage); \
return NONE_VAL(); \
}

View File

@ -113,20 +113,20 @@ static int socket_parse_address(struct socket * self, KrkValue address, struct s
if (self->family == AF_INET) {
/* Should be 2-tuple */
if (!IS_tuple(address)) {
krk_runtimeError(vm.exceptions->typeError, "Expected 2-tuple, not '%s'", krk_typeName(address));
krk_runtimeError(vm.exceptions->typeError, "Expected 2-tuple, not '%T'", address);
return 1;
}
KrkTuple * addr = AS_TUPLE(address);
if (addr->values.count != 2) {
krk_runtimeError(vm.exceptions->typeError, "Expected 2-tuple, not '%s'", krk_typeName(address));
krk_runtimeError(vm.exceptions->typeError, "Expected 2-tuple, not '%T'", address);
return 1;
}
if (!IS_str(addr->values.values[0])) {
krk_runtimeError(vm.exceptions->typeError, "Address should be int, not '%s'", krk_typeName(addr->values.values[0]));
krk_runtimeError(vm.exceptions->typeError, "Address should be int, not '%T'", addr->values.values[0]);
return 1;
}
if (!IS_int(addr->values.values[1])) {
krk_runtimeError(vm.exceptions->typeError, "Port should be int, not '%s'", krk_typeName(addr->values.values[1]));
krk_runtimeError(vm.exceptions->typeError, "Port should be int, not '%T'", addr->values.values[1]);
return 1;
}

View File

@ -27,8 +27,8 @@ KRK_Method(bytes,__init__) {
krk_push(OBJECT_VAL(out));
for (size_t i = 0; i < AS_TUPLE(argv[1])->values.count; ++i) {
if (!IS_INTEGER(AS_TUPLE(argv[1])->values.values[i])) {
return krk_runtimeError(vm.exceptions->typeError, "%s() expects %s, not '%s'",
"bytes", "tuple of ints", krk_typeName(AS_TUPLE(argv[1])->values.values[i]));
return krk_runtimeError(vm.exceptions->typeError, "%s() expects %s, not '%T'",
"bytes", "tuple of ints", AS_TUPLE(argv[1])->values.values[i]);
}
out->bytes[i] = AS_INTEGER(AS_TUPLE(argv[1])->values.values[i]);
}
@ -38,8 +38,8 @@ KRK_Method(bytes,__init__) {
krk_push(OBJECT_VAL(out));
for (size_t i = 0; i < AS_LIST(argv[1])->count; ++i) {
if (!IS_INTEGER(AS_LIST(argv[1])->values[i])) {
return krk_runtimeError(vm.exceptions->typeError, "%s() expects %s, not '%s'",
"bytes", "list of ints", krk_typeName(AS_LIST(argv[1])->values[i]));
return krk_runtimeError(vm.exceptions->typeError, "%s() expects %s, not '%T'",
"bytes", "list of ints", AS_LIST(argv[1])->values[i]);
}
out->bytes[i] = AS_INTEGER(AS_LIST(argv[1])->values[i]);
}
@ -50,7 +50,7 @@ KRK_Method(bytes,__init__) {
AS_BYTES(AS_bytearray(argv[1])->actual)->bytes));
}
return krk_runtimeError(vm.exceptions->typeError, "Can not convert '%s' to bytes", krk_typeName(argv[1]));
return krk_runtimeError(vm.exceptions->typeError, "Can not convert '%T' to bytes", argv[1]);
}
#undef IS_bytes
@ -198,8 +198,8 @@ static int _bytes_join_callback(void * context, const KrkValue * values, size_t
for (size_t i = 0; i < count; ++i) {
if (!IS_BYTES(values[i])) {
krk_runtimeError(vm.exceptions->typeError, "%s() expects %s, not '%s'",
"join", "bytes", krk_typeName(values[i]));
krk_runtimeError(vm.exceptions->typeError, "%s() expects %s, not '%T'",
"join", "bytes", values[i]);
return 1;
}

View File

@ -4,13 +4,6 @@
#include <kuroko/memory.h>
#include <kuroko/util.h>
#define KEY_ERROR(value) {\
KrkClass * type = krk_getType(value); \
krk_push(value); \
KrkValue asString = krk_callDirect(type->_reprer, 1); \
if (IS_STRING(asString)) return krk_runtimeError(vm.exceptions->keyError, "%s", AS_CSTRING(asString)); \
return krk_runtimeError(vm.exceptions->keyError, "key error"); }
/**
* Exposed method called to produce dictionaries from `{expr: expr, ...}` sequences in managed code.
* Expects arguments as `key,value,key,value`...
@ -131,7 +124,7 @@ KRK_Method(dict,__getitem__) {
KrkValue out;
if (!krk_tableGet(&self->entries, argv[1], &out)) {
if (!IS_NONE(krk_currentThread.currentException)) return NONE_VAL();
KEY_ERROR(argv[1]);
return krk_runtimeError(vm.exceptions->keyError, "%V", argv[1]);
}
return out;
}
@ -156,7 +149,7 @@ KRK_Method(dict,__delitem__) {
METHOD_TAKES_EXACTLY(1);
if (!krk_tableDelete(&self->entries, argv[1])) {
if (!IS_NONE(krk_currentThread.currentException)) return NONE_VAL();
KEY_ERROR(argv[1]);
return krk_runtimeError(vm.exceptions->keyError, "%V", argv[1]);
}
return NONE_VAL();
}

View File

@ -253,11 +253,11 @@ int krk_getAwaitable(void) {
krk_push(krk_callStack(0));
KrkClass * _type = krk_getType(krk_peek(0));
if (!_type || !_type->_iter) {
krk_runtimeError(vm.exceptions->attributeError, "__await__ returned non-iterator of type '%s'", krk_typeName(krk_peek(0)));
krk_runtimeError(vm.exceptions->attributeError, "__await__ returned non-iterator of type '%T'", krk_peek(0));
return 0;
}
} else {
krk_runtimeError(vm.exceptions->attributeError, "'%s' object is not awaitable", krk_typeName(krk_peek(0)));
krk_runtimeError(vm.exceptions->attributeError, "'%T' object is not awaitable", krk_peek(0));
return 0;
}

View File

@ -365,14 +365,14 @@ KRK_Method(list,index) {
if (IS_INTEGER(argv[2]))
min = AS_INTEGER(argv[2]);
else
return krk_runtimeError(vm.exceptions->typeError, "%s must be int, not '%s'", "min", krk_typeName(argv[2]));
return krk_runtimeError(vm.exceptions->typeError, "%s must be int, not '%T'", "min", argv[2]);
}
if (argc > 3) {
if (IS_INTEGER(argv[3]))
max = AS_INTEGER(argv[3]);
else
return krk_runtimeError(vm.exceptions->typeError, "%s must be int, not '%s'", "max", krk_typeName(argv[3]));
return krk_runtimeError(vm.exceptions->typeError, "%s must be int, not '%T'", "max", argv[3]);
}
pthread_rwlock_rdlock(&self->rwlock);

View File

@ -1190,15 +1190,12 @@ KRK_Method(long,__init__) {
} else if (IS_STRING(argv[1])) {
/* XXX This should probably work like int(...) does and default to base 10... and take a base at all... */
if (krk_long_parse_string(AS_CSTRING(argv[1]),self->value,0,AS_STRING(argv[1])->length)) {
krk_push(argv[1]);
KrkValue repred = krk_callDirect(vm.baseClasses->strClass->_reprer, 1);
return krk_runtimeError(vm.exceptions->valueError, "invalid literal for long() with base " PRIkrk_int "%s%s",
(krk_integer_type)0, IS_STRING(repred) ? ": " : "", IS_STRING(repred) ? AS_CSTRING(repred) : "");
return krk_runtimeError(vm.exceptions->valueError, "invalid literal for long() with base 0: %R", argv[1]);
}
} else if (IS_long(argv[1])) {
krk_long_init_copy(self->value,AS_long(argv[1])->value);
} else {
return krk_runtimeError(vm.exceptions->typeError, "%s() argument must be a string or a number, not '%s'", "int", krk_typeName(argv[1]));
return krk_runtimeError(vm.exceptions->typeError, "%s() argument must be a string or a number, not '%T'", "int", argv[1]);
}
/* our value should be set */
return argv[0];

View File

@ -28,16 +28,14 @@ FUNC_SIG(int,__init__) {
}
KrkValue result = krk_parse_int(AS_CSTRING(argv[1]), AS_STRING(argv[1])->length, _base);
if (IS_NONE(result)) {
krk_push(argv[1]);
KrkValue repred = krk_callDirect(vm.baseClasses->strClass->_reprer, 1);
return krk_runtimeError(vm.exceptions->valueError, "invalid literal for int() with base " PRIkrk_int "%s%s",
_base, IS_STRING(repred) ? ": " : "", IS_STRING(repred) ? AS_CSTRING(repred) : "");
return krk_runtimeError(vm.exceptions->valueError,
"invalid literal for int() with base %zd: %R", (ssize_t)_base, argv[1]);
}
return result;
}
if (IS_FLOATING(argv[1])) return INTEGER_VAL(AS_FLOATING(argv[1]));
if (IS_BOOLEAN(argv[1])) return INTEGER_VAL(AS_BOOLEAN(argv[1]));
return krk_runtimeError(vm.exceptions->typeError, "%s() argument must be a string or a number, not '%s'", "int", krk_typeName(argv[1]));
return krk_runtimeError(vm.exceptions->typeError, "%s() argument must be a string or a number, not '%T'", "int", argv[1]);
}
KRK_Method(int,__str__) {
@ -573,7 +571,7 @@ FUNC_SIG(float,__init__) {
trySlowMethod(vm.specialMethodNames[METHOD_FLOAT]);
return krk_runtimeError(vm.exceptions->typeError, "%s() argument must be a string or a number, not '%s'", "float", krk_typeName(argv[1]));
return krk_runtimeError(vm.exceptions->typeError, "%s() argument must be a string or a number, not '%T'", "float", argv[1]);
}
KRK_Method(float,__int__) { return INTEGER_VAL(self); }

View File

@ -108,7 +108,7 @@ KRK_Method(set,__and__) {
KrkClass * type = krk_getType(argv[1]);
if (!type->_contains)
return krk_runtimeError(vm.exceptions->typeError, "unsupported operand types for %s: '%s' and '%s'", "&", "set", krk_typeName(argv[1]));
return krk_runtimeError(vm.exceptions->typeError, "unsupported operand types for %s: '%T' and '%T'", "&", argv[0], argv[1]);
for (size_t i = 0; i < self->entries.capacity; ++i) {
KrkTableEntry * entry = &self->entries.entries[i];
@ -136,7 +136,7 @@ KRK_Method(set,__xor__) {
KrkClass * type = krk_getType(argv[1]);
if (!type->_contains)
return krk_runtimeError(vm.exceptions->typeError, "unsupported operand types for %s: '%s' and '%s'", "&", "set", krk_typeName(argv[1]));
return krk_runtimeError(vm.exceptions->typeError, "unsupported operand types for %s: '%T' and '%T'", "&", argv[0], argv[1]);
for (size_t i = 0; i < self->entries.capacity; ++i) {
KrkTableEntry * entry = &self->entries.entries[i];

View File

@ -41,7 +41,7 @@ KRK_Method(str,__init__) {
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]);
if (!krk_getType(argv[1])->_tostr) return krk_runtimeError(vm.exceptions->typeError, "Can not convert %s to str", krk_typeName(argv[1]));
if (!krk_getType(argv[1])->_tostr) return krk_runtimeError(vm.exceptions->typeError, "Can not convert '%T' to str", argv[1]);
return krk_callDirect(krk_getType(argv[1])->_tostr, 1);
}
@ -423,8 +423,8 @@ static int _str_join_callback(void * context, const KrkValue * values, size_t co
for (size_t i = 0; i < count; ++i) {
if (!IS_STRING(values[i])) {
krk_runtimeError(vm.exceptions->typeError, "%s() expects %s, not '%s'",
"join", "str", krk_typeName(values[i]));
krk_runtimeError(vm.exceptions->typeError, "%s() expects %s, not '%T'",
"join", "str", values[i]);
return 1;
}
@ -596,8 +596,7 @@ KRK_Method(str,__mod__) {
} else if (IS_FLOATING(arg)) {
krk_push(INTEGER_VAL(AS_FLOATING(arg)));
} else {
krk_runtimeError(vm.exceptions->typeError, "%%i format: a number is required, not %s",
krk_typeName(arg));
krk_runtimeError(vm.exceptions->typeError, "%%i format: a number is required, not '%T'", arg);
goto _exception;
}
krk_push(krk_callDirect(krk_getType(arg)->_tostr, 1));
@ -606,8 +605,7 @@ KRK_Method(str,__mod__) {
if (ti >= myTuple->values.count) goto _notEnough;
KrkValue arg = myTuple->values.values[ti++];
if (!krk_getType(arg)->_tostr) {
krk_runtimeError(vm.exceptions->typeError, "%%s format: cannot convert %s to string",
krk_typeName(arg));
krk_runtimeError(vm.exceptions->typeError, "%%s format: cannot convert '%T' to string", arg);
goto _exception;
}

View File

@ -177,8 +177,7 @@ KRK_Method(tuple,__add__) {
METHOD_TAKES_EXACTLY(1);
if (!IS_tuple(argv[1]))
return krk_runtimeError(vm.exceptions->typeError,
"can only concatenate tuple (not \"%s\") to tuple",
krk_typeName(argv[1]));
"can only concatenate tuple (not '%T') to tuple", argv[1]);
KrkTuple * other = AS_tuple(argv[1]);
KrkTuple * out = krk_newTuple(self->values.count + other->values.count);

View File

@ -55,7 +55,7 @@ inline int krk_hashValue(KrkValue value, uint32_t *hashOut) {
}
_unhashable:
if (IS_NONE(krk_currentThread.currentException))
krk_runtimeError(vm.exceptions->typeError, "unhashable type: '%s'", krk_typeName(value));
krk_runtimeError(vm.exceptions->typeError, "unhashable type: '%T'", value);
return 1;
}

242
src/vm.c
View File

@ -371,17 +371,132 @@ static void raiseException(KrkValue base, KrkValue cause) {
* found in vm.exceptions and are initialized on startup.
*/
KrkValue krk_runtimeError(KrkClass * type, const char * fmt, ...) {
char buf[1024] = {0};
KrkValue msg = KWARGS_VAL(0);
struct StringBuilder sb = {0};
va_list args;
va_start(args, fmt);
size_t len = vsnprintf(buf, 1024, fmt, args);
if (!strcmp(fmt,"%V")) {
msg = va_arg(args, KrkValue);
goto _finish;
}
for (const char * f = fmt; *f; ++f) {
if (*f != '%') {
pushStringBuilder(&sb, *f);
continue;
}
/* Unset exception flag if it was already set. */
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) {
krk_currentThread.flags &= ~(KRK_THREAD_HAS_EXCEPTION);
}
++f;
int size = ' ';
if (*f == 'z') size = *f++;
else if (*f == 'l') size = *f++;
else if (*f == 'L') size = *f++;
switch (*f) {
case 0: break;
case '%':
pushStringBuilder(&sb, '%');
break;
case 'c': {
char val = (char)va_arg(args, int);
pushStringBuilder(&sb, val);
break;
}
case 's': {
const char * c = va_arg(args, const char *);
pushStringBuilderStr(&sb, c, strlen(c));
break;
}
case 'u': {
size_t val;
if (size == ' ') {
val = va_arg(args, unsigned int);
} else if (size == 'l') {
val = va_arg(args, unsigned long);
} else if (size == 'L') {
val = va_arg(args, unsigned long long);
} else if (size == 'z') {
val = va_arg(args, size_t);
}
char tmp[100];
snprintf(tmp, 32, "%zu", val);
pushStringBuilderStr(&sb, tmp, strlen(tmp));
break;
}
case 'd': {
ssize_t val;
if (size == ' ') {
val = va_arg(args, int);
} else if (size == 'l') {
val = va_arg(args, long);
} else if (size == 'L') {
val = va_arg(args, long long);
} else if (size == 'z') {
val = va_arg(args, ssize_t);
}
char tmp[100];
snprintf(tmp, 32, "%zd", val);
pushStringBuilderStr(&sb, tmp, strlen(tmp));
break;
}
case 'T': {
KrkValue val = va_arg(args, KrkValue);
const char * typeName = krk_typeName(val);
pushStringBuilderStr(&sb, typeName, strlen(typeName));
break;
}
case 'S': {
KrkString * val = va_arg(args, KrkString*);
pushStringBuilderStr(&sb, val->chars, val->length);
break;
}
case 'R': {
KrkValue val = va_arg(args, KrkValue);
KrkClass * type = krk_getType(val);
if (likely(type->_reprer != NULL)) {
krk_push(val);
KrkValue res = krk_callDirect(type->_reprer, 1);
if (IS_STRING(res)) {
pushStringBuilderStr(&sb, AS_CSTRING(res), AS_STRING(res)->length);
}
}
break;
}
default: {
va_arg(args, void*);
pushStringBuilderStr(&sb, "(unsupported: ", 14);
pushStringBuilder(&sb, *f);
pushStringBuilder(&sb, ')');
break;
}
}
}
_finish:
va_end(args);
krk_currentThread.flags |= KRK_THREAD_HAS_EXCEPTION;
/* Allocate an exception object of the requested type. */
KrkInstance * exceptionObject = krk_newInstance(type);
krk_push(OBJECT_VAL(exceptionObject));
krk_attachNamedValue(&exceptionObject->fields, "arg", OBJECT_VAL(krk_copyString(buf, len)));
krk_attachNamedValue(&exceptionObject->fields, "arg", msg == KWARGS_VAL(0) ? finishStringBuilder(&sb) : msg);
krk_attachNamedValue(&exceptionObject->fields, "__cause__", NONE_VAL());
krk_attachNamedValue(&exceptionObject->fields, "__context__", NONE_VAL());
krk_pop();
@ -658,11 +773,11 @@ static inline int checkArgumentCount(const KrkClosure * closure, int argCount) {
}
static void multipleDefs(const KrkClosure * closure, int destination) {
krk_runtimeError(vm.exceptions->typeError, "%s() got multiple values for argument '%s'",
krk_runtimeError(vm.exceptions->typeError, "%s() got multiple values for argument '%S'",
closure->function->name ? closure->function->name->chars : "<unnamed>",
(destination < closure->function->requiredArgs ? AS_CSTRING(closure->function->requiredArgNames.values[destination]) :
(destination - closure->function->requiredArgs < closure->function->keywordArgs ? AS_CSTRING(closure->function->keywordArgNames.values[destination - closure->function->requiredArgs]) :
"<unnamed>")));
(destination < closure->function->requiredArgs ? AS_STRING(closure->function->requiredArgNames.values[destination]) :
(destination - closure->function->requiredArgs < closure->function->keywordArgs ? AS_STRING(closure->function->keywordArgNames.values[destination - closure->function->requiredArgs]) :
S("<unnamed>"))));
}
static int _unpack_op(void * context, const KrkValue * values, size_t count) {
@ -725,7 +840,7 @@ int krk_processComplexArguments(int argCount, KrkValueArray * positionals, KrkTa
return 0;
}
if (!krk_tableSet(keywords, entry->key, entry->value)) {
krk_runtimeError(vm.exceptions->typeError, "%s() got multiple values for argument '%s'", name, AS_CSTRING(entry->key));
krk_runtimeError(vm.exceptions->typeError, "%s() got multiple values for argument '%S'", name, AS_STRING(entry->key));
return 0;
}
}
@ -735,7 +850,7 @@ int krk_processComplexArguments(int argCount, KrkValueArray * positionals, KrkTa
}
} else if (IS_STRING(key)) {
if (!krk_tableSet(keywords, key, value)) {
krk_runtimeError(vm.exceptions->typeError, "%s() got multiple values for argument '%s'", name, AS_CSTRING(key));
krk_runtimeError(vm.exceptions->typeError, "%s() got multiple values for argument '%S'", name, AS_STRING(key));
return 0;
}
}
@ -855,9 +970,9 @@ static inline int _callManaged(KrkClosure * closure, int argCount, int returnDep
}
}
if (!(closure->function->obj.flags & KRK_OBJ_FLAGS_CODEOBJECT_COLLECTS_KWS)) {
krk_runtimeError(vm.exceptions->typeError, "%s() got an unexpected keyword argument '%s'",
krk_runtimeError(vm.exceptions->typeError, "%s() got an unexpected keyword argument '%S'",
closure->function->name ? closure->function->name->chars : "<unnamed>",
AS_CSTRING(name));
AS_STRING(name));
goto _errorAfterPositionals;
}
continue;
@ -880,9 +995,9 @@ _finishKwarg:
for (size_t i = 0; i < (size_t)closure->function->requiredArgs; ++i) {
if (IS_KWARGS(krk_currentThread.stackTop[-argCount + i])) {
krk_runtimeError(vm.exceptions->typeError, "%s() missing required positional argument: '%s'",
krk_runtimeError(vm.exceptions->typeError, "%s() missing required positional argument: '%S'",
closure->function->name ? closure->function->name->chars : "<unnamed>",
AS_CSTRING(closure->function->requiredArgNames.values[i]));
AS_STRING(closure->function->requiredArgNames.values[i]));
goto _errorAfterKeywords;
}
}
@ -1041,7 +1156,7 @@ int krk_callValue(KrkValue callee, int argCount, int returnDepth) {
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, "'%s' object is not callable", krk_typeName(callee));
krk_runtimeError(vm.exceptions->typeError, "'%T' object is not callable", callee);
return 0;
}
}
@ -1056,8 +1171,8 @@ int krk_callValue(KrkValue callee, int argCount, int returnDepth) {
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->chars, argCount);
krk_runtimeError(vm.exceptions->typeError, "%S() takes no arguments (%d given)",
_class->name, argCount);
return 0;
}
krk_currentThread.stackTop -= argCount + returnDepth;
@ -1081,7 +1196,7 @@ int krk_callValue(KrkValue callee, int argCount, int returnDepth) {
break;
}
}
krk_runtimeError(vm.exceptions->typeError, "'%s' object is not callable", krk_typeName(callee));
krk_runtimeError(vm.exceptions->typeError, "'%T' object is not callable", callee);
return 0;
}
@ -1676,8 +1791,8 @@ const char * krk_typeName(KrkValue value) {
} \
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL(); \
return krk_runtimeError(vm.exceptions->typeError, \
"unsupported operand types for %s: '%s' and '%s'", \
operator, krk_typeName(a), krk_typeName(b)); \
"unsupported operand types for %s: '%T' and '%T'", \
operator, a, b); \
}
#define MAKE_BIN_OP(name,operator,inv) \
MAKE_COMPARE_OP(name,operator,inv) \
@ -1729,7 +1844,7 @@ KrkValue krk_operator_is(KrkValue a, KrkValue b) {
return krk_callDirect(type-> sname, 1); \
} \
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL(); \
return krk_runtimeError(vm.exceptions->typeError, "bad operand type for unary %s: '%s'", #op, krk_typeName(value)); \
return krk_runtimeError(vm.exceptions->typeError, "bad operand type for unary %s: '%T'", #op, value); \
}
MAKE_UNARY_OP(_invert,invert,~)
@ -1871,8 +1986,8 @@ int krk_loadModule(KrkString * path, KrkValue * moduleOut, KrkString * runAs, Kr
/* Try to import that. */
KrkValue dotted_main = krk_peek(0);
if (!krk_importModule(AS_STRING(dotted_main),runAs)) {
krk_runtimeError(vm.exceptions->importError, "No module named %s; '%s' is a package and cannot be executed directly",
AS_CSTRING(dotted_main), AS_CSTRING(packageName));
krk_runtimeError(vm.exceptions->importError, "No module named '%S'; '%S' is a package and cannot be executed directly",
AS_STRING(dotted_main), AS_STRING(packageName));
return 0;
}
@ -1955,7 +2070,7 @@ int krk_loadModule(KrkString * path, KrkValue * moduleOut, KrkString * runAs, Kr
if (!dlRef) {
*moduleOut = NONE_VAL();
krk_runtimeError(vm.exceptions->importError,
"Failed to load native module '%s' from shared object '%s'", runAs->chars, fileName);
"Failed to load native module '%S' from shared object '%s'", runAs, fileName);
return 0;
}
@ -1989,7 +2104,7 @@ int krk_loadModule(KrkString * path, KrkValue * moduleOut, KrkString * runAs, Kr
if (!krk_isInstanceOf(*moduleOut, vm.baseClasses->moduleClass)) {
dlClose(dlRef);
krk_runtimeError(vm.exceptions->importError,
"Failed to load module '%s' from '%s'", runAs->chars, fileName);
"Failed to load module '%S' from '%s'", runAs, fileName);
return 0;
}
@ -2024,7 +2139,7 @@ int krk_loadModule(KrkString * path, KrkValue * moduleOut, KrkString * runAs, Kr
krk_push(OBJECT_VAL(runAs));
}
krk_runtimeError(vm.exceptions->importError, "No module named '%s'", AS_CSTRING(krk_peek(0)));
krk_runtimeError(vm.exceptions->importError, "No module named '%S'", AS_STRING(krk_peek(0)));
return 0;
}
@ -2205,7 +2320,7 @@ int krk_importModule(KrkString * name, KrkString * runAs) {
/* Is this a package? */
KrkValue tmp;
if (!krk_tableGet_fast(&AS_INSTANCE(current)->fields, S("__ispackage__"), &tmp) || !IS_BOOLEAN(tmp) || AS_BOOLEAN(tmp) != 1) {
krk_runtimeError(vm.exceptions->importError, "'%s' is not a package", AS_CSTRING(krk_currentThread.stack[argBase+2]));
krk_runtimeError(vm.exceptions->importError, "'%S' is not a package", AS_STRING(krk_currentThread.stack[argBase+2]));
return 0;
}
krk_currentThread.stack[argBase-1] = krk_pop();
@ -2336,15 +2451,17 @@ static int valueGetMethod(KrkString * name) {
}
return 0;
}
int krk_getAttribute(KrkString * name) {
return valueGetProperty(name);
}
KrkValue krk_valueGetAttribute(KrkValue value, char * name) {
krk_push(OBJECT_VAL(krk_copyString(name,strlen(name))));
krk_push(value);
if (!valueGetProperty(AS_STRING(krk_peek(1)))) {
return krk_runtimeError(vm.exceptions->attributeError, "'%s' object has no attribute '%s'", krk_typeName(krk_peek(0)), name);
return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", krk_peek(0), name);
}
krk_swap(1);
krk_pop(); /* String */
@ -2387,11 +2504,15 @@ static int valueDelProperty(KrkString * name) {
return 0;
}
int krk_delAttribute(KrkString * name) {
return valueDelProperty(name);
}
KrkValue krk_valueDelAttribute(KrkValue owner, char * name) {
krk_push(OBJECT_VAL(krk_copyString(name,strlen(name))));
krk_push(owner);
if (!valueDelProperty(AS_STRING(krk_peek(1)))) {
return krk_runtimeError(vm.exceptions->attributeError, "'%s' object has no attribute '%s'", krk_typeName(krk_peek(0)), name);
return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", krk_peek(0), name);
}
krk_pop(); /* String */
return NONE_VAL();
@ -2486,12 +2607,16 @@ static int valueSetProperty(KrkString * name) {
return 1;
}
int krk_setAttribute(KrkString * name) {
return valueSetProperty(name);
}
KrkValue krk_valueSetAttribute(KrkValue owner, char * name, KrkValue to) {
krk_push(OBJECT_VAL(krk_copyString(name,strlen(name))));
krk_push(owner);
krk_push(to);
if (!valueSetProperty(AS_STRING(krk_peek(2)))) {
return krk_runtimeError(vm.exceptions->attributeError, "'%s' object has no attribute '%s'", krk_typeName(krk_peek(1)), name);
return krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", krk_peek(1), name);
}
krk_swap(1);
krk_pop(); /* String */
@ -2564,7 +2689,7 @@ static inline int doFormatString(int options) {
if (unlikely(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) return 1;
} else {
krk_runtimeError(vm.exceptions->typeError,
"Can not convert %s to str", krk_typeName(krk_peek(0)));
"Can not convert '%T' to str", krk_peek(0));
return 1;
}
} else if (options & FORMAT_OP_REPR) {
@ -2574,7 +2699,7 @@ static inline int doFormatString(int options) {
if (unlikely(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) return 1;
} else {
krk_runtimeError(vm.exceptions->typeError,
"Can not repr %s", krk_typeName(krk_peek(0)));
"Can not repr '%T'", krk_peek(0));
return 1;
}
}
@ -2594,7 +2719,7 @@ static inline int doFormatString(int options) {
krk_push(krk_callDirect(type->_format, 2));
if (unlikely(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) return 1;
} else {
krk_runtimeError(vm.exceptions->attributeError, "'%s' object has no attribute '%s'", krk_typeName(krk_peek(1)), "__format__");
krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%s'", krk_peek(1), "__format__");
return 1;
}
@ -2612,7 +2737,7 @@ static inline void commonMethodInvoke(size_t methodOffset, int args, const char
if (likely(method != NULL)) {
krk_push(krk_callDirect(method, args));
} else {
krk_runtimeError(vm.exceptions->attributeError, msgFormat, krk_typeName(krk_peek(args-1)));
krk_runtimeError(vm.exceptions->attributeError, msgFormat, krk_peek(args-1));
}
}
@ -2790,25 +2915,25 @@ _finishReturn: (void)0;
krk_pop();
break;
case OP_INVOKE_GETTER: {
commonMethodInvoke(offsetof(KrkClass,_getter), 2, "'%s' object is not subscriptable");
commonMethodInvoke(offsetof(KrkClass,_getter), 2, "'%T' object is not subscriptable");
break;
}
case OP_INVOKE_SETTER: {
commonMethodInvoke(offsetof(KrkClass,_setter), 3, "'%s' object doesn't support item assignment");
commonMethodInvoke(offsetof(KrkClass,_setter), 3, "'%T' object doesn't support item assignment");
break;
}
case OP_INVOKE_DELETE: {
commonMethodInvoke(offsetof(KrkClass,_delitem), 2, "'%s' object doesn't support item deletion");
commonMethodInvoke(offsetof(KrkClass,_delitem), 2, "'%T' object doesn't support item deletion");
krk_pop(); /* unused result */
break;
}
case OP_INVOKE_ITER: {
commonMethodInvoke(offsetof(KrkClass,_iter), 1, "'%s' object is not iterable");
commonMethodInvoke(offsetof(KrkClass,_iter), 1, "'%T' object is not iterable");
break;
}
case OP_INVOKE_CONTAINS: {
krk_swap(1); /* operands are backwards */
commonMethodInvoke(offsetof(KrkClass,_contains), 2, "'%s' object can not be tested for membership");
commonMethodInvoke(offsetof(KrkClass,_contains), 2, "'%T' object can not be tested for membership");
break;
}
case OP_INVOKE_AWAIT: {
@ -2826,13 +2951,12 @@ _finishReturn: (void)0;
case OP_INHERIT: {
KrkValue superclass = krk_peek(0);
if (unlikely(!IS_CLASS(superclass))) {
krk_runtimeError(vm.exceptions->typeError, "Superclass must be a class, not '%s'",
krk_typeName(superclass));
krk_runtimeError(vm.exceptions->typeError, "Superclass must be a class, not '%T'", superclass);
goto _finishException;
}
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);
krk_runtimeError(vm.exceptions->typeError, "'%S' can not be subclassed",
AS_CLASS(superclass)->name);
goto _finishException;
}
KrkClass * subclass = AS_CLASS(krk_peek(1));
@ -2932,7 +3056,7 @@ _finishReturn: (void)0;
krk_swap(1);
krk_pop();
} else {
krk_runtimeError(vm.exceptions->typeError, "Can not annotate '%s'.", krk_typeName(krk_peek(0)));
krk_runtimeError(vm.exceptions->typeError, "Can not annotate '%T'.", krk_peek(0));
goto _finishException;
}
break;
@ -3079,7 +3203,7 @@ _finishReturn: (void)0;
KrkValue value;
if (!krk_tableGet_fast(frame->globals, name, &value)) {
if (!krk_tableGet_fast(&vm.builtins->fields, name, &value)) {
krk_runtimeError(vm.exceptions->nameError, "Undefined variable '%s'.", name->chars);
krk_runtimeError(vm.exceptions->nameError, "Undefined variable '%S'.", name);
goto _finishException;
}
}
@ -3092,7 +3216,7 @@ _finishReturn: (void)0;
ONE_BYTE_OPERAND;
KrkString * name = READ_STRING(OPERAND);
if (!krk_tableSetIfExists(frame->globals, OBJECT_VAL(name), krk_peek(0))) {
krk_runtimeError(vm.exceptions->nameError, "Undefined variable '%s'.", name->chars);
krk_runtimeError(vm.exceptions->nameError, "Undefined variable '%S'.", name);
goto _finishException;
}
break;
@ -3103,7 +3227,7 @@ _finishReturn: (void)0;
ONE_BYTE_OPERAND;
KrkString * name = READ_STRING(OPERAND);
if (!krk_tableDelete(frame->globals, OBJECT_VAL(name))) {
krk_runtimeError(vm.exceptions->nameError, "Undefined variable '%s'.", name->chars);
krk_runtimeError(vm.exceptions->nameError, "Undefined variable '%S'.", name);
goto _finishException;
}
break;
@ -3222,7 +3346,7 @@ _finishReturn: (void)0;
/* Try to import... */
KrkValue moduleName;
if (!krk_tableGet(&AS_INSTANCE(krk_peek(0))->fields, vm.specialMethodNames[METHOD_NAME], &moduleName)) {
krk_runtimeError(vm.exceptions->importError, "Can not import '%s' from non-module '%s' object", name->chars, krk_typeName(krk_peek(0)));
krk_runtimeError(vm.exceptions->importError, "Can not import '%S' from non-module '%T' object", name, krk_peek(0));
goto _finishException;
}
krk_push(moduleName);
@ -3231,7 +3355,7 @@ _finishReturn: (void)0;
krk_push(OBJECT_VAL(name));
krk_addObjects();
if (!krk_doRecursiveModuleLoad(AS_STRING(krk_peek(0)))) {
krk_runtimeError(vm.exceptions->importError, "Can not import '%s' from '%s'", name->chars, AS_CSTRING(moduleName));
krk_runtimeError(vm.exceptions->importError, "Can not import '%S' from '%S'", name, AS_STRING(moduleName));
goto _finishException;
}
krk_currentThread.stackTop[-3] = krk_currentThread.stackTop[-1];
@ -3244,7 +3368,7 @@ _finishReturn: (void)0;
ONE_BYTE_OPERAND;
KrkString * name = READ_STRING(OPERAND);
if (unlikely(!valueGetProperty(name))) {
krk_runtimeError(vm.exceptions->attributeError, "'%s' object has no attribute '%s'", krk_typeName(krk_peek(0)), name->chars);
krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", krk_peek(0), name);
goto _finishException;
}
break;
@ -3255,7 +3379,7 @@ _finishReturn: (void)0;
ONE_BYTE_OPERAND;
KrkString * name = READ_STRING(OPERAND);
if (unlikely(!valueDelProperty(name))) {
krk_runtimeError(vm.exceptions->attributeError, "'%s' object has no attribute '%s'", krk_typeName(krk_peek(0)), name->chars);
krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", krk_peek(0), name);
goto _finishException;
}
break;
@ -3266,7 +3390,7 @@ _finishReturn: (void)0;
ONE_BYTE_OPERAND;
KrkString * name = READ_STRING(OPERAND);
if (unlikely(!valueSetProperty(name))) {
krk_runtimeError(vm.exceptions->attributeError, "'%s' object has no attribute '%s'", krk_typeName(krk_peek(1)), name->chars);
krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", krk_peek(1), name);
goto _finishException;
}
break;
@ -3293,7 +3417,7 @@ _finishReturn: (void)0;
KrkValue baseClass = krk_peek(1);
if (!IS_CLASS(baseClass)) {
krk_runtimeError(vm.exceptions->typeError,
"super() argument 1 must be class, not %s", krk_typeName(baseClass));
"super() argument 1 must be class, not %T", baseClass);
goto _finishException;
}
if (IS_KWARGS(krk_peek(0))) {
@ -3303,14 +3427,14 @@ _finishReturn: (void)0;
}
if (!krk_isInstanceOf(krk_peek(0), AS_CLASS(baseClass))) {
krk_runtimeError(vm.exceptions->typeError,
"'%s' object is not an instance of '%s'",
krk_typeName(krk_peek(0)), AS_CLASS(baseClass)->name->chars);
"'%T' object is not an instance of '%S'",
krk_peek(0), AS_CLASS(baseClass)->name);
goto _finishException;
}
KrkClass * superclass = AS_CLASS(baseClass)->base ? AS_CLASS(baseClass)->base : vm.baseClasses->objectClass;
if (!krk_bindMethod(superclass, name)) {
krk_runtimeError(vm.exceptions->attributeError, "'%s' object has no attribute '%s'",
superclass->name->chars, name->chars);
krk_runtimeError(vm.exceptions->attributeError, "'%S' object has no attribute '%S'",
superclass->name, name);
goto _finishException;
}
/* Swap bind and superclass */
@ -3330,7 +3454,7 @@ _finishReturn: (void)0;
krk_swap(2);
krk_pop();
} else if (unlikely(!result)) {
krk_runtimeError(vm.exceptions->attributeError, "'%s' object has no attribute '%s'", krk_typeName(krk_peek(0)), name->chars);
krk_runtimeError(vm.exceptions->attributeError, "'%T' object has no attribute '%S'", krk_peek(0), name);
goto _finishException;
} else {
krk_swap(1); /* unbound-method object */
@ -3493,7 +3617,7 @@ _finishReturn: (void)0;
KrkValue s = krk_currentThread.stackTop[-(ssize_t)OPERAND+i];
if (unlikely(!IS_STRING(s))) {
discardStringBuilder(&sb);
krk_runtimeError(vm.exceptions->valueError, "'%s' is not a string", krk_typeName(s));
krk_runtimeError(vm.exceptions->valueError, "'%T' is not a string", s);
goto _finishException;
}
pushStringBuilderStr(&sb, (char*)AS_STRING(s)->chars, AS_STRING(s)->length);