rune icon indicating copy to clipboard operation
rune copied to clipboard

Option for Unsigned Int Literals

Open lupan opened this issue 4 years ago • 7 comments

I wish to start by saying I think having a simple type system is all fair and good, however coming from using LUA as my scripting language within my rust projects: I do have needs for unsigned 64 bit literals for tasks; I understand it adds further complexity, but even if it is something that requires a prefix/suffix, I am happy enough with that; example being: let a = 18446744073709551615U;

lupan avatar May 17 '21 11:05 lupan

I can see the purpose for this due to potentially requiring the full 64 bits. the work around for this however is just having a wrapper type, its bit uglier but does the job well.

LoopyAshy avatar Jul 05 '21 00:07 LoopyAshy

Since this was raised again in #430, I am open to design ideas around how to natively and efficiently support more forms of numerical types. It is a hard problem for dynamic languages, but if anyone has any ideas I'd love to hear them!

udoprog avatar Aug 25 '22 02:08 udoprog

  1. I could see a python like implementation with an unlimited integer size, implemented with something like rug. But I'm not really sure I like this for Rust inspired scripting language.
  2. Another possibility would be to have signed/unsigned integers, but this would possibly require some C like implicit casts to keep the script language usable.

Maybe an optional "upcast" to "bigint" (1.) on overflows could be implemented, so we don't suffer on the performance costs. I could even see both options implemented, however I'm not sure how to conveniently implement this on the Rust side.

SWW13 avatar Aug 25 '22 18:08 SWW13

My suggestion is that unsigned is usually only needed in order to encode the "non-negative" constraint in code. Otherwise, it can just as easily be solved via "bigint" as suggested by @SWW13 if large numbers are called for (for 64-bit, in most of the cases the numbers are already large enough).

For a dynamic language, however, you remove constraints, instead of add them. For instance, you already remove typing constraints (or to be more exact, change to a union typing system). Therefore, encoding the "non-negative" constraint would fundamentally be at odds with a dynamic language -- at least that's my take on the issue, which I have given some thoughts over.

@lupan 's needs probably rose from a requirement to work with 64-bit ID's. A simpler solution might be to have a parse_u64 function that just returns the u64 casted into i64?

Alternatively. why not use let a = 0xffffffffffffffff;?

schungx avatar Aug 26 '22 00:08 schungx

Can't talk for anybody else, but my use case is working with system emulation and usize pointers (u32, u64 depending on architecture). So i64 is often not big enough for an u64 pointer.

Aside the potential performance impact when implementing bigint instead of having unsigned, I can't come up with any real use case for having an unsigned type so far. Maybe runtime underflow checks would be nice to have?

Alternatively. why not use let a = 0xffffffffffffffff;?

Because that's currently not possible:

error: compile error
  ┌─ test.rn:2:10
  │
2 │     let a = 0xffffffffffffffff;
  │             ^^^^^^^^^^^^^^^^^^ number literal out of bounds `-9223372036854775808` to `9223372036854775807`

Also implicitly making a number negative due to an overflow is dangerous.

SWW13 avatar Aug 26 '22 07:08 SWW13

Also implicitly making a number negative due to an overflow is dangerous.

I probably won't say that. The bits are the same. It is only the interpretation that is different.

As long as you understand that a particular variable should not be interpreted as a signed integer, there really is no harm keeping u64's in them (as long as you're not trying to do math on them).

On the other hand, if you really are going to do math on them (for instance calculating offsets to memory), then obviously you'd need real u64 -- but are you sure you're going to address so much memory? I don't think such memory exists right now...

schungx avatar Aug 26 '22 07:08 schungx

As long as you understand that a particular variable should not be interpreted as a signed integer, there really is no harm keeping u64's in them (as long as you're not trying to do math on them).

That's easier said then done. When using custom modules written in Rust (or even the rune std) and other modules written in rune there can be unforeseen side-effects. I don't like the idea of supporting more or less a work-around as the solution to the underlying problem.

but are you sure you're going to address so much memory?

Well, physically we are only at about 48bit memory address lines, but virtually the full 64bit range is used see e.g. the linux kernel memory map.

SWW13 avatar Aug 26 '22 08:08 SWW13