Skip to content

Commit 8388836

Browse files
authored
Merge pull request #186 from BobHanson/master
update of Scanner to handle longs with up to 53 bits only
2 parents 89861c6 + 9923f00 commit 8388836

File tree

23 files changed

+480
-116
lines changed

23 files changed

+480
-116
lines changed
433 Bytes
Binary file not shown.

sources/net.sf.j2s.core/dist/swingjs/differences.txt

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ ever be shadowed or overridden by subclasses. For example, we see in java.lang.T
3131
----------------------------------
3232

3333

34+
updated 12/6/2020 -- note about restrictions on long, including BitSet and Scanner
3435
updated 3/21/2020 -- adds note about HashMap, Hashtable, and HashSet iterator ordering
3536
updated 3/20/2020 -- adds note about interning, new String("xxx"), and "xxx"
3637
updated 2/26/2020 -- adds Graphics.setClip issue
@@ -480,6 +481,8 @@ MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS
480481

481482
See below for a full discussion.
482483

484+
Restrictions on long
485+
Restriction on BitSet and Scanner
483486
HashMap, Hashtable, and HashSet iterator ordering
484487
interning, new String("xxx") vs "xxx"
485488
Names with "$" and "_"
@@ -586,6 +589,60 @@ changed to JSToolkit.isDispatchThread()
586589
MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS
587590
=====================================================================
588591

592+
restrictions on long
593+
--------------------
594+
595+
Java's 64-bit long type is not supported in JavaScript. There is no Int64Array in JavaScript,
596+
and 0x20000000000000 + 1 evaluates to 0x20000000000000, not 0x20000000000001.
597+
(Likewise, -0x20000000000000 - 1 is left unchanged.)
598+
599+
The largest "integer" value in JavaScript is 9007199254740991 (9.007199254740991E13, or 0x1FFFFFFFFFFFFFF).
600+
Effectively, you get to use only 53 bits of the long, not 64. Trying to set a long larger than
601+
0x1FFFFFFFFFFFFFF or smaller than -0x1FFFFFFFFFFFFFF will result in a NumberFormatException.
602+
603+
The transpiler handles conversion to long the same as Java for all cases other than from double.
604+
605+
For small double values, there is no problem, and, in fact, this is a known trick used to round
606+
doubles and floats toward zero:
607+
608+
double d;
609+
d = (long) 3.8;
610+
assert(d == 3);
611+
d = (long) -3.8;
612+
assert(d == -3);
613+
614+
SwingJS will evaluate (long) d as 0 for d > 9007199254740991
615+
or d < -9007199254740991, same as Java returns for Double.NaN.
616+
So, in Java we have:
617+
618+
assert(((long) Double.NaN) == 0);
619+
assert(((int) Double.NaN) == 0);
620+
assert(((long) Float.NaN) == 0);
621+
assert(((int) Float.NaN) == 0);
622+
623+
and also, in JavaScript only, we also have:
624+
625+
double d = 0x2000000000000L;
626+
assert(((long) d) == 0);
627+
628+
629+
restrictions on BitSet and Scanner
630+
----------------------------------
631+
632+
Because of the issue of long being only 53 bits, any time a method returns a long value, considerations must
633+
be made as to whether this will work in JavaScript. In particular, BitSet and Scanner have issues.
634+
635+
In SwingJS, java.util.BitSet has been implemented as a 32-bit integer-based bitset. This was no problem in
636+
Java 6, but starting with Java 7, a method was added to BitSet that allows for the extraction of the
637+
underlying long[] word data. This is not work in JavaScript. Instead, SwingJS java.util.Bitset.toLongArray() will deliver
638+
32-bit int[] data.
639+
640+
SwingJS Scanner has hasNextLong() and nextLong(), and although it will scan through long numbers,
641+
Scanner will choke on long numbers greater than the JavaScript 53-bit limit. hasNextLong() will
642+
return false, and nextLong() will throw an InputMismatchException triggered by the NumberFormatException
643+
thrown by Long.parseLong().
644+
645+
589646
HashMap, Hashtable, and HashSet iterator ordering
590647
-------------------------------------------------
591648

37 Bytes
Binary file not shown.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20201205151557
1+
20201206115202
433 Bytes
Binary file not shown.

sources/net.sf.j2s.core/dist/swingjs/ver/3.2.9/differences.txt

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ ever be shadowed or overridden by subclasses. For example, we see in java.lang.T
3131
----------------------------------
3232

3333

34+
updated 12/6/2020 -- note about restrictions on long, including BitSet and Scanner
3435
updated 3/21/2020 -- adds note about HashMap, Hashtable, and HashSet iterator ordering
3536
updated 3/20/2020 -- adds note about interning, new String("xxx"), and "xxx"
3637
updated 2/26/2020 -- adds Graphics.setClip issue
@@ -480,6 +481,8 @@ MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS
480481

481482
See below for a full discussion.
482483

484+
Restrictions on long
485+
Restriction on BitSet and Scanner
483486
HashMap, Hashtable, and HashSet iterator ordering
484487
interning, new String("xxx") vs "xxx"
485488
Names with "$" and "_"
@@ -586,6 +589,60 @@ changed to JSToolkit.isDispatchThread()
586589
MINOR ISSUES--requiring some rewriting/refactoring outside of SwingJS
587590
=====================================================================
588591

