Skip to content

Commit 8950d9a

Browse files
committed
WIP
1 parent 6a89a88 commit 8950d9a

File tree

6 files changed

+154
-48
lines changed

6 files changed

+154
-48
lines changed

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

Lines changed: 91 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,101 @@ object PickledQuotes {
6161
}.apply(tp)
6262

6363
/** Unpickle the tree contained in the TastyExpr */
64-
def unpickleExpr(tasty: PickledQuote, args: PickledArgs)(implicit ctx: Context): Tree = {
64+
def unpickleExpr(tasty: PickledQuote, splices: PickledArgs)(implicit ctx: Context): Tree = {
6565
val tastyBytes = TastyString.unpickle(tasty)
66-
val unpickled = unpickle(tastyBytes, args, isType = false)(ctx.addMode(Mode.ReadPositions))
66+
val unpickled = unpickle(tastyBytes, splices, isType = false)(ctx.addMode(Mode.ReadPositions))
6767
/** Force unpickling of the tree, removes the spliced type `@quotedTypeTag type` definitions and dealiases references to `@quotedTypeTag type` */
68-
val forceAndCleanArtefacts = new TreeMap {
69-
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match {
68+
69+
if ctx.settings.YprintDebug.value then
70+
71+
72+
val Inlined(call, Nil, expnasion) = unpickled
73+
74+
val (typeSpliceMap, expnasion1) = expnasion match
7075
case Block(stat :: rest, expr1) if stat.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot) =>
71-
assert(rest.forall { case tdef: TypeDef => tdef.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot) })
72-
transform(expr1)
73-
case tree => super.transform(tree).withType(dealiasTypeTags(tree.tpe))
76+
val map = (stat :: rest).iterator.map {
77+
case tdef: TypeDef =>
78+
assert(tdef.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot))
79+
val TypeBoundsTree(_, Hole(_, idx, args), _) = tdef.rhs
80+
val quotedType = splices(idx).asInstanceOf[Seq[Any] => quoted.Type[?]](args)
81+
val tree = PickledQuotes.quotedTypeToTree(quotedType)
82+
(tdef.symbol, tree.tpe)
83+
}.toMap
84+
(map, expr1)
85+
case _ => (Map.empty, expnasion)
86+
87+
def spliceTypes(tp: Type)(implicit ctx: Context): Type = new TypeMap() {
88+
override def apply(tp: Type): Type = {
89+
val tp1 = tp match {
90+
case tp: TypeRef if tp.typeSymbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot) =>
91+
typeSpliceMap(tp.symbol)
92+
case _ => tp
93+
}
94+
mapOver(tp1)
95+
}
96+
}.apply(tp)
97+
// println("::::::::::::::::::::::::::::::::::::")
98+
// println(typeSpliceMap)
99+
// println()
100+
// println()
101+
102+
val evaluateHoles = new TreeMap {
103+
// private var typeSpliceMap = Map.empty[Symbol, Type]
104+
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match {
105+
// case Block(stat :: rest, expr1) if stat.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot) =>
106+
// val splicedTypes = (stat :: rest).map {
107+
// case tdef: TypeDef =>
108+
// assert(tdef.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot))
109+
// val TypeBoundsTree(_, hi, _) = transform(tdef.rhs)
110+
// (tdef.symbol, hi.tpe)
111+
// }
112+
// typeSpliceMap = splicedTypes.toMap
113+
// transform(expr1)
114+
case Hole(isType, idx, args) =>
115+
val splice = splices(idx)
116+
def wrap(arg: Tree) =
117+
if (arg.isTerm) (qctx: scala.quoted.QuoteContext) ?=> new TastyTreeExpr(arg, QuoteContext.scopeId)
118+
else new TreeType(arg, QuoteContext.scopeId)
119+
val reifiedArgs = args.map(wrap)
120+
val filled = if (isType) {
121+
???
122+
val quotedType = splice.asInstanceOf[Seq[Any] => quoted.Type[?]](reifiedArgs)
123+
PickledQuotes.quotedTypeToTree(quotedType)
124+
}
125+
else {
126+
val splice1 = splice.asInstanceOf[Seq[Any] => scala.quoted.QuoteContext ?=> quoted.Expr[?]]
127+
val quotedExpr = splice1(reifiedArgs)(using dotty.tools.dotc.quoted.QuoteContext())
128+
PickledQuotes.quotedExprToTree(quotedExpr)
129+
}
130+
// We need to make sure a hole is created with the source file of the surrounding context, even if
131+
// it filled with contents a different source file. Otherwise nodes contqaining holes might end
132+
// up without a position. PositionPickler makes sure that holes always get spans assigned,
133+
// so we can just return the filler tree with the new source and no span here.
134+
if (filled.source == ctx.source) filled
135+
else {
136+
val filled1 = filled.cloneIn(ctx.source)
137+
// filled1.span = NoSpan
138+
filled1
139+
}
140+
141+
// super.transform(tree).withType(dealiasTypeTags(tree.tpe))
142+
case tree =>
143+
super.transform(tree).withType(spliceTypes(tree.tpe))
144+
}
74145
}
75-
}
76-
forceAndCleanArtefacts.transform(unpickled)
146+
val evaluatedExpansion = evaluateHoles.transform(expnasion1)
147+
cpy.Inlined(unpickled)(call, Nil, evaluatedExpansion)
148+
else
149+
val forceAndCleanArtefacts = new TreeMap {
150+
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match {
151+
case Block(stat :: rest, expr1) if stat.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot) =>
152+
assert(rest.forall { case tdef: TypeDef => tdef.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot) })
153+
transform(expr1)
154+
case tree => super.transform(tree).withType(dealiasTypeTags(tree.tpe))
155+
}
156+
}
157+
forceAndCleanArtefacts.transform(unpickled)
158+
77159
}
78160

