Skip to content

Commit

Permalink
preparations: always explicitly provide type tags
Browse files Browse the repository at this point in the history
In our codebase we now explicitly provide type tags even if they can be materialized.
This is necessary to ease the upcoming reflection refactoring (or refactorings :)).
  • Loading branch information
xeno-by committed Jun 8, 2012
1 parent 3a19897 commit 8ce4787
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 10 deletions.
14 changes: 7 additions & 7 deletions src/compiler/scala/tools/cmd/FromString.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package scala.tools
package cmd package cmd


import nsc.io.{ Path, File, Directory } import nsc.io.{ Path, File, Directory }
import scala.reflect.TypeTag import scala.tools.reflect.StdTags._


/** A general mechanism for defining how a command line argument /** A general mechanism for defining how a command line argument
* (always a String) is transformed into an arbitrary type. A few * (always a String) is transformed into an arbitrary type. A few
Expand All @@ -29,19 +29,19 @@ object FromString {


/** Path related stringifiers. /** Path related stringifiers.
*/ */
val ExistingFile: FromString[File] = new FromString[File] { val ExistingFile: FromString[File] = new FromString[File]()(tagOfFile) {
override def isDefinedAt(s: String) = toFile(s).isFile override def isDefinedAt(s: String) = toFile(s).isFile
def apply(s: String): File = def apply(s: String): File =
if (isDefinedAt(s)) toFile(s) if (isDefinedAt(s)) toFile(s)
else cmd.runAndExit(println("'%s' is not an existing file." format s)) else cmd.runAndExit(println("'%s' is not an existing file." format s))
} }
val ExistingDir: FromString[Directory] = new FromString[Directory] { val ExistingDir: FromString[Directory] = new FromString[Directory]()(tagOfDirectory) {
override def isDefinedAt(s: String) = toDir(s).isDirectory override def isDefinedAt(s: String) = toDir(s).isDirectory
def apply(s: String): Directory = def apply(s: String): Directory =
if (isDefinedAt(s)) toDir(s) if (isDefinedAt(s)) toDir(s)
else cmd.runAndExit(println("'%s' is not an existing directory." format s)) else cmd.runAndExit(println("'%s' is not an existing directory." format s))
} }
def ExistingDirRelativeTo(root: Directory) = new FromString[Directory] { def ExistingDirRelativeTo(root: Directory) = new FromString[Directory]()(tagOfDirectory) {
private def resolve(s: String) = toDir(s) toAbsoluteWithRoot root toDirectory private def resolve(s: String) = toDir(s) toAbsoluteWithRoot root toDirectory
override def isDefinedAt(s: String) = resolve(s).isDirectory override def isDefinedAt(s: String) = resolve(s).isDirectory
def apply(s: String): Directory = def apply(s: String): Directory =
Expand All @@ -52,19 +52,19 @@ object FromString {
/** Argument expander, i.e. turns single argument "foo bar baz" into argument /** Argument expander, i.e. turns single argument "foo bar baz" into argument
* list "foo", "bar", "baz". * list "foo", "bar", "baz".
*/ */
val ArgumentsFromString: FromString[List[String]] = new FromString[List[String]] { val ArgumentsFromString: FromString[List[String]] = new FromString[List[String]]()(tagOfListOfString) {
def apply(s: String) = toArgs(s) def apply(s: String) = toArgs(s)
} }


/** Identity. /** Identity.
*/ */
implicit val StringFromString: FromString[String] = new FromString[String] { implicit val StringFromString: FromString[String] = new FromString[String]()(tagOfString) {
def apply(s: String): String = s def apply(s: String): String = s
} }


/** Implicit as the most likely to be useful as-is. /** Implicit as the most likely to be useful as-is.
*/ */
implicit val IntFromString: FromString[Int] = new FromString[Int] { implicit val IntFromString: FromString[Int] = new FromString[Int]()(tagOfInt) {
override def isDefinedAt(s: String) = safeToInt(s).isDefined override def isDefinedAt(s: String) = safeToInt(s).isDefined
def apply(s: String) = safeToInt(s).get def apply(s: String) = safeToInt(s).get
def safeToInt(s: String): Option[Int] = try Some(java.lang.Integer.parseInt(s)) catch { case _: NumberFormatException => None } def safeToInt(s: String): Option[Int] = try Some(java.lang.Integer.parseInt(s)) catch { case _: NumberFormatException => None }
Expand Down
5 changes: 3 additions & 2 deletions src/compiler/scala/tools/nsc/interpreter/ILoop.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import util.ScalaClassLoader
import ScalaClassLoader._ import ScalaClassLoader._
import scala.tools.util._ import scala.tools.util._
import language.{implicitConversions, existentials} import language.{implicitConversions, existentials}
import scala.tools.reflect.StdTags._


/** The Scala interactive shell. It provides a read-eval-print loop /** The Scala interactive shell. It provides a read-eval-print loop
* around the Interpreter class. * around the Interpreter class.
Expand Down Expand Up @@ -105,7 +106,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
} }


def isAsync = !settings.Yreplsync.value def isAsync = !settings.Yreplsync.value
lazy val power = new Power(intp, new StdReplVals(this)) lazy val power = new Power(intp, new StdReplVals(this))(tagOfStdReplVals)
def history = in.history def history = in.history


/** The context class loader at the time this object was created */ /** The context class loader at the time this object was created */
Expand Down Expand Up @@ -830,7 +831,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
} }
// Bind intp somewhere out of the regular namespace where // Bind intp somewhere out of the regular namespace where
// we can get at it in generated code. // we can get at it in generated code.
addThunk(intp.quietBind("$intp" -> intp)) addThunk(intp.quietBind(NamedParam[IMain]("$intp", intp)(tagOfIMain)))
addThunk({ addThunk({
import scala.tools.nsc.io._ import scala.tools.nsc.io._
import Properties.userHome import Properties.userHome
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/scala/tools/nsc/interpreter/IMain.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import IMain._
import java.util.concurrent.Future import java.util.concurrent.Future
import typechecker.Analyzer import typechecker.Analyzer
import language.implicitConversions import language.implicitConversions
import scala.tools.reflect.StdTags._


/** directory to save .class files to */ /** directory to save .class files to */
private class ReplVirtualDirectory(out: JPrintWriter) extends VirtualDirectory("(memory)", None) { private class ReplVirtualDirectory(out: JPrintWriter) extends VirtualDirectory("(memory)", None) {
Expand Down Expand Up @@ -717,7 +718,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends


val unwrapped = unwrap(t) val unwrapped = unwrap(t)
withLastExceptionLock[String]({ withLastExceptionLock[String]({
directBind[Throwable]("lastException", unwrapped) directBind[Throwable]("lastException", unwrapped)(classTag[Throwable])
util.stackTraceString(unwrapped) util.stackTraceString(unwrapped)
}, util.stackTraceString(unwrapped)) }, util.stackTraceString(unwrapped))
} }
Expand Down
26 changes: 26 additions & 0 deletions src/compiler/scala/tools/reflect/StdTags.scala
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,26 @@
package scala.tools
package reflect

import java.lang.{Class => jClass}
import scala.reflect.mirror._

// [Eugene++] Before 2.10 is released, I suggest we don't rely on automated type tag generation
// sure, it's convenient, but then refactoring reflection / reification becomes a pain
// `ClassTag` tags are fine, because they don't need a reifier to be generated

object StdTags {
lazy val tagOfString = TypeTag.String
lazy val tagOfListOfString = TypeTag[List[String]]({
val pre = ThisType(staticModule("scala.collection.immutable").moduleClass)
TypeRef(pre, definitions.ListClass, List(definitions.StringClass.asTypeConstructor))
}, classOf[List[String]])

private def tagOfStaticClass[T: ClassTag] = TypeTag[T](staticClass(classTag[T].erasure.getName).asTypeConstructor, classTag[T].erasure)
lazy val tagOfInt = TypeTag.Int
lazy val tagOfFile = tagOfStaticClass[scala.tools.nsc.io.File]
lazy val tagOfDirectory = tagOfStaticClass[scala.tools.nsc.io.Directory]
lazy val tagOfStdReplVals = tagOfStaticClass[scala.tools.nsc.interpreter.StdReplVals]
lazy val tagOfIMain = tagOfStaticClass[scala.tools.nsc.interpreter.IMain]
lazy val tagOfThrowable = tagOfStaticClass[java.lang.Throwable]
lazy val tagOfClassLoader = tagOfStaticClass[java.lang.ClassLoader]
}

0 comments on commit 8ce4787

Please sign in to comment.