diff options
author | Paul Phillips <paulp@improving.org> | 2010-09-17 21:20:56 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-09-17 21:20:56 +0000 |
commit | 513fd181bc99263c92f759c4e17889dcb8da53f0 (patch) | |
tree | 1622666cd62bd160b68bc0205de6db4317c6026a | |
parent | ab8f20c1f7cb13f4c9a7bac88ebb82a5ce89e6d9 (diff) | |
download | scala-513fd181bc99263c92f759c4e17889dcb8da53f0.tar.gz scala-513fd181bc99263c92f759c4e17889dcb8da53f0.tar.bz2 scala-513fd181bc99263c92f759c4e17889dcb8da53f0.zip |
Restoring negative literal parsing behavior to ...
Restoring negative literal parsing behavior to what should be the least
surprising option. Thanks much to Johannes Rudolph for identifying the
bug in the bytecode generator which needed addressing for us to arrive
at proper -0.0 behavior, and for writing the majority of this patch.
A '-' followed immediately by either a number or a period should now
always be treated as a single numeric literal, which means the minus
binds more tightly than anything else. A specific example of how this
differs from 2.8 final is:
-5.+(10) == 5.0 // and not -15.0
The full range of potentially ambiguous parses involving prefix
operators, numbers, and dots is quite large and still needs to be
completely and clearly specified.
Closes #2378 and #3657, review by odersky, jrudolph.
-rw-r--r-- | lib/fjbg.jar.desired.sha1 | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 29 | ||||
-rw-r--r-- | src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java | 27 | ||||
-rw-r--r-- | test/files/run/number-parsing.scala | 31 |
4 files changed, 62 insertions, 27 deletions
diff --git a/lib/fjbg.jar.desired.sha1 b/lib/fjbg.jar.desired.sha1 index ff2228066d..c1e938f381 100644 --- a/lib/fjbg.jar.desired.sha1 +++ b/lib/fjbg.jar.desired.sha1 @@ -1 +1 @@ -06769295d0216cf44826d06eda7836c6358110a9 ?fjbg.jar +92c1fe294100f174502593e5429ef5d5dacd4760 ?fjbg.jar diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 61d45114a9..e44806139e 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -453,6 +453,15 @@ self => case _ => false } + def isNumericLit: Boolean = in.token match { + case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT => true + case _ => false + } + def isUnaryOp: Boolean = isIdent && (in.name match { + case MINUS | PLUS | TILDE | BANG => true + case _ => false + }) + def isIdent = in.token == IDENTIFIER || in.token == BACKQUOTED_IDENT def isExprIntroToken(token: Int): Boolean = token match { @@ -1241,24 +1250,14 @@ self => /** PrefixExpr ::= [`-' | `+' | `~' | `!' | `&'] SimpleExpr */ def prefixExpr(): Tree = { - def unaryOp(): Name = "unary_" + ident() - if (isIdent && in.name == MINUS) { - atPos(in.offset) { - val name = unaryOp() - in.token match { - // Don't include double and float here else we lose -0.0 - case INTLIT | LONGLIT => literal(true) - case _ => Select(stripParens(simpleExpr()), name) - } - } - } else if (isIdent && (in.name == PLUS || in.name == TILDE || in.name == BANG)) { + if (isUnaryOp) { atPos(in.offset) { - val name = unaryOp() - Select(stripParens(simpleExpr()), name) + val name: Name = "unary_" + ident() + if (in.name == MINUS && isNumericLit) simpleExprRest(atPos(in.offset)(literal(true)), true) + else Select(stripParens(simpleExpr()), name) } - } else { - simpleExpr() } + else simpleExpr() } def xmlLiteral(): Tree diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java b/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java index 523f960b23..69d0436528 100644 --- a/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java +++ b/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java @@ -146,27 +146,32 @@ public class JExtendedCode extends JCode { } public void emitPUSH(Long value) { emitPUSH(value.longValue()); } - public void emitPUSH(float value) { - if (value == 0.0F) + private static final Float ZEROF = Float.valueOf(0f); + private static final Float ONEF = Float.valueOf(1f); + private static final Float TWOF = Float.valueOf(2f); + public void emitPUSH(Float value) { + if (ZEROF.equals(value)) emitFCONST_0(); - else if (value == 1.0F) + else if (ONEF.equals(value)) emitFCONST_1(); - else if (value == 2.0F) + else if (TWOF.equals(value)) emitFCONST_2(); else - emitPUSH_index(pool.addFloat(value)); + emitPUSH_index(pool.addFloat(value.floatValue())); } - public void emitPUSH(Float value) { emitPUSH(value.floatValue()); } + public void emitPUSH(float value) { emitPUSH(Float.valueOf(value)); } - public void emitPUSH(double value) { - if (value == 0.0) + private static final Double ZEROD = Double.valueOf(0d); + private static final Double ONED = Double.valueOf(1d); + public void emitPUSH(Double value) { + if (ZEROD.equals(value)) emitDCONST_0(); - else if (value == 1.0) + else if (ONED.equals(value)) emitDCONST_1(); else - emitLDC2_W(value); + emitLDC2_W(value.doubleValue()); } - public void emitPUSH(Double value) { emitPUSH(value.doubleValue()); } + public void emitPUSH(double value) { emitPUSH(Double.valueOf(value)); } public void emitPUSH(String s) { emitPUSH_index(pool.addString(s)); diff --git a/test/files/run/number-parsing.scala b/test/files/run/number-parsing.scala new file mode 100644 index 0000000000..ad1481063e --- /dev/null +++ b/test/files/run/number-parsing.scala @@ -0,0 +1,31 @@ +object Test { + def numTests() = { + val MinusZero = Float.box(-0.0f) + val PlusZero = Float.box(0.0f) + + assert(PlusZero match { case MinusZero => false ; case _ => true }) + assert(MinusZero match { case PlusZero => false ; case _ => true }) + assert((MinusZero: scala.Float) == (PlusZero: scala.Float)) + assert(!(MinusZero equals PlusZero)) + + List( + -5f.max(2) , + -5f max 2 , + -5.max(2) , + -5 max 2 + ) foreach (num => assert(num == 2)) + } + + case class Foo(val x: Double) { + def unary_- : Foo = Foo(-x) + def +(other: Foo): Foo = Foo(x + other.x) + } + def objTests = { + assert(-Foo(5.0) + Foo(10.0) == Foo(5.0)) + assert(-Foo(5.0).+(Foo(10.0)) == Foo(-15.0)) + } + + def main(args: Array[String]): Unit = { + numTests() + } +} |