Skip to content
This repository was archived by the owner on Apr 19, 2020. It is now read-only.

Commit af2c60c

Browse files
committed
Merge pull request scala#42 from densh/topic/quasiquotes
improved modifier, flags and symbols splicing
2 parents 5de3f13 + 39edc1b commit af2c60c

26 files changed

+485
-196
lines changed
+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
562f3bf598b4b9c2f3e5e564726558d80df3c3ac ?scala-compiler-src.jar
1+
277f9d9de24b124ae1c6efd827d6f21a460b0334 ?scala-compiler-src.jar

lib/scala-compiler.jar.desired.sha1

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
c3ed1693dd3197d9cfee13392a8f907cc48970a6 ?scala-compiler.jar
1+
9fc8f840d713d9b9a9125dbbd64bf1b084fd7819 ?scala-compiler.jar
+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
376f6c5ee4e3b50909b8bed2ee32202f9ca49748 ?scala-library-src.jar
1+
c701bd150c36b1803941057fe82585d3677595cb ?scala-library-src.jar

lib/scala-library.jar.desired.sha1

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
e6d9ec7f7e1c207b41163045479ce571f1cbd8bd ?scala-library.jar
1+
d7a42b3854500ac0588410c85d65a2e0eab0b62b ?scala-library.jar
+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
73d9ba61872e32fdcd8e40f8c47de28bb43139c0 ?scala-reflect-src.jar
1+
2233de6eb7f9838ef786e57735b0c37bbfd02501 ?scala-reflect-src.jar

lib/scala-reflect.jar.desired.sha1

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
a2551a5bf730d808a98fb477fddd66ba9b72dc2e ?scala-reflect.jar
1+
c8a1731c3fcb24641e24991d3107363a796747c3 ?scala-reflect.jar

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

-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
115115
else AppliedTypeTree(Ident(clazz), targs map TypeTree)
116116
))
117117
}
118-
def mkSuperInitCall: Select = Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR)
119118

120119
def wildcardStar(tree: Tree) =
121120
atPos(tree.pos) { Typed(tree, Ident(tpnme.WILDCARD_STAR)) }

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

+3-75
Original file line numberDiff line numberDiff line change
@@ -77,78 +77,6 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
7777
case xs :: rest => rest.foldLeft(Apply(gen.mkSuperInitCall, xs): Tree)(Apply.apply)
7878
}
7979

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

16997
ClassDef(sym,
170-
Template(sym.info.parents map TypeTree,
171-
if (sym.thisSym == sym || phase.erasedTypes) emptyValDef else ValDef(sym.thisSym),
172-
constrMods, vparamss, body, superPos))
98+
gen.mkTemplate(sym.info.parents map TypeTree,
99+
if (sym.thisSym == sym || phase.erasedTypes) emptyValDef else ValDef(sym.thisSym),
100+
constrMods, vparamss, body, superPos))
173101
}
174102

175103
// --- subcomponents --------------------------------------------------

src/compiler/scala/tools/nsc/ast/parser/Parsers.scala

+8-6
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,8 @@ self =>
608608
case _ => false
609609
}
610610

611+
def isAnnotation: Boolean = in.token == AT
612+
611613
def isLocalModifier: Boolean = in.token match {
612614
case ABSTRACT | FINAL | SEALED | IMPLICIT | LAZY => true
613615
case _ => false
@@ -1410,7 +1412,7 @@ self =>
14101412
} else {
14111413
syntaxErrorOrIncomplete("`*' expected", true)
14121414
}
1413-
} else if (in.token == AT) {
1415+
} else if (isAnnotation) {
14141416
t = (t /: annotations(skipNewLines = false))(makeAnnotated)
14151417
} else {
14161418
t = atPos(t.pos.startOrPoint, colonPos) {
@@ -2855,7 +2857,7 @@ self =>
28552857
if (inScalaRootPackage && ScalaValueClassNames.contains(name))
28562858
Template(parents0, self, anyvalConstructor :: body)
28572859
else
2858-
Template(anyrefParents(), self, constrMods, vparamss, body, o2p(tstart))
2860+
gen.mkTemplate(anyrefParents(), self, constrMods, vparamss, body, o2p(tstart))
28592861
}
28602862
}
28612863

