summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-09-09 22:18:54 +0000
committerPaul Phillips <paulp@improving.org>2009-09-09 22:18:54 +0000
commitc71af41d6ae8dd156ffbb9e5d82890047c33bb7f (patch)
tree5281532ab0d655eea5c79d625d501f57eb5420de /src/compiler
parentbc489c725eb256bc39b555cdf7e6966aa8a8b0a3 (diff)
downloadscala-c71af41d6ae8dd156ffbb9e5d82890047c33bb7f.tar.gz
scala-c71af41d6ae8dd156ffbb9e5d82890047c33bb7f.tar.bz2
scala-c71af41d6ae8dd156ffbb9e5d82890047c33bb7f.zip
Generalized -Xdisable-assertions into an annota...
Generalized -Xdisable-assertions into an annotation (presently called @elidable) so it can be used with arbitrary code. It takes an argument which sets its priority level, and you can control what code is elided from the command line by setting -Xelide-level to desired threshold.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala60
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala10
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala10
4 files changed, 52 insertions, 29 deletions
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index 3225a62049..2452b3adbf 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -10,6 +10,7 @@ import java.io.File
import io.AbstractFile
import util.SourceFile
import Settings._
+import annotation.elidable
class Settings(errorFn: String => Unit) extends ScalacSettings {
def this() = this(Console.println)
@@ -316,8 +317,14 @@ object Settings {
def str(name: String, arg: String, descr: String, default: String) =
new StringSetting(name, arg, descr, default)
- def sint(name: String, descr: String, default: Int, min: Option[Int], max: Option[Int]) =
- new IntSetting(name, descr, default, min, max)
+ def sint(
+ name: String,
+ descr: String,
+ default: Int,
+ range: Option[(Int, Int)] = None,
+ parser: String => Option[Int] = _ => None
+ ) =
+ new IntSetting(name, descr, default, range, parser)
def multi(name: String, arg: String, descr: String) =
new MultiStringSetting(name, arg, descr)
@@ -413,53 +420,55 @@ object Settings {
override def toString() = "%s = %s".format(name, value)
}
- /** A setting represented by a positive integer */
+ /** A setting represented by an integer */
class IntSetting private[Settings](
val name: String,
val descr: String,
val default: Int,
- val min: Option[Int],
- val max: Option[Int])
+ val range: Option[(Int, Int)],
+ parser: String => Option[Int])
extends Setting(descr) {
type T = Int
protected var v = default
+
+ // not stable values!
+ val IntMin = Int.MinValue
+ val IntMax = Int.MaxValue
+ def min = range map (_._1) getOrElse IntMin
+ def max = range map (_._2) getOrElse IntMax
+
override def value_=(s: Int) =
if (isInputValid(s)) super.value_=(s) else errorMsg
// Validate that min and max are consistent
- (min, max) match {
- case (Some(i), Some(j)) => assert(i <= j)
- case _ => ()
- }
+ assert(min <= max)
// Helper to validate an input
- private def isInputValid(k: Int): Boolean = (min, max) match {
- case (Some(i), Some(j)) => (i <= k) && (k <= j)
- case (Some(i), None) => (i <= k)
- case (None, Some(j)) => (k <= j)
- case _ => true
- }
+ private def isInputValid(k: Int): Boolean = (min <= k) && (k <= max)
// Helper to generate a textual explaination of valid inputs
private def getValidText: String = (min, max) match {
- case (Some(i), Some(j)) => "must be between "+i+" and "+j
- case (Some(i), None) => "must be greater than or equal to "+i
- case (None, Some(j)) => "must be less than or equal to "+j
- case _ => throw new Error("this should never be used")
+ case (IntMin, IntMax) => "can be any integer"
+ case (IntMin, x) => "must be less than or equal to "+x
+ case (x, IntMax) => "must be greater than or equal to "+x
+ case _ => "must be between %d and %d".format(min, max)
}
// Ensure that the default value is actually valid
assert(isInputValid(default))
- def parseInt(x: String): Option[Int] =
- try { Some(x.toInt) }
- catch { case _: NumberFormatException => None }
+ def parseArgument(x: String): Option[Int] = {
+ parser(x) orElse {
+ try { Some(x.toInt) }
+ catch { case _: NumberFormatException => None }
+ }
+ }
def errorMsg = errorFn("invalid setting for -"+name+" "+getValidText)
def tryToSet(args: List[String]) =
if (args.isEmpty) errorAndValue("missing argument", None)
- else parseInt(args.head) match {
+ else parseArgument(args.head) match {
case Some(i) => value = i ; Some(args.tail)
case None => errorMsg ; None
}
@@ -740,7 +749,8 @@ trait ScalacSettings {
val assemrefs = StringSetting ("-Xassem-path", "path", "List of assemblies referenced by the program (only relevant with -target:msil)", ".").dependsOn(target, "msil")
val Xchecknull = BooleanSetting ("-Xcheck-null", "Emit warning on selection of nullable reference")
val checkInit = BooleanSetting ("-Xcheckinit", "Add runtime checks on field accessors. Uninitialized accesses result in an exception being thrown.")
- val noassertions = BooleanSetting ("-Xdisable-assertions", "Generate no assertions and assumptions")
+ val elideLevel = IntSetting ("-Xelide-level", "Generate calls to @elidable-marked methods only method priority is greater than argument.",
+ elidable.ASSERTION, None, elidable.byName.get(_))
val Xexperimental = BooleanSetting ("-Xexperimental", "Enable experimental extensions")
val noForwarders = BooleanSetting ("-Xno-forwarders", "Do not generate static forwarders in mirror classes")
val future = BooleanSetting ("-Xfuture", "Turn on future language features")
@@ -787,7 +797,7 @@ trait ScalacSettings {
val Ynogenericsig = BooleanSetting ("-Yno-generic-signatures", "Suppress generation of generic signatures for Java")
val noimports = BooleanSetting ("-Yno-imports", "Compile without any implicit imports")
val nopredefs = BooleanSetting ("-Yno-predefs", "Compile without any implicit predefined values")
- val Yrecursion = IntSetting ("-Yrecursion", "Recursion depth used when locking symbols", 0, Some(0), None)
+ val Yrecursion = IntSetting ("-Yrecursion", "Recursion depth used when locking symbols", 0, Some(0, Int.MaxValue), _ => None)
val selfInAnnots = BooleanSetting ("-Yself-in-annots", "Include a \"self\" identifier inside of annotations")
val Xshowtrees = BooleanSetting ("-Yshow-trees", "Show detailed trees when used in connection with -print:phase")
val skip = PhasesSetting ("-Yskip", "Skip")
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 87c874465a..6f44541098 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -96,6 +96,7 @@ trait Definitions {
lazy val TailrecClass = getClass("scala.annotation.tailrec")
lazy val SwitchClass = getClass("scala.annotation.switch")
lazy val ExperimentalClass = getClass("scala.annotation.experimental")
+ lazy val ElidableMethodClass = getClass("scala.annotation.elidable")
// fundamental reference classes
lazy val ScalaObjectClass = getClass("scala.ScalaObject")
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index b4a2ca9853..745782fbdf 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -441,6 +441,16 @@ trait Symbols {
None
}
}
+ def elisionLevel: Option[Int] = {
+ if (!hasAnnotation(ElidableMethodClass)) None
+ else annotations find (_.atp.typeSymbol == ElidableMethodClass) flatMap { annot =>
+ // since we default to enabled by default, only look hard for falsity
+ annot.args match {
+ case Literal(Constant(x: Int)) :: Nil => Some(x)
+ case x => println(x) ; None
+ }
+ }
+ }
/** Does this symbol denote a wrapper object of the interpreter or its class? */
final def isInterpreterWrapper =
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 7af0c4f56c..32a66c321f 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -543,10 +543,12 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
treeCopy.UnApply(tree, fn1, args1)
case Apply(fn, args) =>
- if (settings.noassertions.value &&
- (fn.symbol ne null) &&
- (fn.symbol.name == nme.assert_ || fn.symbol.name == nme.assume_) &&
- fn.symbol.owner == PredefModule.moduleClass) {
+ def elideFunctionCall(sym: Symbol) =
+ sym != null && (sym.elisionLevel match {
+ case Some(x) => x < settings.elideLevel.value
+ case _ => false
+ })
+ if (elideFunctionCall(fn.symbol)) {
Literal(()).setPos(tree.pos).setType(UnitClass.tpe)
} else if (fn.symbol == Object_synchronized && shouldBeLiftedAnyway(args.head)) {
transform(treeCopy.Apply(tree, fn, List(liftTree(args.head))))