79161
/** Unpickle the tree contained in the TastyType */

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

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,39 +1291,45 @@ class TreeUnpickler(reader: TastyReader,
12911291
}
12921292

12931293
def readHole(end: Addr, isType: Boolean)(implicit ctx: Context): Tree = {
1294-
val idx = readNat()
1295-
val tpe = readType() // FIXME use to set type to the unpickled tree
1296-
val args = until(end)(readTerm())
1297-
val splice = splices(idx)
1298-
// println("++++++++++++++++++++++++++++++=")
1299-
// println(tpe.show)
1300-
// println(isType)
1301-
// println()
1302-
// println()
1303-
def wrap(arg: Tree) =
1304-
if (arg.isTerm) (qctx: scala.quoted.QuoteContext) ?=> new TastyTreeExpr(arg, QuoteContext.scopeId)
1305-
else new TreeType(arg, QuoteContext.scopeId)
1306-
val reifiedArgs = args.map(wrap)
1307-
val filled = if (isType) {
1308-
val quotedType = splice.asInstanceOf[Seq[Any] => quoted.Type[?]](reifiedArgs)
1309-
PickledQuotes.quotedTypeToTree(quotedType)
1310-
}
1311-
else {
1312-
val splice1 = splice.asInstanceOf[Seq[Any] => scala.quoted.QuoteContext ?=> quoted.Expr[?]]
1313-
val quotedExpr = splice1(reifiedArgs)(using dotty.tools.dotc.quoted.QuoteContext())
1314-
val a = PickledQuotes.quotedExprToTree(quotedExpr)
1315-
a.ensureConforms(tpe).withSpan(a.span)
1316-
}
1317-
// We need to make sure a hole is created with the source file of the surrounding context, even if
1318-
// it filled with contents a different source file. Otherwise nodes containing holes might end
1319-
// up without a position. PositionPickler makes sure that holes always get spans assigned,
1320-
// so we can just return the filler tree with the new source and no span here.
1321-
if (filled.source == ctx.source) filled
1322-
else {
1323-
val filled1 = filled.cloneIn(ctx.source)
1324-
filled1.span = NoSpan
1325-
filled1
1326-
}
1294+
if ctx.settings.YprintDebug.value then
1295+
val idx = readNat()
1296+
val tpe = readType()
1297+
val args = until(end)(readTerm())
1298+
TreePickler.Hole(isType, idx, args).withType(tpe)
1299+
else
1300+
val idx = readNat()
1301+
val tpe = readType() // FIXME use to set type to the unpickled tree
1302+
val args = until(end)(readTerm())
1303+
val splice = splices(idx)
1304+
// println("++++++++++++++++++++++++++++++=")
1305+
// println(tpe.show)
1306+
// println(isType)
1307+
// println()
1308+
// println()
1309+
def wrap(arg: Tree) =
1310+
if (arg.isTerm) (qctx: scala.quoted.QuoteContext) ?=> new TastyTreeExpr(arg, QuoteContext.scopeId)
1311+
else new TreeType(arg, QuoteContext.scopeId)
1312+
val reifiedArgs = args.map(wrap)
1313+
val filled = if (isType) {
1314+
val quotedType = splice.asInstanceOf[Seq[Any] => quoted.Type[?]](reifiedArgs)
1315+
PickledQuotes.quotedTypeToTree(quotedType)
1316+
}
1317+
else {
1318+
val splice1 = splice.asInstanceOf[Seq[Any] => scala.quoted.QuoteContext ?=> quoted.Expr[?]]
1319+
val quotedExpr = splice1(reifiedArgs)(using dotty.tools.dotc.quoted.QuoteContext())
1320+
val a = PickledQuotes.quotedExprToTree(quotedExpr)
1321+
a.ensureConforms(tpe).withSpan(a.span)
1322+
}
1323+
// We need to make sure a hole is created with the source file of the surrounding context, even if
1324+
// it filled with contents a different source file. Otherwise nodes containing holes might end
1325+
// up without a position. PositionPickler makes sure that holes always get spans assigned,
1326+
// so we can just return the filler tree with the new source and no span here.
1327+
if (filled.source == ctx.source) filled
1328+
else {
1329+
val filled1 = filled.cloneIn(ctx.source)
1330+
filled1.span = NoSpan
1331+
filled1
1332+
}
13271333
}
13281334

