long type
This commit is contained in:
parent
635dd442ba
commit
f61922d155
@ -705,27 +705,7 @@ static void defineVariable(size_t global) {
|
||||
static void number(int exprType) {
|
||||
const char * start = parser.previous.start;
|
||||
invalidTarget(exprType, "literal");
|
||||
int base = 10;
|
||||
|
||||
/*
|
||||
* Handle base prefixes:
|
||||
* 0x Hexadecimal
|
||||
* 0b Binary
|
||||
* 0o Octal
|
||||
*/
|
||||
if (start[0] == '0' && (start[1] == 'x' || start[1] == 'X')) {
|
||||
base = 16;
|
||||
start += 2;
|
||||
} else if (start[0] == '0' && (start[1] == 'b' || start[1] == 'B')) {
|
||||
base = 2;
|
||||
start += 2;
|
||||
} else if (start[0] == '0' && (start[1] == 'o' || start[1] == 'O')) {
|
||||
base = 8;
|
||||
start += 2;
|
||||
}
|
||||
|
||||
/* If it wasn't a special base, it may be a floating point value. */
|
||||
if (base == 10) {
|
||||
for (size_t j = 0; j < parser.previous.length; ++j) {
|
||||
if (parser.previous.start[j] == '.') {
|
||||
double value = strtod(start, NULL);
|
||||
@ -733,11 +713,14 @@ static void number(int exprType) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got here, it's an integer of some sort. */
|
||||
krk_integer_type value = parseStrInt(start, NULL, base);
|
||||
emitConstant(INTEGER_VAL(value));
|
||||
KrkValue result = krk_parse_int(start, parser.previous.literalWidth, 0);
|
||||
if (IS_NONE(result)) {
|
||||
error("invalid numeric literal");
|
||||
return;
|
||||
}
|
||||
emitConstant(result);
|
||||
}
|
||||
|
||||
static int emitJump(uint8_t opcode) {
|
||||
@ -2566,7 +2549,7 @@ static void string(int exprType) {
|
||||
} \
|
||||
tmpbuf[i] = c[i+2]; \
|
||||
} \
|
||||
unsigned long value = parseStrInt(tmpbuf, NULL, 16); \
|
||||
unsigned long value = strtoul(tmpbuf, NULL, 16); \
|
||||
if (value >= 0x110000) { \
|
||||
error("invalid codepoint in \\%c escape", type); \
|
||||
} \
|
||||
|
@ -11,9 +11,6 @@
|
||||
typedef int64_t krk_integer_type;
|
||||
|
||||
#define ENABLE_THREADING
|
||||
#define PRIkrk_int "%" PRId64
|
||||
#define PRIkrk_hex "%" PRIx64
|
||||
#define parseStrInt strtoll
|
||||
|
||||
#if defined(KRK_DISABLE_THREADS) || defined(__EMSCRIPTEN__) || defined(EFI_PLATFORM)
|
||||
# undef ENABLE_THREADING
|
||||
|
@ -233,6 +233,7 @@ typedef struct KrkClass {
|
||||
KrkObj * _floordiv, * _rfloordiv, * _ifloordiv;
|
||||
|
||||
KrkObj * _lt, * _gt, * _le, * _ge;
|
||||
KrkObj * _invert, * _negate;
|
||||
} KrkClass;
|
||||
|
||||
/**
|
||||
|
@ -180,6 +180,8 @@ extern int krk_valuesEqual(KrkValue a, KrkValue b);
|
||||
*/
|
||||
extern int krk_valuesSame(KrkValue a, KrkValue b);
|
||||
|
||||
extern KrkValue krk_parse_int(const char * start, size_t width, unsigned int base);
|
||||
|
||||
typedef union {
|
||||
KrkValue val;
|
||||
double dbl;
|
||||
@ -233,3 +235,7 @@ typedef union {
|
||||
#define KWARGS_DICT (INT32_MAX-2)
|
||||
#define KWARGS_NIL (INT32_MAX-3)
|
||||
#define KWARGS_UNSET (0)
|
||||
|
||||
#define PRIkrk_int "%" PRId64
|
||||
#define PRIkrk_hex "%" PRIx64
|
||||
|
||||
|
@ -122,6 +122,7 @@ struct BaseClasses {
|
||||
KrkClass * bytearrayClass; /**< Mutable array of bytes */
|
||||
KrkClass * dictvaluesClass; /**< Iterator over values of a dict */
|
||||
KrkClass * sliceClass; /**< Slice object */
|
||||
KrkClass * longClass; /**< Arbitrary precision integer */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -40,6 +40,8 @@ CACHED_METHOD(LT, "__lt__", _lt)
|
||||
CACHED_METHOD(GT, "__gt__", _gt)
|
||||
CACHED_METHOD(LE, "__le__", _le)
|
||||
CACHED_METHOD(GE, "__ge__", _ge)
|
||||
CACHED_METHOD(INVERT, "__invert__", _invert)
|
||||
CACHED_METHOD(NEGATE, "__neg__", _negate)
|
||||
|
||||
/* These are not methods */
|
||||
SPECIAL_ATTRS(CLASS, "__class__")
|
||||
|
1358
src/obj_long.c
Normal file
1358
src/obj_long.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,7 +16,7 @@
|
||||
|
||||
FUNC_SIG(int,__init__) {
|
||||
static __attribute__ ((unused)) const char* _method_name = "__init__";
|
||||
METHOD_TAKES_AT_MOST(1);
|
||||
METHOD_TAKES_AT_MOST(2);
|
||||
if (argc < 2) return INTEGER_VAL(0);
|
||||
if (IS_BOOLEAN(argv[1])) return INTEGER_VAL(AS_INTEGER(argv[1]));
|
||||
if (IS_INTEGER(argv[1])) return argv[1];
|
||||
@ -52,14 +52,40 @@ KRK_METHOD(int,__hash__,{
|
||||
return INTEGER_VAL((uint32_t)AS_INTEGER(argv[0]));
|
||||
})
|
||||
|
||||
/**
|
||||
* We _could_ use the __builtin_XXX_overflow(_p) functions gcc+clang provide,
|
||||
* but let's just do this ourselves, I guess?
|
||||
*
|
||||
* We cheat: We only bother calculating + checking if both values would fit
|
||||
* in int32_t's. This ensures multiplication works fine.
|
||||
*
|
||||
* For any case where an int32_t would overflow, we do the 'long' operation
|
||||
* and then reduce if that still yields something that would fit in our 'int48'.
|
||||
*/
|
||||
#define OVERFLOW_CHECKED_INT_OPERATION(name,operator) \
|
||||
extern KrkValue krk_long_coerced_ ## name (krk_integer_type a, krk_integer_type b); \
|
||||
_noexport \
|
||||
KrkValue krk_int_op_ ## name (krk_integer_type a, krk_integer_type b) { \
|
||||
if (likely((int32_t)a == a && (int32_t)b == b)) { \
|
||||
int32_t result_one = a operator b; \
|
||||
int64_t result_two = a operator b; \
|
||||
if (likely(result_one == result_two)) return INTEGER_VAL(result_two); \
|
||||
} \
|
||||
return krk_long_coerced_ ## name (a, b); \
|
||||
}
|
||||
|
||||
OVERFLOW_CHECKED_INT_OPERATION(add,+)
|
||||
OVERFLOW_CHECKED_INT_OPERATION(sub,-)
|
||||
OVERFLOW_CHECKED_INT_OPERATION(mul,*)
|
||||
|
||||
#define BASIC_BIN_OP(name,operator) \
|
||||
KRK_METHOD(int,__ ## name ## __,{ \
|
||||
if (likely(IS_INTEGER(argv[1]))) return INTEGER_VAL(self operator AS_INTEGER(argv[1])); \
|
||||
if (likely(IS_INTEGER(argv[1]))) return krk_int_op_ ## name(self, AS_INTEGER(argv[1])); \
|
||||
else if (likely(IS_FLOATING(argv[1]))) return FLOATING_VAL((double)self operator AS_FLOATING(argv[1])); \
|
||||
return NOTIMPL_VAL(); \
|
||||
}) \
|
||||
KRK_METHOD(int,__r ## name ## __,{ \
|
||||
if (likely(IS_INTEGER(argv[1]))) return INTEGER_VAL(AS_INTEGER(argv[1]) operator self); \
|
||||
if (likely(IS_INTEGER(argv[1]))) return krk_int_op_ ## name(AS_INTEGER(argv[1]), self); \
|
||||
else if (likely(IS_FLOATING(argv[1]))) return FLOATING_VAL(AS_FLOATING(argv[1]) operator (double)self); \
|
||||
return NOTIMPL_VAL(); \
|
||||
})
|
||||
@ -87,26 +113,20 @@ BASIC_BIN_OP(mul,*)
|
||||
INT_ONLY_BIN_OP(or,|)
|
||||
INT_ONLY_BIN_OP(xor,^)
|
||||
INT_ONLY_BIN_OP(and,&)
|
||||
INT_ONLY_BIN_OP(lshift,<<)
|
||||
INT_ONLY_BIN_OP(rshift,>>)
|
||||
|
||||
KRK_METHOD(int,__mod__,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
if (likely(IS_INTEGER(argv[1]))) {
|
||||
if (unlikely(AS_INTEGER(argv[1]) == 0)) return krk_runtimeError(vm.exceptions->zeroDivisionError, "integer modulo by zero");
|
||||
return INTEGER_VAL(self % AS_INTEGER(argv[1]));
|
||||
}
|
||||
return NOTIMPL_VAL();
|
||||
})
|
||||
#define DEFER_TO_LONG(name) \
|
||||
extern KrkValue krk_long_coerced_ ## name (krk_integer_type a, krk_integer_type b); \
|
||||
KRK_METHOD(int,__ ## name ## __,{ \
|
||||
if (likely(IS_INTEGER(argv[1]))) return krk_long_coerced_ ## name (self, AS_INTEGER(argv[1])); \
|
||||
return NOTIMPL_VAL(); \
|
||||
}) \
|
||||
KRK_METHOD(int,__r ## name ## __,{ \
|
||||
if (likely(IS_INTEGER(argv[1]))) return krk_long_coerced_ ## name (AS_INTEGER(argv[1]), self); \
|
||||
return NOTIMPL_VAL(); \
|
||||
})
|
||||
|
||||
KRK_METHOD(int,__rmod__,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
if (unlikely(self == 0)) return krk_runtimeError(vm.exceptions->zeroDivisionError, "integer modulo by zero");
|
||||
if (likely(IS_INTEGER(argv[1]))) {
|
||||
return INTEGER_VAL(AS_INTEGER(argv[1]) % self);
|
||||
}
|
||||
return NOTIMPL_VAL();
|
||||
})
|
||||
DEFER_TO_LONG(lshift)
|
||||
DEFER_TO_LONG(rshift)
|
||||
|
||||
COMPARE_OP(lt, <)
|
||||
COMPARE_OP(gt, >)
|
||||
@ -144,12 +164,58 @@ KRK_METHOD(int,__rtruediv__,{
|
||||
#define __builtin_floor floor
|
||||
#endif
|
||||
|
||||
/**
|
||||
* These have been corrected to match the behavior with negatives
|
||||
* that Python produces, for compatibility, and also because that's
|
||||
* what our 'long' type does...
|
||||
*/
|
||||
static KrkValue _krk_int_div(krk_integer_type a, krk_integer_type b) {
|
||||
if (unlikely(b == 0)) return krk_runtimeError(vm.exceptions->zeroDivisionError, "integer division or modulo by zero");
|
||||
if (a == 0) return INTEGER_VAL(0);
|
||||
int64_t abs_a = a < 0 ? -a : a;
|
||||
int64_t abs_b = b < 0 ? -b : b;
|
||||
if ((a < 0) != (b < 0)) {
|
||||
/* If signs don't match, the result is negative, and rounding down means away from 0... */
|
||||
int64_t res = -1 - (abs_a - 1) / abs_b;
|
||||
return INTEGER_VAL(res);
|
||||
}
|
||||
return INTEGER_VAL((abs_a / abs_b));
|
||||
}
|
||||
|
||||
static KrkValue _krk_int_mod(krk_integer_type a, krk_integer_type b) {
|
||||
if (unlikely(b == 0)) return krk_runtimeError(vm.exceptions->zeroDivisionError, "integer division or modulo by zero");
|
||||
if (a == 0) return INTEGER_VAL(0);
|
||||
int64_t abs_a = a < 0 ? -a : a;
|
||||
int64_t abs_b = b < 0 ? -b : b;
|
||||
int64_t res;
|
||||
if ((a < 0) != (b < 0)) {
|
||||
/* If quotient would be negative, then remainder is inverted against the divisor. */
|
||||
res = (abs_b - 1 - (abs_a - 1) % abs_b);
|
||||
} else {
|
||||
res = abs_a % abs_b;
|
||||
}
|
||||
/* Negative divisor always yields negative remainder, except when it's 0... */
|
||||
return INTEGER_VAL((b < 0) ? -res : res);
|
||||
|
||||
}
|
||||
|
||||
KRK_METHOD(int,__mod__,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
if (likely(IS_INTEGER(argv[1]))) return _krk_int_mod(self, AS_INTEGER(argv[1]));
|
||||
return NOTIMPL_VAL();
|
||||
})
|
||||
|
||||
KRK_METHOD(int,__rmod__,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
if (likely(IS_INTEGER(argv[1]))) return _krk_int_mod(AS_INTEGER(argv[1]), self);
|
||||
return NOTIMPL_VAL();
|
||||
})
|
||||
|
||||
|
||||
KRK_METHOD(int,__floordiv__,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
if (likely(IS_INTEGER(argv[1]))) {
|
||||
krk_integer_type b = AS_INTEGER(argv[1]);
|
||||
if (unlikely(b == 0)) return krk_runtimeError(vm.exceptions->zeroDivisionError, "integer division by zero");
|
||||
return INTEGER_VAL(self / b);
|
||||
return _krk_int_div(self,AS_INTEGER(argv[1]));
|
||||
} else if (likely(IS_FLOATING(argv[1]))) {
|
||||
double b = AS_FLOATING(argv[1]);
|
||||
if (unlikely(b == 0.0)) return krk_runtimeError(vm.exceptions->zeroDivisionError, "float division by zero");
|
||||
@ -161,7 +227,7 @@ KRK_METHOD(int,__floordiv__,{
|
||||
KRK_METHOD(int,__rfloordiv__,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
if (unlikely(self == 0)) return krk_runtimeError(vm.exceptions->zeroDivisionError, "integer division by zero");
|
||||
else if (likely(IS_INTEGER(argv[1]))) return INTEGER_VAL(AS_INTEGER(argv[1]) / self);
|
||||
else if (likely(IS_INTEGER(argv[1]))) return _krk_int_div(AS_INTEGER(argv[1]), self);
|
||||
else if (likely(IS_FLOATING(argv[1]))) return FLOATING_VAL(__builtin_floor(AS_FLOATING(argv[1]) / (double)self));
|
||||
return NOTIMPL_VAL();
|
||||
})
|
||||
|
@ -99,22 +99,8 @@ KRK_METHOD(str,__setitem__,{
|
||||
/* str.__int__(base=10) */
|
||||
KRK_METHOD(str,__int__,{
|
||||
METHOD_TAKES_AT_MOST(1);
|
||||
int base = (argc < 2 || !IS_INTEGER(argv[1])) ? 10 : (int)AS_INTEGER(argv[1]);
|
||||
char * start = AS_CSTRING(argv[0]);
|
||||
|
||||
/* These special cases for hexadecimal, binary, octal values. */
|
||||
if (start[0] == '0' && (start[1] == 'x' || start[1] == 'X')) {
|
||||
base = 16;
|
||||
start += 2;
|
||||
} else if (start[0] == '0' && (start[1] == 'b' || start[1] == 'B')) {
|
||||
base = 2;
|
||||
start += 2;
|
||||
} else if (start[0] == '0' && (start[1] == 'o' || start[1] == 'O')) {
|
||||
base = 8;
|
||||
start += 2;
|
||||
}
|
||||
krk_integer_type value = parseStrInt(start, NULL, base);
|
||||
return INTEGER_VAL(value);
|
||||
int base = (argc < 2 || !IS_INTEGER(argv[1])) ? 0 : (int)AS_INTEGER(argv[1]);
|
||||
return krk_parse_int(AS_CSTRING(argv[0]), AS_STRING(argv[0])->length, base);
|
||||
})
|
||||
|
||||
/* str.__float__() */
|
||||
@ -242,7 +228,7 @@ KRK_METHOD(str,format,{
|
||||
} else if (counterOffset) {
|
||||
goto _formatSwitchedNumbering;
|
||||
} else {
|
||||
positionalOffset = parseStrInt(fieldStart,NULL,10);
|
||||
positionalOffset = strtoul(fieldStart,NULL,10);
|
||||
}
|
||||
if (positionalOffset >= argc - 1) {
|
||||
erroneousIndex = positionalOffset;
|
||||
|
@ -21,6 +21,7 @@ extern void _createAndBind_sliceClass(void);
|
||||
extern void _createAndBind_builtins(void);
|
||||
extern void _createAndBind_type(void);
|
||||
extern void _createAndBind_exceptions(void);
|
||||
extern void _createAndBind_longClass(void);
|
||||
extern void _createAndBind_gcMod(void);
|
||||
extern void _createAndBind_timeMod(void);
|
||||
extern void _createAndBind_osMod(void);
|
||||
|
@ -154,24 +154,24 @@ static KrkToken number(char c) {
|
||||
/* Hexadecimal */
|
||||
advance();
|
||||
while (isDigit(peek()) || (peek() >= 'a' && peek() <= 'f') ||
|
||||
(peek() >= 'A' && peek() <= 'F')) advance();
|
||||
(peek() >= 'A' && peek() <= 'F') || (peek() == '_')) advance();
|
||||
return makeToken(TOKEN_NUMBER);
|
||||
} else if (peek() == 'b' || peek() == 'B') {
|
||||
/* Binary */
|
||||
advance();
|
||||
while (peek() == '0' || peek() == '1') advance();
|
||||
while (peek() == '0' || peek() == '1' || (peek() == '_')) advance();
|
||||
return makeToken(TOKEN_NUMBER);
|
||||
} if (peek() == 'o' || peek() == 'O') {
|
||||
/* Octal - must be 0o, none of those silly 0123 things */
|
||||
advance();
|
||||
while (peek() >= '0' && peek() <= '7') advance();
|
||||
while ((peek() >= '0' && peek() <= '7') || (peek() == '_')) advance();
|
||||
return makeToken(TOKEN_NUMBER);
|
||||
}
|
||||
/* Otherwise, decimal and maybe 0.123 floating */
|
||||
}
|
||||
|
||||
/* Decimal */
|
||||
while (isDigit(peek())) advance();
|
||||
while (isDigit(peek()) || peek() == '_') advance();
|
||||
|
||||
/* Floating point */
|
||||
if (peek() == '.' && isDigit(peekNext(1))) {
|
||||
|
8
src/vendor/rline.c
vendored
8
src/vendor/rline.c
vendored
@ -654,15 +654,15 @@ void paint_krk_string(struct syntax_state * state, int type, int isFormat) {
|
||||
int paint_krk_numeral(struct syntax_state * state) {
|
||||
if (charat() == '0' && (nextchar() == 'x' || nextchar() == 'X')) {
|
||||
paint(2, FLAG_NUMERAL);
|
||||
while (isxdigit(charat())) paint(1, FLAG_NUMERAL);
|
||||
while (isxdigit(charat()) || charat() == '_') paint(1, FLAG_NUMERAL);
|
||||
} else if (charat() == '0' && (nextchar() == 'o' || nextchar() == 'O')) {
|
||||
paint(2, FLAG_NUMERAL);
|
||||
while (charat() >= '0' && charat() <= '7') paint(1, FLAG_NUMERAL);
|
||||
while ((charat() >= '0' && charat() <= '7') || charat() == '_') paint(1, FLAG_NUMERAL);
|
||||
} else if (charat() == '0' && (nextchar() == 'b' || nextchar() == 'B')) {
|
||||
paint(2, FLAG_NUMERAL);
|
||||
while (charat() == '0' || charat() == '1') paint(1, FLAG_NUMERAL);
|
||||
while (charat() == '0' || charat() == '1' || charat() == '_') paint(1, FLAG_NUMERAL);
|
||||
} else {
|
||||
while (isdigit(charat())) paint(1, FLAG_NUMERAL);
|
||||
while (isdigit(charat()) || charat() == '_') paint(1, FLAG_NUMERAL);
|
||||
if (charat() == '.' && isdigit(nextchar())) {
|
||||
paint(1, FLAG_NUMERAL);
|
||||
while (isdigit(charat())) paint(1, FLAG_NUMERAL);
|
||||
|
45
src/vm.c
45
src/vm.c
@ -1341,6 +1341,7 @@ void krk_initVM(int flags) {
|
||||
_createAndBind_sliceClass();
|
||||
_createAndBind_exceptions();
|
||||
_createAndBind_generatorClass();
|
||||
_createAndBind_longClass();
|
||||
_createAndBind_gcMod();
|
||||
_createAndBind_timeMod();
|
||||
_createAndBind_osMod();
|
||||
@ -2253,9 +2254,12 @@ KrkValue krk_valueSetAttribute(KrkValue owner, char * name, KrkValue to) {
|
||||
a = krk_operator_i ## op (a,b); \
|
||||
krk_currentThread.stackTop[-2] = a; krk_pop(); break; }
|
||||
|
||||
extern KrkValue krk_int_op_add(krk_integer_type a, krk_integer_type b);
|
||||
extern KrkValue krk_int_op_sub(krk_integer_type a, krk_integer_type b);
|
||||
|
||||
/* These operations are most likely to occur on integers, so we special case them */
|
||||
#define LIKELY_INT_BINARY_OP(op,operator) { KrkValue b = krk_peek(0); KrkValue a = krk_peek(1); \
|
||||
if (likely(IS_INTEGER(a) && IS_INTEGER(b))) a = INTEGER_VAL(AS_INTEGER(a) operator AS_INTEGER(b)); \
|
||||
#define LIKELY_INT_BINARY_OP(op) { KrkValue b = krk_peek(0); KrkValue a = krk_peek(1); \
|
||||
if (likely(IS_INTEGER(a) && IS_INTEGER(b))) a = krk_int_op_ ## op (AS_INTEGER(a), AS_INTEGER(b)); \
|
||||
else a = krk_operator_ ## op (a,b); \
|
||||
krk_currentThread.stackTop[-2] = a; krk_pop(); break; }
|
||||
|
||||
@ -2402,8 +2406,8 @@ _finishReturn: (void)0;
|
||||
case OP_GREATER: LIKELY_INT_COMPARE_OP(gt,>)
|
||||
case OP_LESS_EQUAL: LIKELY_INT_COMPARE_OP(le,<=)
|
||||
case OP_GREATER_EQUAL: LIKELY_INT_COMPARE_OP(ge,>=)
|
||||
case OP_ADD: LIKELY_INT_BINARY_OP(add,+)
|
||||
case OP_SUBTRACT: LIKELY_INT_BINARY_OP(sub,-)
|
||||
case OP_ADD: LIKELY_INT_BINARY_OP(add)
|
||||
case OP_SUBTRACT: LIKELY_INT_BINARY_OP(sub)
|
||||
case OP_MULTIPLY: BINARY_OP(mul)
|
||||
case OP_DIVIDE: BINARY_OP(truediv)
|
||||
case OP_FLOORDIV: BINARY_OP(floordiv)
|
||||
@ -2415,16 +2419,35 @@ _finishReturn: (void)0;
|
||||
case OP_SHIFTRIGHT: BINARY_OP(rshift)
|
||||
case OP_POW: BINARY_OP(pow)
|
||||
case OP_BITNEGATE: {
|
||||
KrkValue value = krk_pop();
|
||||
if (IS_INTEGER(value)) krk_push(INTEGER_VAL(~AS_INTEGER(value)));
|
||||
else { krk_runtimeError(vm.exceptions->typeError, "Incompatible operand type for %s negation.", "bit"); goto _finishException; }
|
||||
KrkValue value = krk_peek(0);
|
||||
if (IS_INTEGER(value)) {
|
||||
krk_currentThread.stackTop[-1] = INTEGER_VAL(~AS_INTEGER(value));
|
||||
} else {
|
||||
KrkClass * type = krk_getType(krk_peek(0));
|
||||
if (likely(type->_invert != NULL)) {
|
||||
krk_push(krk_callDirect(type->_invert, 1));
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->typeError, "Incompatible operand type for %s negation.", "bit");
|
||||
goto _finishException;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_NEGATE: {
|
||||
KrkValue value = krk_pop();
|
||||
if (IS_INTEGER(value)) krk_push(INTEGER_VAL(-AS_INTEGER(value)));
|
||||
else if (IS_FLOATING(value)) krk_push(FLOATING_VAL(-AS_FLOATING(value)));
|
||||
else { krk_runtimeError(vm.exceptions->typeError, "Incompatible operand type for %s negation.", "prefix"); goto _finishException; }
|
||||
KrkValue value = krk_peek(0);
|
||||
if (IS_INTEGER(value)) {
|
||||
krk_currentThread.stackTop[-1] = INTEGER_VAL(-AS_INTEGER(value));
|
||||
} else if (IS_FLOATING(value)) {
|
||||
krk_currentThread.stackTop[-1] = FLOATING_VAL(-AS_FLOATING(value));
|
||||
} else {
|
||||
KrkClass * type = krk_getType(krk_peek(0));
|
||||
if (likely(type->_negate != NULL)) {
|
||||
krk_push(krk_callDirect(type->_negate, 1));
|
||||
} else {
|
||||
krk_runtimeError(vm.exceptions->typeError, "Incompatible operand type for %s negation.", "prefix");
|
||||
goto _finishException;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_NONE: krk_push(NONE_VAL()); break;
|
||||
|
53
test/testBigIntegers.krk
Normal file
53
test/testBigIntegers.krk
Normal file
@ -0,0 +1,53 @@
|
||||
def test(thing, operations=None, numbers=None, printers=None, shifts=None, shiftops=None):
|
||||
print('hello world')
|
||||
|
||||
operations = [
|
||||
('+', lambda a, b: a + b),
|
||||
('-', lambda a, b: a - b),
|
||||
('*', lambda a, b: a * b),
|
||||
('|', lambda a, b: a | b),
|
||||
('^', lambda a, b: a ^ b),
|
||||
('&', lambda a, b: a & b),
|
||||
('//', lambda a, b: a // b),
|
||||
('%', lambda a, b: a % b),
|
||||
]
|
||||
|
||||
numbers = [
|
||||
42, 7, 0, -2, -53, -25932, '-30250320993256832943892058390285932532',
|
||||
'29394294398256832432748937248937198578921421', '0x29589239862',
|
||||
'0b1000101010101010000101010010101010001001001000101010001010010',
|
||||
'32932583298439028439285392', '-5392583232948329853251521'
|
||||
]
|
||||
|
||||
shifts = [
|
||||
0, 3, 23, 47, 68, 135, 1035, -4
|
||||
]
|
||||
|
||||
shiftops = [
|
||||
('<<', lambda a, b: a << b),
|
||||
('>>', lambda a, b: a >> b),
|
||||
]
|
||||
|
||||
printers = [
|
||||
str, hex, oct, bin
|
||||
]
|
||||
|
||||
for a in numbers:
|
||||
for printer in printers:
|
||||
print(printer.__name__,printer(thing(a)))
|
||||
for b in numbers:
|
||||
for opname, op in operations:
|
||||
try:
|
||||
print(a, opname, b, '=', op(thing(a), thing(b)))
|
||||
except Exception as e:
|
||||
print(a, opname, b, '=', str(e))
|
||||
for shift in shifts:
|
||||
for opname, op in shiftops:
|
||||
try:
|
||||
print(a, opname, shift, '=', op(thing(a), shift))
|
||||
except Exception as e:
|
||||
print(a, opname, shift, '=', str(e))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test(lambda a: int(a,0) if isinstance(a,str) else int(a))
|
1393
test/testBigIntegers.krk.expect
Normal file
1393
test/testBigIntegers.krk.expect
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user