Permalink
Browse files

brings reification up to speed

Along with recovering from reflection refactoring, I implemented
some new features (e.g. rollback of macro expansions),
and did some stabilizing refactorings (e.g. moved mutable state into a ghetto).

Also used the refactoring as a chance to fix free and aux symbols.
Encapsulated this notion in a symbol table class, which allowed me
to address outstanding issues with symbol table inheritance and inlining.
  • Loading branch information...
xeno-by committed Jun 6, 2012
1 parent ce67870 commit 6355d1a0b825c99560d4ccec1a8769f7421b1a71
Showing with 1,707 additions and 970 deletions.
  1. +4 −2 src/compiler/scala/reflect/internal/StdAttachments.scala
  2. +13 −7 src/compiler/scala/reflect/internal/StdNames.scala
  3. +0 −173 src/compiler/scala/reflect/internal/TreeInfo.scala
  4. +26 −0 src/compiler/scala/reflect/makro/runtime/ContextReifiers.scala
  5. +47 −8 src/compiler/scala/reflect/makro/runtime/Reifiers.scala
  6. +18 −1 src/compiler/scala/reflect/reify/Errors.scala
  7. +0 −24 src/compiler/scala/reflect/reify/NodePrinters.scala
  8. +12 −9 src/compiler/scala/reflect/reify/Phases.scala
  9. +56 −56 src/compiler/scala/reflect/reify/Reifier.scala
  10. +65 −0 src/compiler/scala/reflect/reify/States.scala
  11. +43 −24 src/compiler/scala/reflect/reify/Taggers.scala
  12. +6 −7 src/compiler/scala/reflect/reify/codegen/{AnnotationInfos.scala → GenAnnotationInfos.scala}
  13. +2 −3 src/compiler/scala/reflect/reify/codegen/{Names.scala → GenNames.scala}
  14. +2 −3 src/compiler/scala/reflect/reify/codegen/{Positions.scala → GenPositions.scala}
  15. +109 −0 src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
  16. +51 −88 src/compiler/scala/reflect/reify/codegen/{Trees.scala → GenTrees.scala}
  17. +203 −0 src/compiler/scala/reflect/reify/codegen/GenTypes.scala
  18. +43 −10 src/compiler/scala/reflect/reify/codegen/{Util.scala → GenUtils.scala}
  19. +0 −184 src/compiler/scala/reflect/reify/codegen/Symbols.scala
  20. +0 −168 src/compiler/scala/reflect/reify/codegen/Types.scala
  21. +50 −31 src/compiler/scala/reflect/reify/package.scala
  22. +9 −8 src/compiler/scala/reflect/reify/phases/Calculate.scala
  23. +41 −41 src/compiler/scala/reflect/reify/phases/Metalevels.scala
  24. +12 −19 src/compiler/scala/reflect/reify/phases/Reify.scala
  25. +43 −4 src/compiler/scala/reflect/reify/phases/Reshape.scala
  26. +294 −0 src/compiler/scala/reflect/reify/utils/Extractors.scala
  27. +144 −0 src/compiler/scala/reflect/reify/utils/NodePrinters.scala
  28. +12 −0 src/compiler/scala/reflect/reify/utils/StdAttachments.scala
  29. +223 −0 src/compiler/scala/reflect/reify/utils/SymbolTables.scala
  30. +21 −0 src/compiler/scala/reflect/reify/utils/Utils.scala
  31. +14 −1 src/compiler/scala/reflect/runtime/package.scala
  32. +0 −1 src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
  33. +1 −1 src/compiler/scala/tools/nsc/transform/Erasure.scala
  34. +1 −1 src/compiler/scala/tools/nsc/transform/UnCurry.scala
  35. +3 −3 src/compiler/scala/tools/nsc/typechecker/Implicits.scala
  36. +1 −1 src/compiler/scala/tools/nsc/typechecker/Macros.scala
  37. +0 −71 src/compiler/scala/tools/nsc/typechecker/Taggings.scala
  38. +86 −0 src/compiler/scala/tools/nsc/typechecker/Tags.scala
  39. +13 −5 src/compiler/scala/tools/nsc/typechecker/Typers.scala
  40. +7 −4 src/compiler/scala/tools/reflect/FastTrack.scala
  41. +1 −1 src/compiler/scala/tools/reflect/ToolBoxFactory.scala
  42. +11 −4 src/library/scala/reflect/api/StandardNames.scala
  43. +1 −1 src/library/scala/reflect/makro/Context.scala
  44. +19 −6 src/library/scala/reflect/makro/Reifiers.scala
