diff options
Diffstat (limited to 'src/dotty')
-rw-r--r-- | src/dotty/tools/dotc/config/JavaPlatform.scala | 63 | ||||
-rw-r--r-- | src/dotty/tools/dotc/config/PathResolver.scala | 38 | ||||
-rw-r--r-- | src/dotty/tools/dotc/config/Platform.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/config/ScalaSettings.scala | 172 | ||||
-rw-r--r-- | src/dotty/tools/dotc/config/Settings.scala | 238 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 31 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Definitions.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/NameOps.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymbolLoaders.scala | 4 |
9 files changed, 465 insertions, 93 deletions
diff --git a/src/dotty/tools/dotc/config/JavaPlatform.scala b/src/dotty/tools/dotc/config/JavaPlatform.scala index 3c6ea3a8a..0c91ae2e7 100644 --- a/src/dotty/tools/dotc/config/JavaPlatform.scala +++ b/src/dotty/tools/dotc/config/JavaPlatform.scala @@ -4,72 +4,41 @@ package config import io.{AbstractFile,ClassPath,JavaClassPath,MergedClassPath,DeltaClassPath} import ClassPath.{ JavaContext, DefaultJavaContext } +import core.Contexts._ +import core.SymDenotations._, core.Symbols._, core.SymbolLoader -trait JavaPlatform /*extends Platform { - import global._ - import definitions._ +class JavaPlatform(base: ContextBase) extends Platform(base) { - type BinaryRepr = AbstractFile + private var currentClassPath: Option[MergedClassPath] = None - private var currentClassPath: Option[MergedClassPath[BinaryRepr]] = None - - def classPath: ClassPath[BinaryRepr] = { - if (currentClassPath.isEmpty) currentClassPath = Some(new PathResolver(settings).result) + def classPath(implicit ctx: Context): ClassPath = { + if (currentClassPath.isEmpty) + currentClassPath = Some(new PathResolver(ctx).result) currentClassPath.get } /** Update classpath with a substituted subentry */ - def updateClassPath(subst: Map[ClassPath[BinaryRepr], ClassPath[BinaryRepr]]) = + def updateClassPath(subst: Map[ClassPath, ClassPath]) = 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) + def rootLoader: ClassCompleter = ??? // = new loaders.PackageLoader(classPath) /** 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) = { + def isMaybeBoxed(sym: Symbol)(implicit ctx: Context) = { + val d = defn + import d._ (sym == ObjectClass) || (sym == JavaSerializableClass) || (sym == ComparableClass) || (sym isNonBottomSubClass BoxedNumberClass) || - (sym isNonBottomSubClass BoxedCharacterClass) || + (sym isNonBottomSubClass BoxedCharClass) || (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 -}*/ + def newClassLoader(bin: AbstractFile): SymbolLoader = ??? + // new loaders.ClassfileLoader(bin) +} diff --git a/src/dotty/tools/dotc/config/PathResolver.scala b/src/dotty/tools/dotc/config/PathResolver.scala index 6771e1465..06bb7f04b 100644 --- a/src/dotty/tools/dotc/config/PathResolver.scala +++ b/src/dotty/tools/dotc/config/PathResolver.scala @@ -8,13 +8,14 @@ import io.{ ClassPath, JavaClassPath, File, Directory, Path, AbstractFile } import ClassPath.{ JavaContext, DefaultJavaContext, join, split } import PartialFunction.condOpt import scala.language.postfixOps +import core.Contexts._ +import Settings._ // 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._ @@ -132,11 +133,9 @@ object PathResolver { ) } - def fromPathString(path: String, context: JavaContext = DefaultJavaContext): JavaClassPath = { - val s = new Settings() { - classpath = path - } - new PathResolver(s, context) result + def fromPathString(path: String)(implicit ctx: Context): JavaClassPath = { + val settings = ctx.settings.classpath.update(path) + new PathResolver(ctx.fresh.withSettings(settings)).result } /** With no arguments, show the interesting values in Environment and Defaults. @@ -149,9 +148,11 @@ object PathResolver { println(Defaults) } else { - val settings = new Settings() - val rest = settings.processArguments(args.toList, false)._2 - val pr = new PathResolver(settings) + val ctx = (new ContextBase).initialCtx + val ArgsSummary(sstate, rest, errors) = + ctx.settings.processArguments(args.toList, true)(ctx) + errors.foreach(println) + val pr = new PathResolver(ctx.fresh.withSettings(sstate)) println(" COMMAND: 'scala %s'".format(args.mkString(" "))) println("RESIDUAL: 'scala %s'\n".format(rest.mkString(" "))) pr.result.show @@ -160,7 +161,9 @@ object PathResolver { } import PathResolver.{ Defaults, Environment, firstNonEmpty, ppcp } -class PathResolver(settings: Settings, context: JavaContext = DefaultJavaContext) { +class PathResolver(_ctx: Context) { + implicit val ctx = _ctx + val context = ClassPath.DefaultJavaContext private def cmdLineOrElse(name: String, alt: String) = { (commandLineFor(name) match { @@ -184,7 +187,7 @@ class PathResolver(settings: Settings, context: JavaContext = DefaultJavaContext */ object Calculated { def scalaHome = Defaults.scalaHome - def useJavaClassPath = settings.usejavacp.value || Defaults.useJavaClassPath + def useJavaClassPath = ctx.settings.usejavacp.value || Defaults.useJavaClassPath def javaBootClassPath = cmdLineOrElse("javabootclasspath", Defaults.javaBootClassPath) def javaExtDirs = cmdLineOrElse("javaextdirs", Defaults.javaExtDirs) def javaUserClassPath = if (useJavaClassPath) Defaults.javaUserClassPath else "" @@ -198,7 +201,7 @@ class PathResolver(settings: Settings, context: JavaContext = DefaultJavaContext * 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 "" + def sourcePath = cmdLineOrElse("sourcepath", Defaults.scalaSourcePath) /** Against my better judgment, giving in to martin here and allowing * CLASSPATH to be used automatically. So for the user-specified part @@ -209,8 +212,8 @@ class PathResolver(settings: Settings, context: JavaContext = DefaultJavaContext * - If neither of those, then "." is used. */ def userClassPath = ( - if (!settings.classpath.isDefault) - settings.classpath.value + if (!ctx.settings.classpath.isDefault) + ctx.settings.classpath.value else sys.env.getOrElse("CLASSPATH", ".") ) @@ -251,10 +254,10 @@ class PathResolver(settings: Settings, context: JavaContext = DefaultJavaContext def containers = Calculated.containers - lazy val result = { + lazy val result: JavaClassPath = { val cp = new JavaClassPath(containers.toIndexedSeq, context) - if (settings.Ylogcp.value) { - Console.println("Classpath built from " + settings.toConciseString) + if (ctx.settings.Ylogcp.value) { + Console.println("Classpath built from " + ctx.settings.toConciseString(ctx.sstate)) Console.println("Defaults: " + PathResolver.Defaults) Console.println("Calculated: " + Calculated) @@ -267,5 +270,4 @@ class PathResolver(settings: Settings, context: JavaContext = DefaultJavaContext def asURLs = result.asURLs - */ } diff --git a/src/dotty/tools/dotc/config/Platform.scala b/src/dotty/tools/dotc/config/Platform.scala index 73d32f193..32f2139e7 100644 --- a/src/dotty/tools/dotc/config/Platform.scala +++ b/src/dotty/tools/dotc/config/Platform.scala @@ -8,7 +8,7 @@ package dotc package config import io.{ClassPath, AbstractFile} -import core.Contexts._ +import core.Contexts._, core.Symbols._ import core.SymDenotations.ClassCompleter import core.SymbolLoader @@ -20,7 +20,7 @@ abstract class Platform(base: ContextBase) { def rootLoader: ClassCompleter /** The compiler classpath. */ - def classPath: ClassPath + def classPath(implicit ctx: Context): ClassPath /** Update classpath with a substitution that maps entries to entries */ def updateClassPath(subst: Map[ClassPath, ClassPath]) @@ -29,7 +29,7 @@ abstract class Platform(base: ContextBase) { //def platformPhases: List[SubComponent] /** The various ways a boxed primitive might materialize at runtime. */ - def isMaybeBoxed(sym: Symbol): Boolean + def isMaybeBoxed(sym: Symbol)(implicit ctx: Context): Boolean /** Create a new class loader to load class file `bin` */ def newClassLoader(bin: AbstractFile): SymbolLoader diff --git a/src/dotty/tools/dotc/config/ScalaSettings.scala b/src/dotty/tools/dotc/config/ScalaSettings.scala new file mode 100644 index 000000000..f020ac8ec --- /dev/null +++ b/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -0,0 +1,172 @@ +package dotty.tools.dotc.config + +import PathResolver.Defaults + +class ScalaSettings extends Settings.SettingGroup { + + protected def defaultClasspath = sys.env.getOrElse("CLASSPATH", ".") + + /** Path related settings. + */ + val bootclasspath = PathSetting("-bootclasspath", "Override location of bootstrap class files.", Defaults.scalaBootClassPath) + val extdirs = PathSetting("-extdirs", "Override location of installed extensions.", Defaults.scalaExtDirs) + val javabootclasspath = PathSetting("-javabootclasspath", "Override java boot classpath.", Defaults.javaBootClassPath) + val javaextdirs = PathSetting("-javaextdirs", "Override java extdirs classpath.", Defaults.javaExtDirs) + val sourcepath = PathSetting("-sourcepath", "Specify location(s) of source files.", "") // Defaults.scalaSourcePath + + /** Other settings. + */ + val dependencyfile = StringSetting("-dependencyfile", "file", "Set dependency tracking file.", ".scala_dependencies") + val deprecation = BooleanSetting("-deprecation", "Emit warning and location for usages of deprecated APIs.") + val encoding = StringSetting("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding) + val explaintypes = BooleanSetting("-explaintypes", "Explain type errors in more detail.") + val feature = BooleanSetting("-feature", "Emit warning and location for usages of features that should be imported explicitly.") + val g = ChoiceSetting("-g", "level", "Set level of generated debugging info.", List("none", "source", "line", "vars", "notailcalls"), "vars") + val help = BooleanSetting("-help", "Print a synopsis of standard options") + val nowarn = BooleanSetting("-nowarn", "Generate no warnings.") + val print = BooleanSetting("-print", "Print program with Scala-specific features removed.") + val target = ChoiceSetting("-target", "target", "Target platform for object files. All JVM 1.5 targets are deprecated.", + List("jvm-1.5", "jvm-1.5-fjbg", "jvm-1.5-asm", "jvm-1.6", "jvm-1.7", "msil"), + "jvm-1.6") + val unchecked = BooleanSetting("-unchecked", "Enable additional warnings where generated code depends on assumptions.") + val uniqid = BooleanSetting("-uniqid", "Uniquely tag all identifiers in debugging output.") + val usejavacp = BooleanSetting("-usejavacp", "Utilize the java.class.path in classpath resolution.") + val verbose = BooleanSetting("-verbose", "Output messages about what the compiler is doing.") + val version = BooleanSetting("-version", "Print product version and exit.") + + val jvmargs = PrefixSetting("-J<flag>", "-J", "Pass <flag> directly to the runtime system.") + val defines = PrefixSetting("-Dproperty=value", "-D", "Pass -Dproperty=value directly to the runtime system.") + val toolcp = PathSetting("-toolcp", "Add to the runner classpath.", "") + val nobootcp = BooleanSetting("-nobootcp", "Do not use the boot classpath for the scala jars.") + + val argfiles = BooleanSetting("@<file>", "A text file containing compiler arguments (options and source files)") + val classpath = PathSetting("-classpath", "Specify where to find user class files.", defaultClasspath) withAbbreviation "-cp" + // val d = OutputSetting (outputDirs, ".") + val nospecialization = BooleanSetting("-no-specialization", "Ignore @specialize annotations.") + val language = MultiStringSetting("-language", "feature", "Enable one or more language features.") + + /** -X "Advanced" settings + */ + val Xhelp = BooleanSetting("-X", "Print a synopsis of advanced options.") + val assemname = StringSetting("-Xassem-name", "file", "(Requires -target:msil) Name of the output assembly.", "").dependsOn(target, "msil") + val assemrefs = StringSetting("-Xassem-path", "path", "(Requires -target:msil) List of assemblies referenced by the program.", ".").dependsOn(target, "msil") + val assemextdirs = StringSetting("-Xassem-extdirs", "dirs", "(Requires -target:msil) List of directories containing assemblies. default:lib", Defaults.scalaLibDir.path).dependsOn(target, "msil") + val sourcedir = StringSetting("-Xsourcedir", "directory", "(Requires -target:msil) Mirror source folder structure in output directory.", ".").dependsOn(target, "msil") + val checkInit = BooleanSetting("-Xcheckinit", "Wrap field accessors to throw an exception on uninitialized access.") + val noassertions = BooleanSetting("-Xdisable-assertions", "Generate no assertions or assumptions.") +// val elidebelow = IntSetting("-Xelide-below", "Calls to @elidable methods are omitted if method priority is lower than argument", +// elidable.MINIMUM, None, elidable.byName get _) + val noForwarders = BooleanSetting("-Xno-forwarders", "Do not generate static forwarders in mirror classes.") + val genPhaseGraph = StringSetting("-Xgenerate-phase-graph", "file", "Generate the phase graphs (outputs .dot files) to fileX.dot.", "") + val XlogImplicits = BooleanSetting("-Xlog-implicits", "Show more detail on why some implicits are not applicable.") + val logImplicitConv = BooleanSetting("-Xlog-implicit-conversions", "Print a message whenever an implicit conversion is inserted.") + val logReflectiveCalls = BooleanSetting("-Xlog-reflective-calls", "Print a message when a reflective method call is generated") + val logFreeTerms = BooleanSetting("-Xlog-free-terms", "Print a message when reification creates a free term.") + val logFreeTypes = BooleanSetting("-Xlog-free-types", "Print a message when reification resorts to generating a free type.") + val maxClassfileName = IntSetting("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, 72 to 255) + val Xmigration28 = BooleanSetting("-Xmigration", "Warn about constructs whose behavior may have changed between 2.7 and 2.8.") + val nouescape = BooleanSetting("-Xno-uescape", "Disable handling of \\u unicode escapes.") + val Xnojline = BooleanSetting("-Xnojline", "Do not use JLine for editing.") + val Xverify = BooleanSetting("-Xverify", "Verify generic signatures in generated bytecode (asm backend only.)") + val plugin = MultiStringSetting("-Xplugin", "file", "Load one or more plugins from files.") + val disable = MultiStringSetting("-Xplugin-disable", "plugin", "Disable the given plugin(s).") + val showPlugins = BooleanSetting("-Xplugin-list", "Print a synopsis of loaded plugins.") + val require = MultiStringSetting("-Xplugin-require", "plugin", "Abort unless the given plugin(s) are available.") + val pluginsDir = StringSetting("-Xpluginsdir", "path", "Path to search compiler plugins.", Defaults.scalaPluginPath) + val Xprint = PhasesSetting("-Xprint", "Print out program after") + val writeICode = PhasesSetting("-Xprint-icode", "Log internal icode to *.icode files after", "icode") + val Xprintpos = BooleanSetting("-Xprint-pos", "Print tree positions, as offsets.") + val printtypes = BooleanSetting("-Xprint-types", "Print tree types (debugging option).") + val prompt = BooleanSetting("-Xprompt", "Display a prompt after each error (debugging option).") + val resident = BooleanSetting("-Xresident", "Compiler stays resident: read source filenames from standard input.") + val script = StringSetting("-Xscript", "object", "Treat the source file as a script and wrap it in a main method.", "") + val mainClass = StringSetting("-Xmain-class", "path", "Class for manifest's Main-Class entry (only useful with -d <jar>)", "") + val Xshowcls = StringSetting("-Xshow-class", "class", "Show internal representation of class.", "") + val Xshowobj = StringSetting("-Xshow-object", "object", "Show internal representation of object.", "") + val showPhases = BooleanSetting("-Xshow-phases", "Print a synopsis of compiler phases.") + val sourceReader = StringSetting("-Xsource-reader", "classname", "Specify a custom method for reading source files.", "") + + val XoldPatmat = BooleanSetting("-Xoldpatmat", "Use the pre-2.10 pattern matcher. Otherwise, the 'virtualizing' pattern matcher is used in 2.10.") + val XnoPatmatAnalysis = BooleanSetting("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.") + val XfullLubs = BooleanSetting("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.") + + /** -Y "Private" settings + */ + val overrideObjects = BooleanSetting("-Yoverride-objects", "Allow member objects to be overridden.") + val overrideVars = BooleanSetting("-Yoverride-vars", "Allow vars to be overridden.") + val Yhelp = BooleanSetting("-Y", "Print a synopsis of private options.") + val browse = PhasesSetting("-Ybrowse", "Browse the abstract syntax tree after") + val check = PhasesSetting("-Ycheck", "Check the tree at the end of") + val Yshow = PhasesSetting("-Yshow", "(Requires -Xshow-class or -Xshow-object) Show after") + val Xcloselim = BooleanSetting("-Yclosure-elim", "Perform closure elimination.") + val Ycompacttrees = BooleanSetting("-Ycompact-trees", "Use compact tree printer when displaying trees.") + val noCompletion = BooleanSetting("-Yno-completion", "Disable tab-completion in the REPL.") + val Xdce = BooleanSetting("-Ydead-code", "Perform dead code elimination.") + val debug = BooleanSetting("-Ydebug", "Increase the quantity of debugging output.") + //val doc = BooleanSetting ("-Ydoc", "Generate documentation") + val termConflict = ChoiceSetting("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error") + val inline = BooleanSetting("-Yinline", "Perform inlining when possible.") + val inlineHandlers = BooleanSetting("-Yinline-handlers", "Perform exception handler inlining when possible.") + val YinlinerWarnings = BooleanSetting("-Yinline-warnings", "Emit inlining warnings. (Normally surpressed due to high volume)") + val Xlinearizer = ChoiceSetting("-Ylinearizer", "which", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo") + val log = PhasesSetting("-Ylog", "Log operations during") + val Ylogcp = BooleanSetting("-Ylog-classpath", "Output information about what classpath is being applied.") + val Ynogenericsig = BooleanSetting("-Yno-generic-signatures", "Suppress generation of generic signatures for Java.") + val noimports = BooleanSetting("-Yno-imports", "Compile without importing scala.*, java.lang.*, or Predef.") + val nopredef = BooleanSetting("-Yno-predef", "Compile without importing Predef.") + val noAdaptedArgs = BooleanSetting("-Yno-adapted-args", "Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver.") + val selfInAnnots = BooleanSetting("-Yself-in-annots", "Include a \"self\" identifier inside of annotations.") + val Xshowtrees = BooleanSetting("-Yshow-trees", "(Requires -Xprint:) Print detailed ASTs in formatted form.") + val XshowtreesCompact = BooleanSetting("-Yshow-trees-compact", "(Requires -Xprint:) Print detailed ASTs in compact form.") + val XshowtreesStringified = BooleanSetting("-Yshow-trees-stringified", "(Requires -Xprint:) Print stringifications along with detailed ASTs.") + val Yshowsyms = BooleanSetting("-Yshow-syms", "Print the AST symbol hierarchy after each phase.") + val Yshowsymkinds = BooleanSetting("-Yshow-symkinds", "Print abbreviated symbol kinds next to symbol names.") + val skip = PhasesSetting("-Yskip", "Skip") + val Ygenjavap = StringSetting("-Ygen-javap", "dir", "Generate a parallel output directory of .javap files.", "") + val Ydumpclasses = StringSetting("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "") + val Ynosqueeze = BooleanSetting("-Yno-squeeze", "Disable creation of compact code in matching.") + val stopAfter = PhasesSetting("-Ystop-after", "Stop after") withAbbreviation ("-stop") // backward compat + val stopBefore = PhasesSetting("-Ystop-before", "Stop before") + val refinementMethodDispatch = ChoiceSetting("-Ystruct-dispatch", "policy", "structural method dispatch policy", List("no-cache", "mono-cache", "poly-cache", "invoke-dynamic"), "poly-cache") + val Yrangepos = BooleanSetting("-Yrangepos", "Use range positions for syntax trees.") + val Ybuilderdebug = ChoiceSetting("-Ybuilder-debug", "manager", "Compile using the specified build manager.", List("none", "refined", "simple"), "none") + val Yreifycopypaste = BooleanSetting("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.") + val Yreplsync = BooleanSetting("-Yrepl-sync", "Do not use asynchronous code for repl startup") + val Ynotnull = BooleanSetting("-Ynotnull", "Enable (experimental and incomplete) scala.NotNull.") + val YmethodInfer = BooleanSetting("-Yinfer-argument-types", "Infer types for arguments of overriden methods.") + val etaExpandKeepsStar = BooleanSetting("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.") + val Yinvalidate = StringSetting("-Yinvalidate", "classpath-entry", "Invalidate classpath entry before run", "") + val noSelfCheck = BooleanSetting("-Yno-self-type-checks", "Suppress check for self-type conformance among inherited members.") + val YvirtClasses = false // too embryonic to even expose as a -Y //BooleanSetting ("-Yvirtual-classes", "Support virtual classes") + + def stop = stopAfter + + /** Area-specific debug output. + */ + val Ybuildmanagerdebug = BooleanSetting("-Ybuild-manager-debug", "Generate debug information for the Refined Build Manager compiler.") + val Ycompletion = BooleanSetting("-Ycompletion-debug", "Trace all tab completion activity.") + val Ydocdebug = BooleanSetting("-Ydoc-debug", "Trace all scaladoc activity.") + val Yidedebug = BooleanSetting("-Yide-debug", "Generate, validate and output trees using the interactive compiler.") + val Yinferdebug = BooleanSetting("-Yinfer-debug", "Trace type inference and implicit search.") + val Yissuedebug = BooleanSetting("-Yissue-debug", "Print stack traces when a context issues an error.") + val YmacrodebugLite = BooleanSetting("-Ymacro-debug-lite", "Trace essential macro-related activities.") + val YmacrodebugVerbose = BooleanSetting("-Ymacro-debug-verbose", "Trace all macro-related activities: compilation, generation of synthetics, classloading, expansion, exceptions.") + val Ypmatdebug = BooleanSetting("-Ypmat-debug", "Trace all pattern matcher activity.") + val Yposdebug = BooleanSetting("-Ypos-debug", "Trace position validation.") + val Yreifydebug = BooleanSetting("-Yreify-debug", "Trace reification.") + val Yrepldebug = BooleanSetting("-Yrepl-debug", "Trace all repl activity.") + val Ytyperdebug = BooleanSetting("-Ytyper-debug", "Trace all type assignments.") + val Ypatmatdebug = BooleanSetting("-Ypatmat-debug", "Trace pattern matching translation.") + + val optimise = BooleanSetting("-optimise", "Generates faster bytecode by applying optimisations to the program") withAbbreviation "-optimize" + + /** IDE-specific settings + */ + val YpresentationVerbose = BooleanSetting("-Ypresentation-verbose", "Print information about presentation compiler tasks.") + val YpresentationDebug = BooleanSetting("-Ypresentation-debug", "Enable debugging output for the presentation compiler.") + val YpresentationStrict = BooleanSetting("-Ypresentation-strict", "Do not report type errors in sources with syntax errors.") + + val YpresentationLog = StringSetting("-Ypresentation-log", "file", "Log presentation compiler events into file", "") + val YpresentationReplay = StringSetting("-Ypresentation-replay", "file", "Replay presentation compiler events from file", "") + val YpresentationDelay = IntSetting("-Ypresentation-delay", "Wait number of ms after typing before starting typechecking", 0, 0 to 999) +}
\ No newline at end of file diff --git a/src/dotty/tools/dotc/config/Settings.scala b/src/dotty/tools/dotc/config/Settings.scala index 83c7a747f..eff9c245f 100644 --- a/src/dotty/tools/dotc/config/Settings.scala +++ b/src/dotty/tools/dotc/config/Settings.scala @@ -1,26 +1,240 @@ package dotty.tools.dotc package config +import collection.mutable.{ ArrayBuffer } +import scala.util.{ Try, Success, Failure } +import scala.reflect.internal.util.StringOps +import reflect.ClassTag +import core.Contexts._ -class Settings { +object Settings { - protected def defaultClasspath = sys.env.getOrElse("CLASSPATH", ".") + val BooleanTag = ClassTag.Boolean + val IntTag = ClassTag.Int + val StringTag = ClassTag(classOf[String]) + val ListTag = ClassTag(classOf[List[_]]) - protected implicit def mkSetting[T](x: T): Setting[T] = new Setting(x) + class SettingsState(initialValues: Seq[Any]) { + private var values = ArrayBuffer(initialValues: _*) + private var _wasRead: Boolean = false - var default: Settings = this + def value(idx: Int) = { + _wasRead = true + values + } - var classpath: Setting[String] = defaultClasspath - var debug: Setting[Boolean] = false - var verbose: Setting[Boolean] = false + def update(idx: Int, x: Any): SettingsState = + if (_wasRead) + new SettingsState(values).update(idx, x) + else { + values(idx) = x + this + } + } - var XmaxClassfileName: Setting[Int] = 255 + case class ArgsSummary( + sstate: SettingsState, + arguments: List[String], + errors: List[String]) { - var YtermConflict: Setting[String] = "error" + def fail(msg: String) = + ArgsSummary(sstate, arguments, errors :+ msg) + } - def processArguments(arguments: List[String], processAll: Boolean): (Boolean, List[String]) = ??? + case class Setting[T: ClassTag] private[Settings] ( + name: String, + description: String, + default: T, + helpArg: String = "", + choices: Seq[T] = Nil, + prefix: String = "", + aliases: List[String] = Nil, + depends: List[(Setting[_], Any)] = Nil)(private[Settings] val idx: Int) { + def withAbbreviation(abbrv: String): Setting[T] = + copy(aliases = aliases :+ abbrv)(idx) -} + def dependsOn[U](setting: Setting[U], value: U): Setting[T] = + copy(depends = depends :+ (setting, value))(idx) -case class Setting[T](value: T)
\ No newline at end of file + def valueIn(state: SettingsState): T = + state.value(idx).asInstanceOf[T] + + def updateIn(state: SettingsState, x: Any): SettingsState = x match { + case _: T => state.update(idx, x) + case _ => throw new ClassCastException("illegal argument") + } + + def isDefaultIn(state: SettingsState) = valueIn(state) == default + + def legalChoices: String = + if (choices.isEmpty) "" + else choices match { + case r: Range => r.head + ".." + r.last + case xs: List[_] => xs.mkString(", ") + } + + def isLegal(arg: Any): Boolean = + if (choices.isEmpty) + arg match { + case _: T => true + case _ => false + } + else choices match { + case r: Range => + arg match { + case x: Int => r.head <= x && x <= r.last + case _ => false + } + case xs: List[_] => + xs contains arg + } + + def tryToSet(state: ArgsSummary): ArgsSummary = { + val ArgsSummary(sstate, arg :: args, errors) = state + def update(value: Any, args: List[String]) = + ArgsSummary(updateIn(sstate, value), args, errors) + def fail(msg: String, args: List[String]) = + ArgsSummary(sstate, args, errors :+ msg) + def missingArg = + fail(s"missing argument for option $name", args) + def doSet(argRest: String) = (implicitly[ClassTag[T]], args) match { + case (BooleanTag, _) => + update(true, args) + case (ListTag, _) => + if (argRest.isEmpty) missingArg + else update((argRest split ",").toList, args) + case (StringTag, arg2 :: args2) => + if (choices.nonEmpty && !(choices contains arg2)) + fail(s"$arg2 is not a valid choice for $name", args2) + else + update(arg2, args2) + case (IntTag, arg2 :: args2) => + try { + val x = arg.toInt + choices match { + case r: Range if x < r.head || r.last < x => + fail(s"$arg2 is out of legal range $legalChoices for $name", args2) + case _ => + update(x, args2) + } + } catch { + case _: NumberFormatException => + fail(s"$arg2 is not an integer argument for $name", args2) + } + case (_, Nil) => + missingArg + } + + if (prefix != "" && arg.startsWith(prefix)) + doSet(arg drop prefix.length) + else if (prefix == "" && name == arg.takeWhile(_ != ':')) + doSet(arg.dropWhile(_ != ':').drop(1)) + else + state + } + } + + object Setting { + implicit class SettingDecorator[T](val setting: Setting[T]) extends AnyVal { + def value(implicit ctx: Context): T = setting.valueIn(ctx.sstate) + def update(x: T)(implicit ctx: Context): SettingsState = setting.updateIn(ctx.sstate, x) + def isDefault(implicit ctx: Context): Boolean = setting.isDefaultIn(ctx.sstate) + } + } + + class SettingGroup { + + val _allSettings = new ArrayBuffer[Setting[_]] + def allSettings: Seq[Setting[_]] = _allSettings + + def defaultState = new SettingsState(allSettings map (_.default)) + + def userSetSettings(state: SettingsState) = + allSettings filterNot (_.isDefaultIn(state)) + + def toConciseString(state: SettingsState) = + userSetSettings(state).mkString("(", " ", ")") + + private def checkDependencies(state: ArgsSummary): ArgsSummary = + (state /: userSetSettings(state.sstate))(checkDependenciesOfSetting) + + private def checkDependenciesOfSetting(state: ArgsSummary, setting: Setting[_]) = + (state /: setting.depends) { (s, dep) => + val (depSetting, reqValue) = dep + if (depSetting.valueIn(state.sstate) == reqValue) s + else s.fail(s"incomplete option ${setting.name} (requires ${depSetting.name})") + } + + /** Iterates over the arguments applying them to settings where applicable. + * Then verifies setting dependencies are met. + * + * This temporarily takes a boolean indicating whether to keep + * processing if an argument is seen which is not a command line option. + * This is an expedience for the moment so that you can say + * + * scalac -d /tmp foo.scala -optimise + * + * while also allowing + * + * scala Program opt opt + * + * to get their arguments. + */ + protected def processArguments(state: ArgsSummary, processAll: Boolean, skipped: List[String]): ArgsSummary = { + def stateWithArgs(args: List[String]) = ArgsSummary(state.sstate, args, state.errors) + state.arguments match { + case Nil => + checkDependencies(stateWithArgs(skipped)) + case "--" :: args => + checkDependencies(stateWithArgs(skipped ++ args)) + case x :: _ if x startsWith "-" => + def loop(settings: List[Setting[_]]): ArgsSummary = settings match { + case setting :: settings1 => + val state1 = setting.tryToSet(state) + if (state1 ne state) processArguments(state1, processAll, skipped) + else loop(settings1) + case Nil => + state.fail(s"bad option: '$x'") + } + loop(allSettings.toList) + case arg :: args => + if (processAll) processArguments(stateWithArgs(args), processAll, skipped :+ arg) + else state + } + } + + def processArguments(arguments: List[String], processAll: Boolean)(implicit ctx: Context): ArgsSummary = + processArguments(ArgsSummary(ctx.sstate, arguments, Nil), processAll, Nil) + + def publish[T](settingf: Int => Setting[T]): Setting[T] = { + val setting = settingf(_allSettings.length) + _allSettings += setting + setting + } + + def BooleanSetting(name: String, descr: String): Setting[Boolean] = + publish(Setting(name, descr, false)) + + def StringSetting(name: String, helpArg: String, descr: String, default: String): Setting[String] = + publish(Setting(name, descr, default, helpArg)) + + def ChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: String): Setting[String] = + publish(Setting(name, descr, default, helpArg, choices)) + + def IntSetting(name: String, descr: String, default: Int, range: Seq[Int]): Setting[Int] = + publish(Setting(name, descr, default, choices = range)) + + def MultiStringSetting(name: String, helpArg: String, descr: String): Setting[List[String]] = + publish(Setting(name, descr, Nil, helpArg)) + + def PathSetting(name: String, descr: String, default: String): Setting[String] = + publish(Setting(name, descr, default)) + + def PhasesSetting(name: String, descr: String, default: String = ""): Setting[List[String]] = + publish(Setting(name, descr, if (default.isEmpty) Nil else List(default))) + + def PrefixSetting(name: String, pre: String, descr: String): Setting[List[String]] = + publish(Setting(name, descr, Nil, prefix = pre)) + } +}
\ No newline at end of file diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index d7c8609f1..bbc134d7d 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -8,9 +8,11 @@ import Phases._ import Types._ import Symbols._ import TypeComparers._, Printers._, NameOps._, SymDenotations._ +import config.Settings._ +import config.ScalaSettings import collection.mutable import collection.immutable.BitSet -import config.{Settings, Platform} +import config.{Settings, Platform, JavaPlatform} object Contexts { @@ -54,9 +56,9 @@ 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 + private[this] var _sstate: SettingsState = _ + protected def sstate_=(sstate: SettingsState) = _sstate = sstate + def sstate: SettingsState = _sstate def phase: Phase = ??? // phase(period.phaseId) def enclClass: Context = ??? @@ -79,6 +81,7 @@ object Contexts { def withConstraints(constraints: Constraints): this.type = { this.constraints = constraints; this } def withPrinter(printer: Context => Printer): this.type = { this.printer = printer; this } def withOwner(owner: Symbol): this.type = { this.owner = owner; this } + def withSettings(sstate: SettingsState): this.type = { this.sstate = sstate; this } def withDiagnostics(diagnostics: Option[StringBuilder]): this.type = { this.diagnostics = diagnostics; this } } @@ -94,18 +97,26 @@ object Contexts { val base = unsupported("base") } - class ContextBase extends Transformers.TransformerBase + class ContextBase extends ContextState with Transformers.TransformerBase with Printers.PrinterBase { - val initialCtx: Context = new InitialContext(this) + val settings = new ScalaSettings - lazy val rootLoader: ClassCompleter = ??? + val initialCtx: Context = new InitialContext(this).fresh + .withSettings(settings.defaultState) - lazy val definitions = new Definitions()(initialCtx) + val loaders = new SymbolLoaders - lazy val loaders = new SymbolLoaders + val platform: Platform = new JavaPlatform(this) - lazy val platform: Platform = ??? + val rootLoader: ClassCompleter = platform.rootLoader + + val definitions = new Definitions()(initialCtx) + + } + + /** Mutable state of a context base, collected into a common class */ + class ContextState { // Symbols state /** A map from a superclass id to the class that has it */ diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 2b725c8b4..73c874422 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -76,6 +76,10 @@ class Definitions(implicit ctx: Context) { lazy val NothingType = NothingClass.typeConstructor lazy val NullType = NullClass.typeConstructor + lazy val BoxedNumberClass = requiredClass("java.lang.Number") + lazy val JavaSerializableClass = requiredClass("java.lang.Serializable") + lazy val ComparableClass = requiredClass("java.lang.Comparable") + // ----- Class sets --------------------------------------------------- /** Modules whose members are in the default namespace */ diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala index 5aa7e2e25..334d3a908 100644 --- a/src/dotty/tools/dotc/core/NameOps.scala +++ b/src/dotty/tools/dotc/core/NameOps.scala @@ -27,7 +27,7 @@ object NameOps { */ def apply(s: String)(implicit ctx: Context): String = { val marker = "$$$$" - val limit: Int = ctx.settings.XmaxClassfileName.value + val limit: Int = ctx.settings.maxClassfileName.value val MaxNameLength = (limit - 6) min 2 * (limit - 6 - 2 * marker.length - 32) def toMD5(s: String, edge: Int): String = { diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala index 41bd0fdeb..6aa959887 100644 --- a/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -51,11 +51,11 @@ class SymbolLoaders { // 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 (ctx.settings.YtermConflict == ctx.settings.default.YtermConflict) + if (ctx.settings.termConflict.isDefault) throw new TypeError( 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") { + else if (ctx.settings.termConflict.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) |