13291335
// ------ Setting positions ------------------------------------------------

compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ class BootstrappedOnlyCompilationTests extends ParallelTesting {
100100

101101
@Test def negMacros: Unit = {
102102
implicit val testGroup: TestGroup = TestGroup("compileNegWithCompiler")
103-
compileFilesInDir("tests/neg-macros", defaultOptions).checkExpectedErrors()
103+
compileFilesInDir("tests/neg-macros", defaultOptions and "-Yprint-debug").checkExpectedErrors()
104104
}
105105

106106
@Test def negWithCompiler: Unit = {
@@ -116,17 +116,17 @@ class BootstrappedOnlyCompilationTests extends ParallelTesting {
116116
@Test def runMacros: Unit = {
117117
implicit val testGroup: TestGroup = TestGroup("runMacros")
118118
aggregateTests(
119-
compileFilesInDir("tests/run-macros", defaultOptions),
120-
compileFilesInDir("tests/run-custom-args/Yretain-trees", defaultOptions and "-Yretain-trees"),
121-
compileFilesInDir("tests/run-custom-args/run-macros-erased", defaultOptions and "-Yerased-terms"),
119+
compileFilesInDir("tests/run-macros", defaultOptions and "-Yprint-debug"),
120+
compileFilesInDir("tests/run-custom-args/Yretain-trees", defaultOptions and "-Yretain-trees" and "-Yprint-debug"),
121+
compileFilesInDir("tests/run-custom-args/run-macros-erased", defaultOptions and "-Yerased-terms" and "-Yprint-debug"),
122122
)
123123
}.checkRuns()
124124

125125
@Test def runWithCompiler: Unit = {
126126
implicit val testGroup: TestGroup = TestGroup("runWithCompiler")
127127
aggregateTests(
128128
compileFilesInDir("tests/run-with-compiler", withCompilerOptions),
129-
compileFilesInDir("tests/run-staging", withStagingOptions),
129+
compileFilesInDir("tests/run-staging", withStagingOptions and "-Yprint-debug"),
130130
compileFilesInDir("tests/run-custom-args/tasty-inspector", withTastyInspectorOptions),
131131
compileDir("tests/run-custom-args/tasty-interpreter", withTastyInspectorOptions),
132132
).checkRuns()

tests/pos-macros/i7110/Macro_1.scala renamed to tests/pos-macros/i7110a/Macro_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import scala.quoted._
22

33
object Macros {
44

5-
// inline def m[R](sym: Symantics[R]) : R = ${ mImpl[R]('{sym}) }
5+
inline def m[R](sym: Symantics[R]) : R = ${ mImpl[R]('{sym}) }
66

77
def mImpl[R: Type](using qctx: QuoteContext)(sym: Expr[Symantics[R]]): Expr[R] = '{
88
$sym.Meth(42)

tests/run/i7110.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
trait Symantics[R] {
3+
def Meth(exp: Int): R
4+
def Meth(): R
5+
}
6+
7+
inline def m[R](sym: Symantics[R]) : R =
8+
sym.Meth(42)
9+
10+
@main def Test: Unit = {
11+
12+
val sym = new Symantics[Int] {
13+
def Meth(exp: Int): Int = exp
14+
def Meth(): Int = 43
15+
}
16+
17+
val test = m[Int](sym)
18+
}

0 commit comments

Comments
 (0)