diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2013-10-19 06:46:27 -0700 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2013-10-19 06:46:27 -0700 |
commit | 8848f241616627b0c5beca38a5107c4eca3e10fd (patch) | |
tree | 7f6e5f05e3ab98d86049e493ded1f31be3b4f62d /src/reflect | |
parent | fc892176ec4fd877bae4fc31ad7769ec15bbd858 (diff) | |
parent | d3e04daa658170ffc58f2e1ea3da0f4d55f001a7 (diff) | |
download | scala-8848f241616627b0c5beca38a5107c4eca3e10fd.tar.gz scala-8848f241616627b0c5beca38a5107c4eca3e10fd.tar.bz2 scala-8848f241616627b0c5beca38a5107c4eca3e10fd.zip |
Merge pull request #3007 from densh/pull/fresh-name-and-package-support
Add support for packages into quasiquotes and toolbox, improve handling of fresh names, unhardcode quasiquote expansion logic
Diffstat (limited to 'src/reflect')
8 files changed, 142 insertions, 34 deletions
diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala index 551c27bf9c..28551b1dcd 100644 --- a/src/reflect/scala/reflect/api/BuildUtils.scala +++ b/src/reflect/scala/reflect/api/BuildUtils.scala @@ -80,12 +80,20 @@ private[reflect] trait BuildUtils { self: Universe => def mkRefineStat(stats: List[Tree]): List[Tree] + def mkPackageStat(stat: Tree): Tree + + def mkPackageStat(stats: List[Tree]): List[Tree] + def mkEarlyDef(defn: Tree): Tree def mkEarlyDef(defns: List[Tree]): List[Tree] def RefTree(qual: Tree, sym: Symbol): Tree + def withFreshTermName[T](prefix: String)(f: TermName => T): T + + def withFreshTypeName[T](prefix: String)(f: TypeName => T): T + val ScalaDot: ScalaDotExtractor trait ScalaDotExtractor { @@ -114,12 +122,19 @@ private[reflect] trait BuildUtils { self: Universe => def unapply(tree: Tree): Some[(Tree, List[List[Tree]])] } + val SyntacticApply: SyntacticApplyExtractor + + trait SyntacticApplyExtractor { + def apply(tree: Tree, args: List[Tree]): Tree + def unapply(tree: Tree): Some[(Tree, List[Tree])] + } + val SyntacticClassDef: SyntacticClassDefExtractor trait SyntacticClassDefExtractor { def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], constrMods: Modifiers, vparamss: List[List[ValDef]], earlyDefs: List[Tree], - parents: List[Tree], selfdef: ValDef, body: List[Tree]): ClassDef + parents: List[Tree], selfType: ValDef, body: List[Tree]): ClassDef def unapply(tree: Tree): Option[(Modifiers, TypeName, List[TypeDef], Modifiers, List[List[ValDef]], List[Tree], List[Tree], ValDef, List[Tree])] } @@ -128,19 +143,27 @@ private[reflect] trait BuildUtils { self: Universe => trait SyntacticTraitDefExtractor { def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], - earlyDefs: List[Tree], parents: List[Tree], selfdef: ValDef, body: List[Tree]): ClassDef + earlyDefs: List[Tree], parents: List[Tree], selfType: ValDef, body: List[Tree]): ClassDef def unapply(tree: Tree): Option[(Modifiers, TypeName, List[TypeDef], List[Tree], List[Tree], ValDef, List[Tree])] } - val SyntacticModuleDef: SyntacticModuleDefExtractor + val SyntacticObjectDef: SyntacticObjectDefExtractor - trait SyntacticModuleDefExtractor { + trait SyntacticObjectDefExtractor { def apply(mods: Modifiers, name: TermName, earlyDefs: List[Tree], - parents: List[Tree], selfdef: ValDef, body: List[Tree]): Tree + parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[Tree], ValDef, List[Tree])] } + val SyntacticPackageObjectDef: SyntacticPackageObjectDefExtractor + + trait SyntacticPackageObjectDefExtractor { + def apply(name: TermName, earlyDefs: List[Tree], + parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree + def unapply(tree: Tree): Option[(TermName, List[Tree], List[Tree], ValDef, List[Tree])] + } + val SyntacticTuple: SyntacticTupleExtractor val SyntacticTupleType: SyntacticTupleExtractor @@ -159,7 +182,7 @@ private[reflect] trait BuildUtils { self: Universe => val SyntacticNew: SyntacticNewExtractor trait SyntacticNewExtractor { - def apply(earlyDefs: List[Tree], parents: List[Tree], selfdef: ValDef, body: List[Tree]): Tree + def apply(earlyDefs: List[Tree], parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree def unapply(tree: Tree): Option[(List[Tree], List[Tree], ValDef, List[Tree])] } diff --git a/src/reflect/scala/reflect/api/Quasiquotes.scala b/src/reflect/scala/reflect/api/Quasiquotes.scala index 08d3274ca5..8e993af382 100644 --- a/src/reflect/scala/reflect/api/Quasiquotes.scala +++ b/src/reflect/scala/reflect/api/Quasiquotes.scala @@ -8,7 +8,7 @@ trait Quasiquotes { self: Universe => implicit class Quasiquote(ctx: StringContext) { protected trait api { def apply(args: Any*): Any = macro ??? - def unapply(subpatterns: Any*): Option[Any] = macro ??? + def unapply(scrutinee: Any): Any = macro ??? } object q extends api object tq extends api diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index 951efd90ed..fc6b26db3f 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -98,6 +98,18 @@ trait BuildUtils { self: SymbolTable => def mkRefineStat(stats: List[Tree]): List[Tree] = stats.map(mkRefineStat) + def mkPackageStat(stat: Tree): Tree = { + stat match { + case cd: ClassDef => + case md: ModuleDef => + case pd: PackageDef => + case _ => throw new IllegalArgumentException(s"not legal package stat: $stat") + } + stat + } + + def mkPackageStat(stats: List[Tree]): List[Tree] = stats.map(mkPackageStat) + object ScalaDot extends ScalaDotExtractor { def apply(name: Name): Tree = gen.scalaDot(name) def unapply(tree: Tree): Option[Name] = tree match { @@ -110,7 +122,7 @@ trait BuildUtils { self: SymbolTable => case vdef @ ValDef(mods, _, _, _) if !mods.isDeferred => copyValDef(vdef)(mods = mods | PRESUPER) case tdef @ TypeDef(mods, _, _, _) => - copyTypeDef(tdef)(mods = mods | PRESUPER) + copyTypeDef(tdef)(mods = mods | PRESUPER) case _ => throw new IllegalArgumentException(s"not legal early def: $defn") } @@ -119,6 +131,12 @@ trait BuildUtils { self: SymbolTable => def RefTree(qual: Tree, sym: Symbol) = self.RefTree(qual, sym.name) setSymbol sym + def withFreshTermName[T](prefix: String)(f: TermName => T): T = f(freshTermName(prefix)) + + def withFreshTypeName[T](prefix: String)(f: TypeName => T): T = f(freshTypeName(prefix)) + + private implicit def fresh: FreshNameCreator = self.currentFreshNameCreator + object FlagsRepr extends FlagsReprExtractor { def apply(bits: Long): FlagSet = bits def unapply(flags: Long): Some[Long] = Some(flags) @@ -148,6 +166,15 @@ trait BuildUtils { self: SymbolTable => } } + object SyntacticApply extends SyntacticApplyExtractor { + def apply(tree: Tree, args: List[Tree]): Tree = SyntacticApplied(tree, List(args)) + + def unapply(tree: Tree): Some[(Tree, List[Tree])] = tree match { + case Apply(fun, args) => Some((fun, args)) + case other => Some((other, Nil)) + } + } + private object UnCtor { def unapply(tree: Tree): Option[(Modifiers, List[List[ValDef]], List[Tree])] = tree match { case DefDef(mods, nme.MIXIN_CONSTRUCTOR, _, _, _, Block(lvdefs, _)) => @@ -160,9 +187,9 @@ trait BuildUtils { self: SymbolTable => 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 + val Template(parents, selfType, tbody) = templ def result(ctorMods: Modifiers, vparamss: List[List[ValDef]], edefs: List[Tree], body: List[Tree]) = - Some((parents, selfdef, ctorMods, vparamss, edefs, body)) + Some((parents, selfType, ctorMods, vparamss, edefs, body)) def indexOfCtor(trees: List[Tree]) = trees.indexWhere { case UnCtor(_, _, _) => true ; case _ => false } @@ -202,7 +229,7 @@ trait BuildUtils { self: SymbolTable => object SyntacticClassDef extends SyntacticClassDefExtractor { def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], constrMods: Modifiers, vparamss: List[List[ValDef]], earlyDefs: List[Tree], - parents: List[Tree], selfdef: ValDef, body: List[Tree]): ClassDef = { + parents: List[Tree], selfType: 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) @@ -213,15 +240,15 @@ trait BuildUtils { self: SymbolTable => } else parents ) val body0 = earlyDefs ::: body - val templ = gen.mkTemplate(parents0, selfdef, constrMods, vparamss0, body0) + val templ = gen.mkTemplate(parents0, selfType, constrMods, vparamss0, body0) gen.mkClassDef(mods, name, tparams0, templ) } 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)) + case ClassDef(mods, name, tparams, UnMkTemplate(parents, selfType, ctorMods, vparamss, earlyDefs, body)) if !ctorMods.isTrait && !ctorMods.hasFlag(JAVA) => - Some((mods, name, tparams, ctorMods, vparamss, earlyDefs, parents, selfdef, body)) + Some((mods, name, tparams, ctorMods, vparamss, earlyDefs, parents, selfType, body)) case _ => None } @@ -229,29 +256,42 @@ trait BuildUtils { self: SymbolTable => 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 = { + parents: List[Tree], selfType: ValDef, body: List[Tree]): ClassDef = { val mods0 = mods | TRAIT | ABSTRACT - val templ = gen.mkTemplate(parents, selfdef, Modifiers(TRAIT), Nil, earlyDefs ::: body) + val templ = gen.mkTemplate(parents, selfType, 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)) + case ClassDef(mods, name, tparams, UnMkTemplate(parents, selfType, ctorMods, vparamss, earlyDefs, body)) if mods.isTrait => - Some((mods, name, tparams, earlyDefs, parents, selfdef, body)) + Some((mods, name, tparams, earlyDefs, parents, selfType, body)) case _ => None } } - object SyntacticModuleDef extends SyntacticModuleDefExtractor { + object SyntacticObjectDef extends SyntacticObjectDefExtractor { 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)) + parents: List[Tree], selfType: ValDef, body: List[Tree]) = + ModuleDef(mods, name, gen.mkTemplate(parents, selfType, NoMods, Nil, 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 ModuleDef(mods, name, UnMkTemplate(parents, selfType, _, _, earlyDefs, body)) => + Some((mods, name, earlyDefs, parents, selfType, body)) + case _ => + None + } + } + + object SyntacticPackageObjectDef extends SyntacticPackageObjectDefExtractor { + def apply(name: TermName, earlyDefs: List[Tree], + parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree = + gen.mkPackageObject(SyntacticObjectDef(NoMods, name, earlyDefs, parents, selfType, body)) + + def unapply(tree: Tree): Option[(TermName, List[Tree], List[Tree], ValDef, List[Tree])] = tree match { + case PackageDef(Ident(name: TermName), List(SyntacticObjectDef(NoMods, nme.PACKAGEkw, earlyDefs, parents, selfType, body))) => + Some((name, earlyDefs, parents, selfType, body)) case _ => None } @@ -359,15 +399,15 @@ trait BuildUtils { self: SymbolTable => } object SyntacticNew extends SyntacticNewExtractor { - def apply(earlyDefs: List[Tree], parents: List[Tree], selfdef: ValDef, body: List[Tree]): Tree = - gen.mkNew(parents, selfdef, earlyDefs ::: body, NoPosition, NoPosition) + def apply(earlyDefs: List[Tree], parents: List[Tree], selfType: ValDef, body: List[Tree]): Tree = + gen.mkNew(parents, selfType, earlyDefs ::: body, NoPosition, NoPosition) def unapply(tree: Tree): Option[(List[Tree], List[Tree], ValDef, List[Tree])] = tree match { case SyntacticApplied(Select(New(SyntacticTypeApplied(ident, targs)), nme.CONSTRUCTOR), argss) => Some((Nil, SyntacticApplied(SyntacticTypeApplied(ident, targs), argss) :: Nil, noSelfType, Nil)) - case SyntacticBlock(SyntacticClassDef(_, tpnme.ANON_CLASS_NAME, Nil, _, ListOfNil, earlyDefs, parents, selfdef, body) :: + case SyntacticBlock(SyntacticClassDef(_, tpnme.ANON_CLASS_NAME, Nil, _, ListOfNil, earlyDefs, parents, selfType, body) :: Apply(Select(New(Ident(tpnme.ANON_CLASS_NAME)), nme.CONSTRUCTOR), Nil) :: Nil) => - Some((earlyDefs, parents, selfdef, body)) + Some((earlyDefs, parents, selfType, body)) case _ => None } diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index c39efa26fa..9f56e78059 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -247,11 +247,12 @@ trait StdNames { final val Quasiquote: NameType = "Quasiquote" // quasiquote-specific names - final val QUASIQUOTE_MODS: NameType = "$quasiquote$mods$" - final val QUASIQUOTE_TUPLE: NameType = "$quasiquote$tuple$" - final val QUASIQUOTE_FUNCTION: NameType = "$quasiquote$function$" - final val QUASIQUOTE_REFINE_STAT: NameType = "$quasiquote$refine$stat$" - final val QUASIQUOTE_EARLY_DEF: NameType = "$quasiquote$early$def$" + final val QUASIQUOTE_MODS: NameType = "$quasiquote$mods$" + final val QUASIQUOTE_TUPLE: NameType = "$quasiquote$tuple$" + final val QUASIQUOTE_FUNCTION: NameType = "$quasiquote$function$" + final val QUASIQUOTE_REFINE_STAT: NameType = "$quasiquote$refine$stat$" + final val QUASIQUOTE_EARLY_DEF: NameType = "$quasiquote$early$def$" + final val QUASIQUOTE_PACKAGE_STAT: NameType = "$quasiquote$package$stat$" // Annotation simple names, used in Namer final val BeanPropertyAnnot: NameType = "BeanProperty" @@ -321,6 +322,7 @@ trait StdNames { val REIFY_FREE_VALUE_SUFFIX: NameType = "$value" val REIFY_SYMDEF_PREFIX: NameType = "symdef$" val QUASIQUOTE_PREFIX: String = "qq$" + val QUASIQUOTE_NAME_PREFIX: String = "nn$" val QUASIQUOTE_FILE: String = "<quasiquote>" val QUASIQUOTE_TUPLE: NameType = "$quasiquote$tuple$" val QUASIQUOTE_CASE: NameType = "$quasiquote$case$" @@ -584,13 +586,15 @@ trait StdNames { val Select: NameType = "Select" val SelectFromTypeTree: NameType = "SelectFromTypeTree" val SyntacticApplied: NameType = "SyntacticApplied" + val SyntacticApply: NameType = "SyntacticApply" val SyntacticAssign: NameType = "SyntacticAssign" val SyntacticBlock: NameType = "SyntacticBlock" val SyntacticClassDef: NameType = "SyntacticClassDef" val SyntacticDefDef: NameType = "SyntacticDefDef" val SyntacticFunction: NameType = "SyntacticFunction" - val SyntacticFunctionType: NameType= "SyntacticFunctionType" - val SyntacticModuleDef: NameType = "SyntacticModuleDef" + val SyntacticFunctionType: NameType = "SyntacticFunctionType" + val SyntacticPackageObjectDef: NameType = "SyntacticPackageObjectDef" + val SyntacticObjectDef: NameType = "SyntacticObjectDef" val SyntacticNew: NameType = "SyntacticNew" val SyntacticTraitDef: NameType = "SyntacticTraitDef" val SyntacticTuple: NameType = "SyntacticTuple" @@ -685,6 +689,7 @@ trait StdNames { val mkAnnotation: NameType = "mkAnnotation" val mkRefineStat: NameType = "mkRefineStat" val mkEarlyDef: NameType = "mkEarlyDef" + val mkPackageStat: NameType = "mkPackageStat" val ne: NameType = "ne" val newArray: NameType = "newArray" val newFreeTerm: NameType = "newFreeTerm" diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index 0dff1adda9..8386d02b7c 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -383,6 +383,11 @@ abstract class SymbolTable extends macros.Universe * Adds the `sm` String interpolator to a [[scala.StringContext]]. */ implicit val StringContextStripMarginOps: StringContext => StringContextStripMarginOps = util.StringContextStripMarginOps + + // fresh name creation + def currentFreshNameCreator: FreshNameCreator + def freshTermName(prefix: String = "x$")(implicit creator: FreshNameCreator): TermName = newTermName(creator.newName(prefix)) + def freshTypeName(prefix: String)(implicit creator: FreshNameCreator): TypeName = newTypeName(creator.newName(prefix)) } object SymbolTableStats { diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index 720d8bfe4a..cf7c729a6a 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -448,4 +448,10 @@ abstract class TreeGen extends macros.TreeBuilder { case _ => Assign(lhs, rhs) } + + def mkPackageObject(defn: ModuleDef, pidPos: Position = NoPosition, pkgPos: Position = NoPosition) = { + val module = copyModuleDef(defn)(name = nme.PACKAGEkw) + val pid = atPos(pidPos)(Ident(defn.name)) + atPos(pkgPos)(PackageDef(pid, module :: Nil)) + } } diff --git a/src/reflect/scala/reflect/internal/util/FreshNameCreator.scala b/src/reflect/scala/reflect/internal/util/FreshNameCreator.scala new file mode 100644 index 0000000000..3e54de8e1e --- /dev/null +++ b/src/reflect/scala/reflect/internal/util/FreshNameCreator.scala @@ -0,0 +1,27 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2013 LAMP/EPFL + * @author Martin Odersky + */ + +package scala.reflect.internal +package util + +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.atomic.AtomicLong +import scala.collection.mutable +import scala.reflect.NameTransformer + +class FreshNameCreator { + protected val counters = new ConcurrentHashMap[String, AtomicLong]() + + /** + * Create a fresh name with the given prefix. It is guaranteed + * that the returned name has never been returned by a previous + * call to this function (provided the prefix does not end in a digit). + */ + def newName(prefix: String): String = { + val safePrefix = NameTransformer.encode(prefix) + counters.putIfAbsent(safePrefix, new AtomicLong(0)); + safePrefix + counters.get(safePrefix).incrementAndGet(); + } +} diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala index a6cf3a536f..54b75b8e5b 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala @@ -21,6 +21,8 @@ class JavaUniverse extends internal.SymbolTable with JavaUniverseForce with Refl def newStrictTreeCopier: TreeCopier = new StrictTreeCopier def newLazyTreeCopier: TreeCopier = new LazyTreeCopier + val currentFreshNameCreator = new reflect.internal.util.FreshNameCreator + // can't put this in runtime.Trees since that's mixed with Global in ReflectGlobal, which has the definition from internal.Trees object treeInfo extends { val global: JavaUniverse.this.type = JavaUniverse.this |