@@ -99,16 +99,17 @@ class Splicing extends MacroTransform {
99
99
end MyTransformer
100
100
101
101
class QuoteTransformer extends Transformer :
102
- private val localDefs = mutable.Set .empty[Symbol ]
102
+ private val quotedDefs = mutable.Set .empty[Symbol ]
103
+ private var holeIdx = - 1
103
104
override def transform (tree : tpd.Tree )(using Context ): tpd.Tree =
104
105
tree match
105
106
case Apply (fn, List (splicedCode)) if fn.symbol == defn.QuotedRuntime_exprNestedSplice =>
106
- val spliceTransformer = new SpliceTransformer (localDefs.toSet, ctx.owner)
107
+ val spliceTransformer = new SpliceTransformer (ctx.owner)
107
108
val newSplicedCode1 = spliceTransformer.transformSplice(splicedCode, tree.tpe)
108
109
val newSplicedCode2 = MyTransformer .transform(newSplicedCode1)
109
110
newSplicedCode2
110
111
case tree : DefTree =>
111
- localDefs += tree.symbol
112
+ quotedDefs += tree.symbol
112
113
transformAnnotations(tree)
113
114
super .transform(tree)
114
115
case _ =>
@@ -130,115 +131,117 @@ class Splicing extends MacroTransform {
130
131
}
131
132
}
132
133
133
- end QuoteTransformer
134
-
135
- class SpliceTransformer (quoteDefs : Set [Symbol ], spliceOwner : Symbol ) extends Transformer :
136
- private var refBindingMap = mutable.Map .empty[Symbol , (Tree , Symbol )]
137
- private var level = 0
138
- private var quotes : Tree = null
134
+ class SpliceTransformer (spliceOwner : Symbol ) extends Transformer :
135
+ private var refBindingMap = mutable.Map .empty[Symbol , (Tree , Symbol )]
136
+ private var level = 0
137
+ private var quotes : Tree = null
139
138
140
- def transformSplice (tree : tpd.Tree , tpe : Type )(using Context ): tpd.Tree =
141
- val newTree = transform(tree)
142
- val (refs, bindings) = refBindingMap.values.toList.unzip
143
- val bindingsTypes = bindings.map(_.termRef.widenTermRefExpr)
144
- val methType = MethodType (bindingsTypes, newTree.tpe)
145
- val meth = newSymbol(spliceOwner, nme.ANON_FUN , Synthetic | Method , methType)
146
- val ddef = DefDef (meth, List (bindings), newTree.tpe, newTree.changeOwner(ctx.owner, meth))
147
- val fnType = defn.FunctionType (bindings.size, isContextual = false ).appliedTo(bindingsTypes :+ newTree.tpe)
148
- val closure = Block (ddef :: Nil , Closure (Nil , ref(meth), TypeTree (fnType)))
149
- Hole (true , - 1 , refs, closure, TypeTree (tpe)).withType(tpe)
139
+ def transformSplice (tree : tpd.Tree , tpe : Type )(using Context ): tpd.Tree =
140
+ val newTree = transform(tree)
141
+ val (refs, bindings) = refBindingMap.values.toList.unzip
142
+ val bindingsTypes = bindings.map(_.termRef.widenTermRefExpr)
143
+ val methType = MethodType (bindingsTypes, newTree.tpe)
144
+ val meth = newSymbol(spliceOwner, nme.ANON_FUN , Synthetic | Method , methType)
145
+ val ddef = DefDef (meth, List (bindings), newTree.tpe, newTree.changeOwner(ctx.owner, meth))
146
+ val fnType = defn.FunctionType (bindings.size, isContextual = false ).appliedTo(bindingsTypes :+ newTree.tpe)
147
+ val closure = Block (ddef :: Nil , Closure (Nil , ref(meth), TypeTree (fnType)))
148
+ holeIdx += 1
149
+ Hole (true , holeIdx, refs, closure, TypeTree (tpe)).withType(tpe)
150
150
151
- override def transform (tree : tpd.Tree )(using Context ): tpd.Tree =
152
- tree match
153
- case tree : RefTree =>
154
- if tree.isTerm then
155
- if quoteDefs.contains(tree.symbol) then
156
- val tree1 = splicedTerm(tree)
157
- val tpe = tree.tpe.widenTermRefExpr match {
158
- case tpw : MethodicType => tpw.toFunctionType(isJava = false )
159
- case tpw => tpw
160
- }
161
- tree1.spliced(tpe)
162
- else super .transform(tree)
163
- else // tree.isType then
151
+ override def transform (tree : tpd.Tree )(using Context ): tpd.Tree =
152
+ tree match
153
+ case tree : RefTree =>
154
+ if tree.isTerm then
155
+ if quotedDefs.contains(tree.symbol) then
156
+ val tree1 = splicedTerm(tree)
157
+ val tpe = tree.tpe.widenTermRefExpr match {
158
+ case tpw : MethodicType => tpw.toFunctionType(isJava = false )
159
+ case tpw => tpw
160
+ }
161
+ tree1.spliced(tpe)
162
+ else super .transform(tree)
163
+ else // tree.isType then
164
+ if containsCapturedType(tree.tpe) then
165
+ splicedType(tree).select(defn.QuotedType_splice )
166
+ else super .transform(tree)
167
+ case tree : TypeTree =>
164
168
if containsCapturedType(tree.tpe) then
165
169
splicedType(tree).select(defn.QuotedType_splice )
170
+ else tree
171
+ case Assign (lhs : RefTree , rhs) =>
172
+ if quotedDefs.contains(lhs.symbol) then transformSplicedAssign(lhs, rhs, tree.tpe)
166
173
else super .transform(tree)
167
- case tree : TypeTree =>
168
- if containsCapturedType(tree.tpe) then
169
- splicedType(tree).select(defn.QuotedType_splice )
170
- else tree
171
- case Assign (lhs : RefTree , rhs) =>
172
- if quoteDefs.contains(lhs.symbol) then transformSplicedAssign(lhs, rhs, tree.tpe)
173
- else super .transform(tree)
174
- case Apply (fn, args) if fn.symbol == defn.QuotedRuntime_exprNestedSplice =>
175
- level -= 1
176
- val newArgs = args.mapConserve(transform)
177
- level += 1
178
- cpy.Apply (tree)(fn, newArgs)
179
- case Apply (sel @ Select (app @ Apply (fn, args),nme.apply), quotesArgs)
180
- if fn.symbol == defn.QuotedRuntime_exprQuote =>
181
- args match
182
- case List (tree : RefTree ) if quoteDefs.contains(tree.symbol) =>
183
- splicedTerm(tree)
184
- case _ =>
185
- val oldQuotes = quotes
186
- if level == 0 then quotes = quotesArgs.head
187
- level += 1
188
- val newArgs = args.mapConserve(transform)
174
+ case Apply (fn, args) if fn.symbol == defn.QuotedRuntime_exprNestedSplice =>
189
175
level -= 1
190
- quotes = oldQuotes
191
- cpy.Apply (tree)(cpy.Select (sel)(cpy.Apply (app)(fn, newArgs), nme.apply), quotesArgs)
192
- case Apply (TypeApply (_, List (tpt : Ident )), List (quotes))
193
- if tree.symbol == defn.QuotedTypeModule_of && quoteDefs.contains(tpt.symbol) =>
194
- splicedType(tpt)
195
- case _ =>
196
- super .transform(tree)
176
+ val newArgs = args.mapConserve(transform)
177
+ level += 1
178
+ cpy.Apply (tree)(fn, newArgs)
179
+ case Apply (sel @ Select (app @ Apply (fn, args),nme.apply), quotesArgs)
180
+ if fn.symbol == defn.QuotedRuntime_exprQuote =>
181
+ args match
182
+ case List (tree : RefTree ) if quotedDefs.contains(tree.symbol) =>
183
+ splicedTerm(tree)
184
+ case _ =>
185
+ val oldQuotes = quotes
186
+ if level == 0 then quotes = quotesArgs.head
187
+ level += 1
188
+ val newArgs = args.mapConserve(transform)
189
+ level -= 1
190
+ quotes = oldQuotes
191
+ cpy.Apply (tree)(cpy.Select (sel)(cpy.Apply (app)(fn, newArgs), nme.apply), quotesArgs)
192
+ case Apply (TypeApply (_, List (tpt : Ident )), List (quotes))
193
+ if tree.symbol == defn.QuotedTypeModule_of && quotedDefs.contains(tpt.symbol) =>
194
+ splicedType(tpt)
195
+ case _ =>
196
+ super .transform(tree)
197
197
198
- private def containsCapturedType (tpe : Type )(using Context ): Boolean =
199
- tpe match
200
- case tpe @ TypeRef (prefix, _) => quoteDefs .contains(tpe.symbol) || containsCapturedType(prefix)
201
- case tpe @ TermRef (prefix, _) => quoteDefs .contains(tpe.symbol) || containsCapturedType(prefix)
202
- case AppliedType (tycon, args) => containsCapturedType(tycon) || args.exists(containsCapturedType)
203
- case _ => false
198
+ private def containsCapturedType (tpe : Type )(using Context ): Boolean =
199
+ tpe match
200
+ case tpe @ TypeRef (prefix, _) => quotedDefs .contains(tpe.symbol) || containsCapturedType(prefix)
201
+ case tpe @ TermRef (prefix, _) => quotedDefs .contains(tpe.symbol) || containsCapturedType(prefix)
202
+ case AppliedType (tycon, args) => containsCapturedType(tycon) || args.exists(containsCapturedType)
203
+ case _ => false
204
204
205
- private def transformSplicedAssign (lhs : RefTree , rhs : Tree , tpe : Type )(using Context ): Tree =
206
- // Make `(x: T) => rhs = x`
207
- val methTpe = MethodType (List (lhs.tpe.widenTermRefExpr), tpe)
208
- val meth = newSymbol(spliceOwner, nme.ANON_FUN , Synthetic | Method , methTpe)
209
- val closure = Closure (meth, args => Assign (lhs, args.head.head))
205
+ private def transformSplicedAssign (lhs : RefTree , rhs : Tree , tpe : Type )(using Context ): Tree =
206
+ // Make `(x: T) => rhs = x`
207
+ val methTpe = MethodType (List (lhs.tpe.widenTermRefExpr), tpe)
208
+ val meth = newSymbol(spliceOwner, nme.ANON_FUN , Synthetic | Method , methTpe)
209
+ val closure = Closure (meth, args => Assign (lhs, args.head.head))
210
210
211
- val binding = splicedTerm(closure)
212
- // TODO: `${Expr.betaReduce('{$rhsFn.apply(lhs)})}` ?
213
- // Make `$rhsFn.apply(lhs)`
214
- binding.spliced(methTpe.toFunctionType(isJava = false )).select(nme.apply).appliedTo(transform(rhs))
211
+ val binding = splicedTerm(closure)
212
+ // TODO: `${Expr.betaReduce('{$rhsFn.apply(lhs)})}` ?
213
+ // Make `$rhsFn.apply(lhs)`
214
+ binding.spliced(methTpe.toFunctionType(isJava = false )).select(nme.apply).appliedTo(transform(rhs))
215
215
216
- private def splicedTerm (tree : Tree )(using Context ): Tree =
217
- val tpe = tree.tpe.widenTermRefExpr match {
218
- case tpw : MethodicType => tpw.toFunctionType(isJava = false )
219
- case tpw => tpw
220
- }
221
- def newBinding = newSymbol(
222
- spliceOwner,
223
- UniqueName .fresh(tree.symbol.name.toTermName).toTermName,
224
- Param ,
225
- tpe.exprType,
226
- )
227
- val (_, bindingSym) = refBindingMap.getOrElseUpdate(tree.symbol, (tree, newBinding))
228
- ref(bindingSym)
216
+ private def splicedTerm (tree : Tree )(using Context ): Tree =
217
+ val tpe = tree.tpe.widenTermRefExpr match {
218
+ case tpw : MethodicType => tpw.toFunctionType(isJava = false )
219
+ case tpw => tpw
220
+ }
221
+ def newBinding = newSymbol(
222
+ spliceOwner,
223
+ UniqueName .fresh(tree.symbol.name.toTermName).toTermName,
224
+ Param ,
225
+ tpe.exprType,
226
+ )
227
+ val (_, bindingSym) = refBindingMap.getOrElseUpdate(tree.symbol, (tree, newBinding))
228
+ ref(bindingSym)
229
229
230
- private def splicedType (tree : Tree )(using Context ): Tree =
231
- val tpe = tree.tpe.widenTermRefExpr
232
- def newBinding = newSymbol(
233
- spliceOwner,
234
- UniqueName .fresh(nme.Type ).toTermName,
235
- Param ,
236
- defn.QuotedTypeClass .typeRef.appliedTo(tpe),
237
- )
238
- val (_, bindingSym) = refBindingMap.getOrElseUpdate(tree.symbol, (TypeTree (tree.tpe), newBinding))
239
- ref(bindingSym)
230
+ private def splicedType (tree : Tree )(using Context ): Tree =
231
+ val tpe = tree.tpe.widenTermRefExpr
232
+ def newBinding = newSymbol(
233
+ spliceOwner,
234
+ UniqueName .fresh(nme.Type ).toTermName,
235
+ Param ,
236
+ defn.QuotedTypeClass .typeRef.appliedTo(tpe),
237
+ )
238
+ val (_, bindingSym) = refBindingMap.getOrElseUpdate(tree.symbol, (TypeTree (tree.tpe), newBinding))
239
+ ref(bindingSym)
240
+
241
+ end SpliceTransformer
242
+
243
+ end QuoteTransformer
240
244
241
- end SpliceTransformer
242
245
243
246
}
244
247
0 commit comments