summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/TreeGen.scala
diff options
context:
space:
mode:
authorDen Shabalin <den.shabalin@gmail.com>2013-07-08 20:48:17 +0200
committerEugene Burmako <xeno.by@gmail.com>2013-07-08 21:20:27 +0200
commit7e6c723dff835a681bdc60f87283652e42adc699 (patch)
tree50c602b69b4cd0598d25039ea3cd4da2a160ebcd /src/reflect/scala/reflect/internal/TreeGen.scala
parentcbe5362a62904a88de78e3b068a544612e46c0cc (diff)
downloadscala-7e6c723dff835a681bdc60f87283652e42adc699.tar.gz
scala-7e6c723dff835a681bdc60f87283652e42adc699.tar.bz2
scala-7e6c723dff835a681bdc60f87283652e42adc699.zip
moves template creation logic from nsc to reflect
This routine is going to be necessary in scala-reflect.jar to support ClassDef construction/deconstruction in the upcoming quasiquote patch.
Diffstat (limited to 'src/reflect/scala/reflect/internal/TreeGen.scala')
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index b75fd72526..1af8c225f5 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -2,6 +2,8 @@ package scala
package reflect
package internal
+import Flags._
+
abstract class TreeGen extends macros.TreeBuilder {
val global: SymbolTable
@@ -302,4 +304,78 @@ abstract class TreeGen extends macros.TreeBuilder {
val factory = Select(gen.mkAttributedRef(SeqModule), nme.apply)
Apply(factory, List(arg))
}
+
+ def mkSuperInitCall: Select = Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR)
+
+ /** Generates a template with constructor corresponding to
+ *
+ * constrmods (vparams1_) ... (vparams_n) preSuper { presupers }
+ * extends superclass(args_1) ... (args_n) with mixins { self => body }
+ *
+ * This gets translated to
+ *
+ * extends superclass with mixins { self =>
+ * presupers' // presupers without rhs
+ * vparamss // abstract fields corresponding to value parameters
+ * def <init>(vparamss) {
+ * presupers
+ * super.<init>(args)
+ * }
+ * body
+ * }
+ */
+ def mkTemplate(parents: List[Tree], self: ValDef, constrMods: Modifiers, vparamss: List[List[ValDef]], body: List[Tree], superPos: Position): Template = {
+ /* Add constructor to template */
+
+ // create parameters for <init> as synthetic trees.
+ var vparamss1 = mmap(vparamss) { vd =>
+ atPos(vd.pos.focus) {
+ val mods = Modifiers(vd.mods.flags & (IMPLICIT | DEFAULTPARAM | BYNAMEPARAM) | PARAM | PARAMACCESSOR)
+ ValDef(mods withAnnotations vd.mods.annotations, vd.name, vd.tpt.duplicate, vd.rhs.duplicate)
+ }
+ }
+ val (edefs, rest) = body span treeInfo.isEarlyDef
+ val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef
+ val gvdefs = evdefs map {
+ case vdef @ ValDef(_, _, tpt, _) =>
+ copyValDef(vdef)(
+ // atPos for the new tpt is necessary, since the original tpt might have no position
+ // (when missing type annotation for ValDef for example), so even though setOriginal modifies the
+ // position of TypeTree, it would still be NoPosition. That's what the author meant.
+ tpt = atPos(vdef.pos.focus)(TypeTree() setOriginal tpt setPos tpt.pos.focus),
+ rhs = EmptyTree
+ )
+ }
+ val lvdefs = evdefs collect { case vdef: ValDef => copyValDef(vdef)(mods = vdef.mods | PRESUPER) }
+
+ val constrs = {
+ if (constrMods hasFlag TRAIT) {
+ if (body forall treeInfo.isInterfaceMember) List()
+ else List(
+ atPos(wrappingPos(superPos, lvdefs)) (
+ DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), List(Nil), TypeTree(), Block(lvdefs, Literal(Constant())))))
+ } else {
+ // convert (implicit ... ) to ()(implicit ... ) if its the only parameter section
+ if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit)
+ vparamss1 = List() :: vparamss1
+ val superRef: Tree = atPos(superPos)(mkSuperInitCall)
+ val superCall = pendingSuperCall // we can't know in advance which of the parents will end up as a superclass
+ // this requires knowing which of the parents is a type macro and which is not
+ // and that's something that cannot be found out before typer
+ // (the type macros aren't in the trunk yet, but there is a plan for them to land there soon)
+ // this means that we don't know what will be the arguments of the super call
+ // therefore here we emit a dummy which gets populated when the template is named and typechecked
+ List(
+ // TODO: previously this was `wrappingPos(superPos, lvdefs ::: argss.flatten)`
+ // is it going to be a problem that we can no longer include the `argss`?
+ atPos(wrappingPos(superPos, lvdefs)) (
+ DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(Constant())))))
+ }
+ }
+ constrs foreach (ensureNonOverlapping(_, parents ::: gvdefs, focus=false))
+ // Field definitions for the class - remove defaults.
+ val fieldDefs = vparamss.flatten map (vd => copyValDef(vd)(mods = vd.mods &~ DEFAULTPARAM, rhs = EmptyTree))
+
+ global.Template(parents, self, gvdefs ::: fieldDefs ::: constrs ::: etdefs ::: rest)
+ }
}