Skip to content

Commit 1e9c6bd

Browse files
committed
Implement extractors for TASTY trees
* Define TASTY data types in scala.tasty * Add method get a TASTY term from a quoted.Expr[T] * Implement TASTY tree extractors
1 parent ba2eafc commit 1e9c6bd

File tree

146 files changed

+4143
-240
lines changed

Some content is hidden

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

146 files changed

+4143
-240
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,12 @@ class Definitions {
667667
def Unpickler_liftedExpr = ctx.requiredMethod("scala.runtime.quoted.Unpickler.liftedExpr")
668668
def Unpickler_unpickleType = ctx.requiredMethod("scala.runtime.quoted.Unpickler.unpickleType")
669669

670+
lazy val TastyContextModule = ctx.requiredModule("scala.tasty.Context")
671+
def TastyContextModuleClass(implicit ctx: Context) = TastyContextModule.symbol.asClass
672+
673+
lazy val TastyContext_compilationContextR = TastyContextModule.requiredMethod("compilationContext")
674+
def TastyContext_compilationContext(implicit ctx: Context) = TastyContext_compilationContextR.symbol
675+
670676
lazy val EqType = ctx.requiredClassRef("scala.Eq")
671677
def EqClass(implicit ctx: Context) = EqType.symbol.asClass
672678
def EqModule(implicit ctx: Context) = EqClass.companionModule

compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ object PickledQuotes {
5757
case expr: LiftedExpr[T] =>
5858
expr.value match {
5959
case value: Class[_] => ref(defn.Predef_classOf).appliedToType(classToType(value))
60-
case value=> Literal(Constant(value))
60+
case value => Literal(Constant(value))
6161
}
6262
case expr: TreeExpr[Tree] @unchecked => expr.tree
6363
case expr: FunctionAppliedTo[_, _] =>
@@ -68,7 +68,7 @@ object PickledQuotes {
6868
def quotedTypeToTree(expr: quoted.Type[_])(implicit ctx: Context): Tree = expr match {
6969
case expr: TastyType[_] => unpickleType(expr)
7070
case expr: TaggedType[_] => classTagToTypeTree(expr.ct)
71-
case expr: TreeType[Tree] @unchecked => expr.tree
71+
case expr: TreeType[Tree] @unchecked => expr.typeTree
7272
}
7373

7474
/** Unpickle the tree contained in the TastyExpr */

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1149,7 +1149,10 @@ class TreeUnpickler(reader: TastyReader,
11491149
val idx = readNat()
11501150
val args = until(end)(readTerm())
11511151
val splice = splices(idx)
1152-
val reifiedArgs = args.map(arg => if (arg.isTerm) new TreeExpr(arg, PickledQuotes.pickleExpr(arg)) else new TreeType(arg))
1152+
def wrap(arg: Tree) =
1153+
if (arg.isTerm) new TreeExpr(arg, PickledQuotes.pickleExpr(arg))
1154+
else new TreeType(arg)
1155+
val reifiedArgs = args.map(wrap)
11531156
if (isType) {
11541157
val quotedType = splice.asInstanceOf[Seq[Any] => quoted.Type[_]](reifiedArgs)
11551158
PickledQuotes.quotedTypeToTree(quotedType)

compiler/src/dotty/tools/dotc/quoted/ExprCompiler.scala renamed to compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ import dotty.tools.dotc.util.Positions.Position
2020
import dotty.tools.dotc.util.SourceFile
2121
import dotty.tools.io.{AbstractFile, Path, PlainFile}
2222

23-
import scala.quoted.Expr
23+
import scala.quoted.{Expr, Type}
2424

2525
/** Compiler that takes the contents of a quoted expression `expr` and produces
2626
* a class file with `class ' { def apply: Object = expr }`.
2727
*/
28-
class ExprCompiler(directory: AbstractFile) extends Compiler {
28+
class QuoteCompiler(directory: AbstractFile) extends Compiler {
2929
import tpd._
3030

3131
/** A GenBCode phase that outputs to a virtual directory */
@@ -35,7 +35,7 @@ class ExprCompiler(directory: AbstractFile) extends Compiler {
3535
}
3636

3737
override protected def frontendPhases: List[List[Phase]] =
38-
List(List(new ExprFrontend(putInClass = true)))
38+
List(List(new QuotedFrontend(putInClass = true)))
3939

4040
override protected def picklerPhases: List[List[Phase]] =
4141
List(List(new ReifyQuotes))
@@ -50,8 +50,8 @@ class ExprCompiler(directory: AbstractFile) extends Compiler {
5050

5151
def outputClassName: TypeName = "Quoted".toTypeName
5252

53-
/** Frontend that receives scala.quoted.Expr as input */
54-
class ExprFrontend(putInClass: Boolean) extends FrontEnd {
53+
/** Frontend that receives a scala.quoted.Expr or scala.quoted.Type as input */
54+
class QuotedFrontend(putInClass: Boolean) extends FrontEnd {
5555
import tpd._
5656

5757
override def isTyper = false
@@ -64,6 +64,11 @@ class ExprCompiler(directory: AbstractFile) extends Compiler {
6464
else PickledQuotes.quotedExprToTree(exprUnit.expr)
6565
val source = new SourceFile("", Seq())
6666
CompilationUnit.mkCompilationUnit(source, tree, forceTrees = true)
67+
case typeUnit: TypeCompilationUnit =>
68+
assert(!putInClass)
69+
val tree = PickledQuotes.quotedTypeToTree(typeUnit.tpe)
70+
val source = new SourceFile("", Seq())
71+
CompilationUnit.mkCompilationUnit(source, tree, forceTrees = true)
6772
}
6873
}
6974

@@ -93,6 +98,10 @@ class ExprCompiler(directory: AbstractFile) extends Compiler {
9398
val units = new ExprCompilationUnit(expr) :: Nil
9499
compileUnits(units)
95100
}
101+
def compileType(tpe: Type[_]): Unit = {
102+
val units = new TypeCompilationUnit(tpe) :: Nil
103+
compileUnits(units)
104+
}
96105
}
97106

98107
}

compiler/src/dotty/tools/dotc/quoted/ExprDecompiler.scala renamed to compiler/src/dotty/tools/dotc/quoted/QuoteDecompiler.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import dotty.tools.dotc.ast.tpd
44
import dotty.tools.dotc.core.Contexts.Context
55
import dotty.tools.dotc.core.Phases.Phase
66

7-
/** Compiler that takes the contents of a quoted expression `expr` and outputs it's tree. */
8-
class ExprDecompiler(output: tpd.Tree => Context => Unit) extends ExprCompiler(null) {
7+
/** Compiler that takes the contents of a quoted expression (or type) and outputs it's tree. */
8+
class QuoteDecompiler(output: tpd.Tree => Context => Unit) extends QuoteCompiler(null) {
99
override def phases: List[List[Phase]] = List(
10-
List(new ExprFrontend(putInClass = false)), // Create class from Expr
10+
List(new QuotedFrontend(putInClass = false)), // Create class from Expr
1111
List(new QuoteTreeOutput(output))
1212
)
1313

1414
class QuoteTreeOutput(output: tpd.Tree => Context => Unit) extends Phase {
15-
override def phaseName: String = "quotePrinter"
15+
override def phaseName: String = "quoteOutput"
1616
override def run(implicit ctx: Context): Unit = output(ctx.compilationUnit.tpdTree)(ctx)
1717
}
1818
}

compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import dotty.tools.io.{AbstractFile, Directory, PlainDirectory, VirtualDirectory
77
import dotty.tools.repl.AbstractFileClassLoader
88
import dotty.tools.dotc.printing.DecompilerPrinter
99

10-
import scala.quoted.Expr
10+
import scala.quoted.{Expr, Type}
1111

1212
import java.net.URLClassLoader
1313

@@ -28,7 +28,7 @@ class QuoteDriver extends Driver {
2828
new VirtualDirectory("(memory)", None)
2929
}
3030

31-
val driver = new ExprCompiler(outDir)
31+
val driver = new QuoteCompiler(outDir)
3232
driver.newRun(ctx).compileExpr(expr)
3333

3434
val classLoader = new AbstractFileClassLoader(outDir, this.getClass.getClassLoader)
@@ -58,10 +58,22 @@ class QuoteDriver extends Driver {
5858
assert(output.isEmpty)
5959
output = Some(f(tree, ctx))
6060
}
61-
new ExprDecompiler(registerTree).newRun(ctx).compileExpr(expr)
61+
new QuoteDecompiler(registerTree).newRun(ctx).compileExpr(expr)
6262
output.getOrElse(throw new Exception("Could not extract " + expr))
6363
}
6464

65+
def withTypeTree[T](tpe: Type[_], f: (TypTree, Context) => T, settings: Settings[_]): T = {
66+
val (_, ctx: Context) = setup(settings.compilerArgs.toArray :+ "dummy.scala", initCtx.fresh)
67+
68+
var output: Option[T] = None
69+
def registerTree(tree: tpd.Tree)(ctx: Context): Unit = {
70+
assert(output.isEmpty)
71+
output = Some(f(tree.asInstanceOf[TypTree], ctx))
72+
}
73+
new QuoteDecompiler(registerTree).newRun(ctx).compileType(tpe)
74+
output.getOrElse(throw new Exception("Could not extract " + tpe))
75+
}
76+
6577
override def initCtx: Context = {
6678
val ictx = super.initCtx.fresh
6779
var classpath = System.getProperty("java.class.path")

compiler/src/dotty/tools/dotc/quoted/Toolbox.scala

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package dotty.tools.dotc.quoted
22

3-
import dotty.tools.dotc.ast.Trees._
43
import dotty.tools.dotc.ast.tpd
54
import dotty.tools.dotc.core.Constants._
6-
import dotty.tools.dotc.core.Contexts.Context
7-
import dotty.tools.dotc.core.quoted.PickledQuotes
85
import dotty.tools.dotc.printing.RefinedPrinter
96

107
import scala.quoted.Expr
@@ -48,19 +45,6 @@ object Toolbox {
4845
case _ => new QuoteDriver().show(expr, showSettings)
4946
}
5047

51-
def toConstantOpt(expr: Expr[T]): Option[T] = {
52-
def toConstantOpt(tree: Tree): Option[T] = tree match {
53-
case Literal(Constant(c)) => Some(c.asInstanceOf[T])
54-
case Block(Nil, e) => toConstantOpt(e)
55-
case Inlined(_, Nil, e) => toConstantOpt(e)
56-
case _ => None
57-
}
58-
expr match {
59-
case expr: LiftedExpr[T] => Some(expr.value)
60-
case _ => new QuoteDriver().withTree(expr, (tree, _) => toConstantOpt(tree), Settings.run())
61-
}
62-
}
63-
6448
}
6549

6650
class Settings[T] private (val outDir: Option[String], val rawTree: Boolean, val compilerArgs: List[String])
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package dotty.tools.dotc.quoted
2+
3+
import dotty.tools.dotc.CompilationUnit
4+
import dotty.tools.dotc.util.NoSource
5+
6+
import scala.quoted.Type
7+
8+
/* Compilation unit containing the contents of a quoted type */
9+
class TypeCompilationUnit(val tpe: Type[_]) extends CompilationUnit(NoSource) {
10+
override def toString = s"Type($tpe)"
11+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package dotty.tools.dotc.tasty
2+
package internal
3+
4+
import dotty.tools.dotc.core.Contexts.Context
5+
import dotty.tools.dotc.core.Annotations.Annotation
6+
7+
import scala.tasty.modifiers
8+
9+
object AnnotationModifier {
10+
11+
def apply(tree: Annotation): modifiers.Annotation = new Impl(tree)
12+
13+
def unapplyAnnotation(arg: Impl)(implicit ctx: Context): Option[modifiers.Annotation.Data] = {
14+
Some(Term(arg.annot.tree))
15+
}
16+
17+
private[tasty] class Impl(val annot: Annotation) extends modifiers.Annotation {
18+
override def toString: String = "Annotation"
19+
}
20+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package dotty.tools.dotc.tasty
2+
package internal
3+
4+
import dotty.tools.dotc.ast.Trees
5+
import dotty.tools.dotc.ast.tpd
6+
import dotty.tools.dotc.core.Contexts.Context
7+
8+
import scala.tasty.trees
9+
10+
object CaseDef {
11+
12+
def apply(tree: tpd.CaseDef): trees.CaseDef = new Impl(tree)
13+
14+
def unapplyCaseDef(arg: Impl)(implicit ctx: Context): Option[trees.CaseDef.Data] = {
15+
val Trees.CaseDef(pat, guard, body) = arg.tree
16+
Some(Pattern(pat), if (guard.isEmpty) None else Some(Term(guard)), Term(body))
17+
}
18+
19+
private[tasty] class Impl(val tree: tpd.CaseDef) extends trees.CaseDef with Positioned {
20+
override def toString: String = "CaseDef"
21+
}
22+
}

0 commit comments

Comments
 (0)