Skip to content

Commit 9def2ad

Browse files
committed
Merge pull request scala#2714 from scalamacros/topic/quasiquotes
Quasiquotes
2 parents 5994711 + 114d52b commit 9def2ad

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2780
-240
lines changed

src/compiler/scala/reflect/macros/compiler/Errors.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ trait Errors extends Traces {
6060
(rtpe, atpe) match {
6161
case _ if rtpe eq atpe => success()
6262
case (TypeRef(_, RepeatedParamClass, rtpe :: Nil), TypeRef(_, RepeatedParamClass, atpe :: Nil)) => check(rtpe, atpe)
63-
case (ExprClassOf(_), TreeType()) => success()
64-
case (TreeType(), ExprClassOf(_)) => success()
63+
case (ExprClassOf(_), TreeType()) if rtpe.prefix =:= atpe.prefix => success()
64+
case (SubtreeType(), ExprClassOf(_)) if rtpe.prefix =:= atpe.prefix => success()
6565
case _ => rtpe <:< atpe
6666
}
6767
}

src/compiler/scala/reflect/reify/codegen/GenTrees.scala

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,6 @@ trait GenTrees {
4242
// the second prototype reified external types, but avoided reifying local ones => this created an ugly irregularity
4343
// current approach is uniform and compact
4444
var rtree = tree match {
45-
case global.EmptyTree =>
46-
reifyMirrorObject(EmptyTree)
47-
case global.emptyValDef =>
48-
mirrorSelect(nme.emptyValDef)
49-
case global.pendingSuperCall =>
50-
mirrorSelect(nme.pendingSuperCall)
5145
case FreeDef(_, _, _, _, _) =>
5246
reifyNestedFreeDef(tree)
5347
case FreeRef(_, _) =>
@@ -56,12 +50,8 @@ trait GenTrees {
5650
reifyBoundTerm(tree)
5751
case BoundType(tree) =>
5852
reifyBoundType(tree)
59-
case Literal(const @ Constant(_)) =>
60-
mirrorCall(nme.Literal, reifyProduct(const))
61-
case Import(expr, selectors) =>
62-
mirrorCall(nme.Import, reify(expr), mkList(selectors map reifyProduct))
6353
case _ =>
64-
reifyProduct(tree)
54+
reifyTreeSyntactically(tree)
6555
}
6656

6757
// usually we don't reify symbols/types, because they can be re-inferred during subsequent reflective compilation
@@ -78,6 +68,21 @@ trait GenTrees {
7868
rtree
7969
}
8070

71+
def reifyTreeSyntactically(tree: Tree) = tree match {
72+
case global.EmptyTree =>
73+
reifyMirrorObject(EmptyTree)
74+
case global.emptyValDef =>
75+
mirrorSelect(nme.emptyValDef)
76+
case global.pendingSuperCall =>
77+
mirrorSelect(nme.pendingSuperCall)
78+
case Literal(const @ Constant(_)) =>
79+
mirrorCall(nme.Literal, reifyProduct(const))
80+
case Import(expr, selectors) =>
81+
mirrorCall(nme.Import, reify(expr), mkList(selectors map reifyProduct))
82+
case _ =>
83+
reifyProduct(tree)
84+
}
85+
8186
def reifyModifiers(m: global.Modifiers) =
8287
mirrorFactoryCall(nme.Modifiers, mirrorBuildCall(nme.flagsFromBits, reify(m.flags)), reify(m.privateWithin), reify(m.annotations))
8388

src/compiler/scala/reflect/reify/codegen/GenUtils.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ trait GenUtils {
4242
def mirrorBuildCall(name: TermName, args: Tree*): Tree =
4343
call("" + nme.UNIVERSE_BUILD_PREFIX + name, args: _*)
4444

45+
def reifyBuildCall(name: TermName, args: Any*) =
46+
mirrorBuildCall(name, args map reify: _*)
47+
4548
def mirrorMirrorCall(name: TermName, args: Tree*): Tree =
4649
call("" + nme.MIRROR_PREFIX + name, args: _*)
4750

src/compiler/scala/reflect/reify/package.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ package object reify {
3232
// If we're in the constructor of an object or others don't have easy access to `this`, we have no good way to grab
3333
// the class of that object. Instead, we construct an anonymous class and grab his class file, assuming
3434
// this is enough to get the correct class loadeer for the class we *want* a mirror for, the object itself.
35-
rClassTree orElse Apply(Select(treeBuilder.makeAnonymousNew(Nil), sn.GetClass), Nil)
35+
rClassTree orElse Apply(Select(gen.mkAnonymousNew(Nil), sn.GetClass), Nil)
3636
}
3737
// JavaUniverse is defined in scala-reflect.jar, so we must be very careful in case someone reifies stuff having only scala-library.jar on the classpath
3838
val isJavaUniverse = JavaUniverseClass != NoSymbol && universe.tpe <:< JavaUniverseClass.toTypeConstructor

src/compiler/scala/tools/nsc/Global.scala

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
103103
typer.typed(mkCast(tree, pt))
104104
}
105105

106-
/** Trees fresh from the oven, mostly for use by the parser. */
107-
object treeBuilder extends {
108-
val global: Global.this.type = Global.this
109-
} with TreeBuilder {
110-
def freshName(prefix: String): Name = freshTermName(prefix)
111-
def freshTermName(prefix: String): TermName = currentUnit.freshTermName(prefix)
112-
def freshTypeName(prefix: String): TypeName = currentUnit.freshTypeName(prefix)
113-
def o2p(offset: Int): Position = new OffsetPosition(currentUnit.source, offset)
114-
def r2p(start: Int, mid: Int, end: Int): Position = rangePos(currentUnit.source, start, mid, end)
115-
}
106+
/** A spare instance of TreeBuilder left for backwards compatibility. */
107+
lazy val treeBuilder: TreeBuilder { val global: Global.this.type } = new syntaxAnalyzer.ParserTreeBuilder
116108

117109
/** Fold constants */
118110
object constfold extends {

src/compiler/scala/tools/nsc/ast/TreeGen.scala

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
112112
else AppliedTypeTree(Ident(clazz), targs map TypeTree)
113113
))
114114
}
115-
def mkSuperInitCall: Select = Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR)
116115

