summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools')
-rw-r--r--src/compiler/scala/tools/ant/Scalac.scala2
-rw-r--r--src/compiler/scala/tools/ant/Scaladoc.scala27
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala16
-rw-r--r--src/compiler/scala/tools/nsc/ast/NodePrinters.scala55
-rw-r--r--src/compiler/scala/tools/nsc/ast/Reifiers.scala (renamed from src/compiler/scala/tools/nsc/transform/LiftCode.scala)225
-rw-r--r--src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala75
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Members.scala3
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala8
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala27
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala17
16 files changed, 223 insertions, 258 deletions
diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala
index 04ff0c440d..3c79fcd3fb 100644
--- a/src/compiler/scala/tools/ant/Scalac.scala
+++ b/src/compiler/scala/tools/ant/Scalac.scala
@@ -90,7 +90,7 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
/** Defines valid values for properties that refer to compiler phases. */
object CompilerPhase extends PermissibleValue {
- val values = List("namer", "typer", "pickler", "refchecks", "liftcode",
+ val values = List("namer", "typer", "pickler", "refchecks",
"uncurry", "tailcalls", "specialize", "explicitouter",
"erasure", "lazyvals", "lambdalift", "constructors",
"flatten", "mixin", "cleanup", "icode", "inliner",
diff --git a/src/compiler/scala/tools/ant/Scaladoc.scala b/src/compiler/scala/tools/ant/Scaladoc.scala
index 253d1dec5d..92d6e6320c 100644
--- a/src/compiler/scala/tools/ant/Scaladoc.scala
+++ b/src/compiler/scala/tools/ant/Scaladoc.scala
@@ -43,7 +43,8 @@ import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
* - `deprecation`,
* - `docgenerator`,
* - `docrootcontent`,
- * - `unchecked`.
+ * - `unchecked`,
+ * - `nofail`.
*
* It also takes the following parameters as nested elements:
* - `src` (for srcdir),
@@ -122,7 +123,10 @@ class Scaladoc extends ScalaMatchingTask {
/** Instruct the compiler to generate unchecked information. */
private var unchecked: Boolean = false
-
+
+ /** Instruct the ant task not to fail in the event of errors */
+ private var nofail: Boolean = false
+
/*============================================================================*\
** Properties setters **
\*============================================================================*/
@@ -352,6 +356,17 @@ class Scaladoc extends ScalaMatchingTask {
def setDocUncompilable(input: String) {
docUncompilable = Some(input)
}
+
+ /** Set the `nofail` info attribute.
+ *
+ * @param input One of the flags `yes/no` or `on/off`. Default if no/off.
+ */
+ def setNoFail(input: String) {
+ if (Flag.isPermissible(input))
+ nofail = "yes".equals(input) || "on".equals(input)
+ else
+ buildError("Unknown nofail flag '" + input + "'")
+ }
/*============================================================================*\
** Properties getters **
@@ -553,6 +568,8 @@ class Scaladoc extends ScalaMatchingTask {
Pair(docSettings, sourceFiles)
}
+ def safeBuildError(message: String): Unit = if (nofail) log(message) else buildError(message)
+
/** Performs the compilation. */
override def execute() = {
val Pair(docSettings, sourceFiles) = initialize
@@ -561,7 +578,7 @@ class Scaladoc extends ScalaMatchingTask {
val docProcessor = new scala.tools.nsc.doc.DocFactory(reporter, docSettings)
docProcessor.document(sourceFiles.map (_.toString))
if (reporter.ERROR.count > 0)
- buildError(
+ safeBuildError(
"Document failed with " +
reporter.ERROR.count + " error" +
(if (reporter.ERROR.count > 1) "s" else "") +
@@ -576,11 +593,11 @@ class Scaladoc extends ScalaMatchingTask {
} catch {
case exception: Throwable if exception.getMessage ne null =>
exception.printStackTrace()
- buildError("Document failed because of an internal documenter error (" +
+ safeBuildError("Document failed because of an internal documenter error (" +
exception.getMessage + "); see the error output for details.")
case exception =>
exception.printStackTrace()
- buildError("Document failed because of an internal documenter error " +
+ safeBuildError("Document failed because of an internal documenter error " +
"(no error message provided); see the error output for details.")
}
}
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 8e5ca2156a..281a2eb49b 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -37,6 +37,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
with Plugins
with PhaseAssembly
with Trees
+ with Reifiers
with TreePrinters
with DocComments
with MacroContext
@@ -124,7 +125,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
/** Print tree in detailed form */
object nodePrinters extends {
val global: Global.this.type = Global.this
- } with NodePrinters {
+ } with NodePrinters with ReifyPrinters {
infolevel = InfoLevel.Verbose
}
@@ -134,6 +135,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
} with TreeBrowsers
val nodeToString = nodePrinters.nodeToString
+ val reifiedNodeToString = nodePrinters.reifiedNodeToString
val treeBrowser = treeBrowsers.create()
// ------------ Hooks for interactive mode-------------------------
@@ -463,17 +465,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
val runsRightAfter = None
} with RefChecks
- // phaseName = "liftcode"
- object liftcode extends {
- val global: Global.this.type = Global.this
- val runsAfter = List("refchecks")
- val runsRightAfter = None
- } with LiftCode
-
// phaseName = "uncurry"
override object uncurry extends {
val global: Global.this.type = Global.this
- val runsAfter = List("refchecks", "liftcode")
+ val runsAfter = List("refchecks")
val runsRightAfter = None
} with UnCurry
@@ -659,7 +654,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
extensionMethods -> "add extension methods for inline classes",
pickler -> "serialize symbol tables",
refChecks -> "reference/override checking, translate nested objects",
- liftcode -> "reify trees",
uncurry -> "uncurry, translate function values to anonymous classes",
tailCalls -> "replace tail calls by jumps",
specializeTypes -> "@specialized-driven class and method specialization",
@@ -1090,7 +1084,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
def compiles(sym: Symbol): Boolean =
if (sym == NoSymbol) false
else if (symSource.isDefinedAt(sym)) true
- else if (!sym.owner.isPackageClass) compiles(sym.toplevelClass)
+ else if (!sym.owner.isPackageClass) compiles(sym.enclosingTopLevelClass)
else if (sym.isModuleClass) compiles(sym.sourceModule)
else false
diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
index ea51fc0141..9466d1c1f2 100644
--- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
@@ -71,34 +71,39 @@ abstract class NodePrinters {
def nodeinfo(tree: Tree): String =
if (infolevel == InfoLevel.Quiet) ""
else {
- val buf = new StringBuilder(" // sym=" + tree.symbol)
- if (tree.hasSymbol) {
- if (tree.symbol.isPrimaryConstructor)
- buf.append(", isPrimaryConstructor")
- else if (tree.symbol.isConstructor)
- buf.append(", isConstructor")
- if (tree.symbol != NoSymbol)
- buf.append(", sym.owner=" + tree.symbol.owner)
- buf.append(", sym.tpe=" + tree.symbol.tpe)
- }
- buf.append(", tpe=" + tree.tpe)
- if (tree.tpe != null) {
- var sym = tree.tpe.termSymbol
- if (sym == NoSymbol) sym = tree.tpe.typeSymbol
- buf.append(", tpe.sym=" + sym)
- if (sym != NoSymbol) {
- buf.append(", tpe.sym.owner=" + sym.owner)
- if ((infolevel > InfoLevel.Normal) &&
- !(sym.owner eq definitions.ScalaPackageClass) &&
- !sym.isModuleClass && !sym.isPackageClass &&
- !sym.isJavaDefined) {
- val members = for (m <- tree.tpe.decls)
- yield m.toString() + ": " + m.tpe + ", "
- buf.append(", tpe.decls=" + members)
+ try {
+ val buf = new StringBuilder(" // sym=" + tree.symbol)
+ if (tree.hasSymbol) {
+ if (tree.symbol.isPrimaryConstructor)
+ buf.append(", isPrimaryConstructor")
+ else if (tree.symbol.isConstructor)
+ buf.append(", isConstructor")
+ if (tree.symbol != NoSymbol)
+ buf.append(", sym.owner=" + tree.symbol.owner)
+ buf.append(", sym.tpe=" + tree.symbol.tpe)
+ }
+ buf.append(", tpe=" + tree.tpe)
+ if (tree.tpe != null) {
+ var sym = tree.tpe.termSymbol
+ if (sym == NoSymbol) sym = tree.tpe.typeSymbol
+ buf.append(", tpe.sym=" + sym)
+ if (sym != NoSymbol) {
+ buf.append(", tpe.sym.owner=" + sym.owner)
+ if ((infolevel > InfoLevel.Normal) &&
+ !(sym.owner eq definitions.ScalaPackageClass) &&
+ !sym.isModuleClass && !sym.isPackageClass &&
+ !sym.isJavaDefined) {
+ val members = for (m <- tree.tpe.decls)
+ yield m.toString() + ": " + m.tpe + ", "
+ buf.append(", tpe.decls=" + members)
+ }
}
}
+ buf.toString
+ } catch {
+ case ex: Throwable =>
+ return " // sym= <error> " + ex.getMessage
}
- buf.toString
}
def nodeinfo2(tree: Tree): String =
(if (comma) "," else "") + nodeinfo(tree)
diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/ast/Reifiers.scala
index 8affea56a2..c05475d50c 100644
--- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala
+++ b/src/compiler/scala/tools/nsc/ast/Reifiers.scala
@@ -5,7 +5,7 @@
*/
package scala.tools.nsc
-package transform
+package ast
import symtab._
import Flags._
@@ -14,174 +14,44 @@ import scala.collection.mutable.ListBuffer
import scala.tools.nsc.util.FreshNameCreator
import scala.runtime.ScalaRunTime.{ isAnyVal, isTuple }
-/**
- * Translate expressions of the form reflect.Code.lift(exp)
- * to the reified "reflect trees" representation of exp.
- * Also: mutable variables that are accessed from a local function are wrapped in refs.
+/** Given a tree or type, generate a tree that when executed at runtime produces the original tree or type.
+ * See more info in the comments to `reify' in scala.reflect.macro.Context.
*
* @author Martin Odersky
* @version 2.10
*/
-abstract class LiftCode extends Transform with TypingTransformers {
-
- import global._ // the global environment
- import definitions._ // standard classes and methods
- import typer.{ typed, atOwner } // methods to type trees
-
- val symbols: global.type = global
-
- /** the following two members override abstract members in Transform */
- val phaseName: String = "liftcode"
-
- def newTransformer(unit: CompilationUnit): Transformer =
- new Codifier(unit)
-
- private lazy val MirrorMemberNames =
- ReflectRuntimeMirror.info.nonPrivateMembers filter (_.isTerm) map (_.toString) toSet
-
- // Would be nice if we could use something like this to check the names,
- // but it seems that info is unavailable when I need it.
- private def mirrorFactoryName(value: Any): Option[String] = value match {
- // Modest (inadequate) sanity check that there's a member by this name.
- case x: Product if MirrorMemberNames(x.productPrefix) =>
- Some(x.productPrefix)
- case _ =>
- Some(value.getClass.getName split """[$.]""" last) filter MirrorMemberNames
- }
- private def isMirrorMemberObject(value: Product) = value match {
- case NoType | NoPrefix | NoPosition | EmptyTree => true
- case _ => false
- }
-
- class Codifier(unit: CompilationUnit) extends TypingTransformer(unit) {
-
- val reifyDebug = settings.Yreifydebug.value
- val reifyTyperDebug = settings.Yreifytyperdebug.value
- val debugTrace = util.trace when reifyDebug
-
- val reifyCopypaste = settings.Yreifycopypaste.value
- def printCopypaste(tree: Tree) {
- if (reifyDebug) println("=======================")
- printCopypaste1(tree)
- if (reifyDebug) println("=======================")
- }
- def printCopypaste1(tree: Tree) {
- import scala.reflect.api.Modifier
- import scala.reflect.api.Modifier._
-
- def copypasteModifier(mod: Modifier.Value): String = mod match {
- case mod @ (
- `protected` | `private` | `override` |
- `abstract` | `final` | `sealed` |
- `implicit` | `lazy` | `macro` |
- `case` | `trait`) => "`" + mod.toString + "`"
- case mod => mod.toString
- }
-
- // I fervently hope this is a test case or something, not anything being
- // depended upon. Of more fragile code I cannot conceive.
- for (line <- (tree.toString.split(Properties.lineSeparator) drop 2 dropRight 1)) {
- var s = line.trim
- s = s.replace("$mr.", "")
- s = s.replace(".apply", "")
- s = s.replace("scala.collection.immutable.", "")
- s = "List\\[List\\[.*?\\].*?\\]".r.replaceAllIn(s, "List")
- s = "List\\[.*?\\]".r.replaceAllIn(s, "List")
- s = s.replace("immutable.this.Nil", "List()")
- s = s.replace("modifiersFromInternalFlags", "Modifiers")
- s = s.replace("Modifiers(0L, newTypeName(\"\"), List())", "Modifiers()")
- s = """Modifiers\((\d+)[lL], newTypeName\("(.*?)"\), List\((.*?)\)\)""".r.replaceAllIn(s, m => {
- val buf = new StringBuilder
-
- val flags = m.group(1).toLong
- val s_flags = Flags.modifiersOfFlags(flags) map copypasteModifier mkString ", "
- if (s_flags != "")
- buf.append("Set(" + s_flags + ")")
-
- val privateWithin = "" + m.group(2)
- if (privateWithin != "")
- buf.append(", newTypeName(\"" + privateWithin + "\")")
-
- val annotations = m.group(3)
- if (annotations.nonEmpty)
- buf.append(", List(" + annotations + ")")
-
- "Modifiers(" + buf.toString + ")"
- })
- s = """setInternalFlags\((\d+)L\)""".r.replaceAllIn(s, m => {
- val flags = m.group(1).toLong
- val mods = Flags.modifiersOfFlags(flags) map copypasteModifier
- "setInternalFlags(flagsOfModifiers(List(" + mods.mkString(", ") + ")))"
- })
-
- println(s)
- }
- }
-
- override def transformUnit(unit: CompilationUnit) {
- atPhase(phase.next) {
- super.transformUnit(unit)
- }
- }
-
- override def transform(tree: Tree): Tree = {
- val sym = tree.symbol
- tree match {
- case Apply(_, List(tree)) if sym == Code_lift => // reify Code.lift[T](expr) instances
- val saved = printTypings
- try {
- debugTrace("transforming = ")(if (settings.Xshowtrees.value) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString)
- debugTrace("transformed = ") {
- val untyped = codify(super.transform(tree))
- if (reifyCopypaste) printCopypaste(untyped)
-
- printTypings = reifyTyperDebug
- val typed = localTyper.typedPos(tree.pos)(untyped)
- typed
- }
- } catch {
- case ex: ReifierError =>
- unit.error(ex.pos, ex.msg)
- tree
- } finally {
- printTypings = saved
+trait Reifiers { self: Global =>
+
+ def reify(tree: Tree): Tree = {
+ if (tree.tpe != null) {
+ val saved = printTypings
+ try {
+ val reifyDebug = settings.Yreifydebug.value
+ val debugTrace = util.trace when reifyDebug
+ debugTrace("transforming = ")(if (settings.Xshowtrees.value) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString)
+ debugTrace("transformed = ") {
+ val reifier = new Reifier()
+ val untyped = reifier.reifyTopLevel(tree)
+
+ val reifyCopypaste = settings.Yreifycopypaste.value
+ if (reifyCopypaste) {
+ if (reifyDebug) println("=======================")
+ println(reifiedNodeToString(untyped))
+ if (reifyDebug) println("=======================")
}
- case _ =>
- super.transform(tree)
- }
- }
- def codify(tree: Tree): Tree = debugTrace("codified " + tree + " -> ") {
- val targetType = definitions.CodeClass.primaryConstructor.info.paramTypes.head
- val reifier = new Reifier()
- val arg = gen.mkAsInstanceOf(reifier.reifyTopLevel(tree), targetType, wrapInApply = false)
- val treetpe = // this really should use packedType(tree.tpe, context.owner)
- // where packedType is defined in Typers. But we can do that only if liftCode is moved to Typers.
- if (tree.tpe.typeSymbol.isAnonymousClass) tree.tpe.typeSymbol.classBound
- else tree.tpe
- New(TypeTree(appliedType(definitions.CodeClass.typeConstructor, List(treetpe.widen))),
- List(List(arg)))
+ untyped
+ }
+ } finally {
+ printTypings = saved
+ }
+ } else {
+ CannotReifyPreTyperTrees(tree)
}
}
- /**
- * Given a tree or type, generate a tree that when executed at runtime produces the original tree or type.
- * For instance: Given
- *
- * var x = 1; Code(x + 1)
- *
- * The `x + 1` expression is reified to
- *
- * $mr.Apply($mr.Select($mr.Ident($mr.freeVar("x". <Int>, x), "+"), List($mr.Literal($mr.Constant(1))))))
- *
- * Or, the term name 'abc' is reified to:
- *
- * $mr.Apply($mr.Select($mr.Ident("newTermName")), List(Literal(Constant("abc")))))
- *
- * todo: Treat embedded Code blocks by merging them into containing block
- *
- */
class Reifier() {
+ import definitions._
final val scalaPrefix = "scala."
final val localPrefix = "$local"
@@ -291,8 +161,6 @@ abstract class LiftCode extends Transform with TypingTransformers {
mirrorSelect("definitions.RootClass")
else if (sym == EmptyPackage)
mirrorSelect("definitions.EmptyPackage")
- else if (sym == EmptyPackageClass)
- mirrorSelect("definitions.EmptyPackageClass")
else if (sym.isModuleClass)
Select(reifySymRef(sym.sourceModule), "moduleClass")
else if (sym.isStatic && sym.isClass)
@@ -321,7 +189,7 @@ abstract class LiftCode extends Transform with TypingTransformers {
val symtpe = lambdaLift.boxIfCaptured(sym, sym.tpe, erasedTypes = false)
def markIfCaptured(arg: Ident): Tree =
if (sym.isCapturedVariable) referenceCapturedVariable(arg) else arg
- mirrorCall("freeVar", reify(sym.name.toString), reify(symtpe), markIfCaptured(Ident(sym)))
+ mirrorCall("newFreeVar", reify(sym.name.toString), reify(symtpe), markIfCaptured(Ident(sym)))
} else {
if (reifyDebug) println("Late local: " + sym)
registerReifiableSymbol(sym)
@@ -349,7 +217,7 @@ abstract class LiftCode extends Transform with TypingTransformers {
* Generate code to add type and annotation info to a reified symbol
*/
private def fillInSymbol(sym: Symbol): Tree = {
- val rset = Apply(Select(reifySymRef(sym), nme.setTypeSig), List(reifyType(sym.info)))
+ val rset = Apply(Select(reifySymRef(sym), nme.setTypeSignature), List(reifyType(sym.info)))
if (sym.annotations.isEmpty) rset
else Apply(Select(rset, nme.setAnnotations), List(reify(sym.annotations)))
}
@@ -412,9 +280,9 @@ abstract class LiftCode extends Transform with TypingTransformers {
private def reifyTree(tree: Tree): Tree = tree match {
case EmptyTree =>
reifyMirrorObject(EmptyTree)
- case This(_) if !(boundSyms contains tree.symbol) =>
+ case This(_) if tree.symbol != NoSymbol && !(boundSyms contains tree.symbol) =>
reifyFree(tree)
- case Ident(_) if !(boundSyms contains tree.symbol) =>
+ case Ident(_) if tree.symbol != NoSymbol && !(boundSyms contains tree.symbol) =>
if (tree.symbol.isVariable && tree.symbol.owner.isTerm) {
captureVariable(tree.symbol) // Note order dependency: captureVariable needs to come before reifyTree here.
mirrorCall("Select", reifyFree(tree), reifyName(nme.elem))
@@ -423,19 +291,25 @@ abstract class LiftCode extends Transform with TypingTransformers {
if (definedInLiftedCode(tt.tpe)) {
// erase non-essential (i.e. inferred) types
// reify symless counterparts of essential types
+ // @xeno.by: in general case reflective compiler lacks the context to typecheck the originals
+ // more info here: https://issues.scala-lang.org/browse/SI-5273?focusedCommentId=56057#comment-56057
+ // this is A BIG BAD TODO!
if (tt.original != null) reify(tt.original) else mirrorCall("TypeTree")
} else {
var rtt = mirrorCall(nme.TypeTree, reifyType(tt.tpe))
- if (tt.original != null) {
- val setOriginal = Select(rtt, newTermName("setOriginal"))
- val reifiedOriginal = reify(tt.original)
- rtt = Apply(setOriginal, List(reifiedOriginal))
- }
+ // @xeno.by: originals get typechecked during subsequent reflective compilation, which leads to subtle bugs
+ // https://issues.scala-lang.org/browse/SI-5273?focusedCommentId=56057#comment-56057
+ // until this is somehow sorted out, I disable reification of originals
+ // if (tt.original != null) {
+ // val setOriginal = Select(rtt, newTermName("setOriginal"))
+ // val reifiedOriginal = reify(tt.original)
+ // rtt = Apply(setOriginal, List(reifiedOriginal))
+ // }
rtt
}
case ta @ TypeApply(hk, ts) =>
if (ts exists isErased) reifyTree(hk) else reifyProduct(ta)
- case global.emptyValDef =>
+ case self.emptyValDef =>
mirrorSelect(nme.emptyValDef)
case Literal(constant @ Constant(tpe: Type)) if boundSyms exists (tpe contains _) =>
CannotReifyClassOfBoundType(tree, tpe)
@@ -466,7 +340,7 @@ abstract class LiftCode extends Transform with TypingTransformers {
val sym = tree.symbol
if (reifyDebug) println("This for %s, reified as freeVar".format(sym))
if (reifyDebug) println("Free: " + sym)
- val freeVar = mirrorCall("freeVar", reify(sym.name.toString), reify(sym.tpe), This(sym))
+ val freeVar = mirrorCall("newFreeVar", reify(sym.name.toString), reify(sym.tpe), This(sym))
mirrorCall(nme.Ident, freeVar)
case This(_) =>
if (reifyDebug) println("This for %s, reified as This".format(tree.symbol))
@@ -535,7 +409,7 @@ abstract class LiftCode extends Transform with TypingTransformers {
private def typePath(fullname: String): Tree = path(fullname, newTypeName)
private def mirrorAlias =
- ValDef(NoMods, nme.MIRROR_SHORT, TypeTree(), termPath(fullnme.MirrorPackage))
+ ValDef(NoMods, nme.MIRROR_SHORT, SingletonTypeTree(termPath(fullnme.MirrorPackage)), termPath(fullnme.MirrorPackage))
/**
* Generate code that generates a symbol table of all symbols registered in `reifiableSyms`
@@ -559,6 +433,11 @@ abstract class LiftCode extends Transform with TypingTransformers {
def this(msg: String) = this(NoPosition, msg)
}
+ def CannotReifyPreTyperTrees(tree: Tree) = {
+ val msg = "pre-typer trees are not supported, consider typechecking the tree before passing it to the reifier"
+ throw new ReifierError(tree.pos, msg)
+ }
+
def CannotReifyClassOfBoundType(tree: Tree, tpe: Type) = {
val msg = "cannot reify classOf[%s] which refers to a type declared inside the block being reified".format(tpe)
throw new ReifierError(tree.pos, msg)
diff --git a/src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala b/src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala
new file mode 100644
index 0000000000..98135fadda
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala
@@ -0,0 +1,75 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.tools.nsc
+package ast
+
+import compat.Platform.EOL
+import symtab._
+import Flags._
+
+trait ReifyPrinters { self: NodePrinters =>
+
+ val global: Global
+ import global._
+
+ object reifiedNodeToString extends Function1[Tree, String] {
+ def apply(tree: Tree): String = {
+ import scala.reflect.api.Modifier
+
+ // @PP: I fervently hope this is a test case or something, not anything being
+ // depended upon. Of more fragile code I cannot conceive.
+ // @eb: This stuff is only needed to debug-print out reifications in human-readable format
+ // Rolling a full-fledged, robust TreePrinter would be several times more code.
+ (for (line <- (tree.toString.split(EOL) drop 2 dropRight 1)) yield {
+ var s = line.trim
+ s = s.replace("$mr.", "")
+ s = s.replace(".apply", "")
+ s = s.replace("scala.collection.immutable.", "")
+ s = "List\\[List\\[.*?\\].*?\\]".r.replaceAllIn(s, "List")
+ s = "List\\[.*?\\]".r.replaceAllIn(s, "List")
+ s = s.replace("immutable.this.Nil", "List()")
+ s = s.replace("modifiersFromInternalFlags", "Modifiers")
+ s = s.replace("Modifiers(0L, newTypeName(\"\"), List())", "Modifiers()")
+ s = """Modifiers\((\d+)[lL], newTypeName\("(.*?)"\), List\((.*?)\)\)""".r.replaceAllIn(s, m => {
+ val buf = new StringBuilder
+
+ val flags = m.group(1).toLong
+ val s_flags = Flags.modifiersOfFlags(flags) map (_.sourceString) mkString ", "
+ if (s_flags != "")
+ buf.append("Set(" + s_flags + ")")
+
+ val privateWithin = "" + m.group(2)
+ if (privateWithin != "")
+ buf.append(", newTypeName(\"" + privateWithin + "\")")
+
+ val annotations = m.group(3)
+ if (annotations.nonEmpty)
+ buf.append(", List(" + annotations + ")")
+
+ "Modifiers(" + buf.toString + ")"
+ })
+ s = """setInternalFlags\((\d+)L\)""".r.replaceAllIn(s, m => {
+ val flags = m.group(1).toLong
+ val mods = Flags.modifiersOfFlags(flags) map (_.sourceString)
+ "setInternalFlags(flagsOfModifiers(List(" + mods.mkString(", ") + ")))"
+ })
+
+ s
+ }) mkString EOL
+ }
+ }
+
+
+ def printReifyCopypaste(tree: Tree) {
+ val reifyDebug = settings.Yreifydebug.value
+ if (reifyDebug) println("=======================")
+ printReifyCopypaste1(tree)
+ if (reifyDebug) println("=======================")
+ }
+
+ def printReifyCopypaste1(tree: Tree) {
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index 5c3071739c..c060e938bb 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -58,7 +58,7 @@ trait TreePrinters extends reflect.internal.TreePrinters { this: Global =>
treePrinter.print("<tree with deferred refcheck>")
case SelectFromArray(qualifier, name, _) =>
- treePrinter.print(qualifier, ".<arr>", treePrinter.symName(tree, name))
+ treePrinter.print(qualifier, ".<arr>", symName(tree, name))
case _ =>
super.xprintTree(treePrinter, tree)
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 3baff7da9e..6aee52a354 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -133,7 +133,7 @@ abstract class GenICode extends SubComponent {
if (!ctx1.bb.closed) ctx1.bb.close
prune(ctx1.method)
} else
- ctx1.method.setCode(null)
+ ctx1.method.setCode(NoCode)
ctx1
case Template(_, _, body) =>
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
index 2668e7f29f..298c9171a1 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
@@ -177,8 +177,7 @@ trait Members {
/** method parameters */
var params: List[Local] = Nil
- // TODO - see how null is stil arriving here
- def hasCode = (code ne NoCode) && (code ne null)
+ def hasCode = code ne NoCode
def setCode(code: Code): IMethod = {
this.code = code;
this
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index d1ce460eb9..485a1f3a5c 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -167,8 +167,6 @@ trait ScalaSettings extends AbsScalaSettings
val Yreifycopypaste =
BooleanSetting ("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.")
val Yreifydebug = BooleanSetting ("-Yreify-debug", "Trace reification.")
- val Yreifytyperdebug
- = BooleanSetting ("-Yreifytyper-debug", "Trace typings of reified trees.")
val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup")
val Yrepldebug = BooleanSetting ("-Yrepl-debug", "Trace all repl activity.") .
withPostSetHook(_ => interpreter.replProps.debug setValue true)
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index d8db62a408..ed89acd9e8 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -1269,13 +1269,13 @@ abstract class ClassfileParser {
if ((jflags & (JAVA_ACC_PRIVATE | JAVA_ACC_PROTECTED | JAVA_ACC_PUBLIC)) == 0)
// See ticket #1687 for an example of when topLevelClass is NoSymbol: it
// apparently occurs when processing v45.3 bytecode.
- if (sym.toplevelClass != NoSymbol)
- sym.privateWithin = sym.toplevelClass.owner
+ if (sym.enclosingTopLevelClass != NoSymbol)
+ sym.privateWithin = sym.enclosingTopLevelClass.owner
// protected in java means package protected. #3946
if ((jflags & JAVA_ACC_PROTECTED) != 0)
- if (sym.toplevelClass != NoSymbol)
- sym.privateWithin = sym.toplevelClass.owner
+ if (sym.enclosingTopLevelClass != NoSymbol)
+ sym.privateWithin = sym.enclosingTopLevelClass.owner
}
@inline private def isPrivate(flags: Int) = (flags & JAVA_ACC_PRIVATE) != 0
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index 4fa5b52de3..89f1cc26e0 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -60,8 +60,8 @@ abstract class Flatten extends InfoTransform {
private val flattened = new TypeMap {
def apply(tp: Type): Type = tp match {
case TypeRef(pre, sym, args) if isFlattenablePrefix(pre) =>
- assert(args.isEmpty && sym.toplevelClass != NoSymbol, sym.ownerChain)
- typeRef(sym.toplevelClass.owner.thisType, sym, Nil)
+ assert(args.isEmpty && sym.enclosingTopLevelClass != NoSymbol, sym.ownerChain)
+ typeRef(sym.enclosingTopLevelClass.owner.thisType, sym, Nil)
case ClassInfoType(parents, decls, clazz) =>
var parents1 = parents
val decls1 = scopeTransform(clazz) {
@@ -119,7 +119,7 @@ abstract class Flatten extends InfoTransform {
val sym = tree.symbol
val tree1 = tree match {
case ClassDef(_, _, _, _) if sym.isNestedClass =>
- liftedDefs(sym.toplevelClass.owner) += tree
+ liftedDefs(sym.enclosingTopLevelClass.owner) += tree
EmptyTree
case Select(qual, name) if (sym.isStaticModule && !sym.owner.isPackageClass) =>
atPhase(phase.next) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 036e7fc750..3d2f86d54d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -1163,7 +1163,7 @@ trait Implicits {
/* !!! the following is almost right, but we have to splice nested manifest
* !!! types into this type. This requires a substantial extension of
* !!! reifiers.
- val reifier = new liftcode.Reifier()
+ val reifier = new Reifier()
val rtree = reifier.reifyTopLevel(tp1)
manifestFactoryCall("apply", tp, rtree)
*/
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index eac657da19..b97fbebec2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -228,9 +228,9 @@ trait Infer {
if (sym.isError) {
tree setSymbol sym setType ErrorType
} else {
- val topClass = context.owner.toplevelClass
+ val topClass = context.owner.enclosingTopLevelClass
if (context.unit.exists)
- context.unit.depends += sym.toplevelClass
+ context.unit.depends += sym.enclosingTopLevelClass
var sym1 = sym filter (alt => context.isAccessible(alt, pre, site.isInstanceOf[Super]))
// Console.println("check acc " + (sym, sym1) + ":" + (sym.tpe, sym1.tpe) + " from " + pre);//DEBUG
@@ -640,13 +640,7 @@ trait Infer {
case ExistentialType(tparams, qtpe) =>
isApplicable(undetparams, qtpe, argtpes0, pt)
case MethodType(params, _) =>
- val formals0 = params map { param =>
- param.tpe match {
- case TypeRef(_, sym, List(tpe)) if sym isNonBottomSubClass CodeClass => tpe
- case tpe => tpe
- }
- }
- val formals = formalTypes(formals0, argtpes0.length)
+ val formals = formalTypes(params map { _.tpe }, argtpes0.length)
def tryTupleApply: Boolean = {
// if 1 formal, 1 argtpe (a tuple), otherwise unmodified argtpes0
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index c63ae90ef6..a2c918024f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -98,7 +98,7 @@ trait Macros { self: Analyzer =>
}
/** Return optionally address of companion object and implementation method symbol
- * of given macro; or None if implementation classfile cannot be loaded or does
+ * of given macro; or None if implementation classfile cannot be loaded or does
* not contain the macro implementation.
*/
def macroImpl(mac: Symbol): Option[(AnyRef, mirror.Symbol)] = {
@@ -106,13 +106,16 @@ trait Macros { self: Analyzer =>
val mmeth = macroMeth(mac)
if (mmeth == NoSymbol) None
else {
- val receiverClass: mirror.Symbol = mirror.classWithName(mmeth.owner.fullName)
+ val receiverClass: mirror.Symbol = mirror.symbolForName(mmeth.owner.fullName)
val receiverObj = receiverClass.companionModule
- if (receiverObj == NoSymbol) None
+ if (receiverObj == mirror.NoSymbol) None
else {
- val receiver = mirror.getCompanionObject(receiverClass)
+ val receiver = mirror.companionInstance(receiverClass)
val rmeth = receiverObj.info.member(mirror.newTermName(mmeth.name.toString))
- Some((receiver, rmeth))
+ if (rmeth == mirror.NoSymbol) None
+ else {
+ Some((receiver, rmeth))
+ }
}
}
} catch {
@@ -136,8 +139,16 @@ trait Macros { self: Analyzer =>
else as
}
val rawArgs: Seq[Any] = rawArgss.flatten
+ val savedInfolevel = nodePrinters.infolevel
try {
- Some(mirror.invoke(receiver, rmeth, rawArgs: _*))
+ // @xeno.by: InfoLevel.Verbose examines and prints out infos of symbols
+ // by the means of this'es these symbols can climb up the lexical scope
+ // when these symbols will be examined by a node printer
+ // they will enumerate and analyze their children (ask for infos and tpes)
+ // if one of those children involves macro expansion, things might get nasty
+ // that's why I'm temporarily turning this behavior off
+ nodePrinters.infolevel = nodePrinters.InfoLevel.Quiet
+ Some(mirror.invoke(receiver, rmeth)(rawArgs: _*))
} catch {
case ex =>
val realex = ReflectionUtils.unwrapThrowable(ex)
@@ -146,6 +157,8 @@ trait Macros { self: Analyzer =>
val msg = System.getProperty("line.separator") + stacktrace
context.unit.error(tree.pos, "exception during macro expansion: " + msg)
None
+ } finally {
+ nodePrinters.infolevel = savedInfolevel
}
case None =>
val trace = scala.tools.nsc.util.trace when settings.debug.value
@@ -159,7 +172,7 @@ trait Macros { self: Analyzer =>
macroDef.allOverriddenSymbols match {
case first :: _ =>
Some(Select(qual, name) setPos tree.pos setSymbol first)
- case _ =>
+ case _ =>
trace("macro is not overridden: ")(tree)
notFound()
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 66330d4321..59437dc036 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -708,8 +708,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
}
- def isCodeType(tpe: Type) = tpe.typeSymbol isNonBottomSubClass CodeClass
-
/** Perform the following adaptations of expression, pattern or type `tree` wrt to
* given mode `mode` and given prototype `pt`:
* (-1) For expressions with annotated types, let AnnotationCheckers decide what to do
@@ -2005,8 +2003,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
*/
def typedFunction(fun: Function, mode: Int, pt: Type): Tree = {
val numVparams = fun.vparams.length
- val codeExpected = !forMSIL && (pt.typeSymbol isNonBottomSubClass CodeClass)
-
if (numVparams > definitions.MaxFunctionArity)
return MaxFunctionArityError(fun)
@@ -2023,7 +2019,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
else
(FunctionClass(numVparams), fun.vparams map (x => NoType), WildcardType)
- val (clazz, argpts, respt) = decompose(if (codeExpected) pt.normalize.typeArgs.head else pt)
+ val (clazz, argpts, respt) = decompose(pt)
if (argpts.lengthCompare(numVparams) != 0)
WrongNumberOfParametersError(fun, argpts)
else {
@@ -2033,7 +2029,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (isFullyDefined(argpt)) argpt
else {
fun match {
- case etaExpansion(vparams, fn, args) if !codeExpected =>
+ case etaExpansion(vparams, fn, args) =>
silent(_.typed(fn, forFunMode(mode), pt)) match {
case SilentResultValue(fn1) if context.undetparams.isEmpty =>
// if context,undetparams is not empty, the function was polymorphic,
@@ -2065,13 +2061,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val restpe = packedType(body1, fun.symbol).deconst.resultType
val funtpe = typeRef(clazz.tpe.prefix, clazz, formals :+ restpe)
// body = checkNoEscaping.locals(context.scope, restpe, body)
- val fun1 = treeCopy.Function(fun, vparams, body1).setType(funtpe)
- if (codeExpected) lifted(fun1) else fun1
- }
+ treeCopy.Function(fun, vparams, body1).setType(funtpe)
}
-
- def lifted(tree: Tree): Tree = typedPos(tree.pos) {
- Apply(Select(Ident(CodeModule), nme.lift_), List(tree))
}
def typedRefinement(stats: List[Tree]) {
@@ -3733,7 +3724,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
return typed(treeCopy.Select(tree, qual1, name), mode, pt)
}
if (!reallyExists(sym)) {
- if (context.owner.toplevelClass.isJavaDefined && name.isTypeName) {
+ if (context.owner.enclosingTopLevelClass.isJavaDefined && name.isTypeName) {
val tree1 = atPos(tree.pos) { gen.convertToSelectFromType(qual, name) }
if (tree1 != EmptyTree) return typed1(tree1, mode, pt)
}