@@ -2956,7 +2958,7 @@ self =>
29562958
case IMPORT =>
29572959
in.flushDoc
29582960
importClause()
2959-
case x if x == AT || isTemplateIntro || isModifier =>
2961+
case _ if isAnnotation || isTemplateIntro || isModifier =>
29602962
joinComment(List(topLevelTmplDef))
29612963
case _ =>
29622964
if (!isStatSep)
@@ -3013,11 +3015,11 @@ self =>
30133015
if (in.token == IMPORT) {
30143016
in.flushDoc
30153017
stats ++= importClause()
3018+
} else if (isDefIntro || isModifier || isAnnotation) {
3019+
stats ++= joinComment(nonLocalDefOrDcl)
30163020
} else if (isExprIntro) {
30173021
in.flushDoc
30183022
stats += statement(InTemplate)
3019-
} else if (isDefIntro || isModifier || in.token == AT) {
3020-
stats ++= joinComment(nonLocalDefOrDcl)
30213023
} else if (!isStatSep) {
30223024
syntaxErrorOrIncomplete("illegal start of definition", true)
30233025
}
@@ -3097,7 +3099,7 @@ self =>
30973099
stats += statement(InBlock)
30983100
if (in.token != RBRACE && in.token != CASE) acceptStatSep()
30993101
}
3100-
else if (isDefIntro || isLocalModifier || in.token == AT) {
3102+
else if (isDefIntro || isLocalModifier || isAnnotation) {
31013103
if (in.token == IMPLICIT) {
31023104
val start = in.skipToken()
31033105
if (isIdent) stats += implicitClosure(start, InBlock)

src/compiler/scala/tools/nsc/ast/parser/Scanners.scala

+15-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,21 @@ trait Scanners extends ScannersCommon {
8080
}
8181
}
8282

83-
abstract class Scanner extends CharArrayReader with TokenData with ScannerCommon {
83+
trait ScannerData extends TokenData {
84+
var ch: Char
85+
var charOffset: Int
86+
var lineStartOffset: Int
87+
var lastLineStartOffset: Int
88+
def copyFrom(sd: ScannerData) = {
89+
this.ch = sd.ch
90+
this.charOffset = sd.charOffset
91+
this.lineStartOffset = sd.lineStartOffset
92+
this.lastLineStartOffset = sd.lastLineStartOffset
93+
super.copyFrom(sd)
94+
}
95+
}
96+
97+
abstract class Scanner extends CharArrayReader with TokenData with ScannerData with ScannerCommon {
8498
private def isDigit(c: Char) = java.lang.Character isDigit c
8599

86100
def isAtEnd = charOffset >= buf.length

src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ abstract class TreeBuilder {
225225
atPos(cpos) {
226226
ClassDef(
227227
Modifiers(FINAL), x, Nil,
228-
Template(parents, self, NoMods, ListOfNil, stats, cpos.focus))
228+
gen.mkTemplate(parents, self, NoMods, ListOfNil, stats, cpos.focus))
229229
}),
230230
atPos(npos) {
231231
New(

src/compiler/scala/tools/nsc/typechecker/Unapplies.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ trait Unapplies extends ast.TreeDSL
136136
ModuleDef(
137137
Modifiers(cdef.mods.flags & AccessFlags | SYNTHETIC, cdef.mods.privateWithin),
138138
cdef.name.toTermName,
139-
Template(parents, emptyValDef, NoMods, Nil, body, cdef.impl.pos.focus))
139+
gen.mkTemplate(parents, emptyValDef, NoMods, Nil, body, cdef.impl.pos.focus))
140140
}
141141

142142
private val caseMods = Modifiers(SYNTHETIC | CASE)

src/compiler/scala/tools/reflect/ToolBoxFactory.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
225225

226226
val moduledef = ModuleDef(
227227
obj,
228-
Template(
228+
gen.mkTemplate(
229229
List(TypeTree(ObjectClass.tpe)),
230230
emptyValDef,
231231
NoMods,

src/compiler/scala/tools/reflect/quasiquotes/Macros.scala

+12-32
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,6 @@ import scala.collection.immutable.ListMap
99
trait Macros { self: Quasiquotes =>
1010
import c.universe._
1111

12-
/** This is a shorcut variable that links to "$u" universe variable name.
13-
* With the help of it it's possible to use $u inside of the quasiquote
14-
* and it will have the same meaning in expanded code.
15-
*/
16-
val u = nme.UNIVERSE_SHORT
17-
1812
/** This trait abstracts over all variations of quasiquotes
1913
* and allows to share core logic. The main differences are
2014
* in parser, reifier and wrapping behaviour.
@@ -26,9 +20,6 @@ trait Macros { self: Quasiquotes =>
2620
/** Reifier factory that abstracts over different reifiers need for apply and unapply macros. */
2721
def reifier(universe: Tree, placeholders: Placeholders): Reifier
2822

29-
/** Wraps reified tree into a final result of macro expansion. */
30-
def wrap(universe: Tree, reified: Tree): Tree
31-
3223
/** Extracts universe tree, args trees and params strings from macroApplication. */
3324
def extract = c.macroApplication match {
3425
case q"$universe.Quasiquote($stringContext.apply(..$parts0)).${_}.${_}(..$args)" =>
@@ -46,7 +37,7 @@ trait Macros { self: Quasiquotes =>
4637
/** Generates scala code to be parsed by parser and placeholders map from incoming args and parts. */
4738
def generate(args: List[Tree], parts: List[String]): (String, Placeholders) = {
4839
val sb = new StringBuilder()
49-
var placeholders = ListMap[String, (Tree, Int)]()
40+
var pmap = ListMap[String, (Tree, Int)]()
5041

5142
foreach2(args, parts.init) { (tree, p) =>
5243
val (part, cardinality) =
@@ -59,52 +50,41 @@ trait Macros { self: Quasiquotes =>
5950
val freshname = c.fresh(nme.QUASIQUOTE_PREFIX)
6051
sb.append(part)
6152
sb.append(freshname)
62-
placeholders += freshname -> (tree, cardinality)
53+
pmap += freshname -> (tree, cardinality)
6354
}
6455
sb.append(parts.last)
6556

66-
(sb.toString, placeholders)
57+
(sb.toString, Placeholders(pmap))
6758
}
6859

69-
def debug(msg: String) =
70-
if (settings.Yquasiquotedebug.value) println(msg)
71-
7260
/** Quasiquote macro expansion core logic. */
7361
def apply() = {
7462
val (universe, args, parts) = extract
7563
val (code, placeholders) = generate(args, parts)
7664
debug(s"\ncode to parse=\n$code\n")
7765
val tree = parser.parse(code, placeholders.keys.toSet)
7866
debug(s"parsed tree\n=${tree}\n=${showRaw(tree)}\n")
79-
val reified = reifier(universe, placeholders).reify(tree)
67+
val reified = reifier(universe, placeholders).quasiquoteReify(tree)
8068
debug(s"reified tree\n=${reified}\n=${showRaw(reified)}\n")
81-
val result = wrap(universe, reified)
82-
debug(s"result tree\n=${result}\n=${showRaw(result)}\n")
83-
result
69+
reified
8470
}
8571
}
8672

87-
trait ApplyMacro extends AbstractMacro {
73+
trait ApplyReification {
8874
def reifier(universe: Tree, placeholders: Placeholders): Reifier =
89-
new ApplyReifier(universe, placeholders)
90-
def wrap(universe: Tree, reified: Tree): Tree =
91-
q"""{
92-
val $u: $universe.type = $universe
93-
$reified
94-
}"""
75+
new ApplyReifierWithSymbolSplicing(universe, placeholders)
9576
}
9677

97-
trait UnapplyMacro extends AbstractMacro {
78+
trait UnapplyReification {
9879
def reifier(universe: Tree, placeholders: Placeholders): Reifier =
9980
new UnapplyReifier(universe, placeholders)
100-
def wrap(universe: Tree, reified: Tree) = reified
10181
}
10282

10383
trait TermParsing { val parser = TermParser }
10484
trait TypeParsing { val parser = TypeParser }
10585

106-
def applyQ = (new ApplyMacro with TermParsing).apply()
107-
def applyTq = (new ApplyMacro with TypeParsing).apply()
108-
def unapplyQ = (new UnapplyMacro with TermParsing).apply()
109-
def unapplyTq = (new UnapplyMacro with TypeParsing).apply()
86+
def applyQ = (new AbstractMacro with ApplyReification with TermParsing).apply()
87+
def applyTq = (new AbstractMacro with ApplyReification with TypeParsing).apply()
88+
def unapplyQ = (new AbstractMacro with UnapplyReification with TermParsing).apply()
89+
def unapplyTq = (new AbstractMacro with UnapplyReification with TypeParsing).apply()
11090
}

0 commit comments

Comments
 (0)