summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/BuildUtils.scala
diff options
context:
space:
mode:
authorDen Shabalin <den.shabalin@gmail.com>2013-09-02 16:01:38 +0200
committerDen Shabalin <den.shabalin@gmail.com>2013-09-05 20:42:09 +0200
commit1352fea1c4ecfa0fd66ff1d5ad6e0ee437b1a59f (patch)
treec66d11c9b21a29a7601fedb4d8ad163dad0fa5cf /src/reflect/scala/reflect/internal/BuildUtils.scala
parent73a4f172c3b4f2c7d8bf9936898f031d09899cef (diff)
downloadscala-1352fea1c4ecfa0fd66ff1d5ad6e0ee437b1a59f.tar.gz
scala-1352fea1c4ecfa0fd66ff1d5ad6e0ee437b1a59f.tar.bz2
scala-1352fea1c4ecfa0fd66ff1d5ad6e0ee437b1a59f.zip
first-class early def splicing and extraction support
Diffstat (limited to 'src/reflect/scala/reflect/internal/BuildUtils.scala')
-rw-r--r--src/reflect/scala/reflect/internal/BuildUtils.scala150
1 files changed, 124 insertions, 26 deletions
diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala
index e2894c5b94..528b542361 100644
--- a/src/reflect/scala/reflect/internal/BuildUtils.scala
+++ b/src/reflect/scala/reflect/internal/BuildUtils.scala
@@ -70,6 +70,19 @@ trait BuildUtils { self: SymbolTable =>
case _ => throw new IllegalArgumentException(s"Tree ${showRaw(tree)} isn't a correct representation of annotation, consider passing Ident as a first argument")
}
+ def mkVparamss(argss: List[List[ValDef]]): List[List[ValDef]] = {
+ argss.map { _.map {
+ case vd @ ValDef(mods, _, _, EmptyTree) => copyValDef(vd)(mods = mods | PARAM)
+ case vd @ ValDef(mods, _, _, _) => copyValDef(vd)(mods = mods | PARAM | DEFAULTPARAM)
+ } }
+ }
+
+ def mkTparams(tparams: List[Tree]): List[TypeDef] =
+ tparams.map {
+ case td: TypeDef => copyTypeDef(td)(mods = (td.mods | PARAM) & (~DEFERRED))
+ case other => throw new IllegalArgumentException("can't splice $other as type parameter")
+ }
+
def mkRefineStat(stat: Tree): Tree = {
stat match {
case dd: DefDef => require(dd.rhs.isEmpty, "can't use DefDef with non-empty body as refine stat")
@@ -90,6 +103,17 @@ trait BuildUtils { self: SymbolTable =>
}
}
+ def mkEarlyDef(defn: Tree): Tree = defn match {
+ case vdef @ ValDef(mods, _, _, _) if !mods.isDeferred =>
+ copyValDef(vdef)(mods = mods | PRESUPER)
+ case tdef @ TypeDef(mods, _, _, _) =>
+ copyTypeDef(tdef)(mods = mods | PRESUPER)
+ case _ =>
+ throw new IllegalArgumentException(s"not legal early def: $defn")
+ }
+
+ def mkEarlyDef(defns: List[Tree]): List[Tree] = defns.map(mkEarlyDef)
+
def RefTree(qual: Tree, sym: Symbol) = self.RefTree(qual, sym.name) setSymbol sym
object FlagsRepr extends FlagsReprExtractor {
@@ -121,36 +145,110 @@ trait BuildUtils { self: SymbolTable =>
}
}
+ private object UnCtor {
+ def unapply(tree: Tree): Option[(Modifiers, List[List[ValDef]], List[Tree])] = tree match {
+ case DefDef(mods, nme.MIXIN_CONSTRUCTOR, _, _, _, Block(lvdefs, _)) =>
+ Some(mods | Flag.TRAIT, Nil, lvdefs)
+ case DefDef(mods, nme.CONSTRUCTOR, Nil, vparamss, _, Block(lvdefs :+ _, _)) =>
+ Some(mods, vparamss, lvdefs)
+ case _ => None
+ }
+ }
+
+ private object UnMkTemplate {
+ def unapply(templ: Template): Option[(List[Tree], ValDef, Modifiers, List[List[ValDef]], List[Tree], List[Tree])] = {
+ val Template(parents, selfdef, tbody) = templ
+ def result(ctorMods: Modifiers, vparamss: List[List[ValDef]], edefs: List[Tree], body: List[Tree]) =
+ Some((parents, selfdef, ctorMods, vparamss, edefs, body))
+ def indexOfCtor(trees: List[Tree]) =
+ trees.indexWhere { case UnCtor(_, _, _) => true ; case _ => false }
+
+ if (tbody forall treeInfo.isInterfaceMember)
+ result(NoMods | Flag.TRAIT, Nil, Nil, tbody)
+ else if (indexOfCtor(tbody) == -1)
+ None
+ else {
+ val (rawEdefs, rest) = tbody.span(treeInfo.isEarlyDef)
+ val (gvdefs, etdefs) = rawEdefs.partition(treeInfo.isEarlyValDef)
+ val (fieldDefs, UnCtor(ctorMods, ctorVparamss, lvdefs) :: body) = rest.splitAt(indexOfCtor(rest))
+ val evdefs = gvdefs.zip(lvdefs).map {
+ case (gvdef @ ValDef(_, _, tpt: TypeTree, _), ValDef(_, _, _, rhs)) =>
+ copyValDef(gvdef)(tpt = tpt.original, rhs = rhs)
+ }
+ val edefs = evdefs ::: etdefs
+ if (ctorMods.isTrait)
+ result(ctorMods, Nil, edefs, body)
+ else {
+ // undo conversion from (implicit ... ) to ()(implicit ... ) when its the only parameter section
+ val vparamssRestoredImplicits = ctorVparamss match {
+ case Nil :: (tail @ ((head :: _) :: _)) if head.mods.isImplicit => tail
+ case other => other
+ }
+ // undo flag modifications by mergeing flag info from constructor args and fieldDefs
+ val modsMap = fieldDefs.map { case ValDef(mods, name, _, _) => name -> mods }.toMap
+ val vparamss = mmap(vparamssRestoredImplicits) { vd =>
+ val originalMods = modsMap(vd.name) | (vd.mods.flags & DEFAULTPARAM)
+ atPos(vd.pos)(ValDef(originalMods, vd.name, vd.tpt, vd.rhs))
+ }
+ result(ctorMods, vparamss, edefs, body)
+ }
+ }
+ }
+ }
+
object SyntacticClassDef extends SyntacticClassDefExtractor {
def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef],
- constrMods: Modifiers, vparamss: List[List[ValDef]], parents: List[Tree],
- selfdef: ValDef, body: List[Tree]): Tree =
- ClassDef(mods, name, tparams, gen.mkTemplate(parents, selfdef, constrMods, vparamss, body, NoPosition))
-
- def unapply(tree: Tree): Option[(Modifiers, TypeName, List[TypeDef], Modifiers,
- List[List[ValDef]], List[Tree], ValDef, List[Tree])] = tree match {
- case ClassDef(mods, name, tparams, Template(parents, selfdef, tbody)) =>
- // extract generated fieldDefs and constructor
- val (defs, (ctor: DefDef) :: body) = tbody.splitAt(tbody.indexWhere {
- case DefDef(_, nme.CONSTRUCTOR, _, _, _, _) => true
- case _ => false
- })
- val (earlyDefs, fieldDefs) = defs.span(treeInfo.isEarlyDef)
-
- // undo conversion from (implicit ... ) to ()(implicit ... ) when its the only parameter section
- val vparamssRestoredImplicits = ctor.vparamss match {
- case Nil :: rest if !rest.isEmpty && !rest.head.isEmpty && rest.head.head.mods.isImplicit => rest
- case other => other
- }
+ constrMods: Modifiers, vparamss: List[List[ValDef]], earlyDefs: List[Tree],
+ parents: List[Tree], selfdef: ValDef, body: List[Tree]): ClassDef = {
+ val extraFlags = PARAMACCESSOR | (if (mods.isCase) CASEACCESSOR else 0L)
+ val vparamss0 = vparamss.map { _.map { vd => copyValDef(vd)(mods = (vd.mods | extraFlags) & (~DEFERRED)) } }
+ val tparams0 = mkTparams(tparams)
+ val parents0 = gen.mkParents(mods,
+ if (mods.isCase) parents.filter {
+ case ScalaDot(tpnme.Product | tpnme.Serializable | tpnme.AnyRef) => false
+ case _ => true
+ } else parents
+ )
+ val body0 = earlyDefs ::: body
+ val templ = gen.mkTemplate(parents0, selfdef, constrMods, vparamss0, body0)
+ gen.mkClassDef(mods, name, tparams0, templ)
+ }
- // undo flag modifications by mergeing flag info from constructor args and fieldDefs
- val modsMap = fieldDefs.map { case ValDef(mods, name, _, _) => name -> mods }.toMap
- val vparamss = mmap(vparamssRestoredImplicits) { vd =>
- val originalMods = modsMap(vd.name) | (vd.mods.flags & DEFAULTPARAM)
- atPos(vd.pos)(ValDef(originalMods, vd.name, vd.tpt, vd.rhs))
- }
+ def unapply(tree: Tree): Option[(Modifiers, TypeName, List[TypeDef], Modifiers, List[List[ValDef]],
+ List[Tree], List[Tree], ValDef, List[Tree])] = tree match {
+ case ClassDef(mods, name, tparams, UnMkTemplate(parents, selfdef, ctorMods, vparamss, earlyDefs, body))
+ if !ctorMods.isTrait && !ctorMods.hasFlag(JAVA) =>
+ Some((mods, name, tparams, ctorMods, vparamss, earlyDefs, parents, selfdef, body))
+ case _ =>
+ None
+ }
+ }
+
+ object SyntacticTraitDef extends SyntacticTraitDefExtractor {
+ def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], earlyDefs: List[Tree],
+ parents: List[Tree], selfdef: ValDef, body: List[Tree]): ClassDef = {
+ val mods0 = mods | TRAIT | ABSTRACT
+ val templ = gen.mkTemplate(parents, selfdef, Modifiers(TRAIT), Nil, earlyDefs ::: body)
+ gen.mkClassDef(mods0, name, mkTparams(tparams), templ)
+ }
+
+ def unapply(tree: Tree): Option[(Modifiers, TypeName, List[TypeDef],
+ List[Tree], List[Tree], ValDef, List[Tree])] = tree match {
+ case ClassDef(mods, name, tparams, UnMkTemplate(parents, selfdef, ctorMods, vparamss, earlyDefs, body))
+ if mods.isTrait =>
+ Some((mods, name, tparams, earlyDefs, parents, selfdef, body))
+ case _ => None
+ }
+ }
+
+ object SyntacticModuleDef extends SyntacticModuleDefExtractor {
+ def apply(mods: Modifiers, name: TermName, earlyDefs: List[Tree],
+ parents: List[Tree], selfdef: ValDef, body: List[Tree]) =
+ ModuleDef(mods, name, gen.mkTemplate(parents, selfdef, NoMods, Nil, earlyDefs ::: body))
- Some((mods, name, tparams, ctor.mods, vparamss, parents, selfdef, earlyDefs ::: body))
+ def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[Tree], ValDef, List[Tree])] = tree match {
+ case ModuleDef(mods, name, UnMkTemplate(parents, selfdef, _, _, earlyDefs, body)) =>
+ Some((mods, name, earlyDefs, parents, selfdef, body))
case _ =>
None
}