@@ -6,7 +6,9 @@ import scala.reflect.makro.runtime.{Context => MacroContext}
trait StdAttachments {
self: SymbolTable =>
case class ReifyAttachment(original: Symbol)
case object BackquotedIdentifierAttachment
case class CompoundTypeTreeOriginalAttachment(parents: List[Tree], stats: List[Tree])
case class MacroExpansionAttachment(original: Tree)
}
@@ -213,6 +213,8 @@ trait StdNames {
final val REFINE_CLASS_NAME: NameType = "<refinement>"
final val REPEATED_PARAM_CLASS_NAME: NameType = "<repeated>"
final val WILDCARD_STAR: NameType = "_*"
final val REIFY_TREECREATOR_PREFIX: NameType = "$treecreator"
final val REIFY_TYPECREATOR_PREFIX: NameType = "$typecreator"
final val Any: NameType = "Any"
final val AnyVal: NameType = "AnyVal"
@@ -299,12 +301,17 @@ trait StdNames {
val LAZY_LOCAL: NameType = "$lzy"
val LAZY_SLOW_SUFFIX: NameType = "$lzycompute"
val LOCAL_SUFFIX_STRING = " "
val MIRROR_FREE_PREFIX: NameType = "free$"
val MIRROR_FREE_THIS_SUFFIX: NameType = "$this"
val MIRROR_FREE_VALUE_SUFFIX: NameType = "$value"
val MIRROR_PREFIX: NameType = "$mr."
val MIRROR_SHORT: NameType = "$mr"
val MIRROR_SYMDEF_PREFIX: NameType = "symdef$"
val UNIVERSE_BUILD_PREFIX: NameType = "$u.build."
val UNIVERSE_BUILD: NameType = "$u.build"
val UNIVERSE_PREFIX: NameType = "$u."
val UNIVERSE_SHORT: NameType = "$u"
val MIRROR_PREFIX: NameType = "$m."
val MIRROR_SHORT: NameType = "$m"
val MIRROR_UNTYPED: NameType = "$m$untyped"
val REIFY_FREE_PREFIX: NameType = "free$"
val REIFY_FREE_THIS_SUFFIX: NameType = "$this"
val REIFY_FREE_VALUE_SUFFIX: NameType = "$value"
val REIFY_SYMDEF_PREFIX: NameType = "symdef$"
val MIXIN_CONSTRUCTOR: NameType = "$init$"
val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$"
val OUTER: NameType = "$outer"
@@ -747,7 +754,6 @@ trait StdNames {
val tail: NameType = "tail"
val `then` : NameType = "then"
val this_ : NameType = "this"
val thisModuleType : NameType = "thisModuleType"
val thisPrefix : NameType = "thisPrefix"
val throw_ : NameType = "throw"
val toArray: NameType = "toArray"
@@ -568,177 +568,4 @@ abstract class TreeInfo {
object DynamicUpdate extends DynamicApplicationExtractor(_ == nme.updateDynamic)
object DynamicApplication extends DynamicApplicationExtractor(isApplyDynamicName)
object DynamicApplicationNamed extends DynamicApplicationExtractor(_ == nme.applyDynamicNamed)
// domain-specific extractors for reification
import definitions._
object TypedOrAnnotated {
def unapply(tree: Tree): Option[Tree] = tree match {
case ty @ Typed(_, _) =>
Some(ty)
case at @ Annotated(_, _) =>
Some(at)
case _ =>
None
}
}
object TreeSplice {
def unapply(tree: Tree): Option[Tree] = tree match {
case Select(splicee, _) if tree.symbol == ExprSplice =>
Some(splicee)
case _ =>
None
}
}
object Reified {
def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match {
case ReifiedTree(reifee, symbolTable, reified, _) =>
Some(reifee, symbolTable, reified)
case ReifiedType(reifee, symbolTable, reified) =>
Some(reifee, symbolTable, reified)
case _ =>
None
}
}
object ReifiedTree {
def unapply(tree: Tree): Option[(Tree, List[Tree], Tree, Tree)] = tree match {
case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(Apply(_, List(tree)), List(Apply(_, tpe :: _)))) if mrDef.name == nme.MIRROR_SHORT =>
Some(reifee, symbolTable, tree, tpe)
case _ =>
None
}
}
object InlineableTreeSplice {
def unapply(tree: Tree): Option[(Tree, List[Tree], Tree, Tree, Symbol)] = tree match {
case select @ Select(ReifiedTree(splicee, symbolTable, tree, tpe), _) if select.symbol == ExprSplice =>
Some(splicee, symbolTable, tree, tpe, select.symbol)
case _ =>
None
}
}
object InlinedTreeSplice {
def unapply(tree: Tree): Option[(Tree, List[Tree], Tree, Tree)] = tree match {
case Select(ReifiedTree(splicee, symbolTable, tree, tpe), name) if name == nme.tree =>
Some(splicee, symbolTable, tree, tpe)
case _ =>
None
}
}
object ReifiedType {
def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match {
case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(_, tpe :: _)) if mrDef.name == nme.MIRROR_SHORT =>
Some(reifee, symbolTable, tpe)
case _ =>
None
}
}
object InlinedTypeSplice {
def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match {
case Select(ReifiedType(splicee, symbolTable, tpe), name) if name == nme.tpe =>
Some(splicee, symbolTable, tpe)
case _ =>
None
}
}
object FreeDef {
def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
case FreeTermDef(mrRef, name, binding, flags, origin) =>
Some(mrRef, name, binding, flags, origin)
case FreeTypeDef(mrRef, name, binding, flags, origin) =>
Some(mrRef, name, binding, flags, origin)
case _ =>
None
}
}
object FreeTermDef {
def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
case ValDef(_, name, _, Apply(Select(mrRef @ Ident(_), newFreeTerm), List(_, _, binding, Literal(Constant(flags: Long)), Literal(Constant(origin: String)))))
if mrRef.name == nme.MIRROR_SHORT && newFreeTerm == nme.newFreeTerm =>
Some(mrRef, name, binding, flags, origin)
case _ =>
None
}
}
object FreeTypeDef {
def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
case ValDef(_, name, _, Apply(Select(mrRef1 @ Ident(_), newFreeType), List(_, _, value, Literal(Constant(flags: Long)), Literal(Constant(origin: String)))))
if mrRef1.name == nme.MIRROR_SHORT && (newFreeType == nme.newFreeType || newFreeType == nme.newFreeExistential) =>
value match {
case Apply(TypeApply(Select(Select(mrRef2 @ Ident(_), typeTag), apply), List(binding)), List(Literal(Constant(null)), _))
if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag && apply == nme.apply =>
Some(mrRef1, name, binding, flags, origin)
case Apply(TypeApply(Select(mrRef2 @ Ident(_), typeTag), List(binding)), List(Literal(Constant(null)), _))
if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag =>
Some(mrRef1, name, binding, flags, origin)
case _ =>
throw new Error("unsupported free type def: %s%n%s".format(value, showRaw(value)))
}
case _ =>
None
}
}
object FreeRef {
def unapply(tree: Tree): Option[(Tree, TermName)] = tree match {
case Apply(Select(mrRef @ Ident(_), ident), List(Ident(name: TermName))) if ident == nme.Ident && name.startsWith(nme.MIRROR_FREE_PREFIX) =>
Some(mrRef, name)
case _ =>
None
}
}
object TypeRefToFreeType {
def unapply(tree: Tree): Option[TermName] = tree match {
case Apply(Select(Select(mrRef @ Ident(_), typeRef), apply), List(Select(_, noSymbol), Ident(freeType: TermName), nil))
if (mrRef.name == nme.MIRROR_SHORT && typeRef == nme.TypeRef && noSymbol == nme.NoSymbol && freeType.startsWith(nme.MIRROR_FREE_PREFIX)) =>
Some(freeType)
case _ =>
None
}
}
object NestedExpr {
def unapply(tree: Tree): Option[(Tree, Tree, Tree)] = tree match {
case Apply(Apply(factory @ Select(expr, apply), List(tree)), List(typetag)) if expr.symbol == ExprModule && apply == nme.apply =>
Some(factory, tree, typetag)
case _ =>
None
}
}
object BoundTerm {
def unapply(tree: Tree): Option[Tree] = tree match {
case Ident(name) if name.isTermName =>
Some(tree)
case This(_) =>
Some(tree)
case _ =>
None
}
}
object BoundType {
def unapply(tree: Tree): Option[Tree] = tree match {
case Select(_, name) if name.isTypeName =>
Some(tree)
case SelectFromTypeTree(_, name) if name.isTypeName =>
Some(tree)
case Ident(name) if name.isTypeName =>
Some(tree)
case _ =>
None
}
}
}
@@ -0,0 +1,26 @@
package scala.reflect.makro
package runtime
abstract class ContextReifiers { self =>
val c: Context
import c.universe._
import definitions._
import treeBuild._
import scala.reflect.reify.Taggers
import language.implicitConversions
private implicit def context2taggers(c0: Context) : Taggers { val c: c0.type } = new { val c: c0.type = c0 } with Taggers
private def forMacroContext[T](prefix: Tree)(op: (Tree, Tree) => T): T = {
val universe = gen.mkAttributedSelect(prefix.duplicate, MacroContextUniverse) setType SingleType(prefix.tpe, MacroContextUniverse)
val mirror = TypeApply(Select(Select(prefix.duplicate, nme.mirror), nme.asInstanceOf_), List(Select(Ident(nme.UNIVERSE_SHORT), tpnme.Mirror)))
op(universe, mirror)
}
def materializeExprForMacroContext(prefix: Tree, expr: Tree): Tree =
forMacroContext(prefix)((universe, mirror) => c.materializeExpr(universe, mirror, expr))
def materializeTypeTagForMacroContext(prefix: Tree, tpe: Type, concrete: Boolean): Tree =
forMacroContext(prefix)((universe, mirror) => c.materializeTypeTag(universe, mirror, tpe, concrete))
}
@@ -9,20 +9,59 @@ package runtime
trait Reifiers {
self: Context =>
val global: universe.type = universe
import universe._
import definitions._
lazy val reflectMirrorPrefix: Tree = ???
lazy val basisUniverse: Tree = gen.mkBasisUniverseRef
def reifyTree(prefix: Tree, tree: Tree): Tree =
scala.reflect.reify.`package`.reifyTree(universe)(callsiteTyper, prefix, tree)
lazy val runtimeUniverse: Tree = gen.mkRuntimeUniverseRef
def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Tree =
scala.reflect.reify.`package`.reifyType(universe)(callsiteTyper, prefix, tpe, dontSpliceAtTopLevel, concrete)
def reifyTree(universe: Tree, mirror: Tree, tree: Tree): Tree = {
val result = scala.reflect.reify.`package`.reifyTree(self.universe)(callsiteTyper, universe, mirror, tree)
logFreeVars(enclosingPosition, result)
result
}
def reifyType(universe: Tree, mirror: Tree, tpe: Type, concrete: Boolean = false): Tree = {
val result = scala.reflect.reify.`package`.reifyType(self.universe)(callsiteTyper, universe, mirror, tpe, concrete)
logFreeVars(enclosingPosition, result)
result
}
def reifyRuntimeClass(tpe: Type, concrete: Boolean = true): Tree =
scala.reflect.reify.`package`.reifyRuntimeClass(universe)(callsiteTyper, tpe, concrete)
scala.reflect.reify.`package`.reifyRuntimeClass(universe)(callsiteTyper, tpe, concrete = concrete)
def reifyEnclosingRuntimeClass: Tree =
scala.reflect.reify.`package`.reifyEnclosingRuntimeClass(universe)(callsiteTyper)
def unreifyTree(tree: Tree): Tree = {
assert(ExprSplice != NoSymbol)
Select(tree, ExprSplice)
}
object utils extends {
val global: self.global.type = self.global
val typer: global.analyzer.Typer = self.callsiteTyper
} with scala.reflect.reify.utils.Utils
import utils._
private def logFreeVars(position: Position, reification: Tree): Unit = {
def logFreeVars(symtab: SymbolTable): Unit =
// logging free vars only when they are untyped prevents avalanches of duplicate messages
symtab.syms map (sym => symtab.symDef(sym)) foreach {
case FreeTermDef(_, _, binding, _, origin) if universe.settings.logFreeTerms.value && binding.tpe == null =>
reporter.echo(position, "free term: %s %s".format(showRaw(binding), origin))
case FreeTypeDef(_, _, binding, _, origin) if universe.settings.logFreeTypes.value && binding.tpe == null =>
reporter.echo(position, "free type: %s %s".format(showRaw(binding), origin))
case _ =>
// do nothing
}
def unreifyTree(tree: Tree): Tree =
Select(tree, definitions.ExprSplice)
if (universe.settings.logFreeTerms.value || universe.settings.logFreeTypes.value)
reification match {
case ReifiedTree(_, _, symtab, _, _, _, _) => logFreeVars(symtab)
case ReifiedType(_, _, symtab, _, _, _) => logFreeVars(symtab)
}
}
}
@@ -7,7 +7,7 @@ import scala.reflect.makro.UnexpectedReificationError
trait Errors {
self: Reifier =>
import mirror._
import global._
import definitions._
def defaultErrorPosition = {
@@ -38,6 +38,23 @@ trait Errors {
throw new ReificationError(defaultErrorPosition, msg)
}
def CannotConvertManifestToTagWithoutScalaReflect(tpe: Type, manifestInScope: Tree) = {
val msg = s"""
|to create a type tag here, it is necessary to interoperate with the manifest `$manifestInScope` in scope.
|however manifest -> typetag conversion requires Scala reflection, which is not present on the classpath.
|to proceed put scala-reflect.jar on your compilation classpath and recompile.""".trim.stripMargin
throw new ReificationError(defaultErrorPosition, msg)
}
def CannotReifyRuntimeSplice(tree: Tree) = {
val msg = """
|the splice cannot be resolved statically, which means there is a cross-stage evaluation involved.
|cross-stage evaluations need to be invoked explicitly, so we're showing you this error.
|if you're sure this is not an oversight, add scala-compiler.jar to the classpath,
|import `scala.tools.reflect.Eval` and call `<your expr>.eval` instead.""".trim.stripMargin
throw new ReificationError(tree.pos, msg)
}
// unexpected errors: these can never happen under normal conditions unless there's a bug in the compiler (or in a compiler plugin or in a macro)
// hence, we fail fast and loudly and don't care about being nice - in this situation noone will appreciate our quiet nicety

This file was deleted.

Oops, something went wrong.
Oops, something went wrong.

0 comments on commit 6355d1a

Please sign in to comment.