add __float__ and __int__ and __round__

This commit is contained in:
blueloveTH 2024-11-13 18:57:56 +08:00
parent f182fc3cfa
commit bf208c3733
4 changed files with 63 additions and 34 deletions

View File

@ -59,6 +59,9 @@ MAGIC_METHOD(__package__)
MAGIC_METHOD(__path__)
MAGIC_METHOD(__class__)
MAGIC_METHOD(__abs__)
MAGIC_METHOD(__float__)
MAGIC_METHOD(__int__)
MAGIC_METHOD(__round__)
MAGIC_METHOD(__getattr__)
MAGIC_METHOD(__missing__)

View File

@ -287,11 +287,10 @@ static bool builtins_round(int argc, py_Ref argv) {
return TypeError("round() takes 1 or 2 arguments");
}
if(py_isint(py_arg(0))) {
if(argv->type == tp_int) {
py_assign(py_retval(), py_arg(0));
return true;
}
} else if(argv->type == tp_float) {
PY_CHECK_ARG_TYPE(0, tp_float);
py_f64 x = py_tofloat(py_arg(0));
py_f64 offset = x >= 0 ? 0.5 : -0.5;
@ -299,10 +298,12 @@ static bool builtins_round(int argc, py_Ref argv) {
py_newint(py_retval(), (py_i64)(x + offset));
return true;
}
py_f64 factor = pow(10, ndigits);
py_newfloat(py_retval(), (py_i64)(x * factor + offset) / factor);
return true;
}
return pk_callmagic(__round__, argc, argv);
}
static bool builtins_print(int argc, py_Ref argv) {
@ -442,12 +443,11 @@ static bool builtins_ord(int argc, py_Ref argv) {
PY_CHECK_ARG_TYPE(0, tp_str);
c11_sv sv = py_tosv(py_arg(0));
if(c11_sv__u8_length(sv) != 1) {
return TypeError("ord() expected a character, but string of length %d found", c11_sv__u8_length(sv));
return TypeError("ord() expected a character, but string of length %d found",
c11_sv__u8_length(sv));
}
int u8bytes = c11__u8_header(sv.data[0], true);
if (u8bytes == 0) {
return ValueError("invalid char: %c", sv.data[0]);
}
if(u8bytes == 0) { return ValueError("invalid char: %c", sv.data[0]); }
int value = c11__u8_value(u8bytes, sv.data);
py_newint(py_retval(), value);
return true;

View File

@ -297,7 +297,7 @@ static bool int__new__(int argc, py_Ref argv) {
return true;
}
case tp_str: break; // leave to the next block
default: return TypeError("invalid arguments for int()");
default: return pk_callmagic(__int__, 1, argv+1);
}
}
// 2+ args -> error
@ -350,9 +350,7 @@ static bool float__new__(int argc, py_Ref argv) {
py_newfloat(py_retval(), py_tobool(&argv[1]));
return true;
}
case tp_str: break; // leave to the next block
default: return TypeError("invalid arguments for float()");
}
case tp_str: {
// str to float
c11_sv sv = py_tosv(py_arg(1));
@ -370,6 +368,9 @@ static bool float__new__(int argc, py_Ref argv) {
if(p_end != sv.data + sv.size) return ValueError("invalid literal for float(): %q", sv);
py_newfloat(py_retval(), float_out);
return true;
}
default: return pk_callmagic(__float__, 1, argv+1);
}
}
// tp_bool

View File

@ -51,3 +51,28 @@ assert A()[1:2, :A()[3:4, ::-1]] == (slice(1, 2, None), slice(None, (slice(3, 4,
# test right associative
assert 2**2**3 == 256
assert (2**2**3)**2 == 65536
class Number:
def __float__(self):
return 1.0
def __int__(self):
return 2
def __divmod__(self, other):
return 3, 4
def __round__(self, *args):
return args
assert divmod(Number(), 0) == (3, 4)
assert float(Number()) == 1.0
assert int(Number()) == 2
assert round(Number()) == tuple()
assert round(Number(), 1) == (1,)