haxe icon indicating copy to clipboard operation
haxe copied to clipboard

typing and 64 bit literals

Open ruby0x1 opened this issue 9 years ago • 10 comments

Given:

var a: Float = 111111111112222222.3333;
var b = 0xFFFFFF;
var c = 281474976710655;
var d = 0xFFFFFFFFFFFF;

All of them except for d will compile as expected, regardless of the typing of the assignee.

However, d errors with: Invalid hexadecimal integer

This is a very specific case to disallow explicitly, and I would like to understand why.

A) haxe now has Int64 (even if it is a wrapper). I know that Int64.make(low, high) to create a value to work around this, but the issue is that the typing rejects the constant explicitly without clear reason.

B) This is strange because it doesn't reject decimal or floating point 64 bit constants. It makes an exception for hexadecimal. If the concern is incorrect use (storing a bigger value in a smaller type), it should be a compiler error not a typing error on the literal to even exist in the source code.

C) This is a problem because there are many places where a 64 bit hexadecimal is needed. Many parts of haxe can be considered pass through, since it targets another language, and this is especially true in the context of externs. var a = untyped 0xFFFFFFFFFFFF will also be rejected. There is just no way around this from the haxe syntax, it is treating the literal as invalid syntax.

If I wanted to do bitmasking on a 64 bit value I cannot do it above above 32 bits without resorting to use decimal representation or shifting, which has other problems (Like the compiler converting the constants to 32 bit representations, wrapping them, and then casting them to int anyway! see: int tmp = (int(id) >> int(((::cpp::Int64)((int)-1)))); )

This is hard to understand, given that in js, c++, lua, python, csharp, java, None of these languages impose an arbitrary restriction on hexadecimal. In these languages typically a L is appended to the literal if the user is expecting higher than 32 bits or if the literal is intended to be typed higher than 32 bits.

Is there a way to allow a 64 bit hexadecimal constant, please? I would think the L suffix is the most compatible option that is both clear, consistent with many similar languages, and is also fully backward compatible.

ruby0x1 avatar Apr 21 '16 16:04 ruby0x1

64 bit literals would make the code cleaner and less error-prone

hughsando avatar Apr 22 '16 04:04 hughsando

I agree that we need 64 bit literals but I don't think it's gonna happen before Haxe 4.

Simn avatar Apr 24 '16 08:04 Simn

I regularly miss 64 bits literal too. I don't much like 0x0 but...

Would be awesome if 64bit constant literal would be deduced from context ( caller expression typed as 64 bit or literal longer than 4bytes ) and if we could write 0x0L only to force callee expr type when compiler is out of league.

2016-04-24 10:17 GMT+02:00 Simon Krajewski [email protected]:

I agree that we need 64 bit literals but I don't think it's gonna happen before Haxe 4.

— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub https://github.com/HaxeFoundation/haxe/issues/5150#issuecomment-213912626

David Elahee

delahee avatar Apr 24 '16 08:04 delahee

I think it already works from context, like "var x:Int64 = 0" - but how to get a constant bigger than 2^32? I was hoping this could be slipped in very early in the path "0x123456789" -> Int64.make(....). But I guess you are going to need a new ast const type, which might break macro switches?

hughsando avatar Apr 24 '16 14:04 hughsando

In the cases I'm referring to with bit shifting and externs, implicitly generating make(high,low) is not really useful. It would have to do that differently, but at minimum the literals shouldn't be disallowed because we're dealing with other targets that all support it. Solving higher level type inference to haxe.Int* would come after that I'd think.

ruby0x1 avatar Apr 24 '16 16:04 ruby0x1

I think a possible workaround would be to

  • recognize the literal as a 64bit value either early in the lexer/parser, or when actually typing the constant in the untyped AST
  • store the int64 in some global array in the compiler, and either make the TInt(value) the index of the actual value in the array, or use some metadata for that.
  • the optimizer/analyzer code needs to be aware it can't use the index for things like constant propagation directly, and the targets supporting Int64 literals can use the value they get from the array. This way most of the compiler code can remain untouched and we finally get "early" (harhar) support for Int64 literals.

ousado avatar May 07 '16 12:05 ousado

POC implementation of the above (only supporting hxcpp generator), please see https://github.com/HaxeFoundation/haxe/pull/5212

ousado avatar May 07 '16 18:05 ousado

this issue is currently blocking my bindings for bgfx, which has quite a few of these.

edit: I worked around this by directly binding the defines with an extern class, but it's super ugly.

shakesoda avatar Sep 20 '17 03:09 shakesoda

suggestion: LiteralInt, LiteralFloat (or CompileTimeInt shit too long) which stores the accurate value / just the string literal (think as arbitrary precision arithmetic, but most of the time no/little calculation is needed, just delayed conversion. i think the performance will be acceptable with proper implementation) and only available at compile time.

another idea: more magic following "xx".code as "0xffffffffffffffff".asInt64?

“compile-time/macro constructor/static_extension_getter”

btw it traps me that Std.parseInt on "0x80000000"+ returns positive number which seems not accepted by Int64.make.... https://try.haxe.org/#F7D4c

farteryhr avatar Oct 03 '18 19:10 farteryhr

I know we can define literal Int64 values now with the type suffix

var a:Int64 = 0xFFFFFFFF00000000i64;

Are there plans to allow constants for things like enums. I looked through the current open items but didn't see one specific for it.

enum abstract Foo(Int64)
{
  var XXX = 0xFFFFFFFF00000000i64;
}

rushmobius avatar Apr 26 '24 22:04 rushmobius