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__) {
27 if (!hasKw && argc == 2) {
32 if (!
krk_parseArgs(
"O|V?i?:int", (
const char*[]){
"",
"",
"base"},
33 &cls, &has_x, &x, &has_base, &base))
return NONE_VAL();
35 if (has_base && (base < 2 || base > 36) && base != 0) {
36 return krk_runtimeError(
vm.exceptions->valueError,
"base must be 0 or between 2 and 36");
39 if (!has_x && has_base) {
44 return INTEGER_VAL(0);
47 if (has_base && !IS_STRING(x)) {
48 return krk_runtimeError(
vm.exceptions->typeError,
"can not convert non-str with explicit base");
53 if (IS_INTEGER(x))
return INTEGER_VAL(AS_INTEGER(x));
55 if (IS_FLOATING(x))
return krk_int_from_float(AS_FLOATING(x));
59 KrkValue result = krk_parse_int(AS_CSTRING(x), AS_STRING(x)->length, base);
60 if (IS_NONE(result)) {
62 "invalid literal for int() with base %zd: %R", (ssize_t)base, x);
68 return krk_runtimeError(
vm.exceptions->typeError,
"%s() argument must be a string or a number, not '%T'",
"int", x);
71 KRK_Method(
int,__repr__) {
73 size_t l = snprintf(tmp, 100, PRIkrk_int,
self);
77 KRK_Method(
int,__int__) {
return argv[0]; }
80 KRK_Method(
int,__float__) {
return FLOATING_VAL(
self); }
83 KRK_Method(
int,__chr__) {
84 unsigned char bytes[5] = {0};
89 KRK_Method(
int,__eq__) {
90 METHOD_TAKES_EXACTLY(1);
91 if (likely(IS_INTEGER(argv[1])))
return BOOLEAN_VAL(
self == AS_INTEGER(argv[1]));
93 else if (IS_FLOATING(argv[1]))
return BOOLEAN_VAL(
self == AS_FLOATING(argv[1]));
98 KRK_Method(
int,__hash__) {
99 return INTEGER_VAL((uint32_t)AS_INTEGER(argv[0]));
102 static inline int matches(
char c,
const char * options) {
103 for (
const char * o = options; *o; ++o) {
104 if (*o == c)
return 1;
109 const char * krk_parseCommonFormatSpec(
struct ParsedFormatSpec *result,
const char * spec,
size_t length) {
111 result->fillSize = 1;
116 if ((spec[0] & 0xC0) == 0xC0) {
117 while ((spec[i] & 0xc0) == 0x80) i++;
120 if (matches(spec[i],
"<>=^")) {
122 result->fillSize = i;
127 if (matches(*spec,
"<>=^")) {
128 result->align = *spec;
132 if (matches(*spec,
"+- ")) {
133 result->sign = *spec;
142 if (!result->align && *spec ==
'0') {
145 result->fillSize = 1;
149 if (matches(*spec,
"0123456789")) {
150 result->hasWidth = 1;
153 result->width += (*spec -
'0');
155 }
while (matches(*spec,
"0123456789"));
158 if (matches(*spec,
"_,")) {
165 if (!matches(*spec,
"0123456789")) {
169 result->hasPrecision = 1;
170 while (matches(*spec,
"0123456789")) {
172 result->prec += (*spec -
'0');
177 if (*spec && spec[1] != 0) {
185 typedef int (*fmtCallback)(
void *, int,
int *);
186 KrkValue krk_doFormatString(
const char * typeName,
KrkString * format_spec,
int positive,
void * abs, fmtCallback callback, fmtCallback (*prepCallback)(
void*,
int)) {
189 const char * spec = krk_parseCommonFormatSpec(&opts, format_spec->
chars, format_spec->
length);
190 if (!spec)
return NONE_VAL();
192 const char * altPrefix = NULL;
193 const char * conversions =
"0123456789abcdef";
215 conversions =
"0123456789ABCDEF";
221 "TODO: 'c' format specifier");
225 "TODO: 'n' format specifier");
229 "Unknown format code '%c' for object of type '%s'",
234 if (!opts.sign) opts.sign =
'-';
235 if (!opts.align) opts.align =
'>';
239 int width = opts.width;
242 if (opts.alt && altPrefix && width > 2) width -= 2;
243 if ((!positive || opts.sign ==
'+') && width > 1) width--;
246 int sepcount = (opts.sep ==
',' || base == 10) ? 3 : 4;
249 if (prepCallback) callback = prepCallback(abs, base);
252 int digit = callback(abs, base, &more);
255 discardStringBuilder(&sb);
259 if (digits && !more && digit == 0) {
261 for (
int i = 0; i < opts.fillSize; ++i) {
262 pushStringBuilder(&sb, opts.fill[opts.fillSize-1-i]);
265 pushStringBuilder(&sb, conversions[digit]);
270 if (opts.sep && !(digits % sepcount) && (more || (opts.align ==
'=' && l < width))) {
271 pushStringBuilder(&sb, opts.sep);
273 if (opts.align ==
'=' && l == width) {
275 for (
int i = 0; i < opts.fillSize; ++i) {
276 pushStringBuilder(&sb, opts.fill[opts.fillSize-1-i]);
280 }
while (more || (opts.align ==
'=' && l < width));
282 if (opts.alt && altPrefix) {
283 pushStringBuilder(&sb, altPrefix[1]);
284 pushStringBuilder(&sb, altPrefix[0]);
287 if (!positive || opts.sign ==
'+') {
288 pushStringBuilder(&sb, positive ?
'+' :
'-');
291 if (opts.align ==
'>') {
293 for (
int i = 0; i < opts.fillSize; ++i) {
294 pushStringBuilder(&sb, opts.fill[opts.fillSize-1-i]);
298 }
else if (opts.align ==
'^') {
299 int remaining = (width - l) / 2;
300 for (
int i = 0; i < remaining; ++i) {
301 for (
int i = 0; i < opts.fillSize; ++i) {
302 pushStringBuilder(&sb, opts.fill[opts.fillSize-1-i]);
308 for (
size_t i = 0; i < sb.length / 2; ++i) {
309 char t = sb.bytes[i];
310 sb.bytes[i] = sb.bytes[sb.length - i - 1];
311 sb.bytes[sb.length - i - 1] = t;
314 if (opts.align ==
'<' || opts.align ==
'^') {
316 pushStringBuilderStr(&sb, opts.fill, opts.fillSize);
321 return finishStringBuilder(&sb);
324 static int formatIntCallback(
void * a,
int base,
int *more) {
325 krk_integer_type v = *(krk_integer_type*)a;
326 int digit = v % base;
328 *(krk_integer_type*)a = v;
334 KRK_Method(
int,__format__) {
335 METHOD_TAKES_EXACTLY(1);
338 krk_integer_type abs =
self < 0 ? -self :
self;
340 return krk_doFormatString(
krk_typeName(argv[0]), format_spec,
343 formatIntCallback, NULL);
356 #define OVERFLOW_CHECKED_INT_OPERATION(name,operator) \
357 extern KrkValue krk_long_coerced_ ## name (krk_integer_type a, krk_integer_type b); \
359 KrkValue krk_int_op_ ## name (krk_integer_type a, krk_integer_type b) { \
360 if (likely((int32_t)a == a && (int32_t)b == b)) { \
361 int32_t result_one = a operator b; \
362 int64_t result_two = a operator b; \
363 if (likely(result_one == result_two)) return INTEGER_VAL(result_two); \
365 return krk_long_coerced_ ## name (a, b); \
368 OVERFLOW_CHECKED_INT_OPERATION(add,+)
369 OVERFLOW_CHECKED_INT_OPERATION(sub,-)
370 OVERFLOW_CHECKED_INT_OPERATION(mul,*)
373 # define MAYBE_FLOAT(x) x
375 # define MAYBE_FLOAT(x) krk_runtimeError(vm.exceptions->valueError, "no float support")
378 #define BASIC_BIN_OP(name,operator) \
379 KRK_Method(int,__ ## name ## __) { \
380 if (likely(IS_INTEGER(argv[1]))) return krk_int_op_ ## name(self, AS_INTEGER(argv[1])); \
381 else if (likely(IS_FLOATING(argv[1]))) return MAYBE_FLOAT(FLOATING_VAL((double)self operator AS_FLOATING(argv[1]))); \
382 return NOTIMPL_VAL(); \
384 KRK_Method(int,__r ## name ## __) { \
385 if (likely(IS_INTEGER(argv[1]))) return krk_int_op_ ## name(AS_INTEGER(argv[1]), self); \
386 else if (likely(IS_FLOATING(argv[1]))) return MAYBE_FLOAT(FLOATING_VAL(AS_FLOATING(argv[1]) operator (double)self)); \
387 return NOTIMPL_VAL(); \
390 #define INT_ONLY_BIN_OP(name,operator) \
391 KRK_Method(int,__ ## name ## __) { \
392 if (likely(IS_INTEGER(argv[1]))) return INTEGER_VAL(self operator AS_INTEGER(argv[1])); \
393 return NOTIMPL_VAL(); \
395 KRK_Method(int,__r ## name ## __) { \
396 if (likely(IS_INTEGER(argv[1]))) return INTEGER_VAL(AS_INTEGER(argv[1]) operator self); \
397 return NOTIMPL_VAL(); \
400 #define COMPARE_OP(name,operator) \
401 KRK_Method(int,__ ## name ## __) { \
402 if (likely(IS_INTEGER(argv[1]))) return BOOLEAN_VAL(self operator AS_INTEGER(argv[1])); \
403 else if (likely(IS_FLOATING(argv[1]))) return MAYBE_FLOAT(BOOLEAN_VAL((double)self operator AS_FLOATING(argv[1]))); \
404 return NOTIMPL_VAL(); \
410 INT_ONLY_BIN_OP(or,|)
411 INT_ONLY_BIN_OP(xor,^)
412 INT_ONLY_BIN_OP(and,&)
414 #define DEFER_TO_LONG(name) \
415 extern KrkValue krk_long_coerced_ ## name (krk_integer_type a, krk_integer_type b); \
416 KRK_Method(int,__ ## name ## __) { \
417 if (likely(IS_INTEGER(argv[1]))) return krk_long_coerced_ ## name (self, AS_INTEGER(argv[1])); \
418 return NOTIMPL_VAL(); \
420 KRK_Method(int,__r ## name ## __) { \
421 if (likely(IS_INTEGER(argv[1]))) return krk_long_coerced_ ## name (AS_INTEGER(argv[1]), self); \
422 return NOTIMPL_VAL(); \
425 DEFER_TO_LONG(lshift)
426 DEFER_TO_LONG(rshift)
435 #undef INT_ONLY_BIN_OP
439 KRK_Method(
int,__truediv__) {
440 METHOD_TAKES_EXACTLY(1);
441 if (likely(IS_INTEGER(argv[1]))) {
442 krk_integer_type b = AS_INTEGER(argv[1]);
443 if (unlikely(b == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division by zero");
444 return FLOATING_VAL((
double)
self / (
double)b);
445 }
else if (likely(IS_FLOATING(argv[1]))) {
446 double b = AS_FLOATING(argv[1]);
447 if (unlikely(b == 0.0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"float division by zero");
448 return FLOATING_VAL((
double)
self / b);
450 return NOTIMPL_VAL();
453 KRK_Method(
int,__rtruediv__) {
454 METHOD_TAKES_EXACTLY(1);
455 if (unlikely(
self == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division by zero");
456 else if (likely(IS_INTEGER(argv[1])))
return FLOATING_VAL((
double)AS_INTEGER(argv[1]) / (
double)
self);
457 else if (likely(IS_FLOATING(argv[1])))
return FLOATING_VAL(AS_FLOATING(argv[1]) / (
double)
self);
458 return NOTIMPL_VAL();
464 #define __builtin_floor floor
472 static KrkValue _krk_int_div(krk_integer_type a, krk_integer_type b) {
473 if (unlikely(b == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division or modulo by zero");
474 if (a == 0)
return INTEGER_VAL(0);
475 int64_t abs_a = a < 0 ? -a : a;
476 int64_t abs_b = b < 0 ? -b : b;
477 if ((a < 0) != (b < 0)) {
479 int64_t res = -1 - (abs_a - 1) / abs_b;
480 return INTEGER_VAL(res);
482 return INTEGER_VAL((abs_a / abs_b));
485 static KrkValue _krk_int_mod(krk_integer_type a, krk_integer_type b) {
486 if (unlikely(b == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division or modulo by zero");
487 if (a == 0)
return INTEGER_VAL(0);
488 int64_t abs_a = a < 0 ? -a : a;
489 int64_t abs_b = b < 0 ? -b : b;
491 if ((a < 0) != (b < 0)) {
493 res = (abs_b - 1 - (abs_a - 1) % abs_b);
498 return INTEGER_VAL((b < 0) ? -res : res);
502 KRK_Method(
int,__mod__) {
503 METHOD_TAKES_EXACTLY(1);
504 if (likely(IS_INTEGER(argv[1])))
return _krk_int_mod(
self, AS_INTEGER(argv[1]));
505 return NOTIMPL_VAL();
508 KRK_Method(
int,__rmod__) {
509 METHOD_TAKES_EXACTLY(1);
510 if (likely(IS_INTEGER(argv[1])))
return _krk_int_mod(AS_INTEGER(argv[1]),
self);
511 return NOTIMPL_VAL();
515 KRK_Method(
int,__floordiv__) {
516 METHOD_TAKES_EXACTLY(1);
517 if (likely(IS_INTEGER(argv[1]))) {
518 return _krk_int_div(
self,AS_INTEGER(argv[1]));
519 }
else if (likely(IS_FLOATING(argv[1]))) {
521 double b = AS_FLOATING(argv[1]);
522 if (unlikely(b == 0.0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"float division by zero");
523 return FLOATING_VAL(__builtin_floor((
double)
self / b));
528 return NOTIMPL_VAL();
531 KRK_Method(
int,__rfloordiv__) {
532 METHOD_TAKES_EXACTLY(1);
533 if (unlikely(
self == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division by zero");
534 else if (likely(IS_INTEGER(argv[1])))
return _krk_int_div(AS_INTEGER(argv[1]),
self);
535 else if (likely(IS_FLOATING(argv[1])))
return MAYBE_FLOAT(FLOATING_VAL(__builtin_floor(AS_FLOATING(argv[1]) / (
double)
self)));
536 return NOTIMPL_VAL();
539 KRK_Method(
int,__hex__) {
542 unsigned long long val =
self < 0 ? -self :
self;
543 size_t len = snprintf(tmp, 20,
"%s0x%llx",
self < 0 ?
"-" :
"", val);
547 KRK_Method(
int,__oct__) {
550 unsigned long long val =
self < 0 ? -self :
self;
551 size_t len = snprintf(tmp, 20,
"%s0o%llo",
self < 0 ?
"-" :
"", val);
555 KRK_Method(
int,__bin__) {
557 unsigned long long val =
self;
558 if (
self < 0) val = -val;
562 if (!val) pushStringBuilder(&sb,
'0');
564 pushStringBuilder(&sb, (val & 1) ?
'1' :
'0');
568 pushStringBuilder(&sb,
'b');
569 pushStringBuilder(&sb,
'0');
570 if (
self< 0) pushStringBuilder(&sb,
'-');
573 for (
size_t i = 0; i < sb.length / 2; ++i) {
574 char t = sb.bytes[i];
575 sb.bytes[i] = sb.bytes[sb.length - i - 1];
576 sb.bytes[sb.length - i - 1] = t;
579 return finishStringBuilder(&sb);
582 KRK_Method(
int,__invert__) {
583 return INTEGER_VAL(~
self);
586 KRK_Method(
int,__neg__) {
587 return INTEGER_VAL(-
self);
590 KRK_Method(
int,__abs__) {
591 return self < 0 ? INTEGER_VAL(-
self) : INTEGER_VAL(self);
594 KRK_Method(
int,__pos__) {
599 #define CURRENT_CTYPE double
601 #define trySlowMethod(name) do { \
602 KrkClass * type = krk_getType(argv[1]); \
605 if (krk_tableGet(&type->methods, name, &method)) { \
608 return krk_callStack(1); \
615 KRK_StaticMethod(
float,__new__) {
616 FUNCTION_TAKES_AT_MOST(2);
617 if (argc < 2)
return FLOATING_VAL(0.0);
618 if (IS_FLOATING(argv[1]))
return argv[1];
619 if (IS_INTEGER(argv[1]))
return FLOATING_VAL(AS_INTEGER(argv[1]));
620 if (IS_BOOLEAN(argv[1]))
return FLOATING_VAL(AS_BOOLEAN(argv[1]));
622 trySlowMethod(
vm.specialMethodNames[METHOD_FLOAT]);
624 return krk_runtimeError(
vm.exceptions->typeError,
"%s() argument must be a string or a number, not '%T'",
"float", argv[1]);
627 KRK_Method(
float,__int__) {
return krk_int_from_float(
self); }
628 KRK_Method(
float,__float__) {
return argv[0]; }
631 KRK_Method(
float,__repr__) {
635 KRK_Method(
float,__format__) {
637 size_t format_spec_length;
638 if (!
krk_parseArgs(
".s#", (
const char*[]){
"format_spec"}, &format_spec, &format_spec_length))
return NONE_VAL();
641 const char * spec = krk_parseCommonFormatSpec(&opts, format_spec, format_spec_length);
642 if (!spec)
return NONE_VAL();
644 char formatter =
'g';
646 int forcedigits = opts.alt;
669 "Unknown format code '%c' for object of type '%s'",
674 if (opts.sep)
return krk_runtimeError(
vm.exceptions->valueError,
"unsupported option for float");
675 if (opts.hasPrecision) digits = opts.prec;
676 if (!opts.align) opts.align =
'>';
679 if (!IS_STRING(result) || !opts.width)
return result;
684 size_t avail = (size_t)opts.width > AS_STRING(result)->length ? (size_t)opts.width - AS_STRING(result)->length : 0;
693 if (opts.align ==
'<') {
695 }
else if (opts.align ==
'>') {
697 }
else if (opts.align ==
'^') {
699 before = avail - after;
700 }
else if (opts.align ==
'=') {
702 if (avail && AS_STRING(result)->length && (AS_CSTRING(result)[0] ==
'-' || AS_CSTRING(result)[0] ==
'+')) {
717 KRK_Method(
float,__eq__) {
718 METHOD_TAKES_EXACTLY(1);
719 if (IS_INTEGER(argv[1]))
return BOOLEAN_VAL(
self == (
double)AS_INTEGER(argv[1]));
720 else if (IS_FLOATING(argv[1]))
return BOOLEAN_VAL(
self == AS_FLOATING(argv[1]));
721 return NOTIMPL_VAL();
724 KRK_Method(
float,__hash__) {
725 return INTEGER_VAL((uint32_t)
self);
728 KRK_Method(
float,__neg__) {
729 return FLOATING_VAL(-
self);
732 KRK_Method(
float,__abs__) {
733 return self < 0.0 ? FLOATING_VAL(-
self) : INTEGER_VAL(self);
736 #define BASIC_BIN_OP(name,operator) \
737 KRK_Method(float,__ ## name ## __) { \
738 METHOD_TAKES_EXACTLY(1); \
739 if (likely(IS_FLOATING(argv[1]))) return FLOATING_VAL(self operator AS_FLOATING(argv[1])); \
740 else if (likely(IS_INTEGER(argv[1]))) return FLOATING_VAL(self operator (double)AS_INTEGER(argv[1])); \
741 return NOTIMPL_VAL(); \
743 KRK_Method(float,__r ## name ## __) { \
744 METHOD_TAKES_EXACTLY(1); \
745 if (likely(IS_FLOATING(argv[1]))) return FLOATING_VAL(AS_FLOATING(argv[1]) operator self); \
746 else if (likely(IS_INTEGER(argv[1]))) return FLOATING_VAL((double)AS_INTEGER(argv[1]) operator self); \
747 return NOTIMPL_VAL(); \
750 #define COMPARE_OP(name,operator) \
751 KRK_Method(float,__ ## name ## __) { \
752 METHOD_TAKES_EXACTLY(1); \
753 if (likely(IS_FLOATING(argv[1]))) return BOOLEAN_VAL(self operator AS_FLOATING(argv[1])); \
754 else if (likely(IS_INTEGER(argv[1]))) return BOOLEAN_VAL(self operator (double)AS_INTEGER(argv[1])); \
755 return NOTIMPL_VAL(); \
769 KRK_Method(
float,__truediv__) {
770 METHOD_TAKES_EXACTLY(1);
771 if (likely(IS_FLOATING(argv[1]))) {
772 double b = AS_FLOATING(argv[1]);
773 if (unlikely(b == 0.0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"float division by zero");
774 return FLOATING_VAL(
self / b);
775 }
else if (likely(IS_INTEGER(argv[1]))) {
776 krk_integer_type b = AS_INTEGER(argv[1]);
777 if (unlikely(b == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division by zero");
778 return FLOATING_VAL(
self / (
double)b);
780 return NOTIMPL_VAL();
783 KRK_Method(
float,__rtruediv__) {
784 METHOD_TAKES_EXACTLY(1);
785 if (unlikely(
self == 0.0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"float division by zero");
786 else if (likely(IS_FLOATING(argv[1])))
return FLOATING_VAL(AS_FLOATING(argv[1]) /
self);
787 else if (likely(IS_INTEGER(argv[1])))
return FLOATING_VAL((
double)AS_INTEGER(argv[1]) /
self);
788 return NOTIMPL_VAL();
791 KRK_Method(
float,__floordiv__) {
792 METHOD_TAKES_EXACTLY(1);
793 if (likely(IS_INTEGER(argv[1]))) {
794 krk_integer_type b = AS_INTEGER(argv[1]);
795 if (unlikely(b == 0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"integer division by zero");
796 return FLOATING_VAL(__builtin_floor(
self / (
double)b));
797 }
else if (IS_FLOATING(argv[1])) {
798 double b = AS_FLOATING(argv[1]);
799 if (unlikely(b == 0.0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"float division by zero");
800 return FLOATING_VAL(__builtin_floor(
self / b));
802 return NOTIMPL_VAL();
805 KRK_Method(
float,__rfloordiv__) {
806 METHOD_TAKES_EXACTLY(1);
807 if (unlikely(
self == 0.0))
return krk_runtimeError(
vm.exceptions->zeroDivisionError,
"float division by zero");
808 else if (likely(IS_INTEGER(argv[1])))
return FLOATING_VAL((
double)AS_INTEGER(argv[1]) /
self);
809 else if (IS_FLOATING(argv[1]))
return FLOATING_VAL(__builtin_floor(AS_FLOATING(argv[1]) /
self));
810 return NOTIMPL_VAL();
813 KRK_Method(
float,__pos__) {
818 KRK_Method(
float,as_integer_ratio) {
824 #define CURRENT_CTYPE krk_integer_type
826 KRK_StaticMethod(
bool,__new__) {
827 FUNCTION_TAKES_AT_MOST(2);
828 if (argc < 2)
return BOOLEAN_VAL(0);
832 KRK_Method(
bool,__repr__) {
833 return OBJECT_VAL((
self ? S(
"True") : S(
"False")));
836 KRK_Method(
bool,__format__) {
837 METHOD_TAKES_EXACTLY(1);
840 if (!format_spec->length) {
841 return FUNC_NAME(
bool,__repr__)(argc,argv,hasKw);
843 return FUNC_NAME(
int,__format__)(argc,argv,hasKw);
847 KRK_StaticMethod(NoneType,__new__) {
848 if (argc > 1)
return krk_runtimeError(
vm.exceptions->argumentError,
"%s takes no arguments",
"NoneType");
852 KRK_Method(NoneType,__repr__) {
853 return OBJECT_VAL(S(
"None"));
856 KRK_Method(NoneType,__hash__) {
857 return INTEGER_VAL((uint32_t)AS_INTEGER(argv[0]));
860 KRK_Method(NoneType,__eq__) {
861 METHOD_TAKES_EXACTLY(1);
862 if (IS_NONE(argv[1]))
return BOOLEAN_VAL(1);
863 return NOTIMPL_VAL();
866 #define IS_NotImplementedType(o) IS_NOTIMPL(o)
867 #define AS_NotImplementedType(o) (1)
869 KRK_StaticMethod(NotImplementedType,__new__) {
870 if (argc > 1)
return krk_runtimeError(
vm.exceptions->argumentError,
"%s takes no arguments",
"NotImplementedType");
871 return NOTIMPL_VAL();
874 KRK_Method(NotImplementedType,__repr__) {
875 return OBJECT_VAL(S(
"NotImplemented"));
878 KRK_Method(NotImplementedType,__hash__) {
879 return INTEGER_VAL(0);
882 KRK_Method(NotImplementedType,__eq__) {
883 METHOD_TAKES_EXACTLY(1);
884 if (IS_NOTIMPL(argv[1]))
return BOOLEAN_VAL(1);
885 return NOTIMPL_VAL();
889 #undef BIND_STATICMETHOD
891 #define BIND_METHOD(klass,method) do { krk_defineNative(& _ ## klass->methods, #method, _ ## klass ## _ ## method); } while (0)
892 #define BIND_STATICMETHOD(klass,method) do { krk_defineNativeStaticMethod(& _ ## klass->methods, #method, _ ## klass ## _ ## method); } while (0)
893 #define BIND_TRIPLET(klass,name) \
894 BIND_METHOD(klass,__ ## name ## __); \
895 BIND_METHOD(klass,__r ## name ## __); \
896 krk_defineNative(&_ ## klass->methods,"__i" #name "__",_ ## klass ## ___ ## name ## __);
898 void _createAndBind_numericClasses(
void) {
899 KrkClass * _int = ADD_BASE_CLASS(
vm.baseClasses->intClass,
"int",
vm.baseClasses->objectClass);
900 _int->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
902 BIND_STATICMETHOD(
int,__new__);
903 BIND_METHOD(
int,__repr__);
904 BIND_METHOD(
int,__int__);
905 BIND_METHOD(
int,__chr__);
906 BIND_METHOD(
int,__eq__);
907 BIND_METHOD(
int,__hash__);
908 BIND_METHOD(
int,__format__);
910 BIND_TRIPLET(
int,add);
911 BIND_TRIPLET(
int,sub);
912 BIND_TRIPLET(
int,mul);
913 BIND_TRIPLET(
int,or);
914 BIND_TRIPLET(
int,xor);
915 BIND_TRIPLET(
int,and);
916 BIND_TRIPLET(
int,lshift);
917 BIND_TRIPLET(
int,rshift);
918 BIND_TRIPLET(
int,mod);
919 BIND_TRIPLET(
int,floordiv);
920 BIND_TRIPLET(
int,pow);
923 BIND_METHOD(
int,__float__);
924 BIND_TRIPLET(
int,truediv);
927 BIND_METHOD(
int,__lt__);
928 BIND_METHOD(
int,__gt__);
929 BIND_METHOD(
int,__le__);
930 BIND_METHOD(
int,__ge__);
932 BIND_METHOD(
int,__hex__);
933 BIND_METHOD(
int,__oct__);
934 BIND_METHOD(
int,__bin__);
935 BIND_METHOD(
int,__invert__);
936 BIND_METHOD(
int,__neg__);
937 BIND_METHOD(
int,__abs__);
938 BIND_METHOD(
int,__pos__);
941 KRK_DOC(_int,
"Convert a number or string type to an integer representation.");
943 KrkClass * _float = ADD_BASE_CLASS(
vm.baseClasses->floatClass,
"float",
vm.baseClasses->objectClass);
944 _float->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
947 BIND_STATICMETHOD(
float,__new__);
948 BIND_METHOD(
float,__int__);
949 BIND_METHOD(
float,__float__);
950 BIND_METHOD(
float,__repr__);
951 BIND_METHOD(
float,__eq__);
952 BIND_METHOD(
float,__hash__);
953 BIND_TRIPLET(
float,add);
954 BIND_TRIPLET(
float,sub);
955 BIND_TRIPLET(
float,mul);
956 BIND_TRIPLET(
float,truediv);
957 BIND_TRIPLET(
float,floordiv);
958 BIND_METHOD(
float,__lt__);
959 BIND_METHOD(
float,__gt__);
960 BIND_METHOD(
float,__le__);
961 BIND_METHOD(
float,__ge__);
962 BIND_METHOD(
float,__neg__);
963 BIND_METHOD(
float,__abs__);
964 BIND_METHOD(
float,__pos__);
965 BIND_METHOD(
float,__format__);
966 BIND_METHOD(
float,as_integer_ratio);
969 KRK_DOC(_float,
"Convert a number or string type to a float representation.");
971 KrkClass * _bool = ADD_BASE_CLASS(
vm.baseClasses->boolClass,
"bool",
vm.baseClasses->intClass);
972 _bool->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
973 BIND_STATICMETHOD(
bool,__new__);
974 BIND_METHOD(
bool,__repr__);
975 BIND_METHOD(
bool,__format__);
977 KRK_DOC(_bool,
"Returns False if the argument is 'falsey', otherwise True.");
979 KrkClass * _NoneType = ADD_BASE_CLASS(
vm.baseClasses->noneTypeClass,
"NoneType",
vm.baseClasses->objectClass);
980 _NoneType->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
982 BIND_STATICMETHOD(NoneType, __new__);
983 BIND_METHOD(NoneType, __repr__);
984 BIND_METHOD(NoneType, __hash__);
985 BIND_METHOD(NoneType, __eq__);
988 KrkClass * _NotImplementedType = ADD_BASE_CLASS(
vm.baseClasses->notImplClass,
"NotImplementedType",
vm.baseClasses->objectClass);
989 _NotImplementedType->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
991 BIND_STATICMETHOD(NotImplementedType, __new__);
992 BIND_METHOD(NotImplementedType, __repr__);
993 BIND_METHOD(NotImplementedType, __hash__);
994 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.
KrkValue krk_double_to_string(double a, unsigned int digits, char formatter, int plus, int forcedigits)
Convert a double to a KrkString.
KrkValue krk_float_to_fraction(double d)
Convert a double to a tuple of two longs.
size_t allocSize
Size to allocate when creating instances of this class.
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.
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.
void krk_pushStringBuilderStr(struct StringBuilder *sb, const char *str, size_t len)
Append a string to the end of a string builder.
#define krk_parseArgs(f, n,...)
Parse arguments to a function while accepting keyword arguments.
KrkValue krk_finishStringBuilder(struct StringBuilder *sb)
Finalize a string builder into a string object.
void krk_pushStringBuilder(struct StringBuilder *sb, char c)
Add a character to the end of a string builder.
#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.
krk_threadLocal KrkThreadState krk_currentThread
Thread-local VM state.
#define vm
Convenience macro for namespacing.
KrkValue krk_pop(void)
Pop the top of the stack.
void krk_push(KrkValue value)
Push a stack value.