diff --git a/compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala b/compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala index c718f0fce4a4..99378f0ea37c 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala @@ -295,7 +295,20 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext: case _ => None end TermTypeTest - object Term extends TermModule + object Term extends TermModule: + def betaReduce(tree: Term): Option[Term] = + tree match + case app @ tpd.Apply(tpd.Select(fn, nme.apply), args) if dotc.core.Symbols.defn.isFunctionType(fn.tpe) => + val app1 = dotc.transform.BetaReduce(app, fn, args) + if app1 eq app then None + else Some(app1.withSpan(tree.span)) + case tpd.Block(Nil, expr) => + for e <- betaReduce(expr) yield tpd.cpy.Block(tree)(Nil, e) + case tpd.Inlined(_, Nil, expr) => + betaReduce(expr) + case _ => + None + end Term object TermMethodsImpl extends TermMethods: extension (self: Term): @@ -2655,19 +2668,6 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext: def Definitions_InternalQuotedPatterns_patternHole: Symbol = dotc.core.Symbols.defn.InternalQuotedPatterns_patternHole def Definitions_InternalQuotedPatterns_higherOrderHole: Symbol = dotc.core.Symbols.defn.InternalQuotedPatterns_higherOrderHole - def betaReduce(tree: Term): Option[Term] = - tree match - case app @ tpd.Apply(tpd.Select(fn, nme.apply), args) if dotc.core.Symbols.defn.isFunctionType(fn.tpe) => - val app1 = dotc.transform.BetaReduce(app, fn, args) - if app1 eq app then None - else Some(app1.withSpan(tree.span)) - case tpd.Block(Nil, expr) => - for e <- betaReduce(expr) yield tpd.cpy.Block(tree)(Nil, e) - case tpd.Inlined(_, Nil, expr) => - betaReduce(expr) - case _ => - None - def compilerId: Int = rootContext.outersIterator.toList.last.hashCode() end tasty diff --git a/library/src-bootstrapped/scala/quoted/Expr.scala b/library/src-bootstrapped/scala/quoted/Expr.scala index 0d0a9730a3dd..8218d2115f97 100644 --- a/library/src-bootstrapped/scala/quoted/Expr.scala +++ b/library/src-bootstrapped/scala/quoted/Expr.scala @@ -72,13 +72,15 @@ object Expr { end extension /** `e.betaReduce` returns an expression that is functionally equivalent to `e`, - * however if `e` is of the form `((y1, ..., yn) => e2)(x1, ..., xn)` + * however if `e` is of the form `((y1, ..., yn) => e2)(e1, ..., en)` * then it optimizes this the top most call by returning the result of beta-reducing the application. * Otherwise returns `expr`. + * + * To retain semantics the argument `ei` is bound as `val yi = ei` and by-name arguments to `def yi = ei`. + * Some bindings may be elided as an early optimization. */ def betaReduce[T](expr: Expr[T])(using qctx: QuoteContext): Expr[T] = - val qctx2 = quoteContextWithCompilerInterface(qctx) - qctx2.tasty.betaReduce(expr.unseal) match + qctx.tasty.Term.betaReduce(expr.unseal) match case Some(expr1) => expr1.seal.asInstanceOf[Expr[T]] case _ => expr diff --git a/library/src/scala/internal/tasty/CompilerInterface.scala b/library/src/scala/internal/tasty/CompilerInterface.scala index 931e55b13127..cf465ce4e6d8 100644 --- a/library/src/scala/internal/tasty/CompilerInterface.scala +++ b/library/src/scala/internal/tasty/CompilerInterface.scala @@ -61,9 +61,6 @@ trait CompilerInterface { self: scala.tasty.Reflection => /** Symbol of scala.internal.quoted.Patterns.higherOrderHole */ def Definitions_InternalQuotedPatterns_higherOrderHole: Symbol - /** Returns Some with a beta-reduced application or None */ - def betaReduce(tree: Term): Option[Term] - def compilerId: Int } diff --git a/library/src/scala/tasty/Reflection.scala b/library/src/scala/tasty/Reflection.scala index 62f2b8795619..9466b81751ee 100644 --- a/library/src/scala/tasty/Reflection.scala +++ b/library/src/scala/tasty/Reflection.scala @@ -362,7 +362,20 @@ trait Reflection { reflection => val Term: TermModule - trait TermModule { this: Term.type => } + trait TermModule { this: Term.type => + + /** Returns a term that is functionally equivalent to `t`, + * however if `t` is of the form `((y1, ..., yn) => e2)(e1, ..., en)` + * then it optimizes this the top most call by returning the `Some` + * with the result of beta-reducing the application. + * Otherwise returns `None`. + * + * To retain semantics the argument `ei` is bound as `val yi = ei` and by-name arguments to `def yi = ei`. + * Some bindings may be elided as an early optimization. + */ + def betaReduce(term: Term): Option[Term] + + } given TermMethods as TermMethods = TermMethodsImpl protected val TermMethodsImpl: TermMethods