summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/fjbg.jar.desired.sha12
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala10
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala57
-rw-r--r--src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java10
-rwxr-xr-xsrc/library/scala/reflect/api/Symbols.scala2
-rw-r--r--test/files/run/t5423.check1
-rw-r--r--test/files/run/t5423.scala12
-rw-r--r--test/files/run/virtpatmat_switch.check7
-rw-r--r--test/files/run/virtpatmat_switch.flags1
-rw-r--r--test/files/run/virtpatmat_switch.scala32
-rw-r--r--test/pending/run/t5427a.check1
-rw-r--r--test/pending/run/t5427a.scala10
-rw-r--r--test/pending/run/t5427b.check1
-rw-r--r--test/pending/run/t5427b.scala11
-rw-r--r--test/pending/run/t5427c.check1
-rw-r--r--test/pending/run/t5427c.scala13
-rw-r--r--test/pending/run/t5427d.check1
-rw-r--r--test/pending/run/t5427d.scala11
19 files changed, 177 insertions, 15 deletions
diff --git a/lib/fjbg.jar.desired.sha1 b/lib/fjbg.jar.desired.sha1
index 1b1068b0d3..d24a5d01fc 100644
--- a/lib/fjbg.jar.desired.sha1
+++ b/lib/fjbg.jar.desired.sha1
@@ -1 +1 @@
-9aa9c99b8032e454f1f85d27de31a88b3dec1045 ?fjbg.jar
+c3f9b576c91cb9761932ad936ccc4a71f33d2ef2 ?fjbg.jar
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 94d764067f..e777491300 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -1272,6 +1272,16 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* the annotations attached to member a definition (class, method, type, field).
*/
def annotations: List[AnnotationInfo] = _annotations
+
+ /** This getter is necessary for reflection, see https://issues.scala-lang.org/browse/SI-5423
+ * We could auto-inject completion into `annotations' and `setAnnotations', but I'm not sure about that
+ * @odersky writes: I fear we can't do the forcing for all compiler symbols as that could introduce cycles
+ */
+ def getAnnotations: List[AnnotationInfo] = {
+ initialize
+ _annotations
+ }
+
def setAnnotations(annots: List[AnnotationInfo]): this.type = {
_annotations = annots
this
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 3d650ef753..3baff7da9e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1072,6 +1072,15 @@ abstract class GenICode extends SubComponent {
targets = tmpCtx.bb :: targets
case Ident(nme.WILDCARD) =>
default = tmpCtx.bb
+ case Alternative(alts) =>
+ alts foreach {
+ case Literal(value) =>
+ tags = value.intValue :: tags
+ targets = tmpCtx.bb :: targets
+ case _ =>
+ abort("Invalid case in alternative in switch-like pattern match: " +
+ tree + " at: " + tree.pos)
+ }
case _ =>
abort("Invalid case statement in switch-like pattern match: " +
tree + " at: " + (tree.pos))
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
index 44579400ff..b1e02cb062 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
@@ -1128,23 +1128,35 @@ defined class Foo */
// }
// }
+ private val switchableTpes = Set(ByteClass.tpe, ShortClass.tpe, IntClass.tpe, CharClass.tpe)
+
def emitSwitch(scrut: Tree, scrutSym: Symbol, cases: List[List[TreeMaker]], pt: Type): Option[Tree] = if (!optimizingCodeGen) None else {
def sequence[T](xs: List[Option[T]]): Option[List[T]] =
if (xs exists (_.isEmpty)) None else Some(xs.flatten)
+ def isSwitchableTpe(tpe: Type): Boolean =
+ switchableTpes contains tpe
+ def switchableConstToInt(x: Tree): Tree = {
+ val Literal(const) = x
+ const.tag match {
+ case IntTag => x
+ case ByteTag | ShortTag | CharTag => Literal(Constant(const.intValue))
+ }
+ }
+
val caseDefs = cases map { makers =>
removeSubstOnly(makers) match {
// default case (don't move this to unfold, as it may only occur on the top level, not as an alternative -- well, except in degenerate matches)
case (btm@BodyTreeMaker(body, _)) :: Nil =>
Some(CaseDef(Ident(nme.WILDCARD), EmptyTree, btm.substitution(body)))
// constant
- case (EqualityTestTreeMaker(_, const@SwitchablePattern(), _)) :: (btm@BodyTreeMaker(body, _)) :: Nil => import CODE._
- Some(CaseDef(const, EmptyTree, btm.substitution(body)))
+ case (EqualityTestTreeMaker(_, const@SwitchablePattern(), _)) :: (btm@BodyTreeMaker(body, _)) :: Nil =>
+ Some(CaseDef(switchableConstToInt(const), EmptyTree, btm.substitution(body)))
// alternatives
case AlternativesTreeMaker(_, altss, _) :: (btm@BodyTreeMaker(body, _)) :: Nil => // assert(currLabel.isEmpty && nextLabel.isEmpty)
val caseConstants = altss map {
case EqualityTestTreeMaker(_, const@SwitchablePattern(), _) :: Nil =>
- Some(const)
+ Some(switchableConstToInt(const))
case _ =>
None
}
@@ -1158,16 +1170,35 @@ defined class Foo */
}
}
- sequence(caseDefs) map { caseDefs =>
- import CODE._
- val matcher = BLOCK(
- VAL(scrutSym) === scrut, // TODO: type test for switchable type if patterns allow switch but the scrutinee doesn't
- Match(REF(scrutSym), caseDefs) // match on scrutSym, not scrut to avoid duplicating scrut
- )
-
- // matcher filter (tree => tree.tpe == null) foreach println
- // treeBrowser browse matcher
- matcher // set type to avoid recursion in typedMatch
+ if (!isSwitchableTpe(scrut.tpe))
+ None
+ else {
+ sequence(caseDefs) map { caseDefs =>
+ import CODE._
+ val caseDefsWithDefault = {
+ def isDefault(x: CaseDef): Boolean = x match {
+ case CaseDef(Ident(nme.WILDCARD), EmptyTree, _) => true
+ case _ => false
+ }
+ val hasDefault = caseDefs exists isDefault
+ if (hasDefault) caseDefs else {
+ val default = atPos(scrut.pos) { DEFAULT ==> MATCHERROR(REF(scrutSym)) }
+ caseDefs :+ default
+ }
+ }
+ val matcher = BLOCK(
+ if (scrut.tpe != IntClass.tpe) {
+ scrutSym setInfo IntClass.tpe
+ VAL(scrutSym) === (scrut DOT nme.toInt)
+ } else {
+ VAL(scrutSym) === scrut
+ },
+ Match(REF(scrutSym), caseDefsWithDefault) // match on scrutSym, not scrut to avoid duplicating scrut
+ )
+ // matcher filter (tree => tree.tpe == null) foreach println
+ // treeBrowser browse matcher
+ matcher // set type to avoid recursion in typedMatch
+ }
}
}
diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java b/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java
index 8b0338ed29..d4c5417260 100644
--- a/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java
+++ b/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java
@@ -596,6 +596,16 @@ public class JExtendedCode extends JCode {
double minDensity) {
assert keys.length == branches.length;
+ //The special case for empty keys. It makes sense to allow
+ //empty keys and generate LOOKUPSWITCH with defaultBranch
+ //only. This is exactly what javac does for switch statement
+ //that has only a default case.
+ if (keys.length == 0) {
+ emitLOOKUPSWITCH(keys, branches, defaultBranch);
+ return;
+ }
+ //the rest of the code assumes that keys.length > 0
+
// sorting the tables
// FIXME use quicksort
for (int i = 1; i < keys.length; i++) {
diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala
index 01c1a0f2ae..17d9b06324 100755
--- a/src/library/scala/reflect/api/Symbols.scala
+++ b/src/library/scala/reflect/api/Symbols.scala
@@ -79,7 +79,7 @@ trait Symbols { self: Universe =>
/** A list of annotations attached to this Symbol.
*/
- def annotations: List[self.AnnotationInfo]
+ def getAnnotations: List[self.AnnotationInfo]
/** For a class: the module or case class factory with the same name in the same package.
* For all others: NoSymbol
diff --git a/test/files/run/t5423.check b/test/files/run/t5423.check
new file mode 100644
index 0000000000..ae3d3fb82b
--- /dev/null
+++ b/test/files/run/t5423.check
@@ -0,0 +1 @@
+List(table) \ No newline at end of file
diff --git a/test/files/run/t5423.scala b/test/files/run/t5423.scala
new file mode 100644
index 0000000000..2139773ff1
--- /dev/null
+++ b/test/files/run/t5423.scala
@@ -0,0 +1,12 @@
+import java.lang.Class
+import scala.reflect.mirror._
+import scala.reflect.runtime.Mirror.ToolBox
+import scala.reflect.Code
+
+final class table extends StaticAnnotation
+@table class A
+
+object Test extends App{
+ val s = classToSymbol(classOf[A])
+ println(s.getAnnotations)
+}
diff --git a/test/files/run/virtpatmat_switch.check b/test/files/run/virtpatmat_switch.check
new file mode 100644
index 0000000000..6ded95c010
--- /dev/null
+++ b/test/files/run/virtpatmat_switch.check
@@ -0,0 +1,7 @@
+zero
+one
+many
+got a
+got b
+got some letter
+scala.MatchError: 5 (of class java.lang.Integer) \ No newline at end of file
diff --git a/test/files/run/virtpatmat_switch.flags b/test/files/run/virtpatmat_switch.flags
new file mode 100644
index 0000000000..9769db9257
--- /dev/null
+++ b/test/files/run/virtpatmat_switch.flags
@@ -0,0 +1 @@
+ -Yvirtpatmat -Xexperimental
diff --git a/test/files/run/virtpatmat_switch.scala b/test/files/run/virtpatmat_switch.scala
new file mode 100644
index 0000000000..2e2c31e8e5
--- /dev/null
+++ b/test/files/run/virtpatmat_switch.scala
@@ -0,0 +1,32 @@
+object Test extends App {
+ def intSwitch(x: Int) = x match {
+ case 0 => "zero"
+ case 1 => "one"
+ case _ => "many"
+ }
+
+ println(intSwitch(0))
+ println(intSwitch(1))
+ println(intSwitch(10))
+
+ def charSwitch(x: Char) = x match {
+ case 'a' => "got a"
+ case 'b' => "got b"
+ case _ => "got some letter"
+ }
+
+ println(charSwitch('a'))
+ println(charSwitch('b'))
+ println(charSwitch('z'))
+
+ def implicitDefault(x: Int) = x match {
+ case 0 => 0
+ }
+
+ try {
+ implicitDefault(5)
+ } catch {
+ case e: MatchError => println(e)
+ }
+
+}
diff --git a/test/pending/run/t5427a.check b/test/pending/run/t5427a.check
new file mode 100644
index 0000000000..d8263ee986
--- /dev/null
+++ b/test/pending/run/t5427a.check
@@ -0,0 +1 @@
+2 \ No newline at end of file
diff --git a/test/pending/run/t5427a.scala b/test/pending/run/t5427a.scala
new file mode 100644
index 0000000000..27b28da0ac
--- /dev/null
+++ b/test/pending/run/t5427a.scala
@@ -0,0 +1,10 @@
+import scala.reflect.mirror._
+
+object Foo { val bar = 2 }
+
+object Test extends App {
+ val tpe = getType(Foo)
+ val bar = tpe.nonPrivateMember(newTermName("bar"))
+ val value = getValue(Foo, bar)
+ println(value)
+} \ No newline at end of file
diff --git a/test/pending/run/t5427b.check b/test/pending/run/t5427b.check
new file mode 100644
index 0000000000..d8263ee986
--- /dev/null
+++ b/test/pending/run/t5427b.check
@@ -0,0 +1 @@
+2 \ No newline at end of file
diff --git a/test/pending/run/t5427b.scala b/test/pending/run/t5427b.scala
new file mode 100644
index 0000000000..7a92b6ebbe
--- /dev/null
+++ b/test/pending/run/t5427b.scala
@@ -0,0 +1,11 @@
+import scala.reflect.mirror._
+
+class Foo { val bar = 2 }
+
+object Test extends App {
+ val foo = new Foo
+ val tpe = getType(foo)
+ val bar = tpe.nonPrivateMember(newTermName("bar"))
+ val value = getValue(foo, bar)
+ println(value)
+} \ No newline at end of file
diff --git a/test/pending/run/t5427c.check b/test/pending/run/t5427c.check
new file mode 100644
index 0000000000..32c91abbd6
--- /dev/null
+++ b/test/pending/run/t5427c.check
@@ -0,0 +1 @@
+no public member \ No newline at end of file
diff --git a/test/pending/run/t5427c.scala b/test/pending/run/t5427c.scala
new file mode 100644
index 0000000000..ab41d8b8cd
--- /dev/null
+++ b/test/pending/run/t5427c.scala
@@ -0,0 +1,13 @@
+import scala.reflect.mirror._
+
+class Foo(bar: Int)
+
+object Test extends App {
+ val foo = new Foo(2)
+ val tpe = getType(foo)
+ val bar = tpe.nonPrivateMember(newTermName("bar"))
+ bar match {
+ case NoSymbol => println("no public member")
+ case _ => println("i'm screwed")
+ }
+} \ No newline at end of file
diff --git a/test/pending/run/t5427d.check b/test/pending/run/t5427d.check
new file mode 100644
index 0000000000..d8263ee986
--- /dev/null
+++ b/test/pending/run/t5427d.check
@@ -0,0 +1 @@
+2 \ No newline at end of file
diff --git a/test/pending/run/t5427d.scala b/test/pending/run/t5427d.scala
new file mode 100644
index 0000000000..fd4c62e876
--- /dev/null
+++ b/test/pending/run/t5427d.scala
@@ -0,0 +1,11 @@
+import scala.reflect.mirror._
+
+class Foo(val bar: Int)
+
+object Test extends App {
+ val foo = new Foo(2)
+ val tpe = getType(foo)
+ val bar = tpe.nonPrivateMember(newTermName("bar"))
+ val value = getValue(foo, bar)
+ println(value)
+} \ No newline at end of file