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

Large-ish numbers not parsed correctly in Elm 0.18, Windows x64 #1648

Open
ebhasker opened this issue Oct 13, 2017 · 8 comments
Open

Large-ish numbers not parsed correctly in Elm 0.18, Windows x64 #1648

ebhasker opened this issue Oct 13, 2017 · 8 comments

Comments

@ebhasker
Copy link

ebhasker commented Oct 13, 2017

This seems to be a... Parser / code gen problem

SSCCE (with core and html libraries)

import Html exposing (Html, text)
main : Html msg
main = text (toString (2^31)    " versus "    toString (2147483648))

Compiling using elm-make under Windows 10, x64, gives me the following in the resulting javascript:

var _user$project$Main$main = _elm_lang$virtual_dom$Native_VirtualDom.staticProgram(
	_elm_lang$html$Html$text(
		A2(
			_elm_lang$core$Basics_ops['  '],
			_elm_lang$core$Basics$toString(
				Math.pow(2, 31)),
			A2(
				_elm_lang$core$Basics_ops['  '],
				' versus ',
				_elm_lang$core$Basics$toString(-2147483648)))));

Note the minus sign, specifically. Suspecting a numerical overflow sort of problem.

Embedding this app and opening in any major browser shows the incorrect output:

2147483648 versus -2147483648

Note that this seems specific to the Windows version. Compiling the same example using elm-make under Linux (Ubuntu 16.04, x64 in my case) gives the javascript output:

var _user$project$Main$main = _elm_lang$virtual_dom$Native_VirtualDom.staticProgram(
	_elm_lang$html$Html$text(
		A2(
			_elm_lang$core$Basics_ops['  '],
			_elm_lang$core$Basics$toString(
				Math.pow(2, 31)),
			A2(
				_elm_lang$core$Basics_ops['  '],
				' versus ',
				_elm_lang$core$Basics$toString(2147483648)))));

Which results in the correct output:
2147483648 versus 2147483648

Note: Numbers less than 2^31 seem to not raise the issue. So hopefully this is also a min-SSCCEE (unless you count negative numbers!)

Please let me know if you need more info about my architecture (i.e. if you cannot reproduce this somehow).

@process-bot
Copy link

Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it!

Here is what to expect next, and if anyone wants to comment, keep these things in mind.

@ebhasker ebhasker changed the title Large-ish numbers seem to not be parsed correctly in Windows Elm 0.18 Large-ish numbers not parsed correctly in Elm 0.18, Windows x64 Oct 13, 2017
@zwilias
Copy link
Member

zwilias commented Oct 13, 2017

#1246 for more "int literal weirdness", mentioning it here so these can be batched

@ebhasker
Copy link
Author

Thanks @zwilias - that indeed looks extremely relevant.

@itsgreggreg
Copy link

Running OSX 10.11.6 and getting the incorrect output.

Ellie link for ref https://ellie-app.com/rjrWfjNdwa1/0

@zwilias
Copy link
Member

zwilias commented Oct 23, 2017

Ah. Ellie is sort of a separate case (as it involves the elm-compiler compiled to JS through GHCJS), which makes this effect observable on all platforms due to GHCJS only using 32bits for number, independent of the platform is was compiled on.

Nevertheless, it's the same root-cause listed here: #1246 (comment) - Haskell's Int type doesn't guarantee the same range as representable in the integer part of a JS number.

@rtfeldman
Copy link
Member

Running OSX 10.11.6 and getting the incorrect output.

I can't reproduce this on 0.19 on macOS.

> String.fromInt (2^31)    " versus "    String.fromInt (2147483648)
"2147483648 versus 2147483648" : String

It may still be reproducible on Windows though!

@dullbananas
Copy link

still present in 0.19?

@ebhasker
Copy link
Author

ebhasker commented Sep 4, 2021

It's not present as is, but if you increase to 64-bit integers, the problem comes back.

For example, in elm repl (0.19.1 on Windows):

>elm repl
---- Elm 0.19.1 ----------------------------------------------------------------
Say :help for help and :exit to exit! More at <https://elm-lang.org/0.19.1/repl>
--------------------------------------------------------------------------------
> 9223372036854775807
9223372036854776000 : number
> 9223372036854775808
-9223372036854776000 : number
>

Overflow because we've reached the limit of 64-bit integers.

Underflow gives a syntax error at least, but for a value that should have been representable (-2^63 = -9223372036854775808)?

> -9223372036854775807
-9223372036854776000 : number
> -9223372036854775808
[stdin]:876
var $author$project$Elm_Repl$repl_input_value_ = --9223372036854775808;
                                                   ^^^^^^^^^^^^^^^^^^^

