diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-01-29 01:55:46 -0800 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-01-29 01:55:46 -0800 |
commit | 4506acba688e80a4f778e495a74e7a50f83c4e1b (patch) | |
tree | b05a731dde14ce49f344260ceef2023cd973e646 /src/reflect | |
parent | 057adc70346414c10273f58fcd44114bf0672933 (diff) | |
parent | 8e9862473abd03bded2d3afa60c777099f7872c5 (diff) | |
download | scala-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.scala | 16 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/BuildUtils.scala | 51 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/StdNames.scala | 12 |
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" |