diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2014-02-20 16:04:13 +0100 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2014-02-20 16:04:13 +0100 |
commit | af0b4cf0e8ce760c7b2874872e4587ffc2f70ad5 (patch) | |
tree | 107dcb893a627d78f7c64adb7fa1c65975e7beff /src | |
parent | 2ead4d6aa3de402f269252190aaa9075a990e098 (diff) | |
parent | 23546f94145b1ff60258c893f972fd615c8a30fc (diff) | |
download | scala-af0b4cf0e8ce760c7b2874872e4587ffc2f70ad5.tar.gz scala-af0b4cf0e8ce760c7b2874872e4587ffc2f70ad5.tar.bz2 scala-af0b4cf0e8ce760c7b2874872e4587ffc2f70ad5.zip |
Merge pull request #3568 from densh/topic/qq-terminology
Fix quasiquote terminology to be consistent with Scheme
Diffstat (limited to 'src')
5 files changed, 81 insertions, 81 deletions
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala index c2f1bf430d..8376fca4ad 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala @@ -5,17 +5,17 @@ import scala.collection.{immutable, mutable} import scala.reflect.internal.Flags._ import scala.reflect.macros.TypecheckException -class Cardinality private[Cardinality](val value: Int) extends AnyVal { - def pred = { assert(value - 1 >= 0); new Cardinality(value - 1) } - def succ = new Cardinality(value + 1) +class Rank private[Rank](val value: Int) extends AnyVal { + def pred = { assert(value - 1 >= 0); new Rank(value - 1) } + def succ = new Rank(value + 1) override def toString = if (value == 0) "no dots" else "." * (value + 1) } -object Cardinality { - val NoDot = new Cardinality(0) - val DotDot = new Cardinality(1) - val DotDotDot = new Cardinality(2) - object Dot { def unapply(card: Cardinality) = card != NoDot } +object Rank { + val NoDot = new Rank(0) + val DotDot = new Rank(1) + val DotDotDot = new Rank(2) + object Dot { def unapply(rank: Rank) = rank != NoDot } def parseDots(part: String) = { if (part.endsWith("...")) (part.stripSuffix("..."), DotDotDot) else if (part.endsWith("..")) (part.stripSuffix(".."), DotDot) @@ -27,7 +27,7 @@ object Cardinality { */ trait Holes { self: Quasiquotes => import global._ - import Cardinality._ + import Rank._ import definitions._ import universeTypes._ @@ -43,43 +43,43 @@ trait Holes { self: Quasiquotes => tpe <:< NothingClass.tpe || tpe <:< NullClass.tpe private def extractIterableTParam(tpe: Type) = IterableTParam.asSeenFrom(tpe, IterableClass) - private def stripIterable(tpe: Type, limit: Option[Cardinality] = None): (Cardinality, Type) = + private def stripIterable(tpe: Type, limit: Option[Rank] = None): (Rank, Type) = if (limit.map { _ == NoDot }.getOrElse { false }) (NoDot, tpe) else if (tpe != null && !isIterableType(tpe)) (NoDot, tpe) else if (isBottomType(tpe)) (NoDot, tpe) else { val targ = extractIterableTParam(tpe) - val (card, innerTpe) = stripIterable(targ, limit.map { _.pred }) - (card.succ, innerTpe) + val (rank, innerTpe) = stripIterable(targ, limit.map { _.pred }) + (rank.succ, innerTpe) } - private def iterableTypeFromCard(n: Cardinality, tpe: Type): Type = { + private def iterableTypeFromRank(n: Rank, tpe: Type): Type = { if (n == NoDot) tpe - else appliedType(IterableClass.toType, List(iterableTypeFromCard(n.pred, tpe))) + else appliedType(IterableClass.toType, List(iterableTypeFromRank(n.pred, tpe))) } - /** Hole encapsulates information about splices in quasiquotes. - * It packs together a cardinality of a splice, pre-reified tree - * representation (possibly preprocessed) and position. + /** Hole encapsulates information about unquotees in quasiquotes. + * It packs together a rank, pre-reified tree representation + * (possibly preprocessed) and position. */ abstract class Hole { val tree: Tree val pos: Position - val cardinality: Cardinality + val rank: Rank } object Hole { - def apply(card: Cardinality, tree: Tree): Hole = - if (method != nme.unapply) new ApplyHole(card, tree) - else new UnapplyHole(card, tree) - def unapply(hole: Hole): Some[(Tree, Cardinality)] = Some((hole.tree, hole.cardinality)) + def apply(rank: Rank, tree: Tree): Hole = + if (method != nme.unapply) new ApplyHole(rank, tree) + else new UnapplyHole(rank, tree) + def unapply(hole: Hole): Some[(Tree, Rank)] = Some((hole.tree, hole.rank)) } - class ApplyHole(card: Cardinality, splicee: Tree) extends Hole { + class ApplyHole(annotatedRank: Rank, unquotee: Tree) extends Hole { val (strippedTpe, tpe): (Type, Type) = { - val (strippedCard, strippedTpe) = stripIterable(splicee.tpe, limit = Some(card)) + val (strippedRank, strippedTpe) = stripIterable(unquotee.tpe, limit = Some(annotatedRank)) if (isBottomType(strippedTpe)) cantSplice() - else if (isNativeType(strippedTpe)) (strippedTpe, iterableTypeFromCard(card, strippedTpe)) - else if (isLiftableType(strippedTpe)) (strippedTpe, iterableTypeFromCard(card, treeType)) + else if (isNativeType(strippedTpe)) (strippedTpe, iterableTypeFromRank(annotatedRank, strippedTpe)) + else if (isLiftableType(strippedTpe)) (strippedTpe, iterableTypeFromRank(annotatedRank, treeType)) else cantSplice() } @@ -88,28 +88,28 @@ trait Holes { self: Quasiquotes => if (isNativeType(itpe)) tree else if (isLiftableType(itpe)) lifted(itpe)(tree) else global.abort("unreachable") - if (card == NoDot) inner(strippedTpe)(splicee) - else iterated(card, splicee, splicee.tpe) + if (annotatedRank == NoDot) inner(strippedTpe)(unquotee) + else iterated(annotatedRank, unquotee, unquotee.tpe) } - val pos = splicee.pos + val pos = unquotee.pos - val cardinality = stripIterable(tpe)._1 + val rank = stripIterable(tpe)._1 private def cantSplice(): Nothing = { - val (iterableCard, iterableType) = stripIterable(splicee.tpe) - val holeCardMsg = if (card != NoDot) s" with $card" else "" - val action = "splice " + splicee.tpe + holeCardMsg - val suggestCard = card != iterableCard || card != NoDot - val spliceeCardMsg = if (card != iterableCard && iterableCard != NoDot) s"using $iterableCard" else "omitting the dots" - val cardSuggestion = if (suggestCard) spliceeCardMsg else "" - val suggestLifting = (card == NoDot || iterableCard != NoDot) && !(iterableType <:< treeType) && !isLiftableType(iterableType) - val liftedTpe = if (card != NoDot) iterableType else splicee.tpe + val (iterableRank, iterableType) = stripIterable(unquotee.tpe) + val holeRankMsg = if (annotatedRank != NoDot) s" with $annotatedRank" else "" + val action = "unquote " + unquotee.tpe + holeRankMsg + val suggestRank = annotatedRank != iterableRank || annotatedRank != NoDot + val unquoteeRankMsg = if (annotatedRank != iterableRank && iterableRank != NoDot) s"using $iterableRank" else "omitting the dots" + val rankSuggestion = if (suggestRank) unquoteeRankMsg else "" + val suggestLifting = (annotatedRank == NoDot || iterableRank != NoDot) && !(iterableType <:< treeType) && !isLiftableType(iterableType) + val liftedTpe = if (annotatedRank != NoDot) iterableType else unquotee.tpe val liftSuggestion = if (suggestLifting) s"providing an implicit instance of Liftable[$liftedTpe]" else "" val advice = if (isBottomType(iterableType)) "bottom type values often indicate programmer mistake" - else "consider " + List(cardSuggestion, liftSuggestion).filter(_ != "").mkString(" or ") - c.abort(splicee.pos, s"Can't $action, $advice") + else "consider " + List(rankSuggestion, liftSuggestion).filter(_ != "").mkString(" or ") + c.abort(unquotee.pos, s"Can't $action, $advice") } private def lifted(tpe: Type)(tree: Tree): Tree = { @@ -149,7 +149,7 @@ trait Holes { self: Quasiquotes => else None } - /** Map high-cardinality splice onto an expression that eveluates as a list of given cardinality. + /** Map high-rank unquotee onto an expression that eveluates as a list of given rank. * * All possible combinations of representations are given in the table below: * @@ -166,7 +166,7 @@ trait Holes { self: Quasiquotes => * x is not just an Iterable[T] but a List[T]. Similarly no mapping is performed if mapping function is * known to be an identity. */ - private def iterated(card: Cardinality, tree: Tree, tpe: Type): Tree = (card, tpe) match { + private def iterated(rank: Rank, tree: Tree, tpe: Type): Tree = (rank, tpe) match { case (DotDot, tpe @ IterableType(LiftedType(lift))) => mapF(toList(tree, tpe), lift) case (DotDot, LiftedType(lift)) => toStats(lift(tree)) case (DotDotDot, tpe @ IterableType(inner)) => mapF(toList(tree, tpe), t => iterated(DotDot, t, inner)) @@ -175,7 +175,7 @@ trait Holes { self: Quasiquotes => } } - class UnapplyHole(val cardinality: Cardinality, pat: Tree) extends Hole { + class UnapplyHole(val rank: Rank, pat: Tree) extends Hole { val (placeholderName, pos, tptopt) = pat match { case Bind(pname, inner @ Bind(_, Typed(Ident(nme.WILDCARD), tpt))) => (pname, inner.pos, Some(tpt)) case Bind(pname, inner @ Typed(Ident(nme.WILDCARD), tpt)) => (pname, inner.pos, Some(tpt)) @@ -188,13 +188,13 @@ trait Holes { self: Quasiquotes => try c.typeCheck(TypeDef(NoMods, TypeName("T"), Nil, tpt)) catch { case TypecheckException(pos, msg) => c.abort(pos.asInstanceOf[c.Position], msg) } val tpe = typedTpt.tpe - val (iterableCard, _) = stripIterable(tpe) - if (iterableCard.value < cardinality.value) - c.abort(pat.pos, s"Can't extract $tpe with $cardinality, consider using $iterableCard") - val (_, strippedTpe) = stripIterable(tpe, limit = Some(cardinality)) + val (iterableRank, _) = stripIterable(tpe) + if (iterableRank.value < rank.value) + c.abort(pat.pos, s"Can't extract $tpe with $rank, consider using $iterableRank") + val (_, strippedTpe) = stripIterable(tpe, limit = Some(rank)) if (strippedTpe <:< treeType) treeNoUnlift else - unlifters.spawn(strippedTpe, cardinality).map { + unlifters.spawn(strippedTpe, rank).map { Apply(_, treeNoUnlift :: Nil) }.getOrElse { c.abort(pat.pos, s"Can't find $unliftableType[$strippedTpe], consider providing it") @@ -203,7 +203,7 @@ trait Holes { self: Quasiquotes => } /** Full support for unliftable implies that it's possible to interleave - * deconstruction with higher cardinality and unlifting of the values. + * deconstruction with higher rank and unlifting of the values. * In particular extraction of List[Tree] as List[T: Unliftable] requires * helper extractors that would do the job: UnliftListElementwise[T]. Similarly * List[List[Tree]] needs UnliftListOfListsElementwise[T]. @@ -211,24 +211,24 @@ trait Holes { self: Quasiquotes => * See also "unlift list" tests in UnapplyProps.scala */ object unlifters { - private var records = List.empty[(Type, Cardinality)] + private var records = List.empty[(Type, Rank)] // Materialize unlift helper that does elementwise - // unlifting for corresponding cardinality and type. - def spawn(tpe: Type, card: Cardinality): Option[Tree] = { + // unlifting for corresponding rank and type. + def spawn(tpe: Type, rank: Rank): Option[Tree] = { val unlifter = inferUnliftable(tpe) if (unlifter == EmptyTree) None - else if (card == NoDot) Some(unlifter) + else if (rank == NoDot) Some(unlifter) else { - val idx = records.indexWhere { p => p._1 =:= tpe && p._2 == card } - val resIdx = if (idx != -1) idx else { records +:= (tpe, card); records.length - 1} + val idx = records.indexWhere { p => p._1 =:= tpe && p._2 == rank } + val resIdx = if (idx != -1) idx else { records +:= (tpe, rank); records.length - 1} Some(Ident(TermName(nme.QUASIQUOTE_UNLIFT_HELPER + resIdx))) } } // Returns a list of vals that will defined required unlifters def preamble(): List[Tree] = - records.zipWithIndex.map { case ((tpe, card), idx) => + records.zipWithIndex.map { case ((tpe, rank), idx) => val name = TermName(nme.QUASIQUOTE_UNLIFT_HELPER + idx) - val helperName = card match { + val helperName = rank match { case DotDot => nme.UnliftListElementwise case DotDotDot => nme.UnliftListOfListsElementwise } diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala index 301e7051df..3b93a8933d 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala @@ -123,7 +123,7 @@ trait Parsers { self: Quasiquotes => override def isStatSep(token: Int) = token == EOF || super.isStatSep(token) override def expectedMsg(token: Int): String = - if (isHole) expectedMsgTemplate(token2string(token), "splicee") + if (isHole) expectedMsgTemplate(token2string(token), "unquotee") else super.expectedMsg(token) // $mods def foo diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala index e7730f878f..5986758c2b 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala @@ -12,7 +12,7 @@ import scala.collection.{immutable, mutable} */ trait Placeholders { self: Quasiquotes => import global._ - import Cardinality._ + import Rank._ import universeTypes._ // Step 1: Transform Scala source with holes into vanilla Scala source @@ -29,13 +29,13 @@ trait Placeholders { self: Quasiquotes => posMap += pos -> ((start, end)) } - def appendHole(tree: Tree, cardinality: Cardinality) = { + def appendHole(tree: Tree, rank: Rank) = { val placeholderName = c.freshName(TermName(nme.QUASIQUOTE_PREFIX + sessionSuffix)) sb.append(placeholderName) val holeTree = if (method != nme.unapply) tree else Bind(placeholderName, tree) - holeMap(placeholderName) = Hole(cardinality, holeTree) + holeMap(placeholderName) = Hole(rank, holeTree) } val iargs = method match { @@ -47,9 +47,9 @@ trait Placeholders { self: Quasiquotes => } foreach2(iargs, parts.init) { case (tree, (p, pos)) => - val (part, cardinality) = parseDots(p) + val (part, rank) = parseDots(p) appendPart(part, pos) - appendHole(tree, cardinality) + appendHole(tree, rank) } val (p, pos) = parts.last appendPart(p, pos) diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala index 339937adc3..61fb22bc73 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala @@ -10,7 +10,7 @@ trait Reifiers { self: Quasiquotes => import global.build._ import global.treeInfo._ import global.definitions._ - import Cardinality._ + import Rank._ import universeTypes._ abstract class Reifier(val isReifyingExpressions: Boolean) extends { @@ -23,7 +23,7 @@ trait Reifiers { self: Quasiquotes => lazy val typer = throw new UnsupportedOperationException def isReifyingPatterns: Boolean = !isReifyingExpressions - def action = if (isReifyingExpressions) "splice" else "extract" + def action = if (isReifyingExpressions) "unquote" else "extract" def holesHaveTypes = isReifyingExpressions /** Map that stores freshly generated names linked to the corresponding names in the reified tree. @@ -129,7 +129,7 @@ trait Reifiers { self: Quasiquotes => def reifyTreePlaceholder(tree: Tree): Tree = tree match { case Placeholder(hole: ApplyHole) if hole.tpe <:< treeType => hole.tree case Placeholder(Hole(tree, NoDot)) if isReifyingPatterns => tree - case Placeholder(hole @ Hole(_, card @ Dot())) => c.abort(hole.pos, s"Can't $action with $card here") + case Placeholder(hole @ Hole(_, rank @ Dot())) => c.abort(hole.pos, s"Can't $action with $rank here") case TuplePlaceholder(args) => reifyTuple(args) case TupleTypePlaceholder(args) => reifyTupleType(args) case FunctionTypePlaceholder(argtpes, restpe) => reifyFunctionType(argtpes, restpe) @@ -236,7 +236,7 @@ trait Reifiers { self: Quasiquotes => case List(hole @ Placeholder(Hole(_, NoDot))) => reify(hole) case List(Placeholder(_)) => reifyBuildCall(nme.SyntacticTuple, args) // in a case we only have one element tuple without - // any cardinality annotations this means that this is + // any rank annotations this means that this is // just an expression wrapped in parentheses case List(other) => reify(other) case _ => reifyBuildCall(nme.SyntacticTuple, args) @@ -295,8 +295,8 @@ trait Reifiers { self: Quasiquotes => * * Example: * - * reifyMultiCardinalityList(lst) { - * // first we define patterns that extract high-cardinality holeMap (currently ..) + * reifyHighRankList(lst) { + * // first we define patterns that extract high-rank holeMap (currently ..) * case Placeholder(IterableType(_, _)) => tree * } { * // in the end we define how single elements are reified, typically with default reify call @@ -306,10 +306,10 @@ trait Reifiers { self: Quasiquotes => * Sample execution of previous concrete list reifier: * * > val lst = List(foo, bar, qq$f3948f9s$1) - * > reifyMultiCardinalityList(lst) { ... } { ... } + * > reifyHighRankList(lst) { ... } { ... } * q"List($foo, $bar) ++ ${holeMap(qq$f3948f9s$1).tree}" */ - def reifyMultiCardinalityList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree + def reifyHighRankList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree val fillListHole: PartialFunction[Any, Tree] = { case Placeholder(Hole(tree, DotDot)) => tree @@ -331,16 +331,16 @@ trait Reifiers { self: Quasiquotes => } /** Reifies arbitrary list filling ..$x and ...$y holeMap when they are put - * in the correct position. Fallbacks to regular reification for non-high cardinality + * in the correct position. Fallbacks to regular reification for zero rank * elements. */ - override def reifyList(xs: List[Any]): Tree = reifyMultiCardinalityList(xs)(fillListHole.orElse(fillListOfListsHole))(reify) + override def reifyList(xs: List[Any]): Tree = reifyHighRankList(xs)(fillListHole.orElse(fillListOfListsHole))(reify) - def reifyAnnotList(annots: List[Tree]): Tree = reifyMultiCardinalityList(annots) { + def reifyAnnotList(annots: List[Tree]): Tree = reifyHighRankList(annots) { case AnnotPlaceholder(h @ Hole(_, DotDot)) => reifyAnnotation(h) } { case AnnotPlaceholder(h: ApplyHole) if h.tpe <:< treeType => reifyAnnotation(h) - case AnnotPlaceholder(h: UnapplyHole) if h.cardinality == NoDot => reifyAnnotation(h) + case AnnotPlaceholder(h: UnapplyHole) if h.rank == NoDot => reifyAnnotation(h) case other => reify(other) } @@ -372,7 +372,7 @@ trait Reifiers { self: Quasiquotes => } class ApplyReifier extends Reifier(isReifyingExpressions = true) { - def reifyMultiCardinalityList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree = + def reifyHighRankList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree = if (xs.isEmpty) mkList(Nil) else { def reifyGroup(group: List[Any]): Tree = group match { @@ -399,12 +399,12 @@ trait Reifiers { self: Quasiquotes => } mods match { case hole :: Nil => - if (flags.nonEmpty) c.abort(flags(0).pos, "Can't splice flags together with modifiers, consider merging flags into modifiers") - if (annots.nonEmpty) c.abort(hole.pos, "Can't splice modifiers together with annotations, consider merging annotations into modifiers") + if (flags.nonEmpty) c.abort(flags(0).pos, "Can't unquote flags together with modifiers, consider merging flags into modifiers") + if (annots.nonEmpty) c.abort(hole.pos, "Can't unquote modifiers together with annotations, consider merging annotations into modifiers") ensureNoExplicitFlags(m, hole.pos) hole.tree case _ :: hole :: Nil => - c.abort(hole.pos, "Can't splice multiple modifiers, consider merging them into a single modifiers instance") + c.abort(hole.pos, "Can't unquote multiple modifiers, consider merging them into a single modifiers instance") case _ => val baseFlags = reifyFlags(m.flags) val reifiedFlags = flags.foldLeft[Tree](baseFlags) { case (flag, hole) => Apply(Select(flag, nme.OR), List(hole.tree)) } @@ -423,7 +423,7 @@ trait Reifiers { self: Quasiquotes => // pq"$lhs :: $rhs" private def cons(lhs: Tree, rhs: Tree) = Apply(collectionCons, lhs :: rhs :: Nil) - def reifyMultiCardinalityList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree = { + def reifyHighRankList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree = { val grouped = group(xs) { (a, b) => !fill.isDefinedAt(a) && !fill.isDefinedAt(b) } def appended(lst: List[Any], init: Tree) = lst.foldLeft(init) { (l, r) => append(l, fallback(r)) } def prepended(lst: List[Any], init: Tree) = lst.foldRight(init) { (l, r) => cons(fallback(l), r) } diff --git a/src/reflect/scala/reflect/api/Quasiquotes.scala b/src/reflect/scala/reflect/api/Quasiquotes.scala index fcf8edcec7..c939eee164 100644 --- a/src/reflect/scala/reflect/api/Quasiquotes.scala +++ b/src/reflect/scala/reflect/api/Quasiquotes.scala @@ -7,7 +7,7 @@ trait Quasiquotes { self: Universe => // using the mechanism implemented in `scala.tools.reflect.FastTrack` implicit class Quasiquote(ctx: StringContext) { protected trait api { - def apply[T](args: T*): Any = macro ??? + def apply[T](args: T*): Tree = macro ??? def unapply(scrutinee: Any): Any = macro ??? } object q extends api |