SyntaxError: Invalid left-hand side expression in prefix operation
    at new Script (vm.js:102:7)
    at createScript (vm.js:262:10)
    at Object.runInThisContext (vm.js:310:10)
    at internal/process/execution.js:81:19
    at [stdin]-wrapper:6:22
    at evalScript (internal/process/execution.js:80:60)
    at internal/main/eval_stdin.js:29:5
    at Socket.<anonymous> (internal/process/execution.js:209:5)
    at Socket.emit (events.js:412:35)
    at endReadableNT (internal/streams/readable.js:1317:12)

Another experiment:

> a: Int
| a = -9223372036854775807
|
-9223372036854776000 : Int
> a = -9223372036854775807
-9223372036854776000 : number
> a: Int
| a = -9223372036854775808
|
[stdin]:876
var $author$project$Elm_Repl$a = --9223372036854775808;
                                   ^^^^^^^^^^^^^^^^^^^

SyntaxError: Invalid left-hand side expression in prefix operation
    at new Script (vm.js:102:7)
    at createScript (vm.js:262:10)
    at Object.runInThisContext (vm.js:310:10)
    at internal/process/execution.js:81:19
    at [stdin]-wrapper:6:22
    at evalScript (internal/process/execution.js:80:60)
    at internal/main/eval_stdin.js:29:5
    at Socket.<anonymous> (internal/process/execution.js:209:5)
    at Socket.emit (events.js:412:35)
    at endReadableNT (internal/streams/readable.js:1317:12)
>

In a bizarre twist, if you add another digit (and preserve the previous ones), you get weirdness again (cycles back to 0):

> -92233720368547758070
[stdin]:876
var $author$project$Elm_Repl$repl_input_value_ = --10;
                                                   ^^

SyntaxError: Invalid left-hand side expression in prefix operation
    at new Script (vm.js:102:7)
    at createScript (vm.js:262:10)
    at Object.runInThisContext (vm.js:310:10)
    at internal/process/execution.js:81:19
    at [stdin]-wrapper:6:22
    at evalScript (internal/process/execution.js:80:60)
    at internal/main/eval_stdin.js:29:5
    at Socket.<anonymous> (internal/process/execution.js:209:5)
    at Socket.emit (events.js:412:35)
    at endReadableNT (internal/streams/readable.js:1317:12)
> -92233720368547758071
[stdin]:876
var $author$project$Elm_Repl$repl_input_value_ = --9;
                                                   ^

SyntaxError: Invalid left-hand side expression in prefix operation
    at new Script (vm.js:102:7)
    at createScript (vm.js:262:10)
    at Object.runInThisContext (vm.js:310:10)
    at internal/process/execution.js:81:19
    at [stdin]-wrapper:6:22
    at evalScript (internal/process/execution.js:80:60)
    at internal/main/eval_stdin.js:29:5
    at Socket.<anonymous> (internal/process/execution.js:209:5)
    at Socket.emit (events.js:412:35)
    at endReadableNT (internal/streams/readable.js:1317:12)
> -92233720368547758080
0 : number
> -9223372036854775808092233720368547758070
[stdin]:876
var $author$project$Elm_Repl$repl_input_value_ = --10;
                                                   ^^

SyntaxError: Invalid left-hand side expression in prefix operation
    at new Script (vm.js:102:7)
    at createScript (vm.js:262:10)
    at Object.runInThisContext (vm.js:310:10)
    at internal/process/execution.js:81:19
    at [stdin]-wrapper:6:22
    at evalScript (internal/process/execution.js:80:60)
    at internal/main/eval_stdin.js:29:5
    at Socket.<anonymous> (internal/process/execution.js:209:5)
    at Socket.emit (events.js:412:35)
    at endReadableNT (internal/streams/readable.js:1317:12)
> -9223372036854775808092233720368547758080
0 : number
> -92233720368547758080922337203685477580809223372036854775808092233720368547758070
[stdin]:876
var $author$project$Elm_Repl$repl_input_value_ = --10;
                                                   ^^

SyntaxError: Invalid left-hand side expression in prefix operation
    at new Script (vm.js:102:7)
    at createScript (vm.js:262:10)
    at Object.runInThisContext (vm.js:310:10)
    at internal/process/execution.js:81:19
    at [stdin]-wrapper:6:22
    at evalScript (internal/process/execution.js:80:60)
    at internal/main/eval_stdin.js:29:5
    at Socket.<anonymous> (internal/process/execution.js:209:5)
    at Socket.emit (events.js:412:35)
    at endReadableNT (internal/streams/readable.js:1317:12)
> -92233720368547758080922337203685477580809223372036854775808092233720368547758080
0 : number

I can keep going, but you get the gist... 😄

The "double negative sign" seems to point to some strange substitution that happens ('-' '-10' ?)

This seems related to: #1246

I guess the question transforms into, what should Elm do with an integer overflow / underflow?

My vote is for some sort of make error. Or at least a warning that cautions folks about numbers that are too big/small.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants