summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-01-29 01:55:46 -0800
committerJason Zaugg <jzaugg@gmail.com>2014-01-29 01:55:46 -0800
commit4506acba688e80a4f778e495a74e7a50f83c4e1b (patch)
treeb05a731dde14ce49f344260ceef2023cd973e646 /src/reflect
parent057adc70346414c10273f58fcd44114bf0672933 (diff)
parent8e9862473abd03bded2d3afa60c777099f7872c5 (diff)
downloadscala-4506acba688e80a4f778e495a74e7a50f83c4e1b.tar.gz
scala-4506acba688e80a4f778e495a74e7a50f83c4e1b.tar.bz2
scala-4506acba688e80a4f778e495a74e7a50f83c4e1b.zip
Merge pull request #3374 from densh/si/6844-8076
SI-6844 SI-8076 improve handling of function parameters in quasiquotes
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/api/BuildUtils.scala16
-rw-r--r--src/reflect/scala/reflect/internal/BuildUtils.scala51
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala12
3 files changed, 53 insertions, 26 deletions
diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala
index 3a69390bcf..3bcf751ace 100644
--- a/src/reflect/scala/reflect/api/BuildUtils.scala
+++ b/src/reflect/scala/reflect/api/BuildUtils.scala
@@ -96,6 +96,13 @@ private[reflect] trait BuildUtils { self: Universe =>
def freshTypeName(prefix: String): TypeName
+ val ImplicitParams: ImplicitParamsExtractor
+
+ trait ImplicitParamsExtractor {
+ def apply(paramss: List[List[ValDef]], implparams: List[ValDef]): List[List[ValDef]]
+ def unapply(vparamss: List[List[ValDef]]): Some[(List[List[ValDef]], List[ValDef])]
+ }
+
val ScalaDot: ScalaDotExtractor
trait ScalaDotExtractor {
@@ -128,8 +135,8 @@ private[reflect] trait BuildUtils { self: Universe =>
trait SyntacticClassDefExtractor {
def apply(mods: Modifiers, name: TypeName, tparams: List[Tree],
- constrMods: Modifiers, vparamss: List[List[Tree]], earlyDefs: List[Tree],
- parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef
+ constrMods: Modifiers, vparamss: List[List[Tree]],
+ earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef
def unapply(tree: Tree): Option[(Modifiers, TypeName, List[TypeDef], Modifiers, List[List[ValDef]],
List[Tree], List[Tree], ValDef, List[Tree])]
}
@@ -199,9 +206,10 @@ private[reflect] trait BuildUtils { self: Universe =>
val SyntacticDefDef: SyntacticDefDefExtractor
trait SyntacticDefDefExtractor {
- def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[Tree]], tpt: Tree, rhs: Tree): DefDef
+ def apply(mods: Modifiers, name: TermName, tparams: List[Tree],
+ vparamss: List[List[Tree]], tpt: Tree, rhs: Tree): DefDef
- def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[List[ValDef]], Tree, Tree)]
+ def unapply(tree: Tree): Option[(Modifiers, TermName, List[TypeDef], List[List[ValDef]], Tree, Tree)]
}
val SyntacticValDef: SyntacticValDefExtractor
diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala
index 16bb3e5989..6106339324 100644
--- a/src/reflect/scala/reflect/internal/BuildUtils.scala
+++ b/src/reflect/scala/reflect/internal/BuildUtils.scala
@@ -73,18 +73,25 @@ trait BuildUtils { self: SymbolTable =>
def mkAnnotation(trees: List[Tree]): List[Tree] = trees.map(mkAnnotation)
- def mkVparamss(argss: List[List[Tree]]): List[List[ValDef]] = argss.map(_.map(mkParam))
+ def mkParam(argss: List[List[Tree]], extraFlags: FlagSet = NoFlags): List[List[ValDef]] =
+ argss.map { args => args.map { mkParam(_, extraFlags) } }
- def mkParam(tree: Tree): ValDef = tree match {
+ def mkParam(tree: Tree, extraFlags: FlagSet): ValDef = tree match {
+ case Typed(Ident(name: TermName), tpt) =>
+ mkParam(ValDef(NoMods, name, tpt, EmptyTree), extraFlags)
case vd: ValDef =>
- var newmods = (vd.mods | PARAM) & (~DEFERRED)
+ var newmods = vd.mods & (~DEFERRED)
if (vd.rhs.nonEmpty) newmods |= DEFAULTPARAM
- copyValDef(vd)(mods = newmods)
+ copyValDef(vd)(mods = newmods | extraFlags)
case _ =>
- throw new IllegalArgumentException(s"$tree is not valid represenation of function parameter, " +
+ throw new IllegalArgumentException(s"$tree is not valid represenation of a parameter, " +
"""consider reformatting it into q"val $name: $T = $default" shape""")
}
+ def mkImplicitParam(args: List[Tree]): List[ValDef] = args.map(mkImplicitParam)
+
+ def mkImplicitParam(tree: Tree): ValDef = mkParam(tree, IMPLICIT | PARAM)
+
def mkTparams(tparams: List[Tree]): List[TypeDef] =
tparams.map {
case td: TypeDef => copyTypeDef(td)(mods = (td.mods | PARAM) & (~DEFERRED))
@@ -142,6 +149,16 @@ trait BuildUtils { self: SymbolTable =>
protected implicit def fresh: FreshNameCreator = self.currentFreshNameCreator
+ object ImplicitParams extends ImplicitParamsExtractor {
+ def apply(paramss: List[List[ValDef]], implparams: List[ValDef]): List[List[ValDef]] =
+ if (implparams.nonEmpty) paramss :+ mkImplicitParam(implparams) else paramss
+
+ def unapply(vparamss: List[List[ValDef]]): Some[(List[List[ValDef]], List[ValDef])] = vparamss match {
+ case init :+ (last @ (initlast :: _)) if initlast.mods.isImplicit => Some((init, last))
+ case _ => Some((vparamss, Nil))
+ }
+ }
+
object FlagsRepr extends FlagsReprExtractor {
def apply(bits: Long): FlagSet = bits
def unapply(flags: Long): Some[Long] = Some(flags)
@@ -241,14 +258,10 @@ trait BuildUtils { self: SymbolTable =>
object SyntacticClassDef extends SyntacticClassDefExtractor {
def apply(mods: Modifiers, name: TypeName, tparams: List[Tree],
- constrMods: Modifiers, vparamss: List[List[Tree]], earlyDefs: List[Tree],
- parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef = {
+ constrMods: Modifiers, vparamss: List[List[Tree]],
+ earlyDefs: List[Tree], parents: List[Tree], selfType: Tree, body: List[Tree]): ClassDef = {
val extraFlags = PARAMACCESSOR | (if (mods.isCase) CASEACCESSOR else 0L)
- val vparamss0 = vparamss.map { _.map {
- case vd: ValDef => copyValDef(vd)(mods = (vd.mods | extraFlags) & (~DEFERRED))
- case tree => throw new IllegalArgumentException(s"$tree is not valid representation of class parameter, " +
- """consider reformatting it into q"val $name: $T = $default" shape""")
- } }
+ val vparamss0 = mkParam(vparamss, extraFlags)
val tparams0 = mkTparams(tparams)
val parents0 = gen.mkParents(mods,
if (mods.isCase) parents.filter {
@@ -423,7 +436,7 @@ trait BuildUtils { self: SymbolTable =>
object SyntacticFunction extends SyntacticFunctionExtractor {
def apply(params: List[Tree], body: Tree): Tree = {
- val params0 :: Nil = mkVparamss(params :: Nil)
+ val params0 :: Nil = mkParam(params :: Nil, PARAM)
require(params0.forall { _.rhs.isEmpty }, "anonymous functions don't support parameters with default values")
Function(params0, body)
}
@@ -450,11 +463,15 @@ trait BuildUtils { self: SymbolTable =>
}
object SyntacticDefDef extends SyntacticDefDefExtractor {
- def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[Tree]], tpt: Tree, rhs: Tree): DefDef =
- DefDef(mods, name, mkTparams(tparams), mkVparamss(vparamss), tpt, rhs)
+ def apply(mods: Modifiers, name: TermName, tparams: List[Tree],
+ vparamss: List[List[Tree]], tpt: Tree, rhs: Tree): DefDef = {
+ val vparamss0 = mkParam(vparamss, PARAM)
+ DefDef(mods, name, mkTparams(tparams), vparamss0, tpt, rhs)
+ }
- def unapply(tree: Tree): Option[(Modifiers, TermName, List[Tree], List[List[ValDef]], Tree, Tree)] = tree match {
- case DefDef(mods, name, tparams, vparamss, tpt, rhs) => Some((mods, name, tparams, vparamss, tpt, rhs))
+ def unapply(tree: Tree): Option[(Modifiers, TermName, List[TypeDef], List[List[ValDef]], Tree, Tree)] = tree match {
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ Some((mods, name, tparams, vparamss, tpt, rhs))
case _ => None
}
}
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 256d5759fa..a46cd05efa 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -250,12 +250,13 @@ 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_FUNCTION: NameType = "$quasiquote$function$"
+ final val QUASIQUOTE_MODS: NameType = "$quasiquote$mods$"
final val QUASIQUOTE_PACKAGE_STAT: NameType = "$quasiquote$package$stat$"
+ final val QUASIQUOTE_PARAM: NameType = "$quasiquote$param$"
+ final val QUASIQUOTE_REFINE_STAT: NameType = "$quasiquote$refine$stat$"
+ final val QUASIQUOTE_TUPLE: NameType = "$quasiquote$tuple$"
// Annotation simple names, used in Namer
final val BeanPropertyAnnot: NameType = "BeanProperty"
@@ -577,6 +578,7 @@ trait StdNames {
val Flag : NameType = "Flag"
val FlagsRepr: NameType = "FlagsRepr"
val Ident: NameType = "Ident"
+ val ImplicitParams: NameType = "ImplicitParams"
val Import: NameType = "Import"
val Literal: NameType = "Literal"
val LiteralAnnotArg: NameType = "LiteralAnnotArg"
@@ -705,9 +707,9 @@ trait StdNames {
val materializeTypeTag: NameType = "materializeTypeTag"
val moduleClass : NameType = "moduleClass"
val mkAnnotation: NameType = "mkAnnotation"
- val mkRefineStat: NameType = "mkRefineStat"
val mkEarlyDef: NameType = "mkEarlyDef"
val mkPackageStat: NameType = "mkPackageStat"
+ val mkRefineStat: NameType = "mkRefineStat"
val ne: NameType = "ne"
val newArray: NameType = "newArray"
val newFreeTerm: NameType = "newFreeTerm"