117116
def wildcardStar(tree: Tree) =
118117
atPos(tree.pos) { Typed(tree, Ident(tpnme.WILDCARD_STAR)) }
@@ -255,4 +254,52 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
255254
attrThis,
256255
If(cond, Block(syncBody: _*), EmptyTree)) ::
257256
stats: _*)
257+
258+
/** Creates a tree representing new Object { stats }.
259+
* To make sure an anonymous subclass of Object is created,
260+
* if there are no stats, a () is added.
261+
*/
262+
def mkAnonymousNew(stats: List[Tree]): Tree = {
263+
val stats1 = if (stats.isEmpty) List(Literal(Constant(()))) else stats
264+
mkNew(Nil, emptyValDef, stats1, NoPosition, NoPosition)
265+
}
266+
267+
/** Create positioned tree representing an object creation <new parents { stats }
268+
* @param npos the position of the new
269+
* @param cpos the position of the anonymous class starting with parents
270+
*/
271+
def mkNew(parents: List[Tree], self: ValDef, stats: List[Tree],
272+
npos: Position, cpos: Position): Tree =
273+
if (parents.isEmpty)
274+
mkNew(List(scalaAnyRefConstr), self, stats, npos, cpos)
275+
else if (parents.tail.isEmpty && stats.isEmpty) {
276+
// `Parsers.template` no longer differentiates tpts and their argss
277+
// e.g. `C()` will be represented as a single tree Apply(Ident(C), Nil)
278+
// instead of parents = Ident(C), argss = Nil as before
279+
// this change works great for things that are actually templates
280+
// but in this degenerate case we need to perform postprocessing
281+
val app = treeInfo.dissectApplied(parents.head)
282+
atPos(npos union cpos) { New(app.callee, app.argss) }
283+
} else {
284+
val x = tpnme.ANON_CLASS_NAME
285+
atPos(npos union cpos) {
286+
Block(
287+
List(
288+
atPos(cpos) {
289+
ClassDef(
290+
Modifiers(FINAL), x, Nil,
291+
mkTemplate(parents, self, NoMods, ListOfNil, stats, cpos.focus))
292+
}),
293+
atPos(npos) {
294+
New(
295+
Ident(x) setPos npos.focus,
296+
Nil)
297+
}
298+
)
299+
}
300+
}
301+
302+
def mkSyntheticParam(pname: TermName) =
303+
ValDef(Modifiers(PARAM | SYNTHETIC), pname, TypeTree(), EmptyTree)
304+
258305
}

src/compiler/scala/tools/nsc/ast/Trees.scala

Lines changed: 3 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -54,77 +54,6 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
5454
case xs :: rest => rest.foldLeft(Apply(gen.mkSuperInitCall, xs): Tree)(Apply.apply)
5555
}
5656

