Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unsigned integer parsing problem #6829

Closed
markus-oberhumer opened this issue Nov 28, 2017 · 13 comments
Closed

Unsigned integer parsing problem #6829

markus-oberhumer opened this issue Nov 28, 2017 · 13 comments

Comments

@markus-oberhumer
Copy link
Contributor

Unsigned integer parsing problem:

when sizeof(int) == 8:
  var a = 18446744073709551615'u64
  var b = 18446744073709551615'u     # FAILS TO COMPILE
@Araq
Copy link
Member

Araq commented Nov 28, 2017

That's not a bug. Unsigned is 32 bits depending on the target and we encourage you to write platform independent code.

@markus-oberhumer
Copy link
Contributor Author

This argument does not make much sense, though:

when sizeof(int) == 8:
  var x =  9223372036854775807'i64
  var y =  9223372036854775807       # WORKS
  var a = 18446744073709551615'u64
  var b = 18446744073709551615'u     # FAILS TO COMPILE

@markus-oberhumer
Copy link
Contributor Author

Also:

when sizeof(int) == 8:
  var x = 0xffffffffffffffff'u64
  var y = 0xffffffffffffffff'u       # WORKS !
  var a = 18446744073709551615'u64
  var b = 18446744073709551615'u     # FAILS TO COMPILE

@Araq
Copy link
Member

Araq commented Nov 28, 2017

Like it or not, they all adhere to the spec that at least exists in my head. The type of an integer literal is int unless it's range doesn't fit an int32 then it is an int64. Hexadecimal numbers are ambiguous and not checked. 'u is explicitly asking for uint with cannot hold a 64bit number.

@markus-oberhumer
Copy link
Contributor Author

Well, that specification is surprising, to say the least:

when sizeof(int) == 8:
  var x: int = 9223372036854775807.int
  var y: int = 9223372036854775807      # DOES NOT COMPILE

@markus-oberhumer
Copy link
Contributor Author

markus-oberhumer commented Nov 28, 2017

[EDIT: created issue #6838 for this]

This problem might be unrelated - I can open a new issue if you prefer:

when sizeof(int) == 8:
  var a   = 18446744073709551615'u64.uint
  const b = 18446744073709551615'u64.uint

  doAssert(a is uint)
  doAssert(b is uint)
  doAssert(a == b)

  echo a
  echo b # DOES NOT COMPILE

@Araq
Copy link
Member

Araq commented Nov 28, 2017

Well, that specification is surprising, to say the least.

Come up with a better one, what's the alternative?

@markus-oberhumer
Copy link
Contributor Author

I don't know enough of Nim's internals to suggest a workable alternative, but stumbling over things like setting lastOrd(tyUInt64) to 0x7FFFFFFFFFFFFFFF'i64 makes me realize that the intergral type system has grown and was not designed upfront.

@markus-oberhumer
Copy link
Contributor Author

Here is an interesting variation of the problem:

when sizeof(int) == 8:
  doAssert         0x7fffffff is int
  doAssert         0x80000000 is int64
  doAssert         0xffffffff is int64
  doAssert 0x8000000000000000 is int64
  doAssert 0xffffffff00000000 is int64
  doAssert 0xffffffff7fffffff is int64
  doAssert 0xffffffff80000000 is int      # int and NOT int64 !
  doAssert 0xffffffffffffffff is int      # int and NOT int64 !

@Araq
Copy link
Member

Araq commented Nov 29, 2017

But stumbling over things like setting lastOrd(tyUInt64) to 0x7FFFFFFFFFFFFFFF'i64 makes me realize that the intergral type system has grown and was not designed upfront.

Irrelevant code, high(uint64) is caught earlier in the frontend and doesn't compile. It was designed in the sense we took multiple iterations over it, every one breaking someone's code, no iteration that produced an "intuitive" design because such a thing doesn't exist with unsigned numbers.

@markus-oberhumer
Copy link
Contributor Author

After looking at getNumber() in compiler/lexer.nim I can spot even more problems:

#oAssert 0x7fffffffffffffff'i32 != 0   # number out of range - good
  
doAssert 0x8000000000000000'i32 == 0   # SHOULD NOT COMPILE
doAssert 0xffffffff00000000'i32 == 0   # SHOULD NOT COMPILE
doAssert 0xffffffff7fffffff'i32 != 0   # SHOULD NOT COMPILE
doAssert 0xffffffff80000000'i32 != 0   # SHOULD NOT COMPILE
doAssert 0xffffffffffffffff'i32 != 0   # SHOULD NOT COMPILE

@krux02
Copy link
Contributor

krux02 commented Nov 12, 2018

I suggested once that the type int should be just an alias for either int64 or int32. This would at least fix the problem that the literal is sometimes int and sometimes int64.

But when complaining about the integer type it is important to take into account that integer literals are not the same as integers. Integer literal are automatically downcasted to a smaller type, if a compile time check ensures no over or underflow.

@krux02
Copy link
Contributor

krux02 commented Mar 26, 2020

this does work now.

@krux02 krux02 closed this as completed Mar 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants