summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDen Shabalin <den.shabalin@gmail.com>2013-10-31 12:21:28 +0100
committerDen Shabalin <den.shabalin@gmail.com>2013-11-12 14:04:42 +0100
commitc62a0e78c33dda1db6e73fa5cd3c6ddbd2b238f4 (patch)
treee5b1d545931db70c83844474a802804b164f75e5 /src
parenta4a3ab0d722412b9ecf267b178bb866087867cf9 (diff)
downloadscala-c62a0e78c33dda1db6e73fa5cd3c6ddbd2b238f4.tar.gz
scala-c62a0e78c33dda1db6e73fa5cd3c6ddbd2b238f4.tar.bz2
scala-c62a0e78c33dda1db6e73fa5cd3c6ddbd2b238f4.zip
add support for for loops and for enumerators to quasiquotes
1. q"for (..$enums) $body", q"for (..$enums) yield $body" 2. fq"..." quote to construct/deconstruct enumerators
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala23
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala8
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala1
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala13
-rw-r--r--src/reflect/scala/reflect/api/Quasiquotes.scala1
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala8
6 files changed, 49 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
index f9ecbe35c9..d8ede24f1a 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala
@@ -152,6 +152,13 @@ trait Parsers { self: Quasiquotes =>
in.nextToken()
stats
}
+
+ override def enumerator(isFirst: Boolean, allowNestedIf: Boolean = true) =
+ if (isHole && lookingAhead { in.token == EOF || in.token == RPAREN || isStatSep }) {
+ val res = build.SyntacticValFrom(Bind(in.name, Ident(nme.WILDCARD)), Ident(nme.QUASIQUOTE_FOR_ENUM)) :: Nil
+ in.nextToken()
+ res
+ } else super.enumerator(isFirst, allowNestedIf)
}
}
@@ -174,11 +181,21 @@ trait Parsers { self: Quasiquotes =>
}
}
+ object ForEnumeratorParser extends Parser {
+ def entryPoint = { parser =>
+ val enums = parser.enumerator(isFirst = false, allowNestedIf = false)
+ assert(enums.length == 1)
+ enums.head
+ }
+ }
+
object FreshName {
def unapply(name: Name): Option[String] =
- name.toString.split("\\$") match {
- case Array(qq, left, right) if qq + "$" == nme.QUASIQUOTE_PREFIX && Try(right.toInt).isSuccess =>
- Some(left + "$")
+ name.toString.split("\\$").toSeq match {
+ case qq +: (middle :+ last)
+ if qq + "$" == nme.QUASIQUOTE_PREFIX
+ && Try(last.toInt).isSuccess && middle.nonEmpty =>
+ Some(middle.mkString("", "$", "$"))
case _ =>
None
}
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala
index c31d1fcd12..54be9123c7 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala
@@ -161,4 +161,12 @@ trait Placeholders { self: Quasiquotes =>
case _ => None
}
}
+
+ object ForEnumPlaceholder {
+ def unapply(tree: Tree): Option[(Tree, Location, Cardinality)] = tree match {
+ case build.SyntacticValFrom(Bind(Placeholder(tree, location, card), Ident(nme.WILDCARD)), Ident(nme.QUASIQUOTE_FOR_ENUM)) =>
+ Some((tree, location, card))
+ case _ => None
+ }
+ }
} \ No newline at end of file
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala
index f4d6b39d02..7d777ef7d5 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala
@@ -31,6 +31,7 @@ abstract class Quasiquotes extends Parsers
case nme.tq => TypeParser.parse(_)
case nme.cq => CaseParser.parse(_)
case nme.pq => PatternParser.parse(_)
+ case nme.fq => ForEnumeratorParser.parse(_)
case other => global.abort(s"Unknown quasiquote flavor: $other")
}
(universe0, args0, parts1, parse0, reify0, method0)
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index 3d1ecf95b2..b28c85cfc2 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -127,6 +127,7 @@ trait Reifiers { self: Quasiquotes =>
case RefineStatPlaceholder(tree, _, _) => reifyRefineStat(tree)
case EarlyDefPlaceholder(tree, _, _) => reifyEarlyDef(tree)
case PackageStatPlaceholder(tree, _, _) => reifyPackageStat(tree)
+ case ForEnumPlaceholder(tree, _, _) => tree
case _ => EmptyTree
}
@@ -148,6 +149,16 @@ trait Reifiers { self: Quasiquotes =>
reifyBuildCall(nme.SyntacticValDef, mods, name, tpt, rhs)
case SyntacticVarDef(mods, name, tpt, rhs) =>
reifyBuildCall(nme.SyntacticVarDef, mods, name, tpt, rhs)
+ case SyntacticValFrom(pat, rhs) =>
+ reifyBuildCall(nme.SyntacticValFrom, pat, rhs)
+ case SyntacticValEq(pat, rhs) =>
+ reifyBuildCall(nme.SyntacticValEq, pat, rhs)
+ case SyntacticFilter(cond) =>
+ reifyBuildCall(nme.SyntacticFilter, cond)
+ case SyntacticFor(enums, body) =>
+ reifyBuildCall(nme.SyntacticFor, enums, body)
+ case SyntacticForYield(enums, body) =>
+ reifyBuildCall(nme.SyntacticForYield, enums, body)
case SyntacticAssign(lhs, rhs) =>
reifyBuildCall(nme.SyntacticAssign, lhs, rhs)
case SyntacticApplied(fun, List(args))
@@ -275,7 +286,7 @@ trait Reifiers { self: Quasiquotes =>
case RefineStatPlaceholder(tree, _, DotDot) => reifyRefineStat(tree)
case EarlyDefPlaceholder(tree, _, DotDot) => reifyEarlyDef(tree)
case PackageStatPlaceholder(tree, _, DotDot) => reifyPackageStat(tree)
-
+ case ForEnumPlaceholder(tree, _, DotDot) => tree
case List(Placeholder(tree, _, DotDotDot)) => tree
} {
reify(_)
diff --git a/src/reflect/scala/reflect/api/Quasiquotes.scala b/src/reflect/scala/reflect/api/Quasiquotes.scala
index 3687ccba63..fcf8edcec7 100644
--- a/src/reflect/scala/reflect/api/Quasiquotes.scala
+++ b/src/reflect/scala/reflect/api/Quasiquotes.scala
@@ -14,5 +14,6 @@ trait Quasiquotes { self: Universe =>
object tq extends api
object cq extends api
object pq extends api
+ object fq extends api
}
}
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index bc9c46a141..c26e815df1 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -327,6 +327,7 @@ trait StdNames {
val QUASIQUOTE_FILE: String = "<quasiquote>"
val QUASIQUOTE_TUPLE: NameType = "$quasiquote$tuple$"
val QUASIQUOTE_CASE: NameType = "$quasiquote$case$"
+ val QUASIQUOTE_FOR_ENUM: NameType = "$quasiquote$for$enum$"
val MIXIN_CONSTRUCTOR: NameType = "$init$"
val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$"
val OUTER: NameType = "$outer"
@@ -592,6 +593,9 @@ trait StdNames {
val SyntacticBlock: NameType = "SyntacticBlock"
val SyntacticClassDef: NameType = "SyntacticClassDef"
val SyntacticDefDef: NameType = "SyntacticDefDef"
+ val SyntacticFilter: NameType = "SyntacticFilter"
+ val SyntacticFor: NameType = "SyntacticFor"
+ val SyntacticForYield: NameType = "SyntacticForYield"
val SyntacticFunction: NameType = "SyntacticFunction"
val SyntacticFunctionType: NameType = "SyntacticFunctionType"
val SyntacticPackageObjectDef: NameType = "SyntacticPackageObjectDef"
@@ -602,6 +606,8 @@ trait StdNames {
val SyntacticTupleType: NameType = "SyntacticTupleType"
val SyntacticTypeApplied: NameType = "SyntacticTypeApplied"
val SyntacticValDef: NameType = "SyntacticValDef"
+ val SyntacticValEq: NameType = "SyntacticValEq"
+ val SyntacticValFrom: NameType = "SyntacticValFrom"
val SyntacticVarDef: NameType = "SyntacticVarDef"
val This: NameType = "This"
val ThisType: NameType = "ThisType"
@@ -745,7 +751,6 @@ trait StdNames {
val typedProductIterator: NameType = "typedProductIterator"
val TypeName: NameType = "TypeName"
val typeTagToManifest: NameType = "typeTagToManifest"
-
val unapply: NameType = "unapply"
val unapplySeq: NameType = "unapplySeq"
val unbox: NameType = "unbox"
@@ -764,6 +769,7 @@ trait StdNames {
val tq: NameType = "tq"
val cq: NameType = "cq"
val pq: NameType = "pq"
+ val fq: NameType = "fq"
// unencoded operators
object raw {