Skip to content

Add Reflection.Term.betaReduce #9918

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 all 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
28 changes: 14 additions & 14 deletions compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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
Expand Down
8 changes: 5 additions & 3 deletions library/src-bootstrapped/scala/quoted/Expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 0 additions & 3 deletions library/src/scala/internal/tasty/CompilerInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

}
Expand Down
15 changes: 14 additions & 1 deletion library/src/scala/tasty/Reflection.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down