11 #define IS_NoneType(o) (IS_NONE(o))
12 #define AS_NoneType(o) ((char)0)
14 #define CURRENT_CTYPE krk_integer_type
15 #define CURRENT_NAME self
17 extern KrkValue krk_int_from_float(
double val);
19 KRK_StaticMethod(
int,__new__) {
26 if (!
krk_parseArgs(
"O|V?i?:int", (
const char*[]){
"cls",
"x",
"base"},
27 &cls, &has_x, &x, &has_base, &base))
return NONE_VAL();
29 if (has_base && (base < 2 || base > 36) && base != 0) {
30 return krk_runtimeError(
vm.exceptions->valueError,
"base must be 0 or between 2 and 36");
33 if (!has_x && has_base) {
38 return INTEGER_VAL(0);
41 if (has_base && !IS_STRING(x)) {
42 return krk_runtimeError(
vm.exceptions->typeError,
"can not convert non-str with explicit base");
46 KrkValue result = krk_parse_int(AS_CSTRING(x), AS_STRING(x)->length, base);
47 if (IS_NONE(result)) {
49 "invalid literal for int() with base %zd: %R", (ssize_t)base, x);
54 if (IS_BOOLEAN(x))
return INTEGER_VAL(AS_INTEGER(x));
55 if (IS_INTEGER(x))
return x;
58 if (IS_FLOATING(x))
return krk_int_from_float(AS_FLOATING(x));
60 if (IS_BOOLEAN(x))
return INTEGER_VAL(AS_BOOLEAN(x));
61 return krk_runtimeError(
vm.exceptions->typeError,
"%s() argument must be a string or a number, not '%T'",
"int", x);
64 KRK_Method(
int,__str__) {
66 size_t l = snprintf(tmp, 100, PRIkrk_int,
self);
70 KRK_Method(
int,__int__) {
return argv[0]; }
73 KRK_Method(
int,__float__) {
return FLOATING_VAL(
self); }
76 KRK_Method(
int,__chr__) {
77 unsigned char bytes[5] = {0};
82 KRK_Method(
int,__eq__) {
83 METHOD_TAKES_EXACTLY(1);
84 if (likely(IS_INTEGER(argv[1])))
return BOOLEAN_VAL(
self == AS_INTEGER(argv[1]));
86 else if (IS_FLOATING(argv[1]))
return BOOLEAN_VAL(
self == AS_FLOATING(argv[1]));
91 KRK_Method(
int,__hash__) {
92 return INTEGER_VAL((uint32_t)AS_INTEGER(argv[0]));
95 static inline int matches(
char c,
const char * options) {
96 for (
const char * o = options; *o; ++o) {
97 if (*o == c)
return 1;
102 const char * krk_parseCommonFormatSpec(
struct ParsedFormatSpec *result,
const char * spec,
size_t length) {
104 result->fillSize = 1;
109 if ((spec[0] & 0xC0) == 0xC0) {
110 while ((spec[i] & 0xc0) == 0x80) i++;
113 if (matches(spec[i],
"<>=^")) {
115 result->fillSize = i;
120 if (matches(*spec,
"<>=^")) {
121 result->align = *spec;
125 if (matches(*spec,
"+- ")) {
126 result->sign = *spec;
135 if (!result->align && *spec ==
'0') {
138 result->fillSize = 1;
142 if (matches(*spec,
"0123456789")) {
143 result->hasWidth = 1;
146 result->width += (*spec -
'0');
148 }
while (matches(*spec,
"0123456789"));
151 if (matches(*spec,
"_,")) {
158 if (!matches(*spec,
"0123456789")) {
162 result->hasPrecision = 1;
163 while (matches(*spec,
"0123456789")) {
165 result->prec += (*spec -
'0');
170 if (*spec && spec[1] != 0) {
178 typedef int (*fmtCallback)(
void *, int,
int *);
179 KrkValue krk_doFormatString(
const char * typeName,
KrkString * format_spec,
int positive,
void * abs, fmtCallback callback, fmtCallback (*prepCallback)(
void*,
int)) {
182 const char * spec = krk_parseCommonFormatSpec(&opts, format_spec->
chars, format_spec->
length);
183 if (!spec)
return NONE_VAL();
185 const char * altPrefix = NULL;
186 const char * conversions =
"0123456789abcdef";
208 conversions =
"0123456789ABCDEF";
214 "TODO: 'c' format specifier");
218 "TODO: 'n' format specifier");
222 "Unknown format code '%c' for object of type '%s'",
227 if (!opts.sign) opts.sign =
'-';
228 if (!opts.align) opts.align =
'>';
232 int width = opts.width;
235 if (opts.alt && altPrefix && width > 2) width -= 2;
236 if ((!positive || opts.sign ==
'+') && width > 1) width--;
239 int sepcount = opts.sep ==
',' ? 3 : 4;
242 if (prepCallback) callback = prepCallback(abs, base);
245 int digit = callback(abs, base, &more);
248 discardStringBuilder(&sb);
252 if (digits && !more && digit == 0) {
254 for (
int i = 0; i < opts.fillSize; ++i) {
255 pushStringBuilder(&sb, opts.fill[opts.fillSize-1-i]);
258 pushStringBuilder(&sb, conversions[digit]);
263 if (opts.sep && !(digits % sepcount) && (more || (opts.align ==
'=' && l < width))) {
264 pushStringBuilder(&sb, opts.sep);
266 if (opts.align ==
'=' && l == width) {
268 for (
int i = 0; i < opts.fillSize; ++i) {
269 pushStringBuilder(&sb, opts.fill[opts.fillSize-1-i]);
273 }
while (more || (opts.align ==
'=' && l < width));
275 if (opts.alt && altPrefix) {
276 pushStringBuilder(&sb, altPrefix[1]);
277 pushStringBuilder(&sb, altPrefix[0]);
280 if (!positive || opts.sign ==
'+') {
281 pushStringBuilder(&sb, positive ?
'+' :
'-');
284 if (opts.align ==
'>') {
286 for (
int i = 0; i < opts.fillSize; ++i) {
287 pushStringBuilder(&sb, opts.fill[opts.fillSize-1-i]);
291 }
else if (opts.align ==
'^') {
292 int remaining = (width - l) / 2;
293 for (
int i = 0; i < remaining; ++i) {
294 for (
int i = 0; i < opts.fillSize; ++i) {
295 pushStringBuilder(&sb, opts.fill[opts.fillSize-1-i]);
301 for (
size_t i = 0; i < sb.length / 2; ++i) {
302 char t = sb.bytes[i];
303 sb.bytes[i] = sb.bytes[sb.length - i - 1];
304 sb.bytes[sb.length - i - 1] = t;
307 if (opts.align ==
'<' || opts.align ==
'^') {
309 pushStringBuilderStr(&sb, opts.fill, opts.fillSize);
314 return finishStringBuilder(&sb);
317 static int formatIntCallback(
void * a,
int base,
int *more) {
318 krk_integer_type v = *(krk_integer_type*)a;
319 int digit = v % base;
321 *(krk_integer_type*)a = v;
327 KRK_Method(
int,__format__) {
328 METHOD_TAKES_EXACTLY(1);
331 krk_integer_type abs =
self < 0 ? -self :
self;
333 return krk_doFormatString(
krk_typeName(argv[0]), format_spec,
336 formatIntCallback, NULL);
349 #define OVERFLOW_CHECKED_INT_OPERATION(name,operator) \
350 extern KrkValue krk_long_coerced_ ## name (krk_integer_type a, krk_integer_type b); \
352 KrkValue krk_int_op_ ## name (krk_integer_type a, krk_integer_type b) { \
353 if (likely((int32_t)a == a && (int32_t)b == b)) { \
354 int32_t result_one = a operator b; \
355 int64_t result_two = a operator b; \
356 if (likely(result_one == result_two)) return INTEGER_VAL(result_two); \
358 return krk_long_coerced_ ## name (a, b); \
361 OVERFLOW_CHECKED_INT_OPERATION(add,+)
362 OVERFLOW_CHECKED_INT_OPERATION(sub,-)
363 OVERFLOW_CHECKED_INT_OPERATION(mul,*)
366 # define MAYBE_FLOAT(x) x
368 # define MAYBE_FLOAT(x) krk_runtimeError(vm.exceptions->valueError, "no float support")
371 #define BASIC_BIN_OP(name,operator) \
372 KRK_Method(int,__ ## name ## __) { \
373 if (likely(IS_INTEGER(argv[1]))) return krk_int_op_ ## name(self, AS_INTEGER(argv[1])); \
374 else if (likely(IS_FLOATING(argv[1]))) return MAYBE_FLOAT(FLOATING_VAL((double)self operator AS_FLOATING(argv[1]))); \
375 return NOTIMPL_VAL(); \
377 KRK_Method(int,__r ## name ## __) { \
378 if (likely(IS_INTEGER(argv[1]))) return krk_int_op_ ## name(AS_INTEGER(argv[1]), self); \
379 else if (likely(IS_FLOATING(argv[1]))) return MAYBE_FLOAT(FLOATING_VAL(AS_FLOATING(argv[1]) operator (double)self)); \
380 return NOTIMPL_VAL(); \
383 #define INT_ONLY_BIN_OP(name,operator) \
384 KRK_Method(int,__ ## name ## __) { \
385 if (likely(IS_INTEGER(argv[1]))) return INTEGER_VAL(self operator AS_INTEGER(argv[1])); \
386 return NOTIMPL_VAL(); \
388 KRK_Method(int,__r ## name ## __) { \
389 if (likely(IS_INTEGER(argv[1]))) return INTEGER_VAL(AS_INTEGER(argv[1]) operator self); \
390 return NOTIMPL_VAL(); \
393 #define COMPARE_OP(name,operator) \
394 KRK_Method(int,__ ## name ## __) { \
395 if (likely(IS_INTEGER(argv[1]))) return BOOLEAN_VAL(self operator AS_INTEGER(argv[1])); \
396 else if (likely(IS_FLOATING(argv[1]))) return MAYBE_FLOAT(BOOLEAN_VAL((double)self operator AS_FLOATING(argv[1]))); \
397 return NOTIMPL_VAL(); \
403 INT_ONLY_BIN_OP(or,|)
404 INT_ONLY_BIN_OP(xor,^)
405 INT_ONLY_BIN_OP(and,&)
407 #define DEFER_TO_LONG(name) \
408 extern KrkValue krk_long_coerced_ ## name (krk_integer_type a, krk_integer_type b); \
409 KRK_Method(int,__ ## name ## __) { \
410 if (likely(IS_INTEGER(argv[1]))) return krk_long_coerced_ ## name (self, AS_INTEGER(argv[1])); \
411 return NOTIMPL_VAL(); \
413 KRK_Method(int,__r ## name ## __) { \
414 if (likely(IS_INTEGER(argv[1]))) return krk_long_coerced_ ## name (AS_INTEGER(argv[1]), self); \
415 return NOTIMPL_VAL(); \
418 DEFER_TO_LONG(lshift)
419 DEFER_TO_LONG(rshift)
428 #undef INT_ONLY_BIN_OP
432 KRK_Method(
int,__truediv__) {
433 METHOD_TAKES_EXACTLY(1);
434 if (likely(IS_INTEGER(argv[1]))) {
435 krk_integer_type b = AS_INTEGER(argv[1]);
436 if (unlikely(b == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division by zero");
437 return FLOATING_VAL((
double)
self / (
double)b);
438 }
else if (likely(IS_FLOATING(argv[1]))) {
439 double b = AS_FLOATING(argv[1]);
440 if (unlikely(b == 0.0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"float division by zero");
441 return FLOATING_VAL((
double)
self / b);
443 return NOTIMPL_VAL();
446 KRK_Method(
int,__rtruediv__) {
447 METHOD_TAKES_EXACTLY(1);
448 if (unlikely(
self == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division by zero");
449 else if (likely(IS_INTEGER(argv[1])))
return FLOATING_VAL((
double)AS_INTEGER(argv[1]) / (
double)
self);
450 else if (likely(IS_FLOATING(argv[1])))
return FLOATING_VAL(AS_FLOATING(argv[1]) / (
double)
self);
451 return NOTIMPL_VAL();
457 #define __builtin_floor floor
465 static KrkValue _krk_int_div(krk_integer_type a, krk_integer_type b) {
466 if (unlikely(b == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division or modulo by zero");
467 if (a == 0)
return INTEGER_VAL(0);
468 int64_t abs_a = a < 0 ? -a : a;
469 int64_t abs_b = b < 0 ? -b : b;
470 if ((a < 0) != (b < 0)) {
472 int64_t res = -1 - (abs_a - 1) / abs_b;
473 return INTEGER_VAL(res);
475 return INTEGER_VAL((abs_a / abs_b));
478 static KrkValue _krk_int_mod(krk_integer_type a, krk_integer_type b) {
479 if (unlikely(b == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division or modulo by zero");
480 if (a == 0)
return INTEGER_VAL(0);
481 int64_t abs_a = a < 0 ? -a : a;
482 int64_t abs_b = b < 0 ? -b : b;
484 if ((a < 0) != (b < 0)) {
486 res = (abs_b - 1 - (abs_a - 1) % abs_b);
491 return INTEGER_VAL((b < 0) ? -res : res);
495 KRK_Method(
int,__mod__) {
496 METHOD_TAKES_EXACTLY(1);
497 if (likely(IS_INTEGER(argv[1])))
return _krk_int_mod(
self, AS_INTEGER(argv[1]));
498 return NOTIMPL_VAL();
501 KRK_Method(
int,__rmod__) {
502 METHOD_TAKES_EXACTLY(1);
503 if (likely(IS_INTEGER(argv[1])))
return _krk_int_mod(AS_INTEGER(argv[1]),
self);
504 return NOTIMPL_VAL();
508 KRK_Method(
int,__floordiv__) {
509 METHOD_TAKES_EXACTLY(1);
510 if (likely(IS_INTEGER(argv[1]))) {
511 return _krk_int_div(
self,AS_INTEGER(argv[1]));
512 }
else if (likely(IS_FLOATING(argv[1]))) {
514 double b = AS_FLOATING(argv[1]);
515 if (unlikely(b == 0.0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"float division by zero");
516 return FLOATING_VAL(__builtin_floor((
double)
self / b));
521 return NOTIMPL_VAL();
524 KRK_Method(
int,__rfloordiv__) {
525 METHOD_TAKES_EXACTLY(1);
526 if (unlikely(
self == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division by zero");
527 else if (likely(IS_INTEGER(argv[1])))
return _krk_int_div(AS_INTEGER(argv[1]),
self);
528 else if (likely(IS_FLOATING(argv[1])))
return MAYBE_FLOAT(FLOATING_VAL(__builtin_floor(AS_FLOATING(argv[1]) / (
double)
self)));
529 return NOTIMPL_VAL();
532 KRK_Method(
int,__hex__) {
535 unsigned long long val =
self < 0 ? -self :
self;
536 size_t len = snprintf(tmp, 20,
"%s0x%llx",
self < 0 ?
"-" :
"", val);
540 KRK_Method(
int,__oct__) {
543 unsigned long long val =
self < 0 ? -self :
self;
544 size_t len = snprintf(tmp, 20,
"%s0o%llo",
self < 0 ?
"-" :
"", val);
548 KRK_Method(
int,__bin__) {
550 unsigned long long val =
self;
551 if (
self < 0) val = -val;
555 if (!val) pushStringBuilder(&sb,
'0');
557 pushStringBuilder(&sb, (val & 1) ?
'1' :
'0');
561 pushStringBuilder(&sb,
'b');
562 pushStringBuilder(&sb,
'0');
563 if (
self< 0) pushStringBuilder(&sb,
'-');
566 for (
size_t i = 0; i < sb.length / 2; ++i) {
567 char t = sb.bytes[i];
568 sb.bytes[i] = sb.bytes[sb.length - i - 1];
569 sb.bytes[sb.length - i - 1] = t;
572 return finishStringBuilder(&sb);
575 KRK_Method(
int,__invert__) {
576 return INTEGER_VAL(~
self);
579 KRK_Method(
int,__neg__) {
580 return INTEGER_VAL(-
self);
583 KRK_Method(
int,__abs__) {
584 return self < 0 ? INTEGER_VAL(-
self) : INTEGER_VAL(self);
587 KRK_Method(
int,__pos__) {
592 #define CURRENT_CTYPE double
594 #define trySlowMethod(name) do { \
595 KrkClass * type = krk_getType(argv[1]); \
598 if (krk_tableGet(&type->methods, name, &method)) { \
601 return krk_callStack(1); \
608 KRK_StaticMethod(
float,__new__) {
609 FUNCTION_TAKES_AT_MOST(2);
610 if (argc < 2)
return FLOATING_VAL(0.0);
611 if (IS_FLOATING(argv[1]))
return argv[1];
612 if (IS_INTEGER(argv[1]))
return FLOATING_VAL(AS_INTEGER(argv[1]));
613 if (IS_BOOLEAN(argv[1]))
return FLOATING_VAL(AS_BOOLEAN(argv[1]));
615 trySlowMethod(
vm.specialMethodNames[METHOD_FLOAT]);
617 return krk_runtimeError(
vm.exceptions->typeError,
"%s() argument must be a string or a number, not '%T'",
"float", argv[1]);
620 KRK_Method(
float,__int__) {
return INTEGER_VAL(
self); }
621 KRK_Method(
float,__float__) {
return argv[0]; }
623 static int isDigits(
const char * c) {
625 if (*c !=
'-' && (*c < '0' || *c >
'9'))
return 0;
631 KRK_Method(
float,__str__) {
633 size_t l = snprintf(tmp, 97,
"%.16g",
self);
634 if (!strstr(tmp,
".") && isDigits(tmp)) {
635 l = snprintf(tmp,100,
"%.16g.0",
self);
640 KRK_Method(
float,__eq__) {
641 METHOD_TAKES_EXACTLY(1);
642 if (IS_INTEGER(argv[1]))
return BOOLEAN_VAL(
self == (
double)AS_INTEGER(argv[1]));
643 else if (IS_FLOATING(argv[1]))
return BOOLEAN_VAL(
self == AS_FLOATING(argv[1]));
644 return NOTIMPL_VAL();
647 KRK_Method(
float,__hash__) {
648 return INTEGER_VAL((uint32_t)
self);
651 KRK_Method(
float,__neg__) {
652 return FLOATING_VAL(-
self);
655 KRK_Method(
float,__abs__) {
656 return self < 0.0 ? FLOATING_VAL(-
self) : INTEGER_VAL(self);
659 #define BASIC_BIN_OP(name,operator) \
660 KRK_Method(float,__ ## name ## __) { \
661 METHOD_TAKES_EXACTLY(1); \
662 if (likely(IS_FLOATING(argv[1]))) return FLOATING_VAL(self operator AS_FLOATING(argv[1])); \
663 else if (likely(IS_INTEGER(argv[1]))) return FLOATING_VAL(self operator (double)AS_INTEGER(argv[1])); \
664 return NOTIMPL_VAL(); \
666 KRK_Method(float,__r ## name ## __) { \
667 METHOD_TAKES_EXACTLY(1); \
668 if (likely(IS_FLOATING(argv[1]))) return FLOATING_VAL(AS_FLOATING(argv[1]) operator self); \
669 else if (likely(IS_INTEGER(argv[1]))) return FLOATING_VAL((double)AS_INTEGER(argv[1]) operator self); \
670 return NOTIMPL_VAL(); \
673 #define COMPARE_OP(name,operator) \
674 KRK_Method(float,__ ## name ## __) { \
675 METHOD_TAKES_EXACTLY(1); \
676 if (likely(IS_FLOATING(argv[1]))) return BOOLEAN_VAL(self operator AS_FLOATING(argv[1])); \
677 else if (likely(IS_INTEGER(argv[1]))) return BOOLEAN_VAL(self operator (double)AS_INTEGER(argv[1])); \
678 return NOTIMPL_VAL(); \
692 KRK_Method(
float,__truediv__) {
693 METHOD_TAKES_EXACTLY(1);
694 if (likely(IS_FLOATING(argv[1]))) {
695 double b = AS_FLOATING(argv[1]);
696 if (unlikely(b == 0.0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"float division by zero");
697 return FLOATING_VAL(
self / b);
698 }
else if (likely(IS_INTEGER(argv[1]))) {
699 krk_integer_type b = AS_INTEGER(argv[1]);
700 if (unlikely(b == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division by zero");
701 return FLOATING_VAL(
self / (
double)b);
703 return NOTIMPL_VAL();
706 KRK_Method(
float,__rtruediv__) {
707 METHOD_TAKES_EXACTLY(1);
708 if (unlikely(
self == 0.0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"float division by zero");
709 else if (likely(IS_FLOATING(argv[1])))
return FLOATING_VAL(AS_FLOATING(argv[1]) /
self);
710 else if (likely(IS_INTEGER(argv[1])))
return FLOATING_VAL((
double)AS_INTEGER(argv[1]) /
self);
711 return NOTIMPL_VAL();
714 KRK_Method(
float,__floordiv__) {
715 METHOD_TAKES_EXACTLY(1);
716 if (likely(IS_INTEGER(argv[1]))) {
717 krk_integer_type b = AS_INTEGER(argv[1]);
718 if (unlikely(b == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division by zero");
719 return FLOATING_VAL(__builtin_floor(
self / (
double)b));
720 }
else if (IS_FLOATING(argv[1])) {
721 double b = AS_FLOATING(argv[1]);
722 if (unlikely(b == 0.0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"float division by zero");
723 return FLOATING_VAL(__builtin_floor(
self / b));
725 return NOTIMPL_VAL();
728 KRK_Method(
float,__rfloordiv__) {
729 METHOD_TAKES_EXACTLY(1);
730 if (unlikely(
self == 0.0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"float division by zero");
731 else if (likely(IS_INTEGER(argv[1])))
return FLOATING_VAL((
double)AS_INTEGER(argv[1]) /
self);
732 else if (IS_FLOATING(argv[1]))
return FLOATING_VAL(__builtin_floor(AS_FLOATING(argv[1]) /
self));
733 return NOTIMPL_VAL();
736 KRK_Method(
float,__pos__) {
742 #define CURRENT_CTYPE krk_integer_type
744 KRK_StaticMethod(
bool,__new__) {
745 FUNCTION_TAKES_AT_MOST(2);
746 if (argc < 2)
return BOOLEAN_VAL(0);
750 KRK_Method(
bool,__str__) {
751 return OBJECT_VAL((
self ? S(
"True") : S(
"False")));
754 KRK_Method(
bool,__format__) {
755 METHOD_TAKES_EXACTLY(1);
758 if (!format_spec->
length) {
759 return FUNC_NAME(
bool,__str__)(argc,argv,hasKw);
761 return FUNC_NAME(
int,__format__)(argc,argv,hasKw);
765 KRK_StaticMethod(NoneType,__new__) {
766 if (argc > 1)
return krk_runtimeError(
vm.exceptions->argumentError,
"%s takes no arguments",
"NoneType");
770 KRK_Method(NoneType,__str__) {
771 return OBJECT_VAL(S(
"None"));
774 KRK_Method(NoneType,__hash__) {
775 return INTEGER_VAL((uint32_t)AS_INTEGER(argv[0]));
778 KRK_Method(NoneType,__eq__) {
779 METHOD_TAKES_EXACTLY(1);
780 if (IS_NONE(argv[1]))
return BOOLEAN_VAL(1);
781 return NOTIMPL_VAL();
784 #define IS_NotImplementedType(o) IS_NOTIMPL(o)
785 #define AS_NotImplementedType(o) (1)
787 KRK_StaticMethod(NotImplementedType,__new__) {
788 if (argc > 1)
return krk_runtimeError(
vm.exceptions->argumentError,
"%s takes no arguments",
"NotImplementedType");
789 return NOTIMPL_VAL();
792 KRK_Method(NotImplementedType,__str__) {
793 return OBJECT_VAL(S(
"NotImplemented"));
796 KRK_Method(NotImplementedType,__hash__) {
797 return INTEGER_VAL(0);
800 KRK_Method(NotImplementedType,__eq__) {
801 METHOD_TAKES_EXACTLY(1);
802 if (IS_NOTIMPL(argv[1]))
return BOOLEAN_VAL(1);
803 return NOTIMPL_VAL();
807 #undef BIND_STATICMETHOD
809 #define BIND_METHOD(klass,method) do { krk_defineNative(& _ ## klass->methods, #method, _ ## klass ## _ ## method); } while (0)
810 #define BIND_STATICMETHOD(klass,method) do { krk_defineNativeStaticMethod(& _ ## klass->methods, #method, _ ## klass ## _ ## method); } while (0)
811 #define BIND_TRIPLET(klass,name) \
812 BIND_METHOD(klass,__ ## name ## __); \
813 BIND_METHOD(klass,__r ## name ## __); \
814 krk_defineNative(&_ ## klass->methods,"__i" #name "__",_ ## klass ## ___ ## name ## __);
816 void _createAndBind_numericClasses(
void) {
817 KrkClass * _int = ADD_BASE_CLASS(
vm.baseClasses->intClass,
"int",
vm.baseClasses->objectClass);
818 _int->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
820 BIND_STATICMETHOD(
int,__new__);
821 BIND_METHOD(
int,__str__);
822 BIND_METHOD(
int,__int__);
823 BIND_METHOD(
int,__chr__);
824 BIND_METHOD(
int,__eq__);
825 BIND_METHOD(
int,__hash__);
826 BIND_METHOD(
int,__format__);
828 BIND_TRIPLET(
int,add);
829 BIND_TRIPLET(
int,sub);
830 BIND_TRIPLET(
int,mul);
831 BIND_TRIPLET(
int,or);
832 BIND_TRIPLET(
int,xor);
833 BIND_TRIPLET(
int,and);
834 BIND_TRIPLET(
int,lshift);
835 BIND_TRIPLET(
int,rshift);
836 BIND_TRIPLET(
int,mod);
837 BIND_TRIPLET(
int,floordiv);
838 BIND_TRIPLET(
int,pow);
841 BIND_METHOD(
int,__float__);
842 BIND_TRIPLET(
int,truediv);
845 BIND_METHOD(
int,__lt__);
846 BIND_METHOD(
int,__gt__);
847 BIND_METHOD(
int,__le__);
848 BIND_METHOD(
int,__ge__);
850 BIND_METHOD(
int,__hex__);
851 BIND_METHOD(
int,__oct__);
852 BIND_METHOD(
int,__bin__);
853 BIND_METHOD(
int,__invert__);
854 BIND_METHOD(
int,__neg__);
855 BIND_METHOD(
int,__abs__);
856 BIND_METHOD(
int,__pos__);
860 KRK_DOC(_int,
"Convert a number or string type to an integer representation.");
862 KrkClass * _float = ADD_BASE_CLASS(
vm.baseClasses->floatClass,
"float",
vm.baseClasses->objectClass);
863 _float->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
866 BIND_STATICMETHOD(
float,__new__);
867 BIND_METHOD(
float,__int__);
868 BIND_METHOD(
float,__float__);
869 BIND_METHOD(
float,__str__);
870 BIND_METHOD(
float,__eq__);
871 BIND_METHOD(
float,__hash__);
872 BIND_TRIPLET(
float,add);
873 BIND_TRIPLET(
float,sub);
874 BIND_TRIPLET(
float,mul);
875 BIND_TRIPLET(
float,truediv);
876 BIND_TRIPLET(
float,floordiv);
877 BIND_METHOD(
float,__lt__);
878 BIND_METHOD(
float,__gt__);
879 BIND_METHOD(
float,__le__);
880 BIND_METHOD(
float,__ge__);
881 BIND_METHOD(
float,__neg__);
882 BIND_METHOD(
float,__abs__);
883 BIND_METHOD(
float,__pos__);
887 KRK_DOC(_float,
"Convert a number or string type to a float representation.");
889 KrkClass * _bool = ADD_BASE_CLASS(
vm.baseClasses->boolClass,
"bool",
vm.baseClasses->intClass);
890 _bool->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
891 BIND_STATICMETHOD(
bool,__new__);
892 BIND_METHOD(
bool,__str__);
893 BIND_METHOD(
bool,__format__);
896 KRK_DOC(_bool,
"Returns False if the argument is 'falsey', otherwise True.");
898 KrkClass * _NoneType = ADD_BASE_CLASS(
vm.baseClasses->noneTypeClass,
"NoneType",
vm.baseClasses->objectClass);
899 _NoneType->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
901 BIND_STATICMETHOD(NoneType, __new__);
902 BIND_METHOD(NoneType, __str__);
903 BIND_METHOD(NoneType, __hash__);
904 BIND_METHOD(NoneType, __eq__);
908 KrkClass * _NotImplementedType = ADD_BASE_CLASS(
vm.baseClasses->notImplClass,
"NotImplementedType",
vm.baseClasses->objectClass);
909 _NotImplementedType->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
911 BIND_STATICMETHOD(NotImplementedType, __new__);
912 BIND_METHOD(NotImplementedType, __str__);
913 BIND_METHOD(NotImplementedType, __hash__);
914 BIND_METHOD(NotImplementedType, __eq__);
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
Functions for dealing with garbage collection and memory allocation.
size_t allocSize
Size to allocate when creating instances of this class.
KrkTable methods
General attributes table.
void krk_finalizeClass(KrkClass *_class)
Finalize a class by collecting pointers to core methods.
The most basic object type.
uint16_t flags
General object flags, mostly related to garbage collection.
Immutable sequence of Unicode codepoints.
KrkString * krk_copyString(const char *chars, size_t length)
Obtain a string object representation of the given C string.
char * chars
UTF8 canonical data.
size_t length
String length in bytes.
size_t krk_codepointToBytes(krk_integer_type value, unsigned char *out)
Convert an integer codepoint to a UTF-8 byte representation.
KrkNative * krk_defineNative(KrkTable *table, const char *name, NativeFn function)
Attach a native C function to an attribute table.
void krk_attachNamedValue(KrkTable *table, const char name[], KrkValue obj)
Attach a value to an attribute table.
Stack reference or primative value.
const char * krk_typeName(KrkValue value)
Get the name of the type of a value.
int krk_isInstanceOf(KrkValue obj, const KrkClass *type)
Determine if a class is an instance or subclass of a given type.
int krk_isFalsey(KrkValue value)
Determine the truth of a value.
Inline flexible string array.
Utilities for creating native bindings.
#define krk_parseArgs(f, n,...)
Parse arguments to a function while accepting keyword arguments.
#define KRK_DOC(thing, text)
Attach documentation to a thing of various types.
Definitions for primitive stack references.
Core API for the bytecode virtual machine.
#define vm
Convenience macro for namespacing.
threadLocal KrkThreadState krk_currentThread
Thread-local VM state.