diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index 5bedbb06375b..2c04a5f89b0c 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -129,12 +129,11 @@ object Scanners { @inline def isNumberSeparator(c: Char): Boolean = c == '_' - @inline def removeNumberSeparators(s: String): String = - if (s.indexOf('_') > 0) s.replaceAllLiterally("_", "") else s + @inline def removeNumberSeparators(s: String): String = if (s.indexOf('_') == -1) s else s.replace("_", "") // disallow trailing numeric separator char, but continue lexing def checkNoTrailingSeparator(): Unit = - if (isNumberSeparator(litBuf.last)) + if (!litBuf.isEmpty && isNumberSeparator(litBuf.last)) errorButContinue("trailing separator is not allowed", offset + litBuf.length - 1) } @@ -706,28 +705,18 @@ object Scanners { getOperatorRest() } case '0' => - def fetchZero() = { - putChar(ch) + def fetchLeadingZero(): Unit = { nextChar() - if (ch == 'x' || ch == 'X') { - nextChar() - base = 16 - if (isNumberSeparator(ch)) - errorButContinue("leading separator is not allowed", offset + 2) + ch match { + case 'x' | 'X' => base = 16 ; nextChar() + //case 'b' | 'B' => base = 2 ; nextChar() + case _ => base = 10 ; putChar('0') } - else { - /** - * What should leading 0 be in the future? It is potentially dangerous - * to let it be base-10 because of history. Should it be an error? Is - * there a realistic situation where one would need it? - */ - if (isDigit(ch) || (isNumberSeparator(ch) && isDigit(lookaheadChar()))) - error("Numbers may not have a leading zero.") - base = 10 - } - getNumber() + if (base != 10 && !isNumberSeparator(ch) && digit2int(ch, base) < 0) + error("invalid literal number") } - fetchZero() + fetchLeadingZero() + getNumber() case '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' => base = 10 getNumber() diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index fe5e62eb490a..bec58811d6e6 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -633,11 +633,11 @@ trait ParallelTesting extends RunnerOrchestration { self => lazy val actualErrors = reporters.foldLeft(0)(_ + _.errorCount) def hasMissingAnnotations = getMissingExpectedErrors(errorMap, reporters.iterator.flatMap(_.errors)) - if (compilerCrashed) Some(s"Compiler crashed when compiling: ${testSource.title}" ) - else if (actualErrors == 0) Some(s"\nNo errors found when compiling neg test $testSource" ) + if (compilerCrashed) Some(s"Compiler crashed when compiling: ${testSource.title}") + else if (actualErrors == 0) Some(s"\nNo errors found when compiling neg test $testSource") else if (expectedErrors != actualErrors) Some(s"\nWrong number of errors encountered when compiling $testSource, expected: $expectedErrors, actual: $actualErrors") - else if (hasMissingAnnotations) Some(s"\nErrors found on incorrect row numbers when compiling $testSource" ) - else if (!errorMap.isEmpty) Some(s"\nExpected error(s) have {=}: $errorMap" ) + else if (hasMissingAnnotations) Some(s"\nErrors found on incorrect row numbers when compiling $testSource") + else if (!errorMap.isEmpty) Some(s"\nExpected error(s) have {=}: $errorMap") else None } diff --git a/tests/neg/literals.scala b/tests/neg/literals.scala new file mode 100644 index 000000000000..4b847a74df66 --- /dev/null +++ b/tests/neg/literals.scala @@ -0,0 +1,58 @@ +trait RejectedLiterals { + def missingHex: Int = { 0x } // error: invalid literal number +} +/* +// scalac: -Ywarn-octal-literal -Xfatal-warnings -deprecation +trait RejectedLiterals { + + def missingHex: Int = { 0x } // line 4: was: not reported, taken as zero + + def leadingZeros: Int = { 01 } // line 6: no leading zero + + def tooManyZeros: Int = { 00 } // line 8: no leading zero + + def zeroOfNine: Int = { 09 } // line 10: no leading zero + + def orphanDot: Int = { 9. } // line 12: ident expected + + def zeroOfNineDot: Int = { 09. } // line 14: malformed integer, ident expected + + def noHexFloat: Double = { 0x1.2 } // line 16: ';' expected but double literal found. + +} + +trait Braceless { + + def missingHex: Int = 0x // line 22: was: not reported, taken as zero + + def leadingZeros: Int = 01 // line 24: no leading zero + + def tooManyZeros: Int = 00 // line 26: no leading zero + + def zeroOfNine: Int = 09 // line 28: no leading zero + + def orphanDot: Int = 9. // line 30: ident expected + + def zeroOfNineDot: Int = 09. // line 32: malformed integer, ident expected + + def noHexFloat: Double = 0x1.2 // line 34: ';' expected but double literal found. +} + +trait MoreSadness { + + def tooTiny: Float = { 0.7e-45f } // floating point number too small + + def twoTiny: Double = { 2.0e-324 } // double precision floating point number too small + + def tooHuge: Float = { 3.4028236E38f } // floating point number too large + + def twoHuge: Double = { 1.7976931348623159e308 } // double precision floating point number too large +} + +trait Lengthy { + + def bad = 1l + + def worse = 123l +} +*/ diff --git a/tests/neg/t6124.check b/tests/neg/t6124.check index f4ca79338fe2..098f453913c1 100644 --- a/tests/neg/t6124.check +++ b/tests/neg/t6124.check @@ -46,46 +46,10 @@ 24 | val x5 = 0_x52 // error | ^ | trailing separator is not allowed --- Error: tests/neg/t6124.scala:25:13 ---------------------------------------------------------------------------------- -25 | val x6 = 0x_52 // error - | ^ - | leading separator is not allowed --- Error: tests/neg/t6124.scala:26:14 ---------------------------------------------------------------------------------- +-- Error: tests/neg/t6124.scala:26:13 ---------------------------------------------------------------------------------- 26 | val x8 = 0x52_ // error - | ^ - | trailing separator is not allowed --- Error: tests/neg/t6124.scala:27:11 ---------------------------------------------------------------------------------- -27 | val x9 = 0_52 // error - | ^ - | Numbers may not have a leading zero. --- Error: tests/neg/t6124.scala:28:12 ---------------------------------------------------------------------------------- -28 | val x10 = 052 // error - | ^ - | Numbers may not have a leading zero. --- Error: tests/neg/t6124.scala:29:12 ---------------------------------------------------------------------------------- -29 | val x11 = 0_0.52 // error - | ^ - | Numbers may not have a leading zero. --- Error: tests/neg/t6124.scala:30:12 ---------------------------------------------------------------------------------- -30 | val x12 = 00.52 // error - | ^ - | Numbers may not have a leading zero. --- Error: tests/neg/t6124.scala:31:12 ---------------------------------------------------------------------------------- -31 | val x13 = 00 // error - | ^ - | Numbers may not have a leading zero. --- Error: tests/neg/t6124.scala:32:12 ---------------------------------------------------------------------------------- -32 | val x14 = 00d // error - | ^ - | Numbers may not have a leading zero. --- Error: tests/neg/t6124.scala:33:12 ---------------------------------------------------------------------------------- -33 | val x15 = 00.0 // error - | ^ - | Numbers may not have a leading zero. --- Error: tests/neg/t6124.scala:34:12 ---------------------------------------------------------------------------------- -34 | val x16 = 0_0 // error - | ^ - | Numbers may not have a leading zero. + | ^ + | trailing separator is not allowed -- Error: tests/neg/t6124.scala:12:17 ---------------------------------------------------------------------------------- 12 | def tooSmall = 1.0E-325 // error | ^^^^^^^^ diff --git a/tests/neg/t6124.scala b/tests/neg/t6124.scala index 4ac8c36defac..a0c7e6fd7d26 100644 --- a/tests/neg/t6124.scala +++ b/tests/neg/t6124.scala @@ -22,16 +22,16 @@ trait T { val x3 = 52_ // error val x5 = 0_x52 // error - val x6 = 0x_52 // error + val x6 = 0x_52 val x8 = 0x52_ // error - val x9 = 0_52 // error - val x10 = 052 // error - val x11 = 0_0.52 // error - val x12 = 00.52 // error - val x13 = 00 // error - val x14 = 00d // error - val x15 = 00.0 // error - val x16 = 0_0 // error + val x9 = 0_52 + val x10 = 052 + val x11 = 0_0.52 + val x12 = 00.52 + val x13 = 00 + val x14 = 00d + val x15 = 00.0 + val x16 = 0_0 def z = 0 } diff --git a/tests/run/literals.check b/tests/run/literals.check deleted file mode 100644 index 46b9a1c7f7e2..000000000000 --- a/tests/run/literals.check +++ /dev/null @@ -1,55 +0,0 @@ -test '\u0024' == '$' was successful -test '\u005f' == '_' was successful -test 65.asInstanceOf[Char] == 'A' was successful -test "\141\142" == "ab" was successful -test "\0x61\0x62".trim() == "x61\0x62" was successful - -test (65 : Byte) == 'A' was successful - -test 0X01 == 1 was successful -test 0x01 == 1 was successful -test 0x10 == 16 was successful -test 0xa == 10 was successful -test 0x0a == 10 was successful -test +0x01 == 1 was successful -test +0x10 == 16 was successful -test +0xa == 10 was successful -test +0x0a == 10 was successful -test -0x01 == -1 was successful -test -0x10 == -16 was successful -test -0xa == -10 was successful -test -0x0a == -10 was successful -test 0x7fffffff == 2147483647 was successful -test 0x80000000 == -2147483648 was successful -test 0xffffffff == -1 was successful - -test 1l == 1L was successful -test 1L == 1l was successful -test 1.asInstanceOf[Long] == 1l was successful -test 0x7fffffffffffffffL == 9223372036854775807L was successful -test 0x8000000000000000L == -9223372036854775808L was successful -test 0xffffffffffffffffL == -1L was successful - -test 1e1f == 10.0f was successful -test .3f == 0.3f was successful -test 0f == 0.0f was successful -test 3.14f == 3.14f was successful -test 6.022e23f == 6.022e23f was successful -test 09f == 9.0f was successful -test 1.asInstanceOf[Float] == 1.0 was successful -test 1l.asInstanceOf[Float] == 1.0 was successful - -test 1e1 == 10.0 was successful -test .3 == 0.3 was successful -test 0.0 == 0.0 was successful -test 0d == 0.0 was successful -test 01.23 == 1.23 was successful -test 01.23d == 1.23d was successful -test 3.14 == 3.14 was successful -test 1e-9d == 1.0e-9 was successful -test 1e137 == 1.0e137 was successful -test 1.asInstanceOf[Double] == 1.0 was successful -test 1l.asInstanceOf[Double] == 1.0 was successful - -test "".length() was successful -test ggg == 3 was successful diff --git a/tests/run/literals.scala b/tests/run/literals.scala index ea00802be0c1..929eabd6988f 100644 --- a/tests/run/literals.scala +++ b/tests/run/literals.scala @@ -2,11 +2,11 @@ // Literals //############################################################################ -//############################################################################ +import scala.util.{Failure, Success, Try} object Test { - /* I add a couple of Unicode identifier tests here temporarily */ + /* I add a couple of Unicode identifier tests here "temporarily" */ def \u03b1\u03c1\u03b5\u03c4\u03b7 = "alpha rho epsilon tau eta" @@ -14,22 +14,11 @@ object Test { def \u03b1\u03b1(that: GGG) = i + that.i } - def check_success[a](name: String, closure: => a, expected: a): Unit = { - print("test " + name) - try { - val actual: a = closure - if (actual == expected) { - print(" was successful"); - } else { - print(" failed: expected "+ expected +", found "+ actual); - } - } catch { - case exception: Throwable => { - print(" raised exception " + exception); - } + def check_success[A](name: String, closure: => A, expected: A): Unit = + Try(closure) match { + case Success(actual) => assert(actual == expected, s"test $name failed: expected $expected, found $actual") + case Failure(error) => throw new AssertionError(s"test $name raised exception $error") } - println - } def main(args: Array[String]): Unit = { // char @@ -39,13 +28,9 @@ object Test { check_success("\"\\141\\142\" == \"ab\"", "\141\142", "ab") check_success("\"\\0x61\\0x62\".trim() == \"x61\\0x62\"", "\0x61\0x62".substring(1), "x61\0x62") - println - // boolean check_success("(65 : Byte) == 'A'", (65: Byte) == 'A', true) // contrib #176 - println - // int check_success("0X01 == 1", 0X01, 1) check_success("0x01 == 1", 0x01, 1) @@ -67,12 +52,10 @@ object Test { check_success("0x80000000 == -2147483648", 0x80000000, -2147483648) check_success("0xffffffff == -1", 0xffffffff, -1) - println - // long check_success("1l == 1L", 1l, 1L) check_success("1L == 1l", 1L, 1l) - check_success("1.asInstanceOf[Long] == 1l", 1.asInstanceOf[Long], 1l) + check_success("1.asInstanceOf[Long] == 1L", 1.asInstanceOf[Long], 1L) check_success("0x7fffffffffffffffL == 9223372036854775807L", 0x7fffffffffffffffL, 9223372036854775807L) @@ -81,8 +64,6 @@ object Test { check_success("0xffffffffffffffffL == -1L", 0xffffffffffffffffL, -1L) - println - // see JLS at address: // http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#230798 @@ -90,28 +71,41 @@ object Test { check_success("1e1f == 10.0f", 1e1f, 10.0f) check_success(".3f == 0.3f", .3f, 0.3f) check_success("0f == 0.0f", 0f, 0.0f) + check_success("0f == -0.000000000000000000e+00f", 0f, -0.000000000000000000e+00f) + check_success("0f == -0.000000000000000000e+00F", 0f, -0.000000000000000000e+00F) + check_success("0f == -0.0000000000000000e14f", 0f, -0.0000000000000000e14f) + check_success("01.23f == 1.23f", 01.23f, 1.23f) check_success("3.14f == 3.14f", 3.14f, 3.14f) check_success("6.022e23f == 6.022e23f", 6.022e23f, 6.022e23f) - check_success("09f == 9.0f", 9f, 9.0f) + check_success("9f == 9.0f", 9f, 9.0f) + check_success("09f == 9.0f", 09f, 9.0f) + check_success("1.00000017881393421514957253748434595763683319091796875001f == 1.0000001f", + 1.00000017881393421514957253748434595763683319091796875001f, + 1.0000001f) + check_success("3.4028235E38f == Float.MaxValue", 3.4028235E38f, Float.MaxValue) check_success("1.asInstanceOf[Float] == 1.0", 1.asInstanceOf[Float], 1.0f) - check_success("1l.asInstanceOf[Float] == 1.0", 1l.asInstanceOf[Float], 1.0f) - - println + check_success("1L.asInstanceOf[Float] == 1.0", 1L.asInstanceOf[Float], 1.0f) // double check_success("1e1 == 10.0", 1e1, 10.0) check_success(".3 == 0.3", .3, 0.3) check_success("0.0 == 0.0", 0.0, 0.0) check_success("0d == 0.0", 0d, 0.0) - check_success("01.23 == 1.23", 1.23, 1.23) + check_success("0d == 0.000000000000000000e+00d", 0d, 0.000000000000000000e+00d) + check_success("0d == -0.000000000000000000e+00d", 0d, -0.000000000000000000e+00d) + check_success("0d == -0.000000000000000000e+00D", 0d, -0.000000000000000000e+00D) + check_success("0.0 == 0.000000000000000000e+00", 0.0, 0.000000000000000000e+00) + check_success("0.0 == -0.000000000000000000e+00", 0.0, -0.000000000000000000e+00) + check_success("1.23 == 1.23", 1.23, 1.23) + check_success("01.23 == 1.23", 01.23, 1.23) check_success("01.23d == 1.23d", 1.23d, 1.23d) check_success("3.14 == 3.14", 3.14, 3.14) check_success("1e-9d == 1.0e-9", 1e-9d, 1.0e-9) check_success("1e137 == 1.0e137", 1e137, 1.0e137) + check_success("1.7976931348623157e308d == Double.MaxValue", 1.7976931348623157e308d, Double.MaxValue) check_success("1.asInstanceOf[Double] == 1.0", 1.asInstanceOf[Double], 1.0) - check_success("1l.asInstanceOf[Double] == 1.0", 1l.asInstanceOf[Double], 1.0) + check_success("1L.asInstanceOf[Double] == 1.0", 1L.asInstanceOf[Double], 1.0) - println check_success("\"\".length()", "\u001a".length(), 1) val ggg = GGG(1) \u03b1\u03b1 GGG(2)