alan icon indicating copy to clipboard operation
alan copied to clipboard

Get non-int64/float64 numeric constants working efficiently

Open dfellis opened this issue 5 years ago • 3 comments

It is currently actually impossible to define numeric constants other than int64 and float64. First-time usage in another size goes through a conversion function to load the global constant data in a smaller size.

Perhaps steal Rust's 0i8 style postfix annotation to declare them, or have the compiler detect 0.toInt8() as a unit and replace with the smaller constant type.

dfellis avatar Aug 19 '20 17:08 dfellis

Thinking about it with the new syntax, if I make built-in functions to work with the Int and Float types directly, I should be able to have it automatically match the type of the other integer or floating point value (or Fail if it is out-of-bounds).

dfellis avatar Jun 02 '24 16:06 dfellis

How to handle situations like const val = 1 + 2; is the problem. Maybe it just stays the Int type and is figured out based on where it is used, but that would require some sort of "fall back to type operators" logic in the operator parsing logic, which I am not sure if it is a good idea. Would it be too magical? What if the "meaning" of the type operator it falls to doesn't match the function operator?

dfellis avatar Jun 02 '24 16:06 dfellis

For the new setup, I think the AnyOf type can help here, as long as I also add in a mechanism to select from that type when multiple possible values remain.

I am hesitant to have a "spooky action at a distance" with this, so I'm still thinking of the resolution happening at the end of the statement, though, and the resolution being based on the "last" possible AnyOf value. But what is that ordering and which should be last?

Well, phooey, or rather F-U-I. Floats, Unsigned Ints, Ints. That should be the order specified, and then because the majority of my APIs assume i64 and f64 by default, we go up in order of bit size.

So AnyOf{f32, f64, u8, u16, u32, u64, i8, i16, i32, i64} as all of the possible types for a small integer constant and AnyOf{f32, f64} for a floating point constant.

The difference, though, is that we can use the constant size and polarity to automatically eliminate types from this list.

Eg, -3 is initially typed as AnyOf{f32, f64, i8, i16, i32, i64} with the unsigned ints gone since they can't hold that value, while 1024 is initially typed AnyOf{f32, f64, u16, u32, u64, i16, i32, i64} because the 8-bit integer types can't hold that value. In that sense, 2.5 is reduced to AnyOf{f32, f64} because none of the integer types can hold the decimal value.

If there's no explicit type associated with the value, it'll pick the last one in that list, which will usually be f64 or i64, but could be u64 if it's a massive integer. But you'd no longer need to cast a constant when passing it into a function if the function constrains the possible value or the type annotation for the variable assignment provides that constraint.

dfellis avatar Nov 19 '24 11:11 dfellis