Implement Python 3 division semantics

This commit is contained in:
K. Lange 2021-04-02 15:33:33 +09:00
parent a90ca22f4c
commit 40836cba21
12 changed files with 64 additions and 27 deletions

View File

@ -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

View File

@ -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),

View File

@ -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,

View File

@ -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,

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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())

View File

@ -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

View File

@ -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:

View File

@ -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