Skip to content

Commit

Permalink
Merge pull request #9810 from som-snytt/issue/11873
Browse files Browse the repository at this point in the history
  • Loading branch information
SethTisue committed Feb 20, 2022
2 parents 9312709 + 655d3e1 commit c917d72
Show file tree
Hide file tree
Showing 71 changed files with 371 additions and 245 deletions.
1 change: 1 addition & 0 deletions build.sbt
Expand Up @@ -682,6 +682,7 @@ lazy val bench = project.in(file("test") / "benchmarks")
if (benchmarkScalaVersion == "") Nil
else "org.scala-lang" % "scala-compiler" % benchmarkScalaVersion :: Nil
},
//scalacOptions ++= Seq("-feature", "-opt:inline:scala/**", "-Wopt"),
scalacOptions ++= Seq("-feature", "-opt:l:inline", "-opt-inline-from:scala/**", "-opt-warnings"),
// Skips JMH source generators during IDE import to avoid needing to compile scala-library during the import
// should not be needed once sbt-jmh 0.4.3 is out (https://github.com/sbt/sbt-jmh/pull/207)
Expand Down
1 change: 1 addition & 0 deletions project/ScriptCommands.scala
Expand Up @@ -161,6 +161,7 @@ object ScriptCommands {
}

private[this] val enableOptimizer = Seq(
//ThisBuild / Compile / scalacOptions ++= Seq("-opt:inline:scala/**")
ThisBuild / Compile / scalacOptions ++= Seq("-opt:l:inline", "-opt-inline-from:scala/**")
)

Expand Down
Expand Up @@ -211,7 +211,7 @@ object PostProcessorFrontendAccess {
val optAllowSkipClassLoading: Boolean = s.optAllowSkipClassLoading

val optInlinerEnabled: Boolean = s.optInlinerEnabled
val optInlineFrom: List[String] = s.optInlineFrom.value
val optInlineFrom: List[String] = s.optInlineFrom
val optInlineHeuristics: String = s.YoptInlineHeuristics.value

val optWarningNoInlineMixed: Boolean = s.optWarningNoInlineMixed
Expand Down
112 changes: 69 additions & 43 deletions src/compiler/scala/tools/nsc/settings/MutableSettings.scala
Expand Up @@ -122,11 +122,7 @@ class MutableSettings(val errorFn: String => Unit, val pathFactory: PathFactory)
args: List[String],
setter: (Setting) => (List[String] => Option[List[String]])
): Option[List[String]] =
lookupSetting(cmd) match {
//case None => errorFn("Parameter '" + cmd + "' is not recognised by Scalac.") ; None
case None => None //error reported in processArguments
case Some(cmd) => setter(cmd)(args)
}
lookupSetting(cmd).flatMap(setter(_)(args))

