summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-05-16 21:08:41 +0000
committerPaul Phillips <paulp@improving.org>2011-05-16 21:08:41 +0000
commit806a524f9a3aedb850c604c7e2d0338b20459432 (patch)
tree4f7d7186df9e1879ca087e3dd5ce2fa6f014dfb9
parenta3d53243c6ac56d973d437cf16d4d235bb64141b (diff)
downloadscala-806a524f9a3aedb850c604c7e2d0338b20459432.tar.gz
scala-806a524f9a3aedb850c604c7e2d0338b20459432.tar.bz2
scala-806a524f9a3aedb850c604c7e2d0338b20459432.zip
Some largely self-contained utility classes int...
Some largely self-contained utility classes into common.util, no review.
-rw-r--r--src/compiler/scala/reflect/common/util/Chars.scala92
-rw-r--r--src/compiler/scala/reflect/common/util/HashSet.scala106
-rw-r--r--src/compiler/scala/reflect/common/util/Set.scala28
-rw-r--r--src/compiler/scala/reflect/common/util/StatBase.scala97
-rw-r--r--src/compiler/scala/reflect/common/util/Statistics.scala34
5 files changed, 357 insertions, 0 deletions
diff --git a/src/compiler/scala/reflect/common/util/Chars.scala b/src/compiler/scala/reflect/common/util/Chars.scala
new file mode 100644
index 0000000000..4175455f1f
--- /dev/null
+++ b/src/compiler/scala/reflect/common/util/Chars.scala
@@ -0,0 +1,92 @@
+/* NSC -- new Scala compiler
+ * Copyright 2006-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+package scala.reflect.common.util
+
+import annotation.{ tailrec, switch }
+import java.lang.{ Character => JCharacter }
+
+/** Contains constants and classifier methods for characters */
+trait Chars {
+ // Be very careful touching these.
+ // Apparently trivial changes to the way you write these constants
+ // will cause Scanners.scala to go from a nice efficient switch to
+ // a ghastly nested if statement which will bring the type checker
+ // to its knees. See ticket #1456
+ // Martin: (this should be verified now that the pattern rules have been redesigned).
+ final val LF = '\u000A'
+ final val FF = '\u000C'
+ final val CR = '\u000D'
+ final val SU = '\u001A'
+
+ /** Convert a character digit to an Int according to given base,
+ * -1 if no success */
+ def digit2int(ch: Char, base: Int): Int = {
+ if ('0' <= ch && ch <= '9' && ch < '0' + base)
+ ch - '0'
+ else if ('A' <= ch && ch < 'A' + base - 10)
+ ch - 'A' + 10
+ else if ('a' <= ch && ch < 'a' + base - 10)
+ ch - 'a' + 10
+ else
+ -1
+ }
+
+ /** Convert a character to a backslash-u escape */
+ def char2uescape(c: Char): String = {
+ var rest = c.toInt
+ val buf = new StringBuilder
+ for (i <- 1 to 4) {
+ buf ++= (rest % 16).toHexString
+ rest = rest / 16
+ }
+ "\\u" + buf.toString.reverse
+ }
+
+ /** Is character a line break? */
+ @inline def isLineBreakChar(c: Char) = (c: @switch) match {
+ case LF|FF|CR|SU => true
+ case _ => false
+ }
+
+ /** Is character a whitespace character (but not a new line)? */
+ def isWhitespace(c: Char) =
+ c == ' ' || c == '\t' || c == CR
+
+ /** Can character form part of a doc comment variable $xxx? */
+ def isVarPart(c: Char) =
+ '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
+
+ /** Can character start an alphanumeric Scala identifier? */
+ def isIdentifierStart(c: Char): Boolean =
+ (c == '_') || (c == '$') || Character.isUnicodeIdentifierStart(c)
+
+ /** Can character form part of an alphanumeric Scala identifier? */
+ def isIdentifierPart(c: Char) =
+ (c == '$') || Character.isUnicodeIdentifierPart(c)
+
+ /** Is character a math or other symbol in Unicode? */
+ def isSpecial(c: Char) = {
+ val chtp = Character.getType(c)
+ chtp == Character.MATH_SYMBOL.toInt || chtp == Character.OTHER_SYMBOL.toInt
+ }
+
+ private final val otherLetters = Set[Char]('\u0024', '\u005F') // '$' and '_'
+ private final val letterGroups = {
+ import JCharacter._
+ Set[Byte](LOWERCASE_LETTER, UPPERCASE_LETTER, OTHER_LETTER, TITLECASE_LETTER, LETTER_NUMBER)
+ }
+ def isScalaLetter(ch: Char) = letterGroups(JCharacter.getType(ch).toByte) || otherLetters(ch)
+
+ /** Can character form part of a Scala operator name? */
+ def isOperatorPart(c : Char) : Boolean = (c: @switch) match {
+ case '~' | '!' | '@' | '#' | '%' |
+ '^' | '*' | '+' | '-' | '<' |
+ '>' | '?' | ':' | '=' | '&' |
+ '|' | '/' | '\\' => true
+ case c => isSpecial(c)
+ }
+}
+
+object Chars extends Chars { }
diff --git a/src/compiler/scala/reflect/common/util/HashSet.scala b/src/compiler/scala/reflect/common/util/HashSet.scala
new file mode 100644
index 0000000000..53e7835418
--- /dev/null
+++ b/src/compiler/scala/reflect/common/util/HashSet.scala
@@ -0,0 +1,106 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect.common.util
+
+object HashSet {
+ def apply[T >: Null <: AnyRef](): HashSet[T] = this(16)
+ def apply[T >: Null <: AnyRef](label: String): HashSet[T] = this(label, 16)
+ def apply[T >: Null <: AnyRef](initialCapacity: Int): HashSet[T] = this("No Label", initialCapacity)
+ def apply[T >: Null <: AnyRef](label: String, initialCapacity: Int): HashSet[T] =
+ new HashSet[T](label, initialCapacity)
+}
+
+class HashSet[T >: Null <: AnyRef](val label: String, initialCapacity: Int) extends Set[T] {
+ private var used = 0
+ private var table = new Array[AnyRef](initialCapacity)
+ private def index(x: Int): Int = math.abs(x % table.length)
+
+ def size: Int = used
+ def clear() {
+ used = 0
+ table = new Array[AnyRef](initialCapacity)
+ }
+
+ def findEntryOrUpdate(x: T): T = {
+ var h = index(x.##)
+ var entry = table(h)
+ while (entry ne null) {
+ if (x == entry)
+ return entry.asInstanceOf[T]
+
+ h = index(h + 1)
+ entry = table(h)
+ }
+ table(h) = x
+ used += 1
+ if (used > (table.length >> 2)) growTable()
+ x
+ }
+
+ def findEntry(x: T): T = {
+ var h = index(x.##)
+ var entry = table(h)
+ while ((entry ne null) && x != entry) {
+ h = index(h + 1)
+ entry = table(h)
+ }
+ entry.asInstanceOf[T]
+ }
+
+ def addEntry(x: T) {
+ var h = index(x.##)
+ var entry = table(h)
+ while (entry ne null) {
+ if (x == entry) return
+ h = index(h + 1)
+ entry = table(h)
+ }
+ table(h) = x
+ used += 1
+ if (used > (table.length >> 2)) growTable()
+ }
+ def addEntries(xs: TraversableOnce[T]) {
+ xs foreach addEntry
+ }
+
+ def iterator = new Iterator[T] {
+ private var i = 0
+ def hasNext: Boolean = {
+ while (i < table.length && (table(i) eq null)) i += 1
+ i < table.length
+ }
+ def next: T =
+ if (hasNext) { i += 1; table(i - 1).asInstanceOf[T] }
+ else null
+ }
+
+ private def addOldEntry(x: T) {
+ var h = index(x.##)
+ var entry = table(h)
+ while (entry ne null) {
+ h = index(h + 1)
+ entry = table(h)
+ }
+ table(h) = x
+ }
+
+ private def growTable() {
+ val oldtable = table
+ val growthFactor =
+ if (table.length <= initialCapacity) 8
+ else if (table.length <= (initialCapacity * 8)) 4
+ else 2
+
+ table = new Array[AnyRef](table.length * growthFactor)
+ var i = 0
+ while (i < oldtable.length) {
+ val entry = oldtable(i)
+ if (entry ne null) addOldEntry(entry.asInstanceOf[T])
+ i += 1
+ }
+ }
+ override def toString() = "HashSet %s(%d / %d)".format(label, used, table.length)
+}
diff --git a/src/compiler/scala/reflect/common/util/Set.scala b/src/compiler/scala/reflect/common/util/Set.scala
new file mode 100644
index 0000000000..f4618e4432
--- /dev/null
+++ b/src/compiler/scala/reflect/common/util/Set.scala
@@ -0,0 +1,28 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+package scala.reflect.common.util
+
+/** A common class for lightweight sets.
+ */
+abstract class Set[T <: AnyRef] {
+
+ def findEntry(x: T): T
+
+ def addEntry(x: T): Unit
+
+ def iterator: Iterator[T]
+
+ def foreach[U](f: T => U): Unit = iterator foreach f
+
+ def apply(x: T): Boolean = contains(x)
+
+ @deprecated("use `iterator' instead", "2.9.0") def elements = iterator
+
+ def contains(x: T): Boolean =
+ findEntry(x) ne null
+
+ def toList = iterator.toList
+
+}
diff --git a/src/compiler/scala/reflect/common/util/StatBase.scala b/src/compiler/scala/reflect/common/util/StatBase.scala
new file mode 100644
index 0000000000..12083938b7
--- /dev/null
+++ b/src/compiler/scala/reflect/common/util/StatBase.scala
@@ -0,0 +1,97 @@
+package scala.reflect.common.util
+
+class StatBase {
+
+ private var _enabled = false
+
+ def enabled = _enabled
+ def enabled_=(cond: Boolean) = {
+ if (cond && !_enabled) {
+ val test = new Timer()
+ val start = System.nanoTime()
+ var total = 0L
+ for (i <- 1 to 10000) {
+ val time = System.nanoTime()
+ total += System.nanoTime() - time
+ }
+ val total2 = System.nanoTime() - start
+ println("Enabling statistics, measuring overhead = "+
+ total/10000.0+"ns to "+total2/10000.0+"ns per timer")
+ _enabled = true
+ }
+ }
+
+ def currentTime() =
+ if (_enabled) System.nanoTime() else 0L
+
+ def showPercent(x: Double, base: Double) =
+ if (base == 0) "" else " ("+"%2.1f".format(x / base * 100)+"%)"
+
+ def incCounter(c: Counter) {
+ if (_enabled) c.value += 1
+ }
+
+ def incCounter(c: Counter, delta: Int) {
+ if (_enabled) c.value += delta
+ }
+
+ def startCounter(sc: SubCounter): IntPair =
+ if (_enabled) sc.start() else null
+
+ def stopCounter(sc: SubCounter, start: IntPair) {
+ if (_enabled) sc.stop(start)
+ }
+
+ def startTimer(tm: Timer): LongPair =
+ if (_enabled) tm.start() else null
+
+ def stopTimer(tm: Timer, start: LongPair) {
+ if (_enabled) tm.stop(start)
+ }
+
+ case class IntPair(x: Int, y: Int)
+ case class LongPair(x: Long, y: Long)
+
+ class Counter {
+ var value: Int = 0
+ override def toString = value.toString
+ }
+
+ class SubCounter(c: Counter) {
+ var value: Int = 0
+ def start(): IntPair =
+ if (_enabled) IntPair(value, c.value) else null
+ def stop(prev: IntPair) {
+ if (_enabled) {
+ val IntPair(value0, cvalue0) = prev
+ value = value0 + c.value - cvalue0
+ }
+ }
+ override def toString =
+ value+showPercent(value, c.value)
+ }
+
+ class Timer {
+ var nanos: Long = 0
+ var timings = 0
+ def start(): LongPair =
+ if (_enabled) {
+ timings += 1
+ LongPair(nanos, System.nanoTime())
+ } else null
+ def stop(prev: LongPair) {
+ if (_enabled) {
+ val LongPair(nanos0, start) = prev
+ nanos = nanos0 + System.nanoTime() - start
+ timings += 1
+ }
+ }
+ override def toString = (timings/2)+" spans, "+nanos.toString+"ns"
+ }
+
+ import Predef.Class
+
+ class ClassCounts extends scala.collection.mutable.HashMap[Class[_], Int] {
+ override def default(key: Class[_]) = 0
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/common/util/Statistics.scala b/src/compiler/scala/reflect/common/util/Statistics.scala
new file mode 100644
index 0000000000..85a02c9f37
--- /dev/null
+++ b/src/compiler/scala/reflect/common/util/Statistics.scala
@@ -0,0 +1,34 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+package scala.reflect.common.util
+
+class Statistics extends StatBase {
+ val singletonBaseTypeSeqCount = new Counter
+ val compoundBaseTypeSeqCount = new Counter
+ val typerefBaseTypeSeqCount = new Counter
+ val findMemberCount = new Counter
+ val noMemberCount = new Counter
+ val multMemberCount = new Counter
+ val findMemberNanos = new Timer
+ val asSeenFromCount = new Counter
+ val asSeenFromNanos = new Timer
+ val subtypeCount = new Counter
+ val subtypeNanos = new Timer
+ val sametypeCount = new Counter
+ val rawTypeCount = new Counter
+ val rawTypeFailed = new SubCounter(rawTypeCount)
+ val findMemberFailed = new SubCounter(findMemberCount)
+ val subtypeFailed = new SubCounter(subtypeCount)
+ val rawTypeImpl = new SubCounter(rawTypeCount)
+ val findMemberImpl = new SubCounter(findMemberCount)
+ val subtypeImpl = new SubCounter(subtypeCount)
+ val baseTypeSeqCount = new Counter
+ val baseTypeSeqLenTotal = new Counter
+ val typeSymbolCount = new Counter
+ val classSymbolCount = new Counter
+}
+
+object Statistics extends Statistics
+