aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-02-01 17:52:00 +0100
committerMartin Odersky <odersky@gmail.com>2013-02-01 17:52:00 +0100
commitabc8f5e1c382b1ead761976227878c4c38ebfbf5 (patch)
treeb135a1bd0945f375e256af8e4ddfbd818c567865 /src/dotty/tools/dotc
parent5610fe1abbb8e4cb005d644f37669f872327828b (diff)
downloaddotty-abc8f5e1c382b1ead761976227878c4c38ebfbf5.tar.gz
dotty-abc8f5e1c382b1ead761976227878c4c38ebfbf5.tar.bz2
dotty-abc8f5e1c382b1ead761976227878c4c38ebfbf5.zip
Added config package with settings, platform.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/config/JavaPlatform.scala75
-rw-r--r--src/dotty/tools/dotc/config/PathResolver.scala271
-rw-r--r--src/dotty/tools/dotc/config/Platform.scala38
-rw-r--r--src/dotty/tools/dotc/config/Properties.scala165
-rw-r--r--src/dotty/tools/dotc/config/Settings.scala26
-rw-r--r--src/dotty/tools/dotc/config/WrappedProperties.scala34
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala14
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala2
-rw-r--r--src/dotty/tools/dotc/core/NameOps.scala63
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala2
-rw-r--r--src/dotty/tools/dotc/core/SymbolLoaders.scala107
11 files changed, 697 insertions, 100 deletions
diff --git a/src/dotty/tools/dotc/config/JavaPlatform.scala b/src/dotty/tools/dotc/config/JavaPlatform.scala
new file mode 100644
index 000000000..3c6ea3a8a
--- /dev/null
+++ b/src/dotty/tools/dotc/config/JavaPlatform.scala
@@ -0,0 +1,75 @@
+package dotty.tools
+package dotc
+package config
+
+import io.{AbstractFile,ClassPath,JavaClassPath,MergedClassPath,DeltaClassPath}
+import ClassPath.{ JavaContext, DefaultJavaContext }
+
+trait JavaPlatform /*extends Platform {
+ import global._
+ import definitions._
+
+ type BinaryRepr = AbstractFile
+
+ private var currentClassPath: Option[MergedClassPath[BinaryRepr]] = None
+
+ def classPath: ClassPath[BinaryRepr] = {
+ if (currentClassPath.isEmpty) currentClassPath = Some(new PathResolver(settings).result)
+ currentClassPath.get
+ }
+
+ /** Update classpath with a substituted subentry */
+ def updateClassPath(subst: Map[ClassPath[BinaryRepr], ClassPath[BinaryRepr]]) =
+ currentClassPath = Some(new DeltaClassPath(currentClassPath.get, subst))
+
+ def rootLoader = new loaders.PackageLoader(classPath.asInstanceOf[ClassPath[platform.BinaryRepr]])
+ // [Martin] Why do we need a cast here?
+ // The problem is that we cannot specify at this point that global.platform should be of type JavaPlatform.
+ // So we cannot infer that global.platform.BinaryRepr is AbstractFile.
+ // Ideally, we should be able to write at the top of the JavaPlatform trait:
+ // val global: Global { val platform: JavaPlatform }
+ // import global._
+ // Right now, this does nothing because the concrete definition of platform in Global
+ // replaces the tighter abstract definition here. If we had DOT typing rules, the two
+ // types would be conjoined and everything would work out. Yet another reason to push for DOT.
+
+ private def depAnalysisPhase =
+ if (settings.make.isDefault) Nil
+ else List(dependencyAnalysis)
+
+ private def classEmitPhase =
+ if (settings.target.value == "jvm-1.5-fjbg") genJVM
+ else genASM
+
+ def platformPhases = List(
+ flatten, // get rid of inner classes
+ classEmitPhase // generate .class files
+ ) ++ depAnalysisPhase
+
+ lazy val externalEquals = getDecl(BoxesRunTimeClass, nme.equals_)
+ lazy val externalEqualsNumNum = getDecl(BoxesRunTimeClass, nme.equalsNumNum)
+ lazy val externalEqualsNumChar = getDecl(BoxesRunTimeClass, nme.equalsNumChar)
+ lazy val externalEqualsNumObject = getDecl(BoxesRunTimeClass, nme.equalsNumObject)
+
+ /** We could get away with excluding BoxedBooleanClass for the
+ * purpose of equality testing since it need not compare equal
+ * to anything but other booleans, but it should be present in
+ * case this is put to other uses.
+ */
+ def isMaybeBoxed(sym: Symbol) = {
+ (sym == ObjectClass) ||
+ (sym == JavaSerializableClass) ||
+ (sym == ComparableClass) ||
+ (sym isNonBottomSubClass BoxedNumberClass) ||
+ (sym isNonBottomSubClass BoxedCharacterClass) ||
+ (sym isNonBottomSubClass BoxedBooleanClass)
+ }
+
+ def newClassLoader(bin: AbstractFile): loaders.SymbolLoader =
+ new loaders.ClassfileLoader(bin)
+
+ def doLoad(cls: ClassPath[BinaryRepr]#ClassRep): Boolean = true
+
+ def needCompile(bin: AbstractFile, src: AbstractFile) =
+ src.lastModified >= bin.lastModified
+}*/
diff --git a/src/dotty/tools/dotc/config/PathResolver.scala b/src/dotty/tools/dotc/config/PathResolver.scala
new file mode 100644
index 000000000..6771e1465
--- /dev/null
+++ b/src/dotty/tools/dotc/config/PathResolver.scala
@@ -0,0 +1,271 @@
+package dotty.tools
+package dotc
+package config
+
+import java.net.{ URL, MalformedURLException }
+import WrappedProperties.AccessControl
+import io.{ ClassPath, JavaClassPath, File, Directory, Path, AbstractFile }
+import ClassPath.{ JavaContext, DefaultJavaContext, join, split }
+import PartialFunction.condOpt
+import scala.language.postfixOps
+
+// Loosely based on the draft specification at:
+// https://wiki.scala-lang.org/display/SW/Classpath
+
+object PathResolver {
+
+ /*
+ // Imports property/environment functions which suppress
+ // security exceptions.
+ import AccessControl._
+
+ def firstNonEmpty(xs: String*) = xs find (_ != "") getOrElse ""
+
+ /** Map all classpath elements to absolute paths and reconstruct the classpath.
+ */
+ def makeAbsolute(cp: String) = ClassPath.map(cp, x => Path(x).toAbsolute.path)
+
+ /** pretty print class path */
+ def ppcp(s: String) = split(s) match {
+ case Nil => ""
+ case Seq(x) => x
+ case xs => xs map ("\n" + _) mkString
+ }
+
+ /** Values found solely by inspecting environment or property variables.
+ */
+ object Environment {
+ private def searchForBootClasspath = (
+ systemProperties find (_._1 endsWith ".boot.class.path") map (_._2) getOrElse ""
+ )
+
+ /** Environment variables which java pays attention to so it
+ * seems we do as well.
+ */
+ def classPathEnv = envOrElse("CLASSPATH", "")
+ def sourcePathEnv = envOrElse("SOURCEPATH", "")
+
+ def javaBootClassPath = propOrElse("sun.boot.class.path", searchForBootClasspath)
+ def javaExtDirs = propOrEmpty("java.ext.dirs")
+ def scalaHome = propOrEmpty("scala.home")
+ def scalaExtDirs = propOrEmpty("scala.ext.dirs")
+
+ /** The java classpath and whether to use it. */
+ def javaUserClassPath = propOrElse("java.class.path", "")
+ def useJavaClassPath = propOrFalse("scala.usejavacp")
+
+ override def toString = """
+ |object Environment {
+ | scalaHome = %s (useJavaClassPath = %s)
+ | javaBootClassPath = <%d chars>
+ | javaExtDirs = %s
+ | javaUserClassPath = %s
+ | scalaExtDirs = %s
+ |}""".trim.stripMargin.format(
+ scalaHome, useJavaClassPath,
+ javaBootClassPath.length,
+ ppcp(javaExtDirs),
+ ppcp(javaUserClassPath),
+ ppcp(scalaExtDirs)
+ )
+ }
+
+ /** Default values based on those in Environment as interpreted according
+ * to the path resolution specification.
+ */
+ object Defaults {
+ def scalaSourcePath = Environment.sourcePathEnv
+ def javaBootClassPath = Environment.javaBootClassPath
+ def javaUserClassPath = Environment.javaUserClassPath
+ def javaExtDirs = Environment.javaExtDirs
+ def useJavaClassPath = Environment.useJavaClassPath
+
+ def scalaHome = Environment.scalaHome
+ def scalaHomeDir = Directory(scalaHome)
+ def scalaHomeExists = scalaHomeDir.isDirectory
+ def scalaLibDir = Directory(scalaHomeDir / "lib")
+ def scalaClassesDir = Directory(scalaHomeDir / "classes")
+
+ def scalaLibAsJar = File(scalaLibDir / "scala-library.jar")
+ def scalaLibAsDir = Directory(scalaClassesDir / "library")
+
+ def scalaLibDirFound: Option[Directory] =
+ if (scalaLibAsJar.isFile) Some(scalaLibDir)
+ else if (scalaLibAsDir.isDirectory) Some(scalaClassesDir)
+ else None
+
+ def scalaLibFound =
+ if (scalaLibAsJar.isFile) scalaLibAsJar.path
+ else if (scalaLibAsDir.isDirectory) scalaLibAsDir.path
+ else ""
+
+ // XXX It must be time for someone to figure out what all these things
+ // are intended to do. This is disabled here because it was causing all
+ // the scala jars to end up on the classpath twice: one on the boot
+ // classpath as set up by the runner (or regular classpath under -nobootcp)
+ // and then again here.
+ def scalaBootClassPath = ""
+ // scalaLibDirFound match {
+ // case Some(dir) if scalaHomeExists =>
+ // val paths = ClassPath expandDir dir.path
+ // join(paths: _*)
+ // case _ => ""
+ // }
+
+ def scalaExtDirs = Environment.scalaExtDirs
+
+ def scalaPluginPath = (scalaHomeDir / "misc" / "scala-devel" / "plugins").path
+
+ override def toString = """
+ |object Defaults {
+ | scalaHome = %s
+ | javaBootClassPath = %s
+ | scalaLibDirFound = %s
+ | scalaLibFound = %s
+ | scalaBootClassPath = %s
+ | scalaPluginPath = %s
+ |}""".trim.stripMargin.format(
+ scalaHome,
+ ppcp(javaBootClassPath),
+ scalaLibDirFound, scalaLibFound,
+ ppcp(scalaBootClassPath), ppcp(scalaPluginPath)
+ )
+ }
+
+ def fromPathString(path: String, context: JavaContext = DefaultJavaContext): JavaClassPath = {
+ val s = new Settings() {
+ classpath = path
+ }
+ new PathResolver(s, context) result
+ }
+
+ /** With no arguments, show the interesting values in Environment and Defaults.
+ * If there are arguments, show those in Calculated as if those options had been
+ * given to a scala runner.
+ */
+ def main(args: Array[String]): Unit = {
+ if (args.isEmpty) {
+ println(Environment)
+ println(Defaults)
+ }
+ else {
+ val settings = new Settings()
+ val rest = settings.processArguments(args.toList, false)._2
+ val pr = new PathResolver(settings)
+ println(" COMMAND: 'scala %s'".format(args.mkString(" ")))
+ println("RESIDUAL: 'scala %s'\n".format(rest.mkString(" ")))
+ pr.result.show
+ }
+ }
+}
+import PathResolver.{ Defaults, Environment, firstNonEmpty, ppcp }
+
+class PathResolver(settings: Settings, context: JavaContext = DefaultJavaContext) {
+
+ private def cmdLineOrElse(name: String, alt: String) = {
+ (commandLineFor(name) match {
+ case Some("") => None
+ case x => x
+ }) getOrElse alt
+ }
+
+ private def commandLineFor(s: String): Option[String] = ???
+ /*condOpt(s) {
+ case "javabootclasspath" => settings.javabootclasspath.value
+ case "javaextdirs" => settings.javaextdirs.value
+ case "bootclasspath" => settings.bootclasspath.value
+ case "extdirs" => settings.extdirs.value
+ case "classpath" | "cp" => settings.classpath.value
+ case "sourcepath" => settings.sourcepath.value
+ }*/
+
+ /** Calculated values based on any given command line options, falling back on
+ * those in Defaults.
+ */
+ object Calculated {
+ def scalaHome = Defaults.scalaHome
+ def useJavaClassPath = settings.usejavacp.value || Defaults.useJavaClassPath
+ def javaBootClassPath = cmdLineOrElse("javabootclasspath", Defaults.javaBootClassPath)
+ def javaExtDirs = cmdLineOrElse("javaextdirs", Defaults.javaExtDirs)
+ def javaUserClassPath = if (useJavaClassPath) Defaults.javaUserClassPath else ""
+ def scalaBootClassPath = cmdLineOrElse("bootclasspath", Defaults.scalaBootClassPath)
+ def scalaExtDirs = cmdLineOrElse("extdirs", Defaults.scalaExtDirs)
+ /** Scaladoc doesn't need any bootstrapping, otherwise will create errors such as:
+ * [scaladoc] ../scala-trunk/src/reflect/scala/reflect/macros/Reifiers.scala:89: error: object api is not a member of package reflect
+ * [scaladoc] case class ReificationException(val pos: reflect.api.PositionApi, val msg: String) extends Throwable(msg)
+ * [scaladoc] ^
+ * because the bootstrapping will look at the sourcepath and create package "reflect" in "<root>"
+ * and then when typing relative names, instead of picking <root>.scala.relect, typedIdentifier will pick up the
+ * <root>.reflect package created by the bootstrapping. Thus, no bootstrapping for scaladoc!
+ * TODO: we should refactor this as a separate -bootstrap option to have a clean implementation, no? */
+ def sourcePath = if (!settings.isScaladoc) cmdLineOrElse("sourcepath", Defaults.scalaSourcePath) else ""
+
+ /** Against my better judgment, giving in to martin here and allowing
+ * CLASSPATH to be used automatically. So for the user-specified part
+ * of the classpath:
+ *
+ * - If -classpath or -cp is given, it is that
+ * - Otherwise, if CLASSPATH is set, it is that
+ * - If neither of those, then "." is used.
+ */
+ def userClassPath = (
+ if (!settings.classpath.isDefault)
+ settings.classpath.value
+ else sys.env.getOrElse("CLASSPATH", ".")
+ )
+
+ import context._
+
+ // Assemble the elements!
+ def basis = List[Traversable[ClassPath]](
+ classesInPath(javaBootClassPath), // 1. The Java bootstrap class path.
+ contentsOfDirsInPath(javaExtDirs), // 2. The Java extension class path.
+ classesInExpandedPath(javaUserClassPath), // 3. The Java application class path.
+ classesInPath(scalaBootClassPath), // 4. The Scala boot class path.
+ contentsOfDirsInPath(scalaExtDirs), // 5. The Scala extension class path.
+ classesInExpandedPath(userClassPath), // 6. The Scala application class path.
+ sourcesInPath(sourcePath) // 7. The Scala source path.
+ )
+
+ lazy val containers = basis.flatten.distinct
+
+ override def toString = """
+ |object Calculated {
+ | scalaHome = %s
+ | javaBootClassPath = %s
+ | javaExtDirs = %s
+ | javaUserClassPath = %s
+ | useJavaClassPath = %s
+ | scalaBootClassPath = %s
+ | scalaExtDirs = %s
+ | userClassPath = %s
+ | sourcePath = %s
+ |}""".trim.stripMargin.format(
+ scalaHome,
+ ppcp(javaBootClassPath), ppcp(javaExtDirs), ppcp(javaUserClassPath),
+ useJavaClassPath,
+ ppcp(scalaBootClassPath), ppcp(scalaExtDirs), ppcp(userClassPath),
+ ppcp(sourcePath)
+ )
+ }
+
+ def containers = Calculated.containers
+
+ lazy val result = {
+ val cp = new JavaClassPath(containers.toIndexedSeq, context)
+ if (settings.Ylogcp.value) {
+ Console.println("Classpath built from " + settings.toConciseString)
+ Console.println("Defaults: " + PathResolver.Defaults)
+ Console.println("Calculated: " + Calculated)
+
+ val xs = (Calculated.basis drop 2).flatten.distinct
+ println("After java boot/extdirs classpath has %d entries:" format xs.size)
+ xs foreach (x => println(" " + x))
+ }
+ cp
+ }
+
+ def asURLs = result.asURLs
+
+ */
+}
diff --git a/src/dotty/tools/dotc/config/Platform.scala b/src/dotty/tools/dotc/config/Platform.scala
new file mode 100644
index 000000000..73d32f193
--- /dev/null
+++ b/src/dotty/tools/dotc/config/Platform.scala
@@ -0,0 +1,38 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2012 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package dotty.tools
+package dotc
+package config
+
+import io.{ClassPath, AbstractFile}
+import core.Contexts._
+import core.SymDenotations.ClassCompleter
+import core.SymbolLoader
+
+/** The platform dependent pieces of Global.
+ */
+abstract class Platform(base: ContextBase) {
+
+ /** The root symbol loader. */
+ def rootLoader: ClassCompleter
+
+ /** The compiler classpath. */
+ def classPath: ClassPath
+
+ /** Update classpath with a substitution that maps entries to entries */
+ def updateClassPath(subst: Map[ClassPath, ClassPath])
+
+ /** Any platform-specific phases. */
+ //def platformPhases: List[SubComponent]
+
+ /** The various ways a boxed primitive might materialize at runtime. */
+ def isMaybeBoxed(sym: Symbol): Boolean
+
+ /** Create a new class loader to load class file `bin` */
+ def newClassLoader(bin: AbstractFile): SymbolLoader
+
+}
+
diff --git a/src/dotty/tools/dotc/config/Properties.scala b/src/dotty/tools/dotc/config/Properties.scala
new file mode 100644
index 000000000..4507568e4
--- /dev/null
+++ b/src/dotty/tools/dotc/config/Properties.scala
@@ -0,0 +1,165 @@
+package dotty.tools
+package dotc
+package config
+
+import java.io.{ IOException, PrintWriter }
+import java.util.jar.Attributes.{ Name => AttributeName }
+
+/** Loads `library.properties` from the jar. */
+object Properties extends PropertiesTrait {
+ protected def propCategory = "library"
+ protected def pickJarBasedOn = classOf[Option[_]]
+
+ /** Scala manifest attributes.
+ */
+ val ScalaCompilerVersion = new AttributeName("Scala-Compiler-Version")
+}
+
+trait PropertiesTrait {
+ protected def propCategory: String // specializes the remainder of the values
+ protected def pickJarBasedOn: Class[_] // props file comes from jar containing this
+
+ /** The name of the properties file */
+ protected val propFilename = "/" + propCategory + ".properties"
+
+ /** The loaded properties */
+ protected lazy val scalaProps: java.util.Properties = {
+ val props = new java.util.Properties
+ val stream = pickJarBasedOn getResourceAsStream propFilename
+ if (stream ne null)
+ quietlyDispose(props load stream, stream.close)
+
+ props
+ }
+
+ private def quietlyDispose(action: => Unit, disposal: => Unit) =
+ try { action }
+ finally {
+ try { disposal }
+ catch { case _: IOException => }
+ }
+
+ def propIsSet(name: String) = System.getProperty(name) != null
+ def propIsSetTo(name: String, value: String) = propOrNull(name) == value
+ def propOrElse(name: String, alt: String) = System.getProperty(name, alt)
+ def propOrEmpty(name: String) = propOrElse(name, "")
+ def propOrNull(name: String) = propOrElse(name, null)
+ def propOrNone(name: String) = Option(propOrNull(name))
+ def propOrFalse(name: String) = propOrNone(name) exists (x => List("yes", "on", "true") contains x.toLowerCase)
+ def setProp(name: String, value: String) = System.setProperty(name, value)
+ def clearProp(name: String) = System.clearProperty(name)
+
+ def envOrElse(name: String, alt: String) = Option(System getenv name) getOrElse alt
+ def envOrNone(name: String) = Option(System getenv name)
+
+ // for values based on propFilename
+ def scalaPropOrElse(name: String, alt: String): String = scalaProps.getProperty(name, alt)
+ def scalaPropOrEmpty(name: String): String = scalaPropOrElse(name, "")
+ def scalaPropOrNone(name: String): Option[String] = Option(scalaProps.getProperty(name))
+
+ /** The numeric portion of the runtime Scala version, if this is a final
+ * release. If for instance the versionString says "version 2.9.0.final",
+ * this would return Some("2.9.0").
+ *
+ * @return Some(version) if this is a final release build, None if
+ * it is an RC, Beta, etc. or was built from source, or if the version
+ * cannot be read.
+ */
+ val releaseVersion =
+ for {
+ v <- scalaPropOrNone("maven.version.number")
+ if !(v endsWith "-SNAPSHOT")
+ } yield v
+
+ /** The development Scala version, if this is not a final release.
+ * The precise contents are not guaranteed, but it aims to provide a
+ * unique repository identifier (currently the svn revision) in the
+ * fourth dotted segment if the running version was built from source.
+ *
+ * @return Some(version) if this is a non-final version, None if this
+ * is a final release or the version cannot be read.
+ */
+ val developmentVersion =
+ for {
+ v <- scalaPropOrNone("maven.version.number")
+ if v endsWith "-SNAPSHOT"
+ ov <- scalaPropOrNone("version.number")
+ } yield ov
+
+ /** Either the development or release version if known, otherwise
+ * the empty string.
+ */
+ def versionNumberString = scalaPropOrEmpty("version.number")
+
+ /** The version number of the jar this was loaded from plus "version " prefix,
+ * or "version (unknown)" if it cannot be determined.
+ */
+ val versionString = "version " + scalaPropOrElse("version.number", "(unknown)")
+ val copyrightString = scalaPropOrElse("copyright.string", "(c) 2002-2011 LAMP/EPFL")
+
+ /** This is the encoding to use reading in source files, overridden with -encoding
+ * Note that it uses "prop" i.e. looks in the scala jar, not the system properties.
+ */
+ def sourceEncoding = scalaPropOrElse("file.encoding", "UTF-8")
+ def sourceReader = scalaPropOrElse("source.reader", "scala.tools.nsc.io.SourceReader")
+
+ /** This is the default text encoding, overridden (unreliably) with
+ * `JAVA_OPTS="-Dfile.encoding=Foo"`
+ */
+ def encodingString = propOrElse("file.encoding", "UTF-8")
+
+ /** The default end of line character.
+ */
+ def lineSeparator = propOrElse("line.separator", "\n")
+
+ /** Various well-known properties.
+ */
+ def javaClassPath = propOrEmpty("java.class.path")
+ def javaHome = propOrEmpty("java.home")
+ def javaVendor = propOrEmpty("java.vendor")
+ def javaVersion = propOrEmpty("java.version")
+ def javaVmInfo = propOrEmpty("java.vm.info")
+ def javaVmName = propOrEmpty("java.vm.name")
+ def javaVmVendor = propOrEmpty("java.vm.vendor")
+ def javaVmVersion = propOrEmpty("java.vm.version")
+ def osName = propOrEmpty("os.name")
+ def scalaHome = propOrEmpty("scala.home")
+ def tmpDir = propOrEmpty("java.io.tmpdir")
+ def userDir = propOrEmpty("user.dir")
+ def userHome = propOrEmpty("user.home")
+ def userName = propOrEmpty("user.name")
+
+ /** Some derived values.
+ */
+ def isWin = osName startsWith "Windows"
+ def isMac = javaVendor startsWith "Apple"
+
+ // This is looking for javac, tools.jar, etc.
+ // Tries JDK_HOME first, then the more common but likely jre JAVA_HOME,
+ // and finally the system property based javaHome.
+ def jdkHome = envOrElse("JDK_HOME", envOrElse("JAVA_HOME", javaHome))
+
+ def versionMsg = "Scala %s %s -- %s".format(propCategory, versionString, copyrightString)
+ def scalaCmd = if (isWin) "scala.bat" else "scala"
+ def scalacCmd = if (isWin) "scalac.bat" else "scalac"
+
+ /** Can the java version be determined to be at least as high as the argument?
+ * Hard to properly future proof this but at the rate 1.7 is going we can leave
+ * the issue for our cyborg grandchildren to solve.
+ */
+ def isJavaAtLeast(version: String) = {
+ val okVersions = version match {
+ case "1.5" => List("1.5", "1.6", "1.7")
+ case "1.6" => List("1.6", "1.7")
+ case "1.7" => List("1.7")
+ case _ => Nil
+ }
+ okVersions exists (javaVersion startsWith _)
+ }
+
+ // provide a main method so version info can be obtained by running this
+ def main(args: Array[String]) {
+ val writer = new PrintWriter(Console.err, true)
+ writer println versionMsg
+ }
+}
diff --git a/src/dotty/tools/dotc/config/Settings.scala b/src/dotty/tools/dotc/config/Settings.scala
new file mode 100644
index 000000000..83c7a747f
--- /dev/null
+++ b/src/dotty/tools/dotc/config/Settings.scala
@@ -0,0 +1,26 @@
+package dotty.tools.dotc
+package config
+
+
+class Settings {
+
+ protected def defaultClasspath = sys.env.getOrElse("CLASSPATH", ".")
+
+ protected implicit def mkSetting[T](x: T): Setting[T] = new Setting(x)
+
+ var default: Settings = this
+
+ var classpath: Setting[String] = defaultClasspath
+ var debug: Setting[Boolean] = false
+ var verbose: Setting[Boolean] = false
+
+ var XmaxClassfileName: Setting[Int] = 255
+
+ var YtermConflict: Setting[String] = "error"
+
+ def processArguments(arguments: List[String], processAll: Boolean): (Boolean, List[String]) = ???
+
+
+}
+
+case class Setting[T](value: T) \ No newline at end of file
diff --git a/src/dotty/tools/dotc/config/WrappedProperties.scala b/src/dotty/tools/dotc/config/WrappedProperties.scala
new file mode 100644
index 000000000..07972b99b
--- /dev/null
+++ b/src/dotty/tools/dotc/config/WrappedProperties.scala
@@ -0,0 +1,34 @@
+package dotty.tools
+package dotc
+package config
+
+import java.security.AccessControlException
+
+/** For placing a wrapper function around property functions.
+ * Motivated by places like google app engine throwing exceptions
+ * on property lookups.
+ */
+trait WrappedProperties extends PropertiesTrait {
+ def wrap[T](body: => T): Option[T]
+
+ protected def propCategory = "wrapped"
+ protected def pickJarBasedOn = this.getClass
+
+ override def propIsSet(name: String) = wrap(super.propIsSet(name)) exists (x => x)
+ override def propOrElse(name: String, alt: String) = wrap(super.propOrElse(name, alt)) getOrElse alt
+ override def setProp(name: String, value: String) = wrap(super.setProp(name, value)).orNull
+ override def clearProp(name: String) = wrap(super.clearProp(name)).orNull
+ override def envOrElse(name: String, alt: String) = wrap(super.envOrElse(name, alt)) getOrElse alt
+ override def envOrNone(name: String) = wrap(super.envOrNone(name)).flatten
+
+ def systemProperties: Iterator[(String, String)] = {
+ import scala.collection.JavaConverters._
+ wrap(System.getProperties.asScala.iterator) getOrElse Iterator.empty
+ }
+}
+
+object WrappedProperties {
+ object AccessControl extends WrappedProperties {
+ def wrap[T](body: => T) = try Some(body) catch { case _: AccessControlException => None }
+ }
+}
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index e2fe9822f..d7c8609f1 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -10,6 +10,7 @@ import Symbols._
import TypeComparers._, Printers._, NameOps._, SymDenotations._
import collection.mutable
import collection.immutable.BitSet
+import config.{Settings, Platform}
object Contexts {
@@ -53,12 +54,16 @@ object Contexts {
protected def owner_=(owner: Symbol) = _owner = owner
def owner: Symbol = _owner
+ private[this] var _settings: Settings = _
+ protected def settings_=(settings: Settings) = _settings = settings
+ def settings: Settings = _settings
+
def phase: Phase = ??? // phase(period.phaseId)
def enclClass: Context = ???
def erasedTypes: Boolean = ???
def debug: Boolean = ???
-// def settings: Settings = ???
def warning(msg: String) = ???
+ def inform(msg: String) = ???
def fresh: FreshContext = {
val newctx = super.clone.asInstanceOf[FreshContext]
@@ -90,8 +95,7 @@ object Contexts {
}
class ContextBase extends Transformers.TransformerBase
- with Printers.PrinterBase
- with NameOps.NameOpsBase {
+ with Printers.PrinterBase {
val initialCtx: Context = new InitialContext(this)
@@ -99,6 +103,10 @@ object Contexts {
lazy val definitions = new Definitions()(initialCtx)
+ lazy val loaders = new SymbolLoaders
+
+ lazy val platform: Platform = ???
+
// Symbols state
/** A map from a superclass id to the class that has it */
private[core] var classOfId = new Array[ClassSymbol](InitialSuperIdsSize)
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index cafc4495d..13392a1c9 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -331,7 +331,7 @@ object Flags {
/** Flags representing access rights */
final val AccessFlags = Private | Protected | Local
- final val ModuleFlags: FlagSet = ???
+ final val RetainedModuleFlags: FlagSet = ???
final val UninstantiatableFlags = Abstract | Final
diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala
index 2bbfa1360..5aa7e2e25 100644
--- a/src/dotty/tools/dotc/core/NameOps.scala
+++ b/src/dotty/tools/dotc/core/NameOps.scala
@@ -10,25 +10,24 @@ import Decorators.StringDecorator
object NameOps {
- trait NameOpsBase { this: ContextBase =>
-
- final object compactify extends (String => String) {
- val md5 = MessageDigest.getInstance("MD5")
-
- /** COMPACTIFY
- *
- * The hashed name has the form (prefix + marker + md5 + marker + suffix), where
- * - prefix/suffix.length = MaxNameLength / 4
- * - md5.length = 32
- *
- * We obtain the formula:
- *
- * FileNameLength = 2*(MaxNameLength / 4) + 2.marker.length + 32 + 6
- *
- * (+6 for ".class"). MaxNameLength can therefore be computed as follows:
- */
+ final object compactify {
+ lazy val md5 = MessageDigest.getInstance("MD5")
+
+ /** COMPACTIFY
+ *
+ * The hashed name has the form (prefix + marker + md5 + marker + suffix), where
+ * - prefix/suffix.length = MaxNameLength / 4
+ * - md5.length = 32
+ *
+ * We obtain the formula:
+ *
+ * FileNameLength = 2*(MaxNameLength / 4) + 2.marker.length + 32 + 6
+ *
+ * (+6 for ".class"). MaxNameLength can therefore be computed as follows:
+ */
+ def apply(s: String)(implicit ctx: Context): String = {
val marker = "$$$$"
- val limit: Int = ??? // !!! settings.maxClassfileName.value
+ val limit: Int = ctx.settings.XmaxClassfileName.value
val MaxNameLength = (limit - 6) min 2 * (limit - 6 - 2 * marker.length - 32)
def toMD5(s: String, edge: Int): String = {
@@ -42,21 +41,11 @@ object NameOps {
prefix + marker + md5chars + marker + suffix
}
- def apply(s: String): String =
- if (s.length <= MaxNameLength) s else toMD5(s, MaxNameLength / 4)
+
+ if (s.length <= MaxNameLength) s else toMD5(s, MaxNameLength / 4)
}
}
- private val Boxed = Map[TypeName, TypeName](
- tpnme.Boolean -> jtpnme.BoxedBoolean,
- tpnme.Byte -> jtpnme.BoxedByte,
- tpnme.Char -> jtpnme.BoxedCharacter,
- tpnme.Short -> jtpnme.BoxedShort,
- tpnme.Int -> jtpnme.BoxedInteger,
- tpnme.Long -> jtpnme.BoxedLong,
- tpnme.Float -> jtpnme.BoxedFloat,
- tpnme.Double -> jtpnme.BoxedDouble)
-
implicit class NameDecorator(val name: Name) extends AnyVal {
import nme._
@@ -147,9 +136,21 @@ object NameOps {
}
/** If name length exceeds allowable limit, replace part of it by hash */
- def compactified(implicit ctx: Context): TermName = termName(ctx.compactify(name.toString))
+ def compactified(implicit ctx: Context): TermName = termName(compactify(name.toString))
}
+ // needed???
+ private val Boxed = Map[TypeName, TypeName](
+ tpnme.Boolean -> jtpnme.BoxedBoolean,
+ tpnme.Byte -> jtpnme.BoxedByte,
+ tpnme.Char -> jtpnme.BoxedCharacter,
+ tpnme.Short -> jtpnme.BoxedShort,
+ tpnme.Int -> jtpnme.BoxedInteger,
+ tpnme.Long -> jtpnme.BoxedLong,
+ tpnme.Float -> jtpnme.BoxedFloat,
+ tpnme.Double -> jtpnme.BoxedDouble)
+
+ // needed???
implicit class TypeNameDecorator(val name: TypeName) extends AnyVal {
def isUnboxedName = Boxed contains name
def boxedName: TypeName = Boxed(name)
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 0b61906b1..e916d0e70 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -721,7 +721,7 @@ object SymDenotations {
def classDenot(denot: LazySymDenotation) =
denot.moduleClass.denot.asInstanceOf[LazyClassDenotation]
def copyLoadedFields(denot: LazySymDenotation, from: LazyClassDenotation) = {
- denot.setFlags(from.flags.toTermFlags & ModuleFlags)
+ denot.setFlags(from.flags.toTermFlags & RetainedModuleFlags)
denot.privateWithin = from.privateWithin
}
def copyCompletedFields(denot: LazySymDenotation, from: LazyClassDenotation) = {
diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala
index 972242fbd..41bd0fdeb 100644
--- a/src/dotty/tools/dotc/core/SymbolLoaders.scala
+++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala
@@ -10,108 +10,84 @@ package core
import java.io.IOException
import scala.compat.Platform.currentTime
import dotty.tools.io.{ClassPath, AbstractFile}
-import Contexts._, Symbols._, Flags._, SymDenotations._
+import Contexts._, Symbols._, Flags._, SymDenotations._, Types._
import Decorators.StringDecorator
//import classfile.ClassfileParser
+abstract class SymbolLoader extends ClassCompleter
-abstract class SymbolLoaders(implicit ctx: Context) {
- protected def enterIfNew(owner: Symbol, member: Symbol, completer: SymbolLoader): Symbol = {
+class SymbolLoaders {
+
+ protected def enterIfNew(owner: Symbol, member: Symbol, completer: SymbolLoader)(implicit ctx: Context): Symbol = {
assert(owner.info.decls.lookup(member.name) == NoSymbol, owner.fullName + "." + member.name)
owner.info.decls enter member
member
}
- /** Enter class with given `name` into scope of `root`
- * and give them `completer` as type.
+ /** Enter class with given `name` into scope of `owner`.
*/
- def enterClass(owner: Symbol, name: String, completer: SymbolLoader): Symbol = {
+ def enterClass(owner: Symbol, name: String, completer: SymbolLoader)(implicit ctx: Context): Symbol = {
val cls = ctx.newLazyClassSymbol(owner, name.toTypeName, EmptyFlags, completer)
enterIfNew(owner, cls, completer)
}
- /** Enter module with given `name` into scope of `root`
- * and give them `completer` as type.
+ /** Enter module with given `name` into scope of `owner`.
*/
- def enterModule(owner: Symbol, name: String, completer: SymbolLoader): Symbol = {
+ def enterModule(owner: Symbol, name: String, completer: SymbolLoader)(implicit ctx: Context): Symbol = {
val module = ctx.newLazyModuleSymbol(owner, name.toTermName, EmptyFlags, completer)
enterIfNew(owner, module, completer)
}
- abstract class SymbolLoader extends ClassCompleter
-}
-/*
- /** Enter module with given `name` into scope of `root`
- * and give them `completer` as type.
- */
- def enterModule(owner: Symbol, name: String, completer: SymbolLoader): Symbol = {
- val module = owner.newModule(newTermName(name))
- module setInfo completer
- module.moduleClass setInfo moduleClassLoader
- enterIfNew(owner, module, completer)
- }
-
- /** Enter package with given `name` into scope of `root`
+ /** Enter package with given `name` into scope of `owner`
* and give them `completer` as type.
*/
- def enterPackage(root: Symbol, name: String, completer: SymbolLoader): Symbol = {
- val pname = newTermName(name)
- val preExisting = root.info.decls lookup pname
+ def enterPackage(owner: Symbol, name: String, completer: SymbolLoader)(implicit ctx: Context): Symbol = {
+ val pname = name.toTermName
+ val preExisting = owner.info.decls lookup pname
if (preExisting != NoSymbol) {
// Some jars (often, obfuscated ones) include a package and
// object with the same name. Rather than render them unusable,
// offer a setting to resolve the conflict one way or the other.
// This was motivated by the desire to use YourKit probes, which
// require yjp.jar at runtime. See SI-2089.
- if (settings.termConflict.isDefault)
+ if (ctx.settings.YtermConflict == ctx.settings.default.YtermConflict)
throw new TypeError(
- root+" contains object and package with same name: "+
- name+"\none of them needs to be removed from classpath"
- )
- else if (settings.termConflict.value == "package") {
- global.warning(
- "Resolving package/object name conflict in favor of package " +
- preExisting.fullName + ". The object will be inaccessible."
- )
- root.info.decls.unlink(preExisting)
- }
- else {
- global.warning(
- "Resolving package/object name conflict in favor of object " +
- preExisting.fullName + ". The package will be inaccessible."
- )
+ s"""$owner contains object and package with same name: $name
+ |one of them needs to be removed from classpath""".stripMargin)
+ else if (ctx.settings.YtermConflict.value == "package") {
+ ctx.warning(
+ s"Resolving package/object name conflict in favor of package ${preExisting.fullName}. The object will be inaccessible.")
+ owner.info.decls.unlink(preExisting)
+ } else {
+ ctx.warning(
+ s"Resolving package/object name conflict in favor of object ${preExisting.fullName}. The package will be inaccessible.")
return NoSymbol
}
}
- // todo: find out initialization sequence for pkg/pkg.moduleClass is different from enterModule
- val pkg = root.newPackage(pname)
- pkg.moduleClass setInfo completer
- pkg setInfo pkg.moduleClass.tpe
- root.info.decls enter pkg
- pkg
+ ctx.newLazyModuleSymbol(owner, pname, PackageCreationFlags, completer).entered
}
- /** Enter class and module with given `name` into scope of `root`
+ /** Enter class and module with given `name` into scope of `owner`
* and give them `completer` as type.
*/
- def enterClassAndModule(root: Symbol, name: String, completer: SymbolLoader) {
- val clazz = enterClass(root, name, completer)
- val module = enterModule(root, name, completer)
+ def enterClassAndModule(owner: Symbol, name: String, completer: SymbolLoader)(implicit ctx: Context) {
+ val clazz = enterClass(owner, name, completer)
+ val module = enterModule(owner, name, completer)
if (!clazz.isAnonymousClass) {
assert(clazz.companionModule == module, module)
assert(module.companionClass == clazz, clazz)
}
}
- /** In batch mode: Enter class and module with given `name` into scope of `root`
+ /** In batch mode: Enter class and module with given `name` into scope of `owner`
* and give them a source completer for given `src` as type.
- * In IDE mode: Find all toplevel definitions in `src` and enter then into scope of `root`
+ * In IDE mode: Find all toplevel definitions in `src` and enter then into scope of `owner`
* with source completer for given `src` as type.
* (overridden in interactive.Global).
*/
- def enterToplevelsFromSource(root: Symbol, name: String, src: AbstractFile) {
- enterClassAndModule(root, name, new SourcefileLoader(src))
+ def enterToplevelsFromSource(owner: Symbol, name: String, src: AbstractFile)(implicit ctx: Context) {
+ ??? // !!! enterClassAndModule(owner, name, new SourcefileLoader(src))
}
/** The package objects of scala and scala.reflect should always
@@ -121,26 +97,29 @@ abstract class SymbolLoaders(implicit ctx: Context) {
* Note: We do a name-base comparison here because the method is called before we even
* have ReflectPackage defined.
*/
- def binaryOnly(owner: Symbol, name: String): Boolean =
+ def binaryOnly(owner: Symbol, name: String)(implicit ctx: Context): Boolean =
name == "package" &&
(owner.fullName == "scala" || owner.fullName == "scala.reflect")
/** Initialize toplevel class and module symbols in `owner` from class path representation `classRep`
*/
- def initializeFromClassPath(owner: Symbol, classRep: ClassPath[platform.BinaryRepr]#ClassRep) {
+ def initializeFromClassPath(owner: Symbol, classRep: ClassPath#ClassRep)(implicit ctx: Context) {
((classRep.binary, classRep.source) : @unchecked) match {
case (Some(bin), Some(src))
- if platform.needCompile(bin, src) && !binaryOnly(owner, classRep.name) =>
- if (settings.verbose.value) inform("[symloader] picked up newer source file for " + src.path)
- global.loaders.enterToplevelsFromSource(owner, classRep.name, src)
+ if needCompile(bin, src) && !binaryOnly(owner, classRep.name) =>
+ if (ctx.settings.verbose.value) ctx.inform("[symloader] picked up newer source file for " + src.path)
+ enterToplevelsFromSource(owner, classRep.name, src)
case (None, Some(src)) =>
- if (settings.verbose.value) inform("[symloader] no class, picked up source file for " + src.path)
- global.loaders.enterToplevelsFromSource(owner, classRep.name, src)
+ if (ctx.settings.verbose.value) ctx.inform("[symloader] no class, picked up source file for " + src.path)
+ enterToplevelsFromSource(owner, classRep.name, src)
case (Some(bin), _) =>
- global.loaders.enterClassAndModule(owner, classRep.name, platform.newClassLoader(bin))
+ enterClassAndModule(owner, classRep.name, ctx.platform.newClassLoader(bin))
}
}
+ def needCompile(bin: AbstractFile, src: AbstractFile) =
+ src.lastModified >= bin.lastModified
+}/*
/**
* A lazy type that completes itself by calling parameter doComplete.
* Any linked modules/classes or module classes are also initialized.