57-
/** Generates a template with constructor corresponding to
58-
*
59-
* constrmods (vparams1_) ... (vparams_n) preSuper { presupers }
60-
* extends superclass(args_1) ... (args_n) with mixins { self => body }
61-
*
62-
* This gets translated to
63-
*
64-
* extends superclass with mixins { self =>
65-
* presupers' // presupers without rhs
66-
* vparamss // abstract fields corresponding to value parameters
67-
* def <init>(vparamss) {
68-
* presupers
69-
* super.<init>(args)
70-
* }
71-
* body
72-
* }
73-
*/
74-
def Template(parents: List[Tree], self: ValDef, constrMods: Modifiers, vparamss: List[List[ValDef]], body: List[Tree], superPos: Position): Template = {
75-
/* Add constructor to template */
76-
77-
// create parameters for <init> as synthetic trees.
78-
var vparamss1 = mmap(vparamss) { vd =>
79-
atPos(vd.pos.focus) {
80-
val mods = Modifiers(vd.mods.flags & (IMPLICIT | DEFAULTPARAM | BYNAMEPARAM) | PARAM | PARAMACCESSOR)
81-
ValDef(mods withAnnotations vd.mods.annotations, vd.name, vd.tpt.duplicate, vd.rhs.duplicate)
82-
}
83-
}
84-
val (edefs, rest) = body span treeInfo.isEarlyDef
85-
val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef
86-
val gvdefs = evdefs map {
87-
case vdef @ ValDef(_, _, tpt, _) =>
88-
copyValDef(vdef)(
89-
// atPos for the new tpt is necessary, since the original tpt might have no position
90-
// (when missing type annotation for ValDef for example), so even though setOriginal modifies the
91-
// position of TypeTree, it would still be NoPosition. That's what the author meant.
92-
tpt = atPos(vdef.pos.focus)(TypeTree() setOriginal tpt setPos tpt.pos.focus),
93-
rhs = EmptyTree
94-
)
95-
}
96-
val lvdefs = evdefs collect { case vdef: ValDef => copyValDef(vdef)(mods = vdef.mods | PRESUPER) }
97-
98-
val constrs = {
99-
if (constrMods hasFlag TRAIT) {
100-
if (body forall treeInfo.isInterfaceMember) List()
101-
else List(
102-
atPos(wrappingPos(superPos, lvdefs)) (
103-
DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), ListOfNil, TypeTree(), Block(lvdefs, Literal(Constant(()))))))
104-
} else {
105-
// convert (implicit ... ) to ()(implicit ... ) if its the only parameter section
106-
if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit)
107-
vparamss1 = List() :: vparamss1
108-
val superCall = pendingSuperCall // we can't know in advance which of the parents will end up as a superclass
109-
// this requires knowing which of the parents is a type macro and which is not
110-
// and that's something that cannot be found out before typer
111-
// (the type macros aren't in the trunk yet, but there is a plan for them to land there soon)
112-
// this means that we don't know what will be the arguments of the super call
113-
// therefore here we emit a dummy which gets populated when the template is named and typechecked
114-
List(
115-
// TODO: previously this was `wrappingPos(superPos, lvdefs ::: argss.flatten)`
116-
// is it going to be a problem that we can no longer include the `argss`?
117-
atPos(wrappingPos(superPos, lvdefs)) (
118-
DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(Constant(()))))))
119-
}
120-
}
121-
constrs foreach (ensureNonOverlapping(_, parents ::: gvdefs, focus=false))
122-
// Field definitions for the class - remove defaults.
123-
val fieldDefs = vparamss.flatten map (vd => copyValDef(vd)(mods = vd.mods &~ DEFAULTPARAM, rhs = EmptyTree))
124-
125-
Template(parents, self, gvdefs ::: fieldDefs ::: constrs ::: etdefs ::: rest)
126-
}
127-
12857
/** Construct class definition with given class symbol, value parameters,
12958
* supercall arguments and template body.
13059
*
@@ -143,9 +72,9 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
14372
)
14473

14574
ClassDef(sym,
146-
Template(sym.info.parents map TypeTree,
147-
if (sym.thisSym == sym || phase.erasedTypes) emptyValDef else ValDef(sym.thisSym),
148-
constrMods, vparamss, body, superPos))
75+
gen.mkTemplate(sym.info.parents map TypeTree,
76+
if (sym.thisSym == sym || phase.erasedTypes) emptyValDef else ValDef(sym.thisSym),
77+
constrMods, vparamss, body, superPos))
14978
}
15079

15180
// --- subcomponents --------------------------------------------------

0 commit comments

Comments
 (0)