aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-03-14 18:41:55 +0100
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2014-03-20 12:47:39 +0100
commitbff6b093d28bfc6918fa86d640353ba60b1a24e4 (patch)
tree0dac2d76ae4f92053d3793fd2d110b2636ccf4e6
parent2df29a28c8e0b2e36a341f5f969b00aee727b188 (diff)
downloaddotty-bff6b093d28bfc6918fa86d640353ba60b1a24e4.tar.gz
dotty-bff6b093d28bfc6918fa86d640353ba60b1a24e4.tar.bz2
dotty-bff6b093d28bfc6918fa86d640353ba60b1a24e4.zip
Add language feature mechanism
Add a method "featureEnabled" that checks whether a feature is enabled. Features can be enabled by imports or by command-line options. The Scala 2.10 way of enabling features by implicits got dropped, because the use of the feature mechanism is now different. Previously, features imposed restrictions on what used to work. So it was important to offer way to avoid the restrictions it that was as smooth as possible, and implicits fit the bill. Furthermore, features did not change the way things were compiled, so it was OK to test them only once all types were compiled. Now, features are essentially switches that change compile time behavior. keepUnions and noAutoTupling, if on, will modify the way type inference works. So we need to interprete a switch on the spot, and doing an implicit search to determine a switch value is too dangerous in what concerns causing cyclic references. At the same time, because we are dealing with new functionality, there is less of a concern for being able to set or reset features for large pieces of code with some implicit. You could argue that's not even desirable, and that an explicit import or command line option is preferable. Conflicts: src/dotty/tools/dotc/core/SymDenotations.scala
-rw-r--r--src/dotty/language.scala16
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala1
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala3
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala14
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala34
5 files changed, 67 insertions, 1 deletions
diff --git a/src/dotty/language.scala b/src/dotty/language.scala
new file mode 100644
index 000000000..169b2604c
--- /dev/null
+++ b/src/dotty/language.scala
@@ -0,0 +1,16 @@
+package dotty
+
+object language {
+
+ class Feature
+
+ /** Allow higher-kinded type syntax (not yet checked) */
+ val higherKinds = new Feature
+
+ /** Keep union types */
+ val keepUnions = new Feature
+
+ /** No auto tupling */
+ val noAutoTupling = new Feature
+
+} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 5f6698b33..5c2890f29 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -215,6 +215,7 @@ class Definitions {
lazy val JavaSerializableClass = ctx.requiredClass("java.lang.Serializable")
lazy val ComparableClass = ctx.requiredClass("java.lang.Comparable")
lazy val ProductClass = ctx.requiredClass("scala.Product")
+ lazy val LanguageModuleClass = ctx.requiredModule("dotty.language").moduleClass
// Annotation base classes
lazy val AnnotationClass = ctx.requiredClass("scala.annotation.Annotation")
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index 0cbcfa5a7..6cd9da4b5 100644
--- a/src/dotty/tools/dotc/core/StdNames.scala
+++ b/src/dotty/tools/dotc/core/StdNames.scala
@@ -375,6 +375,7 @@ object StdNames {
val hashCode_ : N = "hashCode"
val hash_ : N = "hash"
val head: N = "head"
+ val higherKinds: N = "higherKinds"
val identity: N = "identity"
val implicitly: N = "implicitly"
val in: N = "in"
@@ -387,6 +388,7 @@ object StdNames {
val isInstanceOf_ : N = "isInstanceOf"
val isInstanceOf_Ob : N = "$isInstanceOf"
val java: N = "java"
+ val keepUnions: N = "keepUnions"
val key: N = "key"
val lang: N = "lang"
val length: N = "length"
@@ -415,6 +417,7 @@ object StdNames {
val next: N = "next"
val nmeNewTermName: N = "newTermName"
val nmeNewTypeName: N = "newTypeName"
+ val noAutoTupling: N = "noAutoTupling"
val normalize: N = "normalize"
val notifyAll_ : N = "notifyAll"
val notify_ : N = "notify"
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 08566e3db..362738caf 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -9,7 +9,7 @@ import collection.mutable
import collection.immutable.BitSet
import scala.reflect.io.AbstractFile
import Decorators.SymbolIteratorDecorator
-import ast.tpd
+import ast._
import annotation.tailrec
import util.SimpleMap
import util.Stats
@@ -195,6 +195,18 @@ object SymDenotations {
final def hasAnnotation(cls: Symbol)(implicit ctx: Context) =
dropOtherAnnotations(annotations, cls).nonEmpty
+ /** Optionally, the arguments of the first annotation matching the given class symbol */
+ final def getAnnotationArgs(cls: Symbol)(implicit ctx: Context): Option[List[tpd.Tree]] =
+ dropOtherAnnotations(annotations, cls) match {
+ case annot :: _ =>
+ Some(
+ annot.tree match {
+ case Trees.Apply(_, args) => args
+ case _ => Nil
+ })
+ case nil => None
+ }
+
/** Add given annotation to the annotations of this denotation */
final def addAnnotation(annot: Annotation): Unit =
annotations = annot :: myAnnotations
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index 152f8d1b7..4ace0bebe 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -266,6 +266,40 @@ trait TypeOps { this: Context =>
}
parentRefs
}
+
+ /** Is `feature` enabled in class `owner`?
+ * This is the case if one of the following two alternatives holds:
+ *
+ * 1. The feature is imported by a named import
+ *
+ * import owner.feature
+ *
+ * (the feature may be bunched with others, or renamed, but wildcard imports
+ * don't count).
+ *
+ * 2. The feature is enabled by a compiler option
+ *
+ * - language:<prefix>feature
+ *
+ * where <prefix> is the full name of the owner followed by a "." minus
+ * the prefix "dotty.language.".
+ */
+ def featureEnabled(owner: ClassSymbol, feature: TermName): Boolean = {
+ def toPrefix(sym: Symbol): String =
+ if (sym eq defn.LanguageModuleClass) "" else toPrefix(sym.owner) + sym.name + "."
+ def featureName = toPrefix(owner) + feature
+ def hasImport(implicit ctx: Context): Boolean = (
+ ctx.importInfo != null
+ && ( (ctx.importInfo.site.widen.typeSymbol eq owner)
+ && ctx.importInfo.originals.contains(feature)
+ ||
+ { var c = ctx.outer
+ while (c.importInfo eq ctx.importInfo) c = c.outer
+ hasImport(c)
+ }))
+ def hasOption = ctx.base.settings.language.value exists (s => s == featureName || s == "_")
+ hasImport || hasOption
+ }
}
object TypeOps {