1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-19 15:14:48 +00:00

add int/to-number: converts s64 and u64 to numbers

(int/to-number value) converts an s64 or u64 to a number.
It restricts the value to the int32 range,
so that `int32?` will always suceeded when called on the result.
This commit is contained in:
Ian Shehadeh 2022-02-20 16:16:52 -05:00
parent 6f645c4cb7
commit 88db9751d7
2 changed files with 47 additions and 0 deletions

View File

@ -207,6 +207,38 @@ JANET_CORE_FN(cfun_it_u64_new,
return janet_wrap_u64(janet_unwrap_u64(argv[0]));
}
JANET_CORE_FN(cfun_to_number,
"(int/to-number value)",
"Convert an int/u64 or int/s64 to a number. Fails if the number is out of range for an int32.") {
janet_fixarity(argc, 1);
if (janet_type(argv[0]) == JANET_ABSTRACT) {
void* abst = janet_unwrap_abstract(argv[0]);
if (janet_abstract_type(abst) == &janet_s64_type) {
int64_t value = *((int64_t*)abst);
if (value > INT32_MAX) {
janet_panicf("cannot convert %q to a number, exceededs int32 max", argv[0]);
}
if (value < INT32_MIN) {
janet_panicf("cannot convert %q to a number, exceededs int32 min", argv[0]);
}
return janet_wrap_integer(value);
}
if (janet_abstract_type(abst) == &janet_u64_type) {
uint64_t value = *((uint64_t*)abst);
if (value > INT32_MAX) {
janet_panicf("cannot convert %q to a number, exceededs int32 max", argv[0]);
}
return janet_wrap_integer(value);
}
}
janet_panicf("expected int/u64 or int/s64, got %q", argv[0]);
}
/*
* Code to support polymorphic comparison.
* int/u64 and int/s64 support a "compare" method that allows
@ -514,6 +546,7 @@ void janet_lib_inttypes(JanetTable *env) {
JanetRegExt it_cfuns[] = {
JANET_CORE_REG("int/s64", cfun_it_s64_new),
JANET_CORE_REG("int/u64", cfun_it_u64_new),
JANET_CORE_REG("int/to-number", cfun_to_number),
JANET_REG_END
};
janet_core_cfuns_ext(env, NULL, it_cfuns);

View File

@ -39,6 +39,20 @@
(def c (u64 "32rvv_vv_vv_vv"))
(def d (u64 "123456789"))))
# Conversion back to an int32
(assert (= (int/to-number (u64 0xFaFa)) 0xFaFa))
(assert (= (int/to-number (i64 0xFaFa)) 0xFaFa))
(assert-error
"int64 out of bounds for int32"
(do
(int/to-number (u64 "0x7fff_ffff_ffff_ffff"))
(int/to-number (i64 "-0x7fff_ffff_ffff_ffff"))))
(assert-error
"int/to-number fails on non-abstract types"
(int/to-number 1))
(assert-no-error
"create some int64 bigints"
(do