diff options
author | Den Shabalin <den.shabalin@gmail.com> | 2013-09-02 15:51:56 +0200 |
---|---|---|
committer | Den Shabalin <den.shabalin@gmail.com> | 2013-09-05 14:39:12 +0200 |
commit | 901cdc1855e8e80957b18add4991736b9f458d77 (patch) | |
tree | b6ac94c657f262d3a4e398e36b07d042ba4fbfa1 /src/reflect | |
parent | f9d5e3d4e8cca61ee75072ab13c2935061a1850e (diff) | |
download | scala-901cdc1855e8e80957b18add4991736b9f458d77.tar.gz scala-901cdc1855e8e80957b18add4991736b9f458d77.tar.bz2 scala-901cdc1855e8e80957b18add4991736b9f458d77.zip |
refine block and applied/typeapplied splicing/matching semantics
1. blocks now match single term-level expressions to account for
automatic block elimination. E.g.
val q"{ ..$stats }" = q"foo"
will match into stats = List(q"foo"). This is useful to uniformly
deal with blocks on term level.
2. blocks in quasiquotes collapse into single expressions
3. Applied and TypeApplied now have constructors too which helps
to unify matching and extraction in quasiquote reifier
4. TypeApplied now matches AppliedTypeTree too
5. Add Syntactic prefix to Applied and TypeApplied
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/scala/reflect/api/BuildUtils.scala | 21 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/BuildUtils.scala | 37 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/StdNames.scala | 5 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/TreeGen.scala | 7 |
4 files changed, 48 insertions, 22 deletions
diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala index 03980f5f0a..ef9f9ab834 100644 --- a/src/reflect/scala/reflect/api/BuildUtils.scala +++ b/src/reflect/scala/reflect/api/BuildUtils.scala @@ -64,8 +64,6 @@ private[reflect] trait BuildUtils { self: Universe => def Ident(sym: Symbol): Ident - def Block(stats: List[Tree]): Block - def TypeTree(tp: Type): TypeTree def thisPrefix(sym: Symbol): Type @@ -80,6 +78,8 @@ private[reflect] trait BuildUtils { self: Universe => def mkRefineStat(stats: List[Tree]): List[Tree] + def RefTree(qual: Tree, sym: Symbol): Tree + val FlagsRepr: FlagsReprExtractor trait FlagsReprExtractor { @@ -87,15 +87,17 @@ private[reflect] trait BuildUtils { self: Universe => def unapply(flags: Long): Some[Long] } - val TypeApplied: TypeAppliedExtractor + val SyntacticTypeApplied: SyntacticTypeAppliedExtractor - trait TypeAppliedExtractor { + trait SyntacticTypeAppliedExtractor { + def apply(tree: Tree, targs: List[Tree]): Tree def unapply(tree: Tree): Some[(Tree, List[Tree])] } - val Applied: AppliedExtractor + val SyntacticApplied: SyntacticAppliedExtractor - trait AppliedExtractor { + trait SyntacticAppliedExtractor { + def apply(tree: Tree, argss: List[List[Tree]]): Tree def unapply(tree: Tree): Some[(Tree, List[List[Tree]])] } @@ -117,6 +119,11 @@ private[reflect] trait BuildUtils { self: Universe => def unapply(tree: Tree): Option[List[Tree]] } - def RefTree(qual: Tree, sym: Symbol): Tree + val SyntacticBlock: SyntacticBlockExtractor + + trait SyntacticBlockExtractor { + def apply(stats: List[Tree]): Tree + def unapply(tree: Tree): Option[List[Tree]] + } } } diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index 208a61d9d3..928395b7c9 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -53,12 +53,6 @@ trait BuildUtils { self: SymbolTable => def Ident(sym: Symbol): Ident = self.Ident(sym) - def Block(stats: List[Tree]): Block = stats match { - case Nil => self.Block(Nil, Literal(Constant(()))) - case elem :: Nil => self.Block(Nil, elem) - case elems => self.Block(elems.init, elems.last) - } - def TypeTree(tp: Type): TypeTree = self.TypeTree(tp) def thisPrefix(sym: Symbol): Type = sym.thisPrefix @@ -88,25 +82,34 @@ trait BuildUtils { self: SymbolTable => def mkRefineStat(stats: List[Tree]): List[Tree] = stats.map(mkRefineStat) + def RefTree(qual: Tree, sym: Symbol) = self.RefTree(qual, sym.name) setSymbol sym + object FlagsRepr extends FlagsReprExtractor { def apply(bits: Long): FlagSet = bits def unapply(flags: Long): Some[Long] = Some(flags) } - object TypeApplied extends TypeAppliedExtractor { + object SyntacticTypeApplied extends SyntacticTypeAppliedExtractor { + def apply(tree: Tree, targs: List[Tree]): Tree = + if (targs.isEmpty) tree + else if (tree.isTerm) TypeApply(tree, targs) + else if (tree.isType) AppliedTypeTree(tree, targs) + else throw new IllegalArgumentException(s"can't apply types to $tree") + def unapply(tree: Tree): Some[(Tree, List[Tree])] = tree match { case TypeApply(fun, targs) => Some((fun, targs)) + case AppliedTypeTree(tpe, targs) => Some((tpe, targs)) case _ => Some((tree, Nil)) } } - object Applied extends AppliedExtractor { + object SyntacticApplied extends SyntacticAppliedExtractor { + def apply(tree: Tree, argss: List[List[Tree]]): Tree = + argss.foldLeft(tree) { Apply(_, _) } + def unapply(tree: Tree): Some[(Tree, List[List[Tree]])] = { val treeInfo.Applied(fun, targs, argss) = tree - targs match { - case Nil => Some((fun, argss)) - case _ => Some((TypeApply(fun, targs), argss)) - } + Some((SyntacticTypeApplied(fun, targs), argss)) } } @@ -189,7 +192,15 @@ trait BuildUtils { self: SymbolTable => } } - def RefTree(qual: Tree, sym: Symbol) = self.RefTree(qual, sym.name) setSymbol sym + object SyntacticBlock extends SyntacticBlockExtractor { + def apply(stats: List[Tree]): Tree = gen.mkBlock(stats) + + def unapply(tree: Tree): Option[List[Tree]] = tree match { + case self.Block(stats, expr) => Some(stats :+ expr) + case _ if tree.isTerm => Some(tree :: Nil) + case _ => None + } + } } val build: BuildApi = new BuildImpl diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index eb24706f29..6cbf1f1046 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -561,7 +561,6 @@ trait StdNames { val Any: NameType = "Any" val AnyVal: NameType = "AnyVal" val Apply: NameType = "Apply" - val Applied: NameType = "Applied" val ArrayAnnotArg: NameType = "ArrayAnnotArg" val Block: NameType = "Block" val ConstantType: NameType = "ConstantType" @@ -588,7 +587,10 @@ trait StdNames { val Select: NameType = "Select" val SelectFromTypeTree: NameType = "SelectFromTypeTree" val StringContext: NameType = "StringContext" + val SyntacticApplied: NameType = "SyntacticApplied" + val SyntacticBlock: NameType = "SyntacticBlock" val SyntacticClassDef: NameType = "SyntacticClassDef" + val SyntacticTypeApplied: NameType = "SyntacticTypeApplied" val This: NameType = "This" val ThisType: NameType = "ThisType" val True : NameType = "True" @@ -596,7 +598,6 @@ trait StdNames { val TupleN: NameType = "TupleN" val TupleTypeN: NameType = "TupleTypeN" val TYPE_ : NameType = "TYPE" - val TypeApplied: NameType = "TypeApplied" val TypeRef: NameType = "TypeRef" val TypeTree: NameType = "TypeTree" val UNIT : NameType = "UNIT" diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index a7ea8c816f..9623cc31f6 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -414,4 +414,11 @@ abstract class TreeGen extends macros.TreeBuilder { ) } } + + /** Create block of statements `stats` */ + def mkBlock(stats: List[Tree]): Tree = + if (stats.isEmpty) Literal(Constant(())) + else if (!stats.last.isTerm) Block(stats, Literal(Constant(()))) + else if (stats.length == 1) stats.head + else Block(stats.init, stats.last) } |