diff options
author | Den Shabalin <den.shabalin@gmail.com> | 2013-11-14 14:51:58 +0100 |
---|---|---|
committer | Den Shabalin <den.shabalin@gmail.com> | 2013-11-17 18:17:50 +0100 |
commit | 1080da80769cdc2bef2f06977094caff625b4a15 (patch) | |
tree | 83400ad47cc77390528ff5207ccfe989230b76b1 /src/reflect | |
parent | 69e62de87d80cf5b9d8c7f4eefcea0638fb2759d (diff) | |
download | scala-1080da80769cdc2bef2f06977094caff625b4a15.tar.gz scala-1080da80769cdc2bef2f06977094caff625b4a15.tar.bz2 scala-1080da80769cdc2bef2f06977094caff625b4a15.zip |
refactor out fresh name prefix extraction logic
1. refactor out FreshNameExtractor out of Quasiquotes cake into
SymbolTable (can’t put it outside due to the fact that names are
path-dependent)
2. add optional parameter to the fresh name creator to cover additional
qq$ prefix needed for quasiquotes
3. add unit tests
Diffstat (limited to 'src/reflect')
4 files changed, 41 insertions, 8 deletions
diff --git a/src/reflect/scala/reflect/internal/FreshNames.scala b/src/reflect/scala/reflect/internal/FreshNames.scala new file mode 100644 index 0000000000..ab9e488fa7 --- /dev/null +++ b/src/reflect/scala/reflect/internal/FreshNames.scala @@ -0,0 +1,35 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2013 LAMP/EPFL + */ + +package scala +package reflect +package internal + +import scala.reflect.internal.util.FreshNameCreator + +trait FreshNames { self: SymbolTable => + // default fresh name creator used to abstract over currentUnit.fresh and runtime fresh name creator + def currentFreshNameCreator: FreshNameCreator + + // create fresh term/type name using implicit fresh name creator + 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)) + + // Extractor that matches names which were generated by some + // FreshNameCreator with known prefix. Extracts user-specified + // prefix that was used as a parameter to newName by stripping + // global creator prefix and unique number in the end of the name. + class FreshNameExtractor(creatorPrefix: String = "") { + // quote prefix so that it can be used with replaceFirst + // which expects regExp rather than simple string + val quotedCreatorPrefix = java.util.regex.Pattern.quote(creatorPrefix) + + def unapply(name: Name): Option[String] = { + val sname = name.toString + // name should start with creatorPrefix and end with number + if (!sname.startsWith(creatorPrefix) || !sname.matches("^.*\\d*$")) None + else Some(NameTransformer.decode(sname.replaceFirst(quotedCreatorPrefix, "").replaceAll("\\d*$", ""))) + } + } +}
\ No newline at end of file diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index 4998580a7d..c3f3e35fb3 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -42,6 +42,7 @@ abstract class SymbolTable extends macros.Universe with BuildUtils with PrivateWithin with pickling.Translations + with FreshNames { val gen = new TreeGen { val global: SymbolTable.this.type = SymbolTable.this } @@ -398,11 +399,6 @@ 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/util/FreshNameCreator.scala b/src/reflect/scala/reflect/internal/util/FreshNameCreator.scala index 3e54de8e1e..8442c1015f 100644 --- a/src/reflect/scala/reflect/internal/util/FreshNameCreator.scala +++ b/src/reflect/scala/reflect/internal/util/FreshNameCreator.scala @@ -11,7 +11,7 @@ import java.util.concurrent.atomic.AtomicLong import scala.collection.mutable import scala.reflect.NameTransformer -class FreshNameCreator { +class FreshNameCreator(creatorPrefix: String = "") { protected val counters = new ConcurrentHashMap[String, AtomicLong]() /** @@ -21,7 +21,8 @@ class FreshNameCreator { */ def newName(prefix: String): String = { val safePrefix = NameTransformer.encode(prefix) - counters.putIfAbsent(safePrefix, new AtomicLong(0)); - safePrefix + counters.get(safePrefix).incrementAndGet(); + counters.putIfAbsent(safePrefix, new AtomicLong(0)) + val idx = counters.get(safePrefix).incrementAndGet() + s"$creatorPrefix$safePrefix$idx" } } diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index bce506ee0a..344f7682c1 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -51,6 +51,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => // inaccessible: this.SimpleNameOrdering this.traceSymbols this.perRunCaches + this.FreshNameExtractor this.FixedMirrorTreeCreator this.FixedMirrorTypeCreator this.CompoundTypeTreeOriginalAttachment |