Skip to content

Move inlining into ReifyQuotes and remove Inlined from TASTy #5241

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ class Compiler {
/** Phases dealing with TASTY tree pickling and unpickling */
protected def picklerPhases: List[List[Phase]] =
List(new Pickler) :: // Generate TASTY info
List(new InlineCalls) :: // β-reduce inline calls
List(new ReifyQuotes) :: // Turn quoted trees into explicit run-time data structures
Nil

Expand Down
107 changes: 50 additions & 57 deletions compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ Standard-Section: "ASTs" TopLevelStat*
TYPED Length expr_Term ascriptionType_Tern
ASSIGN Length lhs_Term rhs_Term
BLOCK Length expr_Term Stat*
INLINED Length expr_Term call_Term? ValOrDefDef*
LAMBDA Length meth_Term target_Type?
IF Length cond_Term then_Term else_Term
MATCH Length sel_Term CaseDef*
Expand Down Expand Up @@ -185,7 +184,6 @@ Standard-Section: "ASTs" TopLevelStat*
OVERRIDE
INLINE
MACRO // inline method containing toplevel splices
INLINEPROXY // symbol of binding representing an inline parameter
STATIC // mapped to static Java member
OBJECT // an object or its class
TRAIT // a trait
Expand Down Expand Up @@ -236,7 +234,7 @@ Standard Section: "Comments" Comment*
object TastyFormat {

final val header: Array[Int] = Array(0x5C, 0xA1, 0xAB, 0x1F)
val MajorVersion: Int = 11
val MajorVersion: Int = 12
val MinorVersion: Int = 0

/** Tags used to serialize names */
Expand Down Expand Up @@ -289,27 +287,26 @@ object TastyFormat {
final val IMPLICIT = 13
final val LAZY = 14
final val OVERRIDE = 15
final val INLINEPROXY = 16
final val INLINE = 17
final val STATIC = 18
final val OBJECT = 19
final val TRAIT = 20
final val ENUM = 21
final val LOCAL = 22
final val SYNTHETIC = 23
final val ARTIFACT = 24
final val MUTABLE = 25
final val LABEL = 26
final val FIELDaccessor = 27
final val CASEaccessor = 28
final val COVARIANT = 29
final val CONTRAVARIANT = 30
final val SCALA2X = 31
final val DEFAULTparameterized = 32
final val STABLE = 33
final val MACRO = 34
final val ERASED = 35
final val PARAMsetter = 36
final val INLINE = 16
final val STATIC = 17
final val OBJECT = 18
final val TRAIT = 19
final val ENUM = 20
final val LOCAL = 21
final val SYNTHETIC = 22
final val ARTIFACT = 23
final val MUTABLE = 24
final val LABEL = 25
final val FIELDaccessor = 26
final val CASEaccessor = 27
final val COVARIANT = 28
final val CONTRAVARIANT = 29
final val SCALA2X = 30
final val DEFAULTparameterized = 31
final val STABLE = 32
final val MACRO = 33
final val ERASED = 34
final val PARAMsetter = 35

// Cat. 2: tag Nat

Expand Down Expand Up @@ -383,36 +380,35 @@ object TastyFormat {
final val RETURN = 144
final val WHILE = 145
final val TRY = 146
final val INLINED = 147
final val SELECTouter = 148
final val REPEATED = 149
final val BIND = 150
final val ALTERNATIVE = 151
final val UNAPPLY = 152
final val ANNOTATEDtype = 153
final val ANNOTATEDtpt = 154
final val CASEDEF = 155
final val TEMPLATE = 156
final val SUPER = 157
final val SUPERtype = 158
final val REFINEDtype = 159
final val REFINEDtpt = 160
final val APPLIEDtype = 161
final val APPLIEDtpt = 162
final val TYPEBOUNDS = 163
final val TYPEBOUNDStpt = 164
final val ANDtype = 165
final val ANDtpt = 166
final val ORtype = 167
final val ORtpt = 168
final val POLYtype = 169
final val TYPELAMBDAtype = 170
final val LAMBDAtpt = 171
final val PARAMtype = 172
final val ANNOTATION = 173
final val TERMREFin = 174
final val TYPEREFin = 175
final val OBJECTDEF = 176
final val SELECTouter = 147
final val REPEATED = 148
final val BIND = 149
final val ALTERNATIVE = 150
final val UNAPPLY = 151
final val ANNOTATEDtype = 152
final val ANNOTATEDtpt = 153
final val CASEDEF = 154
final val TEMPLATE = 155
final val SUPER = 156
final val SUPERtype = 157
final val REFINEDtype = 158
final val REFINEDtpt = 159
final val APPLIEDtype = 160
final val APPLIEDtpt = 161
final val TYPEBOUNDS = 162
final val TYPEBOUNDStpt = 163
final val ANDtype = 164
final val ANDtpt = 165
final val ORtype = 166
final val ORtpt = 167
final val POLYtype = 168
final val TYPELAMBDAtype = 169
final val LAMBDAtpt = 170
final val PARAMtype = 171
final val ANNOTATION = 172
final val TERMREFin = 173
final val TYPEREFin = 174
final val OBJECTDEF = 175

// In binary: 101101EI
// I = implicit method type
Expand Down Expand Up @@ -462,7 +458,6 @@ object TastyFormat {
| LAZY
| OVERRIDE
| INLINE
| INLINEPROXY
| MACRO
| STATIC
| OBJECT
Expand Down Expand Up @@ -520,7 +515,6 @@ object TastyFormat {
case LAZY => "LAZY"
case OVERRIDE => "OVERRIDE"
case INLINE => "INLINE"
case INLINEPROXY => "INLINEPROXY"
case MACRO => "MACRO"
case STATIC => "STATIC"
case OBJECT => "OBJECT"
Expand Down Expand Up @@ -589,7 +583,6 @@ object TastyFormat {
case MATCH => "MATCH"
case RETURN => "RETURN"
case WHILE => "WHILE"
case INLINED => "INLINED"
case SELECTouter => "SELECTouter"
case TRY => "TRY"
case REPEATED => "REPEATED"
Expand Down
12 changes: 0 additions & 12 deletions compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -442,17 +442,6 @@ class TreePickler(pickler: TastyPickler) {
case SeqLiteral(elems, elemtpt) =>
writeByte(REPEATED)
withLength { pickleTree(elemtpt); elems.foreach(pickleTree) }
case Inlined(call, bindings, expansion) =>
writeByte(INLINED)
bindings.foreach(preRegister)
withLength {
pickleTree(expansion)
if (!call.isEmpty) pickleTree(call)
bindings.foreach { b =>
assert(b.isInstanceOf[DefDef] || b.isInstanceOf[ValDef])
pickleTree(b)
}
}
case Bind(name, body) =>
registerDef(tree.symbol)
writeByte(BIND)
Expand Down Expand Up @@ -619,7 +608,6 @@ class TreePickler(pickler: TastyPickler) {
if (flags is Case) writeByte(CASE)
if (flags is Override) writeByte(OVERRIDE)
if (flags is Inline) writeByte(INLINE)
if (flags is InlineProxy) writeByte(INLINEPROXY)
if (flags is Macro) writeByte(MACRO)
if (flags is JavaStatic) writeByte(STATIC)
if (flags is Module) writeByte(OBJECT)
Expand Down
12 changes: 0 additions & 12 deletions compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,6 @@ class TreeUnpickler(reader: TastyReader,
case LAZY => addFlag(Lazy)
case OVERRIDE => addFlag(Override)
case INLINE => addFlag(Inline)
case INLINEPROXY => addFlag(InlineProxy)
case MACRO => addFlag(Macro)
case STATIC => addFlag(JavaStatic)
case OBJECT => addFlag(Module)
Expand Down Expand Up @@ -1074,17 +1073,6 @@ class TreeUnpickler(reader: TastyReader,
val stats = readStats(ctx.owner, end)
val expr = exprReader.readTerm()
Block(stats, expr)
case INLINED =>
val exprReader = fork
skipTree()
def maybeCall = nextUnsharedTag match {
case VALDEF | DEFDEF => EmptyTree
case _ => readTerm()
}
val call = ifBefore(end)(maybeCall, EmptyTree)
val bindings = readStats(ctx.owner, end).asInstanceOf[List[ValOrDefDef]]
val expansion = exprReader.readTerm() // need bindings in scope, so needs to be read before
Inlined(call, bindings, expansion)
case IF =>
If(readTerm(), readTerm(), readTerm())
case LAMBDA =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package dotty.tools.dotc.decompiler

import dotty.tools.dotc.fromtasty._
import dotty.tools.dotc.core.Phases.Phase
import dotty.tools.dotc.transform.InlineCalls
import dotty.tools.dotc.transform.ReifyQuotes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should think about a name for both inlining and quoting and splicing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe Staging


/** Compiler from tasty to user readable high text representation
* of the compiled scala code.
Expand All @@ -15,9 +15,7 @@ class TASTYDecompiler extends TASTYCompiler {
List(new ReadTastyTreesFromClasses) :: // Load classes from tasty
Nil

override protected def picklerPhases: List[List[Phase]] =
List(new InlineCalls) :: // TODO should we really inline for the decompiler?
Nil
override protected def picklerPhases: List[List[Phase]] = Nil

override protected def transformPhases: List[List[Phase]] = Nil

Expand Down
45 changes: 0 additions & 45 deletions compiler/src/dotty/tools/dotc/transform/InlineCalls.scala

This file was deleted.

42 changes: 35 additions & 7 deletions compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ package dotty.tools.dotc
package transform

import core._
import Decorators._, Flags._, Types._, Contexts._, Symbols._, Constants._
import Decorators._
import Flags._
import Types._
import Contexts._
import Symbols._
import Constants._
import ast.Trees._
import ast.{TreeTypeMap, untpd}
import util.Positions._
Expand All @@ -15,11 +20,12 @@ import typer.Implicits.SearchFailureType
import scala.collection.mutable
import dotty.tools.dotc.core.StdNames._
import dotty.tools.dotc.core.quoted._
import dotty.tools.dotc.typer.{ConstFold, Inliner}
import dotty.tools.dotc.util.SourcePosition


/** Translates quoted terms and types to `unpickle` method calls.
* Checks that the phase consistency principle (PCP) holds.
/** Inline calls to inline methods, evaluates macros, translates quoted terms (and types)
* to `unpickle` method calls and checks that the phase consistency principle (PCP) holds.
*
*
* Transforms top level quote
Expand Down Expand Up @@ -60,7 +66,7 @@ import dotty.tools.dotc.util.SourcePosition
* The Splicer is used to check that the RHS will be interpretable (with the `Splicer`) once inlined.
*/
class ReifyQuotes extends MacroTransformWithImplicits {
import ast.tpd._
import tpd._
import ReifyQuotes._

/** Classloader used for loading macros */
Expand Down Expand Up @@ -88,7 +94,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
}

override def run(implicit ctx: Context): Unit =
if (ctx.compilationUnit.containsQuotesOrSplices) super.run
if (ctx.compilationUnit.containsInlineCalls || ctx.compilationUnit.containsQuotesOrSplices) super.run

protected def newTransformer(implicit ctx: Context): Transformer =
new Reifier(inQuote = false, null, 0, new LevelInfo, new Embedded, ctx)
Expand Down Expand Up @@ -437,7 +443,8 @@ class ReifyQuotes extends MacroTransformWithImplicits {
else if (enclosingInlineds.nonEmpty) { // level 0 in an inlined call
val spliceCtx = ctx.outer // drop the last `inlineContext`
val pos: SourcePosition = Decorators.sourcePos(enclosingInlineds.head.pos)(spliceCtx)
val evaluatedSplice = Splicer.splice(splice.qualifier, pos, macroClassLoader)(spliceCtx).withPos(splice.pos)
val splicedTree = new InlineCalls().transform(splice.qualifier) // inline calls that where inlined at level -1
val evaluatedSplice = Splicer.splice(splicedTree, pos, macroClassLoader)(spliceCtx).withPos(splice.pos)
if (ctx.reporter.hasErrors) splice else transform(evaluatedSplice)
}
else if (!ctx.owner.isInlineMethod) { // level 0 outside an inline method
Expand Down Expand Up @@ -560,6 +567,9 @@ class ReifyQuotes extends MacroTransformWithImplicits {
enteredSyms = enteredSyms.tail
}
tree match {
case tree if isInlineCall(tree) && level == 0 && !ctx.reporter.hasErrors && !ctx.settings.YnoInline.value =>
val tree2 = super.transform(tree) // transform arguments before inlining (inline arguments and constant fold arguments)
transform(Inliner.inlineCall(tree2, tree.tpe.widen))
case Quoted(quotedTree) =>
quotation(quotedTree, tree)
case tree: TypeTree if tree.tpe.typeSymbol.isSplice =>
Expand Down Expand Up @@ -610,7 +620,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
}
case _ =>
markDef(tree)
checkLevel(mapOverTree(enteredSyms))
ConstFold(checkLevel(mapOverTree(enteredSyms)))
}
}

Expand All @@ -635,6 +645,8 @@ class ReifyQuotes extends MacroTransformWithImplicits {
}

object ReifyQuotes {
import tpd._

val name: String = "reifyQuotes"

def toValue(tree: tpd.Tree): Option[Any] = tree match {
Expand Down Expand Up @@ -664,4 +676,20 @@ object ReifyQuotes {
/** Get the list of embedded trees */
def getTrees: List[tpd.Tree] = trees.toList
}

/** β-reduce all calls to inline methods and preform constant folding */
class InlineCalls extends TreeMap {
override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
case tree if isInlineCall(tree) && !ctx.reporter.hasErrors && !ctx.settings.YnoInline.value =>
val tree2 = super.transform(tree) // transform arguments before inlining (inline arguments and constant fold arguments)
transform(Inliner.inlineCall(tree2, tree.tpe.widen))
case _: MemberDef =>
val newTree = super.transform(tree)
if (newTree.symbol.exists)
newTree.symbol.defTree = newTree // set for inlined members
newTree
case _ =>
ConstFold(super.transform(tree))
}
}
}
Loading