From 40836cba21a5d67ef2ea377d28c14993806d6074 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Fri, 2 Apr 2021 15:33:33 +0900 Subject: [PATCH] Implement Python 3 division semantics --- modules/codecs/bespokecodecs.krk | 6 ++-- src/compiler.c | 4 +++ src/kuroko/chunk.h | 3 +- src/kuroko/scanner.h | 2 ++ src/opcodes.h | 1 + src/scanner.c | 2 +- src/vm.c | 37 +++++++++++++++++--- test/day5.krk | 12 +++---- test/testReflectedBinaryOperators.krk | 6 ++-- test/testReflectedBinaryOperators.krk.expect | 2 ++ test/testThreading.krk | 2 +- tools/codectools/gen_dbdata.krk | 14 ++++---- 12 files changed, 64 insertions(+), 27 deletions(-) diff --git a/modules/codecs/bespokecodecs.krk b/modules/codecs/bespokecodecs.krk index ed944cd..b94f3dd 100644 --- a/modules/codecs/bespokecodecs.krk +++ b/modules/codecs/bespokecodecs.krk @@ -54,11 +54,11 @@ class Gb18030IncrementalEncoder(IncrementalEncoder): basecodepoint = nextcodepoint pointer = (ord(i) - basecodepoint) + basepointer let running = pointer - let first = 0x81 + (running / (10 * 126 * 10)) + let first = 0x81 + (running // (10 * 126 * 10)) running %= 10 * 126 * 10 - let second = 0x30 + (running / (10 * 126)) + let second = 0x30 + (running // (10 * 126)) running %= 10 * 126 - let third = 0x81 + (running / 10) + let third = 0x81 + (running // 10) let fourth = 0x30 + (running % 10) out.add(bytes([first, second, third, fourth])) offset += 1 diff --git a/src/compiler.c b/src/compiler.c index 19ce410..a228f08 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -583,6 +583,7 @@ static void binary(int canAssign) { case TOKEN_ASTERISK: emitByte(OP_MULTIPLY); break; case TOKEN_POW: emitByte(OP_POW); break; case TOKEN_SOLIDUS: emitByte(OP_DIVIDE); break; + case TOKEN_DOUBLE_SOLIDUS: emitByte(OP_FLOORDIV); break; case TOKEN_MODULO: emitByte(OP_MODULO); break; case TOKEN_IN: emitByte(OP_EQUAL); break; default: return; @@ -625,6 +626,7 @@ static void assignmentValue(void) { case TOKEN_ASTERISK_EQUAL: emitByte(OP_MULTIPLY); break; case TOKEN_POW_EQUAL: emitByte(OP_POW); break; case TOKEN_SOLIDUS_EQUAL: emitByte(OP_DIVIDE); break; + case TOKEN_DSOLIDUS_EQUAL: emitByte(OP_FLOORDIV); break; case TOKEN_MODULO_EQUAL: emitByte(OP_MODULO); break; default: @@ -2787,6 +2789,7 @@ ParseRule krk_parseRules[] = { RULE(TOKEN_PLUS, unary, binary, PREC_TERM), RULE(TOKEN_SEMICOLON, NULL, NULL, PREC_NONE), RULE(TOKEN_SOLIDUS, NULL, binary, PREC_FACTOR), + RULE(TOKEN_DOUBLE_SOLIDUS,NULL, binary, PREC_FACTOR), RULE(TOKEN_ASTERISK, NULL, binary, PREC_FACTOR), RULE(TOKEN_POW, NULL, binary, PREC_EXPONENT), RULE(TOKEN_MODULO, NULL, binary, PREC_FACTOR), @@ -2850,6 +2853,7 @@ ParseRule krk_parseRules[] = { RULE(TOKEN_RSHIFT_EQUAL, NULL, NULL, PREC_NONE), RULE(TOKEN_AMP_EQUAL, NULL, NULL, PREC_NONE), RULE(TOKEN_SOLIDUS_EQUAL, NULL, NULL, PREC_NONE), + RULE(TOKEN_DSOLIDUS_EQUAL,NULL, NULL, PREC_NONE), RULE(TOKEN_ASTERISK_EQUAL,NULL, NULL, PREC_NONE), RULE(TOKEN_MODULO_EQUAL, NULL, NULL, PREC_NONE), diff --git a/src/kuroko/chunk.h b/src/kuroko/chunk.h index c5776d3..a1c677f 100644 --- a/src/kuroko/chunk.h +++ b/src/kuroko/chunk.h @@ -71,7 +71,8 @@ typedef enum { OP_GREATER_EQUAL, OP_LESS_EQUAL, OP_INVOKE_AWAIT, - /* current highest: 48 */ + OP_FLOORDIV, + /* current highest: 49 */ OP_CALL = 64, OP_CLASS, diff --git a/src/kuroko/scanner.h b/src/kuroko/scanner.h index 4c9e4a4..6111dbf 100644 --- a/src/kuroko/scanner.h +++ b/src/kuroko/scanner.h @@ -15,6 +15,7 @@ typedef enum { TOKEN_PLUS, TOKEN_SEMICOLON, TOKEN_SOLIDUS, + TOKEN_DOUBLE_SOLIDUS, TOKEN_ASTERISK, TOKEN_POW, TOKEN_MODULO, @@ -52,6 +53,7 @@ typedef enum { TOKEN_ASTERISK_EQUAL, TOKEN_POW_EQUAL, TOKEN_MODULO_EQUAL, + TOKEN_DSOLIDUS_EQUAL, TOKEN_STRING, TOKEN_BIG_STRING, diff --git a/src/opcodes.h b/src/opcodes.h index 3f351b8..7608392 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -45,6 +45,7 @@ SIMPLE(OP_BEGIN_FINALLY) SIMPLE(OP_END_FINALLY) SIMPLE(OP_GREATER_EQUAL) SIMPLE(OP_LESS_EQUAL) +SIMPLE(OP_FLOORDIV) CONSTANT(OP_DEFINE_GLOBAL,(void)0) CONSTANT(OP_CONSTANT,(void)0) CONSTANT(OP_GET_GLOBAL,(void)0) diff --git a/src/scanner.c b/src/scanner.c index 35aee6e..89f2b75 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -360,7 +360,7 @@ KrkToken krk_scanToken() { case '^': return makeToken(match('=') ? TOKEN_CARET_EQUAL : TOKEN_CARET); case '|': return makeToken(match('=') ? TOKEN_PIPE_EQUAL : TOKEN_PIPE); case '&': return makeToken(match('=') ? TOKEN_AMP_EQUAL : TOKEN_AMPERSAND); - case '/': return makeToken(match('=') ? TOKEN_SOLIDUS_EQUAL : TOKEN_SOLIDUS); + case '/': return makeToken(match('=') ? TOKEN_SOLIDUS_EQUAL : (match('/') ? (match('=') ? TOKEN_DSOLIDUS_EQUAL : TOKEN_DOUBLE_SOLIDUS) : TOKEN_SOLIDUS)); case '*': return makeToken(match('=') ? TOKEN_ASTERISK_EQUAL: (match('*') ? (match('=') ? TOKEN_POW_EQUAL : TOKEN_POW) : TOKEN_ASTERISK)); case '%': return makeToken(match('=') ? TOKEN_MODULO_EQUAL : TOKEN_MODULO); diff --git a/src/vm.c b/src/vm.c index 97d06ac..584c0ac 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1429,7 +1429,30 @@ _success: MAKE_BIN_OP(add,+,radd) MAKE_BIN_OP(sub,-,ssub) MAKE_BIN_OP(mul,*,rmul) -MAKE_BIN_OP(div,/,rdiv) + +/** + * Division operators. + */ +KrkValue krk_operator_truediv(KrkValue a, KrkValue b) { + if (IS_INTEGER(a)) { + if (IS_INTEGER(b)) return FLOATING_VAL((double)AS_INTEGER(a) / (double)AS_INTEGER(b)); + else if (IS_FLOATING(b)) return FLOATING_VAL((double)AS_INTEGER(a) / AS_FLOATING(b)); + } else if (IS_FLOATING(a)) { + if (IS_FLOATING(b)) return FLOATING_VAL(AS_FLOATING(a) / AS_FLOATING(b)); + else if (IS_INTEGER(b)) return FLOATING_VAL(AS_FLOATING(a) / (double)AS_INTEGER(b)); + } + return tryBind("__truediv__", a, b, "/", "unsupported operand types for %s: '%s' and '%s'", "__rtruediv__"); +} + +KrkValue krk_operator_floordiv(KrkValue numerator, KrkValue divisor) { + if (IS_INTEGER(divisor) && IS_INTEGER(numerator)) return INTEGER_VAL(AS_INTEGER(numerator) / AS_INTEGER(divisor)); + else if (IS_INTEGER(divisor) && IS_FLOATING(numerator)) return FLOATING_VAL(__builtin_floor(AS_FLOATING(numerator) / (double)AS_INTEGER(divisor))); + else if (IS_FLOATING(divisor)) { + if (IS_FLOATING(numerator)) return FLOATING_VAL(__builtin_floor(AS_FLOATING(numerator) / AS_FLOATING(divisor))); + else if (IS_INTEGER(numerator)) return FLOATING_VAL(__builtin_floor((double)AS_INTEGER(numerator) / AS_FLOATING(divisor))); + } + return tryBind("__floordiv__", numerator, divisor, "//", "unsupported operand types for %s: '%s' and '%s'", "__rfloordiv__"); +} #define MAKE_UNOPTIMIZED_BIN_OP(name,operator,inv) \ KrkValue krk_operator_ ## name (KrkValue a, KrkValue b) { \ @@ -1986,11 +2009,14 @@ KrkValue krk_valueSetAttribute(KrkValue owner, char * name, KrkValue to) { } #define READ_BYTE() (*frame->ip++) -#define BINARY_OP(op) { KrkValue b = krk_pop(); KrkValue a = krk_pop(); krk_push(krk_operator_ ## op (a,b)); break; } -#define BINARY_OP_CHECK_ZERO(op) { KrkValue b = krk_pop(); KrkValue a = krk_pop(); \ +#define BINARY_OP(op) { KrkValue b = krk_peek(0); KrkValue a = krk_peek(1); \ + a = krk_operator_ ## op (a,b); \ + krk_currentThread.stackTop[-2] = a; krk_pop(); break; } +#define BINARY_OP_CHECK_ZERO(op) { KrkValue b = krk_peek(0); KrkValue a = krk_peek(1); \ if ((IS_INTEGER(b) && AS_INTEGER(b) == 0)) { krk_runtimeError(vm.exceptions->zeroDivisionError, "integer division or modulo by zero"); goto _finishException; } \ else if ((IS_FLOATING(b) && AS_FLOATING(b) == 0.0)) { krk_runtimeError(vm.exceptions->zeroDivisionError, "float division by zero"); goto _finishException; } \ - krk_push(krk_operator_ ## op (a,b)); break; } + a = krk_operator_ ## op (a,b); \ + krk_currentThread.stackTop[-2] = a; krk_pop(); break; } #define READ_CONSTANT(s) (frame->closure->function->chunk.constants.values[OPERAND]) #define READ_STRING(s) AS_STRING(READ_CONSTANT(s)) @@ -2150,7 +2176,8 @@ _finishReturn: (void)0; case OP_ADD: BINARY_OP(add); case OP_SUBTRACT: BINARY_OP(sub) case OP_MULTIPLY: BINARY_OP(mul) - case OP_DIVIDE: BINARY_OP_CHECK_ZERO(div) + case OP_DIVIDE: BINARY_OP_CHECK_ZERO(truediv) + case OP_FLOORDIV: BINARY_OP_CHECK_ZERO(floordiv) case OP_MODULO: BINARY_OP_CHECK_ZERO(mod) case OP_BITOR: BINARY_OP(or) case OP_BITXOR: BINARY_OP(xor) diff --git a/test/day5.krk b/test/day5.krk index 7e971d7..9df2a89 100644 --- a/test/day5.krk +++ b/test/day5.krk @@ -9,10 +9,10 @@ def process_row(seat): let size = 128 for c in seat[:7]: if c == 'F': - top -= size / 2 + top -= size // 2 else if c == 'B': - bottom += size / 2 - size = size / 2 + bottom += size // 2 + size = size // 2 return bottom def process_seat(seat): @@ -21,10 +21,10 @@ def process_seat(seat): let size = 8 for c in seat[7:]: if c == 'L': - top -= size / 2 + top -= size // 2 else if c == 'R': - bottom += size / 2 - size = size / 2 + bottom += size // 2 + size = size // 2 return bottom print(process_row("FBFBBFFRLR")) # 44 diff --git a/test/testReflectedBinaryOperators.krk b/test/testReflectedBinaryOperators.krk index 57d6c3d..c78c45e 100644 --- a/test/testReflectedBinaryOperators.krk +++ b/test/testReflectedBinaryOperators.krk @@ -7,8 +7,8 @@ class RAdder: print("__rmul__ called", o) return f'{o} * RAdder()' - def __rdiv__(self, o): - print("__rdiv__ called", o) + def __rtruediv__(self, o): + print("__rtruediv__ called", o) return f'{o} / RAdder()' def __rpow__(self, o): @@ -41,7 +41,7 @@ class RAdder: print(42 + RAdder()) print(42 * RAdder()) -#print(42 / RAdder()) +print(42 / RAdder()) print(42 ** RAdder()) print(42 >> RAdder()) print(42 << RAdder()) diff --git a/test/testReflectedBinaryOperators.krk.expect b/test/testReflectedBinaryOperators.krk.expect index d65d90c..a3648b5 100644 --- a/test/testReflectedBinaryOperators.krk.expect +++ b/test/testReflectedBinaryOperators.krk.expect @@ -2,6 +2,8 @@ __radd__ called 42 42 + RAdder() __rmul__ called 42 42 * RAdder() +__rtruediv__ called 42 +42 / RAdder() __rpow__ called 42 42 ** RAdder() __rrshift__ called 42 diff --git a/test/testThreading.krk b/test/testThreading.krk index be8506b..b2be5da 100644 --- a/test/testThreading.krk +++ b/test/testThreading.krk @@ -29,7 +29,7 @@ if __name__ == '__main__': print("Starting {} threads.".format(numThreads)) let threads = [] let totalCount = 5000000 - let chunkSize = totalCount / numThreads + let chunkSize = totalCount // numThreads let numbers = list(range(totalCount)) let cnt = 0 if totalCount > chunkSize * numThreads: diff --git a/tools/codectools/gen_dbdata.krk b/tools/codectools/gen_dbdata.krk index 5677a68..28159f2 100644 --- a/tools/codectools/gen_dbdata.krk +++ b/tools/codectools/gen_dbdata.krk @@ -107,7 +107,7 @@ let trailrange_big5 = tupleOf(*range(0x40, 0x7E + 1), *range(0xA1, 0xFE + 1)) for pointer, ucs in enumerate(indices['jis0208']): if ucs == None: continue - let sku = (pointer / 188) + 1 + let sku = (pointer // 188) + 1 let sten = (pointer % 188) + 1 let first = 0x80 + sku if first >= 0xA0: first += 0x40 @@ -116,7 +116,7 @@ for pointer, ucs in enumerate(indices['jis0208']): decode_shiftjis[(first,second)] = ucs if ucs not in encode_shiftjis and not (8272 <= pointer and pointer <= 8835): encode_shiftjis[ucs] = (first, second) - let ku = (pointer / 94) + 1 + let ku = (pointer // 94) + 1 let ten = (pointer % 94) + 1 if ku <= 94: let firste = 0xA0 + ku @@ -130,7 +130,7 @@ for pointer, ucs in enumerate(indices['jis0208']): for pointer, ucs in enumerate(indices['jis0212']): if ucs == None: continue - let ku = (pointer / 94) + 1 + let ku = (pointer // 94) + 1 let ten = (pointer % 94) + 1 let second = 0xA0 + ku let third = 0xA0 + ten @@ -150,7 +150,7 @@ for i in range(63): for i in range(94 * 20): let pointer = 8836 + i let ucs = 0xE000 + i - let sku = (pointer / 188) + 1 + let sku = (pointer // 188) + 1 let sten = (pointer % 188) + 1 let first = 0xC0 + sku let second = 0x3F + sten @@ -159,7 +159,7 @@ for i in range(94 * 20): for pointer, ucs in enumerate(indices['euc-kr']): if ucs == None: continue - let uku = (pointer / 190) + 1 + let uku = (pointer // 190) + 1 let uten = (pointer % 190) + 1 let first = 0x80 + uku let second = 0x40 + uten @@ -168,7 +168,7 @@ for pointer, ucs in enumerate(indices['euc-kr']): for pointer, ucs in enumerate(indices['gb18030']): if ucs == None: continue - let uku = (pointer / 190) + 1 + let uku = (pointer // 190) + 1 let uten = (pointer % 190) + 1 let first = 0x80 + uku let second = 0x3F + uten @@ -179,7 +179,7 @@ for pointer, ucs in enumerate(indices['gb18030']): for pointer, ucs in enumerate(indices['big5']): if ucs == None: continue - let bku = (pointer / 157) + 1 + let bku = (pointer // 157) + 1 let bten = (pointer % 157) + 1 let first = 0x80 + bku let second = 0x3F + bten