// -Xfoo: clears Clearables
def clearIfExists(cmd: String): Option[List[String]] = lookupSetting(cmd) match {
Expand All @@ -139,14 +135,14 @@ class MutableSettings(val errorFn: String => Unit, val pathFactory: PathFactory)
// the entire arg is consumed, so return None for failure
// any non-Nil return value means failure and we return s unmodified
def parseColonArg(s: String): Option[List[String]] =
if (s endsWith ":") {
if (s endsWith ":")
clearIfExists(s.init)
} else {
else
StringOps.splitWhere(s, _ == ':', doDropIndex = true).flatMap {
case (p, args) =>
tryToSetIfExists(p, (args split ",").toList, (s: Setting) => s.tryToSetColon(_))
// p:arg:a,b,c is taken as arg with selections a,b,c for a multichoice setting
case (p, args) if args.contains(":") && lookupSetting(p).map(_.isInstanceOf[MultiChoiceSetting[_]]).getOrElse(false) => tryToSetIfExists(p, List(args), (s: Setting) => s.tryToSetColon(_))
case (p, args) => tryToSetIfExists(p, args.split(",").toList, (s: Setting) => s.tryToSetColon(_))
}
}

// if arg is of form -Xfoo or -Xfoo bar (name = "-Xfoo")
def parseNormalArg(p: String, args: List[String]): Option[List[String]] =
Expand Down Expand Up @@ -559,7 +555,9 @@ class MutableSettings(val errorFn: String => Unit, val pathFactory: PathFactory)
* not present in the multiChoiceSetting.value set, only their expansion.
*/
abstract class MultiChoiceEnumeration extends Enumeration {
case class Choice(name: String, help: String = "", expandsTo: List[Choice] = Nil) extends Val(name)
case class Choice(name: String, help: String = "", expandsTo: List[Choice] = Nil, requiresSelections: Boolean = false) extends Val(name) {
var selections: List[String] = Nil
}
def wildcardChoices: ValueSet = values.filter { case c: Choice => c.expandsTo.isEmpty case _ => true }
}

Expand Down Expand Up @@ -614,10 +612,11 @@ class MutableSettings(val errorFn: String => Unit, val pathFactory: PathFactory)
private var sawAll = false

private def badChoice(s: String) = errorFn(s"'$s' is not a valid choice for '$name'")
private def isChoice(s: String) = (s == "_") || (choices contains pos(s))
private def isChoice(s: String) = s == "_" || choices.contains(pos(s))
private def choiceOf(s: String): domain.Choice = domain.withName(pos(s)).asInstanceOf[domain.Choice]

private def pos(s: String) = s stripPrefix "-"
private def isPos(s: String) = !(s startsWith "-")
private def pos(s: String) = s.stripPrefix("-")
private def isPos(s: String) = !s.startsWith("-")

override val choices: List[String] = domain.values.toList map {
case ChoiceOrVal(name, _, _) => name
Expand All @@ -629,7 +628,7 @@ class MutableSettings(val errorFn: String => Unit, val pathFactory: PathFactory)
case _ => ""
}

/** (Re)compute from current yeas, nays, wildcard status. */
/** (Re)compute from current yeas, nays, wildcard status. Assign option value. */
def compute() = {
def simple(v: domain.Value) = v match {
case c: domain.Choice => c.expandsTo.isEmpty
Expand All @@ -648,8 +647,8 @@ class MutableSettings(val errorFn: String => Unit, val pathFactory: PathFactory)
}

// yeas from _ or expansions are weak: an explicit nay will disable them
val weakYeas = if (sawAll) domain.wildcardChoices else expand(yeas filterNot simple)
value = (yeas filter simple) | (weakYeas &~ nays)
val weakYeas = if (sawAll) domain.wildcardChoices else expand(yeas.filterNot(simple))
value = yeas.filter(simple) | (weakYeas &~ nays)
}

/** Add a named choice to the multichoice value. */
Expand All @@ -660,10 +659,10 @@ class MutableSettings(val errorFn: String => Unit, val pathFactory: PathFactory)
sawAll = true
compute()
case _ if isPos(arg) =>
yeas += domain withName arg
yeas += domain.withName(arg)
compute()
case _ =>
val choice = domain withName pos(arg)
val choice = domain.withName(pos(arg))
choice match {
case ChoiceOrVal(_, _, _ :: _) => errorFn(s"'${pos(arg)}' cannot be negated, it enables other arguments")
case _ =>
Expand All @@ -672,6 +671,12 @@ class MutableSettings(val errorFn: String => Unit, val pathFactory: PathFactory)
compute()
}

// refine a choice with selections. -opt:inline:**
def add(arg: String, selections: List[String]): Unit = {
add(arg)
domain.withName(arg).asInstanceOf[domain.Choice].selections ++= selections
}

def tryToSet(args: List[String]) = tryToSetArgs(args, halting = true)
override def tryToSetColon(args: List[String]) = tryToSetArgs(args, halting = false)
override def tryToSetFromPropertyValue(s: String) = tryToSet(s.trim.split(',').toList) // used from ide
Expand All @@ -680,37 +685,57 @@ class MutableSettings(val errorFn: String => Unit, val pathFactory: PathFactory)
* The "halting" parameter means args were "-option a b c -else" so halt
* on "-else" or other non-choice. Otherwise, args were "-option:a,b,c,d",
* so process all and report non-choices as errors.
*
* If a choice is seen as colonated, then set the choice selections:
* "-option:choice:selection1,selection2"
*
* @param args args to process
* @param halting stop on non-arg
*/
private def tryToSetArgs(args: List[String], halting: Boolean) = {
val added = collection.mutable.ListBuffer.empty[String]

def tryArg(arg: String) = arg match {
case "help" => sawHelp = true
case s if isChoice(s) => added += s // this case also adds "_"
case s => badChoice(s)
}
@tailrec
def loop(args: List[String]): List[String] = args match {
case arg :: _ if halting && (!isPos(arg) || !isChoice(arg)) => args
case arg :: rest => tryArg(arg) ; loop(rest)
case Nil => Nil
}
val rest = loop(args)

// if no arg consumed, use defaults or error; otherwise, add what they added
if (rest.size == args.size) default match {
case Some(defaults) => defaults foreach add
case None => errorFn(s"'$name' requires an option. See '$name:help'.")
} else {
added foreach add
val colonnade = raw"([^:]+):(.*)".r
var count = 0
val rest = {
@tailrec
def loop(args: List[String]): List[String] = args match {
case "help" :: rest =>
sawHelp = true
count += 1
loop(rest)
case arg :: rest =>
val (argx, selections) = arg match {
case colonnade(x, y) => (x, y)
case _ => (arg, "")
}
if (halting && (!isPos(argx) || !isChoice(argx)))
args
else {
if (isChoice(argx)) {
if (selections.nonEmpty) add(argx, selections.split(",").toList)
else if (argx != "_" && isPos(argx) && choiceOf(argx).requiresSelections) errorFn(s"'$argx' requires '$argx:<selection>'. See '$name:help'.")
else add(argx) // this case also adds "_"
postSetHook() // support -opt:l:method
}
else
badChoice(argx)
count += 1
loop(rest)
}
case _ => Nil
}
loop(args)
}

// if no arg applied, use defaults or error; otherwise, add what they added
if (count == 0)
default match {
case Some(defaults) => defaults.foreach(add)
case None => errorFn(s"'$name' requires an option. See '$name:help'.")
}
Some(rest)
}

def contains(choice: domain.Value): Boolean = value contains choice
def contains(choice: domain.Value): Boolean = value.contains(choice)

// programmatically.
def enable(choice: domain.Value): Unit = { nays -= choice ; yeas += choice ; compute() }
Expand All @@ -736,14 +761,15 @@ class MutableSettings(val errorFn: String => Unit, val pathFactory: PathFactory)
choices.zipAll(descriptions, "", "").map(describe).mkString(f"${descr}%n", f"%n", orelse)
}

def clear(): Unit = {
def clear(): Unit = {
domain.values.foreach { case c: domain.Choice => c.selections = Nil ; case _ => }
v = domain.ValueSet.empty
yeas = domain.ValueSet.empty
nays = domain.ValueSet.empty
sawAll = false
sawHelp = false
}
def unparse: List[String] = value.toList map (s => s"$name:$s")
def unparse: List[String] = value.toList.map(s => s"$name:$s")
def contains(s: String) = domain.values.find(_.toString == s).exists(value.contains)
}

Expand Down

0 comments on commit c917d72

Please sign in to comment.