3 ms·
Every _BitInt(N) is a subtype of _BitInt(N+1). For practical purposes though, you'd usually make each intN a subtype of intN*2, up to some top integer type whic
by sparkie 2y ago
Every _BitInt(N) is a subtype of _BitInt(N+1). For practical purposes though, you'd usually make each intN a subtype of intN*2, up to some top integer type which supports arbitrary precision.
int8 <= int16 <= int32 <= int64 <= bigint
For this mini subtype hierarchy, you can literally just number the types in increasing order, and use `<=`, rather than bitmasks.
For inclusion of unsigned integers, the same rule applies, but each `unsigned _BitInt(N)` is also a subtype of `signed _BitInt(N+1)`. It might make sense to number the unsigned integers one higher than their signed variants of the same width to simplify testing for compatibility. A specific bit, such as 1000b could indicate a signed integer.
UNSIGNED = 0000b;
SIGNED = 1000b;
enum IntType {
UINT8 = UNSIGNED | 1,
UINT16 = UNSIGNED | 2,
UINT32 = UNSIGNED | 3,
UINT64 = UNSIGNED | 4,
UBIGINT = UNSIGNED | 7,
INT8 = SIGNED | 0,
INT16 = SIGNED | 1,
INT32 = SIGNED | 2,
INT64 = SIGNED | 3,
BIGINT = SIGNED | 7,
};
is_uint8_subtype(ty) = (ty | UNSIGNED) <= UINT8
is_uint16_subtype(ty) = (ty | UNSIGNED) <= UINT16
is_uint32_subtype(ty) = (ty | UNSIGNED) <= UINT32
is_uint64_subtype(ty) = (ty | UNSIGNED) <= UINT64
is_natural(ty) = (ty | UNSIGNED) <= UBIGINT
is_int8_subtype(ty) = (ty | SIGNED) <= INT8
is_int16_subtype(ty) = (ty | SIGNED) <= INT16
is_int32_subtype(ty) = (ty | SIGNED) <= INT32
is_int64_subtype(ty) = (ty | SIGNED) <= INT64
is_integer(ty) = (ty | SIGNED) <= BIGINT
This is approximately how I handle it the numerical tower in my interpreter (extended with some ad-hoc rules to also support rationals, real, complex and quaternions).
- cobertos 2y agoInteresting, I wasn't thinking of sized integers when thinking of int ranges (moreso of Python ranges like `3..7` for integers `3 | 4 | 5 | 6 | 7`) but this is fascinating as well. The interplay between different types of ranges feels like it might be complex to model. I wonder if a type system exists that can modify the type lattice at run-time or just before run-time, so user-defined types can be added to a system even if the program is already built. As the types usually require explicit language support but I can always foresee more explicit un-typable things that might be useful just not useful enough to put in a general type system