diff options
-rw-r--r-- | src/compiler/scala/reflect/reify/codegen/Types.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/reflect/reify/phases/Reify.scala | 66 |
2 files changed, 39 insertions, 29 deletions
diff --git a/src/compiler/scala/reflect/reify/codegen/Types.scala b/src/compiler/scala/reflect/reify/codegen/Types.scala index 841ec61e60..8fa24c5b00 100644 --- a/src/compiler/scala/reflect/reify/codegen/Types.scala +++ b/src/compiler/scala/reflect/reify/codegen/Types.scala @@ -84,7 +84,7 @@ trait Types { def spliceType(tpe: Type): Tree = { // [Eugene] it seems that depending on the context the very same symbol can be either a spliceable tparam or a quantified existential. very weird! - val quantified = currents collect { case ExistentialType(quantified, _) => quantified } flatMap identity + val quantified = currentQuantified if (tpe.isSpliceable && !(quantified contains tpe.typeSymbol)) { if (reifyDebug) println("splicing " + tpe) diff --git a/src/compiler/scala/reflect/reify/phases/Reify.scala b/src/compiler/scala/reflect/reify/phases/Reify.scala index a1ff486ed7..e03ff5832c 100644 --- a/src/compiler/scala/reflect/reify/phases/Reify.scala +++ b/src/compiler/scala/reflect/reify/phases/Reify.scala @@ -19,37 +19,47 @@ trait Reify extends Symbols import definitions._ import treeInfo._ + // `reify` looked so nice, I wanted to push the last bit of orthogonal + // logic out of it so you can see the improvement. There is no cost to + // wrapper methods of this form because the inliner will eliminate them, + // but they are very good at separating concerns like pushing/popping + // a stack, and they are great for composition and reuse. + // + // Also, please avoid public vars whenever possible. + private object reifyStack { + var currents: List[Any] = reifee :: Nil + + @inline final def push[T](reifee: Any)(body: => T): T = { + currents ::= reifee + try body + finally currents = currents.tail + } + } + def currentQuantified = flatCollect(reifyStack.currents)({ case ExistentialType(quantified, _) => quantified }) + def current = reifyStack.currents.head + /** * Reifies any supported value. * For internal use only, use ``reified'' instead. */ - var currents: List[Any] = reifee :: Nil - def current = currents.head - def reify(reifee: Any): Tree = { - currents = reifee :: currents - try { - reifee match { - // before adding some case here, in global scope, please, consider - // whether it can be localized like reifyAnnotationInfo or reifyScope - // this will help reification stay as sane as possible - case sym: Symbol => reifySymRef(sym) - case tpe: Type => reifyType(tpe) - case name: Name => reifyName(name) - case tree: Tree => reifyTree(tree) - // disabled because this is a very special case that I plan to remove later - // why do I dislike annotations? see comments to `reifyAnnotationInfo` + def reify(reifee: Any): Tree = reifyStack.push(reifee)(reifee match { + // before adding some case here, in global scope, please, consider + // whether it can be localized like reifyAnnotationInfo or reifyScope + // this will help reification stay as sane as possible + case sym: Symbol => reifySymRef(sym) + case tpe: Type => reifyType(tpe) + case name: Name => reifyName(name) + case tree: Tree => reifyTree(tree) + // disabled because this is a very special case that I plan to remove later + // why do I dislike annotations? see comments to `reifyAnnotationInfo` // case ann: AnnotationInfo => reifyAnnotationInfo(ann) - case pos: Position => reifyPosition(pos) - case mods: mirror.Modifiers => reifyModifiers(mods) - case xs: List[_] => reifyList(xs) - case s: String => Literal(Constant(s)) - case v if isAnyVal(v) => Literal(Constant(v)) - case null => Literal(Constant(null)) - case _ => - throw new Error("reifee %s of type %s is not supported".format(reifee, reifee.getClass)) - } - } finally { - currents = currents.tail - } - } + case pos: Position => reifyPosition(pos) + case mods: mirror.Modifiers => reifyModifiers(mods) + case xs: List[_] => reifyList(xs) + case s: String => Literal(Constant(s)) + case v if isAnyVal(v) => Literal(Constant(v)) + case null => Literal(Constant(null)) + case _ => + throw new Error("reifee %s of type %s is not supported".format(reifee, reifee.getClass)) + }) }
\ No newline at end of file |