592+
restrictions on long
593+
--------------------
594+
595+
Java's 64-bit long type is not supported in JavaScript. There is no Int64Array in JavaScript,
596+
and 0x20000000000000 + 1 evaluates to 0x20000000000000, not 0x20000000000001.
597+
(Likewise, -0x20000000000000 - 1 is left unchanged.)
598+
599+
The largest "integer" value in JavaScript is 9007199254740991 (9.007199254740991E13, or 0x1FFFFFFFFFFFFFF).
600+
Effectively, you get to use only 53 bits of the long, not 64. Trying to set a long larger than
601+
0x1FFFFFFFFFFFFFF or smaller than -0x1FFFFFFFFFFFFFF will result in a NumberFormatException.
602+
603+
The transpiler handles conversion to long the same as Java for all cases other than from double.
604+
605+
For small double values, there is no problem, and, in fact, this is a known trick used to round
606+
doubles and floats toward zero:
607+
608+
double d;
609+
d = (long) 3.8;
610+
assert(d == 3);
611+
d = (long) -3.8;
612+
assert(d == -3);
613+
614+
SwingJS will evaluate (long) d as 0 for d > 9007199254740991
615+
or d < -9007199254740991, same as Java returns for Double.NaN.
616+
So, in Java we have:
617+
618+
assert(((long) Double.NaN) == 0);
619+
assert(((int) Double.NaN) == 0);
620+
assert(((long) Float.NaN) == 0);
621+
assert(((int) Float.NaN) == 0);
622+
623+
and also, in JavaScript only, we also have:
624+
625+
double d = 0x2000000000000L;
626+
assert(((long) d) == 0);
627+
628+
629+
restrictions on BitSet and Scanner
630+
----------------------------------
631+
632+
Because of the issue of long being only 53 bits, any time a method returns a long value, considerations must
633+
be made as to whether this will work in JavaScript. In particular, BitSet and Scanner have issues.
634+
635+
In SwingJS, java.util.BitSet has been implemented as a 32-bit integer-based bitset. This was no problem in
636+
Java 6, but starting with Java 7, a method was added to BitSet that allows for the extraction of the
637+
underlying long[] word data. This is not work in JavaScript. Instead, SwingJS java.util.Bitset.toLongArray() will deliver
638+
32-bit int[] data.
639+
640+
SwingJS Scanner has hasNextLong() and nextLong(), and although it will scan through long numbers,
641+
Scanner will choke on long numbers greater than the JavaScript 53-bit limit. hasNextLong() will
642+
return false, and nextLong() will throw an InputMismatchException triggered by the NumberFormatException
643+
thrown by Long.parseLong().
644+
645+
589646
HashMap, Hashtable, and HashSet iterator ordering
590647
-------------------------------------------------
591648

37 Bytes
Binary file not shown.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20201205151557
1+
20201206115202

sources/net.sf.j2s.core/src/net/sf/j2s/core/CorePlugin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public class CorePlugin extends Plugin {
3030
// if you change the x.x.x number, be sure to also indicate that in
3131
// j2sApplet.js and also (Bob only) update.bat, update-clean.bat
3232

33-
33+
// BH 2020.12.06 -- 3.2.9-v1r fix for (long) double using |0
3434
// BH 2020.11.20 -- 3.2.9-v1q fix for new ImmutableCollections.ListN<>(E...) should use Object[]
3535
// BH 2020.08.03 -- 3.2.9-v1p fix for boxing boolean should be Boolean.valueOf$, not new Boolean
3636
// BH 2020.08.01 -- 3.2.9-v1o fix for lambda expressions too static

sources/net.sf.j2s.core/src/net/sf/j2s/core/Java2ScriptVisitor.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@
135135

136136
// TODO: superclass inheritance for JAXB XmlAccessorType
137137

138+
//BH 2020.12.06 -- 3.2.9-v1r fix for (long) double using |0
138139
//BH 2020.11.20 -- 3.2.9-v1q fix for new ImmutableCollections.ListN<>(E...) should use Object[]
139140
//BH 2020.08.03 -- 3.2.9-v1p fix for boxing boolean should be Boolean.valueOf$, not new Boolean
140141
//BH 2020.08.01 -- 3.2.9-v1o fix for lambda expressions too static
@@ -4589,7 +4590,7 @@ private boolean addPrimitiveTypedExpression(Expression left, IVariableBinding as
45894590
// a = ($b$[0] = a | right, $b$[0])
45904591

45914592
String classIntArray = null;
4592-
String more = null;
4593+
String more = null, less = null;
45934594

45944595
String prefix = (isAssignment ? "=" : "");
45954596
boolean fromChar = ("char".equals(rightName));
@@ -4611,7 +4612,8 @@ private boolean addPrimitiveTypedExpression(Expression left, IVariableBinding as
46114612
break;
46124613
case "long":
46134614
if (isDiv || !fromIntType) {
4614-
more = "|0)";
4615+
less = "Clazz.toLong(";
4616+
more = ")";
46154617
addParens = true;
46164618
} else {
46174619
left = null;
@@ -4662,6 +4664,8 @@ private boolean addPrimitiveTypedExpression(Expression left, IVariableBinding as
46624664
buffer.append("(");
46634665
buffer.append(classIntArray).append(" = ");
46644666
temp_processingArrayIndex = true;
4667+
} else if (less != null) {
4668+
buffer.append(less);
46654669
} else if (more == "|0)") {
46664670
buffer.append("(");
46674671
}

0 commit comments

Comments
 (0)