Skip to content

Commit e7ffcae

Browse files
committed
WIP
1 parent 11ccfb1 commit e7ffcae

File tree

1 file changed

+36
-37
lines changed

1 file changed

+36
-37
lines changed

compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
8383
if (ctx.compilationUnit.needsStaging) super.run
8484

8585
protected def newTransformer(implicit ctx: Context): Transformer =
86-
new Reifier(inQuote = false, null, 0, new LevelInfo, new Embedded, ctx)
86+
new Reifier(null, new LevelInfo, new Embedded, ctx)
8787

8888
private class LevelInfo {
8989
/** A map from locally defined symbols to the staging levels of their definitions */
@@ -115,15 +115,14 @@ class ReifyQuotes extends MacroTransformWithImplicits {
115115
* @param embedded a list of embedded quotes (if `inSplice = true`) or splices (if `inQuote = true`
116116
* @param rctx the contex in the destination lifted lambda
117117
*/
118-
private class Reifier(inQuote: Boolean, val outer: Reifier, val level: Int, levels: LevelInfo,
118+
private class Reifier(val outer: Reifier, levels: LevelInfo,
119119
val embedded: Embedded, val rctx: Context) extends ImplicitsTransformer {
120120
import levels._
121-
assert(level >= -1)
122121

123122
/** A nested reifier for a quote (if `isQuote = true`) or a splice (if not) */
124123
def nested(isQuote: Boolean)(implicit ctx: Context): Reifier = {
125-
val nestedEmbedded = if (level > 1 || (level == 1 && isQuote)) embedded else new Embedded
126-
new Reifier(isQuote, this, if (isQuote) level + 1 else level - 1, levels, nestedEmbedded, ctx)
124+
val nestedEmbedded = if (quotationLevel > 1 || (quotationLevel == 1 && isQuote)) embedded else new Embedded
125+
new Reifier(this, levels, nestedEmbedded, ctx)
127126
}
128127

129128
/** We are not in a `~(...)` or a `'(...)` */
@@ -212,23 +211,23 @@ class ReifyQuotes extends MacroTransformWithImplicits {
212211
case tree: DefTree =>
213212
val sym = tree.symbol
214213
if ((sym.isClass || !sym.maybeOwner.isType) && !levelOf.contains(sym)) {
215-
levelOf(sym) = level
214+
levelOf(sym) = quotationLevel
216215
enteredSyms = sym :: enteredSyms
217216
}
218217
case _ =>
219218
}
220219

221-
/** Does the level of `sym` match the current level?
222-
* An exception is made for inline vals in macros. These are also OK if their level
223-
* is one higher than the current level, because on execution such values
220+
/** Does the quotationLevel of `sym` match the current quotationLevel?
221+
* An exception is made for inline vals in macros. These are also OK if their quotationLevel
222+
* is one higher than the current quotationLevel, because on execution such values
224223
* are constant expression trees and we can pull out the constant from the tree.
225224
*/
226225
def levelOK(sym: Symbol)(implicit ctx: Context): Boolean = levelOf.get(sym) match {
227226
case Some(l) =>
228-
l == level ||
229-
level == -1 && (
227+
l == quotationLevel ||
228+
quotationLevel == -1 && (
230229
sym == defn.TastyReflection_macroContext ||
231-
// here we assume that Splicer.canBeSpliced was true before going to level -1,
230+
// here we assume that Splicer.canBeSpliced was true before going to quotationLevel -1,
232231
// this implies that all non-inline arguments are quoted and that the following two cases are checked
233232
// on inline parameters or type parameters.
234233
sym.is(Param) ||
@@ -245,7 +244,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
245244
*/
246245
def tryHeal(tp: Type, pos: SourcePosition)(implicit ctx: Context): Option[String] = tp match {
247246
case tp: TypeRef =>
248-
if (level == -1) {
247+
if (quotationLevel == -1) {
249248
assert(ctx.inInlineMethod)
250249
None
251250
} else {
@@ -258,7 +257,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
258257
| The access would be accepted with the right type tag, but
259258
| ${ctx.typer.missingArgMsg(tag, reqType, "")}""")
260259
case _ =>
261-
importedTags(tp) = nested(isQuote = false).transform(tag)
260+
importedTags(tp) = nested(isQuote = false).transform(tag)(spliceContext)
262261
None
263262
}
264263
}
@@ -277,24 +276,24 @@ class ReifyQuotes extends MacroTransformWithImplicits {
277276
else i"${sym.name}.this"
278277
if (!isThis && sym.maybeOwner.isType && !sym.is(Param))
279278
check(sym.owner, sym.owner.thisType, pos)
280-
else if (level == 1 && sym.isType && sym.is(Param) && sym.owner.isInlineMethod && !outer.isRoot)
279+
else if (quotationLevel == 1 && sym.isType && sym.is(Param) && sym.owner.isInlineMethod && !outer.isRoot)
281280
importedTags(sym.typeRef) = capturers(sym)(ref(sym))
282281
else if (sym.exists && !sym.isStaticOwner && !levelOK(sym))
283282
for (errMsg <- tryHeal(tp, pos))
284283
assert(false,
285284
em"""access to $symStr from wrong staging level:
286285
| - the definition is at level ${levelOf.getOrElse(sym, 0)},
287-
| - but the access is at level $level.$errMsg
286+
| - but the access is at quotationLevel $quotationLevel.$errMsg
288287
| at line ${pos.line} column ${pos.column}
289288
|""".stripMargin)
290289
}
291290

292291
/** Check all named types and this-types in a given type for phase consistency. */
293292
def checkType(pos: SourcePosition)(implicit ctx: Context): TypeAccumulator[Unit] = new TypeAccumulator[Unit] {
294-
def apply(acc: Unit, tp: Type): Unit = reporting.trace(i"check type level $tp at $level") {
293+
def apply(acc: Unit, tp: Type): Unit = reporting.trace(i"check type level $tp at $quotationLevel") {
295294
tp match {
296295
case tp: TypeRef if tp.symbol.isSplice =>
297-
if (level > 0) {
296+
if (quotationLevel > 0) {
298297
explicitTags += tp
299298
outer.checkType(pos).foldOver(acc, tp)
300299
}
@@ -358,20 +357,20 @@ class ReifyQuotes extends MacroTransformWithImplicits {
358357
val Select(splice, _) = body
359358
transform(splice)
360359
}
361-
else if (level > 0) {
362-
val body1 = nested(isQuote = true).transform(body)
360+
else if (quotationLevel > 0) {
361+
val body1 = nested(isQuote = true).transform(body)(quoteContext)
363362
// Keep quotes as trees to reduce pickled size and have a Expr.show without pickled quotes
364363
if (isType) ref(defn.QuotedType_apply).appliedToType(body1.tpe.widen)
365364
else ref(defn.QuotedExpr_apply).appliedToType(body1.tpe.widen).appliedTo(body1)
366365
}
367366
else body match {
368-
case body: RefTree if isCaptured(body.symbol, level + 1) =>
367+
case body: RefTree if isCaptured(body.symbol, quotationLevel + 1) =>
369368
// Optimization: avoid the full conversion when capturing `x`
370369
// in '{ x } to '{ x$1.unary_~ } and go directly to `x$1`
371370
capturers(body.symbol)(body)
372371
case _=>
373-
val (body1, splices) = nested(isQuote = true).split(body)
374-
if (level == 0 && !ctx.inInlineMethod) {
372+
val (body1, splices) = nested(isQuote = true).split(body)(quoteContext)
373+
if (quotationLevel == 0 && !ctx.inInlineMethod) {
375374
val body2 =
376375
if (body1.isType) body1
377376
else Inlined(Inliner.inlineCallTrace(ctx.owner, quote.sourcePos), Nil, body1)
@@ -420,12 +419,12 @@ class ReifyQuotes extends MacroTransformWithImplicits {
420419
* are in the body of an inline method.
421420
*/
422421
private def splice(splice: Select)(implicit ctx: Context): Tree = {
423-
if (level > 1) {
424-
val body1 = nested(isQuote = false).transform(splice.qualifier)
422+
if (quotationLevel > 1) {
423+
val body1 = nested(isQuote = false).transform(splice.qualifier)(spliceContext)
425424
body1.select(splice.name)
426425
}
427-
else if (level == 1) {
428-
val (body1, quotes) = nested(isQuote = false).split(splice.qualifier)
426+
else if (quotationLevel == 1) {
427+
val (body1, quotes) = nested(isQuote = false).split(splice.qualifier)(spliceContext)
429428
val tpe = outer.embedded.getHoleType(splice)
430429
val hole = makeHole(body1, quotes, tpe).withSpan(splice.span)
431430
// We do not place add the inline marker for trees that where lifted as they come from the same file as their
@@ -435,17 +434,17 @@ class ReifyQuotes extends MacroTransformWithImplicits {
435434
if (splice.isType || outer.embedded.isLiftedSymbol(splice.qualifier.symbol)) hole
436435
else Inlined(EmptyTree, Nil, hole).withSpan(splice.span)
437436
}
438-
else if (!ctx.owner.isInlineMethod) { // level 0 outside an inline method
437+
else if (!ctx.owner.isInlineMethod) { // quotationLevel 0 outside an inline method
439438
// TODO assert(...)?
440439
ctx.error(i"splice outside quotes or inline method", splice.sourcePos)
441440
splice
442441
}
443-
else if (Splicer.canBeSpliced(splice.qualifier)) { // level 0 inside an inline definition
442+
else if (Splicer.canBeSpliced(splice.qualifier)) { // quotationLevel 0 inside an inline definition
444443
// TODO remove?
445-
nested(isQuote = false).split(splice.qualifier) // Just check PCP
444+
nested(isQuote = false).split(splice.qualifier)(spliceContext) // Just check PCP
446445
splice
447446
}
448-
else { // level 0 inside an inline definition
447+
else { // quotationLevel 0 inside an inline definition
449448
// TODO remove?
450449
ctx.error(
451450
"Malformed macro call. The contents of the ~ must call a static method and arguments must be quoted or inline.".stripMargin,
@@ -509,10 +508,10 @@ class ReifyQuotes extends MacroTransformWithImplicits {
509508
)
510509
}
511510
/* Lambdas are generated outside the quote that is beeing reified (i.e. in outer.rctx.owner).
512-
* In case the case that level == -1 the code is not in a quote, it is in an inline method,
511+
* In case the case that quotationLevel == -1 the code is not in a quote, it is in an inline method,
513512
* hence we should take that as owner directly.
514513
*/
515-
val lambdaOwner = if (level == -1) ctx.owner else outer.rctx.owner
514+
val lambdaOwner = if (quotationLevel == -1) ctx.owner else outer.rctx.owner
516515

517516
val tpe = MethodType(defn.SeqType.appliedTo(defn.AnyType) :: Nil, tree.tpe.widen)
518517
val meth = ctx.newSymbol(lambdaOwner, UniqueName.fresh(nme.ANON_FUN), Synthetic | Method, tpe)
@@ -539,7 +538,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
539538
* or splices as a pair, after performing the `addTags` transform.
540539
*/
541540
private def split(tree: Tree)(implicit ctx: Context): (Tree, List[Tree]) = {
542-
val tree1 = if (inQuote) addTags(transform(tree)) else makeLambda(tree)
541+
val tree1 = if (quotationLevel == 1) addTags(transform(tree)) else makeLambda(tree)
543542
(tree1, embedded.getTrees)
544543
}
545544

@@ -552,7 +551,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
552551
}
553552

554553
override def transform(tree: Tree)(implicit ctx: Context): Tree =
555-
reporting.trace(i"reify $tree at $level", show = true) {
554+
reporting.trace(i"reify $tree at $quotationLevel", show = true) {
556555
def mapOverTree(lastEntered: List[Symbol]) =
557556
try super.transform(tree)
558557
finally
@@ -575,7 +574,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
575574
splice(tree)
576575
case tree: RefTree if tree.symbol.is(Inline) && tree.symbol.is(Param) =>
577576
tree
578-
case tree: RefTree if isCaptured(tree.symbol, level) =>
577+
case tree: RefTree if isCaptured(tree.symbol, quotationLevel) =>
579578
val t = capturers(tree.symbol).apply(tree)
580579
splice(t.select(if (tree.isTerm) nme.UNARY_~ else tpnme.UNARY_~))
581580
case Block(stats, _) =>
@@ -594,7 +593,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
594593
mapOverTree(last)
595594
case _: Import =>
596595
tree
597-
case tree: DefDef if tree.symbol.is(Macro) && level == 0 =>
596+
case tree: DefDef if tree.symbol.is(Macro) && quotationLevel == 0 =>
598597
if (enclosingInlineds.nonEmpty)
599598
return EmptyTree // Already checked at definition site and already inlined
600599
markDef(tree)

0 commit comments

Comments
 (0)