I have a proposal for implementing integer and float literals for custom types that I would like feedback for.
The few proposals I've seen for extending integer and float literals to programmer-defined types have the complication of compile-time-only big integer types and such. This is a much simpler proposal as far as the compiler goes.
The compiler transforms the literal from something like -28_384BigInteger
into IntegerLiteral { base: Base::Decimal, negative: true, digits: vec![2, 8, 3, 8, 4] }
, which is then fed into BigInteger
's FromIntegerLiteral
implementation to produce a Result<BigInteger, IntegerLiteralError>
.
Through this, parsing is taken care of by the compiler, avoiding the need for every implementation to reimplement it from scratch. Then the compiler can give its normal error messages if needed.
Is there some way of ensuring that existing implementations can run at compile time other than waiting for traits to be able to force implementing methods to be const fn
s?
pub enum Base {
Binary,
Octal,
Decimal,
Hexadecimal,
}
pub struct IntegerLiteral {
pub base: Base,
pub negative: bool,
pub digits: Vec<u8>,
}
pub struct FloatLiteral {
pub base: Base,
pub negative: bool,
pub digits_before_point: Vec<u8>,
pub digits_after_point: Vec<u8>,
pub exponent_is_negative: bool,
pub exponent_digits: Vec<u8>,
}
pub enum IntegerLiteralError {
TooHigh,
TooLow,
/* ... */
}
pub enum FloatLiteralError {
TooHigh,
TooLow,
/* ... */
}
pub trait FromIntegerLiteral {
fn from_integer_literal(literal: IntegerLiteral) -> Result<Self, IntegerLiteralError>;
}
pub trait FromFloatLiteral {
fn from_float_literal(literal: FloatLiteral) -> Result<Self, FloatLiteralError>;
}
FloatLiteral
also has a base
field in case Rust follows the example of Java in allowing literals in another base. The base
field doesn't apply to the exponent digits, which are always in decimal.