Skip to content

Commit 8b776bd

Browse files
committed
Factor out common β-reduction code
1 parent caff137 commit 8b776bd

File tree

2 files changed

+37
-36
lines changed

2 files changed

+37
-36
lines changed

compiler/src/dotty/tools/dotc/transform/BetaReduce.scala

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,38 @@ class BetaReduce extends MiniPhase:
4646
fn match
4747
case Typed(expr, _) => betaReduce(tree, expr, args)
4848
case Block(Nil, expr) => betaReduce(tree, expr, args)
49-
case Block((anonFun: DefDef) :: Nil, closure: Closure) =>
50-
val argSyms =
51-
for arg <- args yield
52-
arg.tpe.dealias match
53-
case ref @ TermRef(NoPrefix, _) if isPurePath(arg) => ref.symbol
54-
case _ => NoSymbol
55-
val vparams = anonFun.vparamss.head
56-
if argSyms.forall(_.exists) && argSyms.hasSameLengthAs(vparams) then
57-
TreeTypeMap(
58-
oldOwners = anonFun.symbol :: Nil,
59-
newOwners = ctx.owner :: Nil,
60-
substFrom = vparams.map(_.symbol),
61-
substTo = argSyms).transform(anonFun.rhs)
62-
else tree
49+
case Block((anonFun: DefDef) :: Nil, closure: Closure) => BetaReduce(tree)(anonFun, args, true)
6350
case _ => tree
51+
52+
object BetaReduce:
53+
import ast.tpd._
54+
55+
/** Beta-reduces a call to `ddef` with arguments `argSyms` */
56+
def apply(tree: Tree)(ddef: DefDef, args: List[Tree], noBindings: Boolean)(using ctx: Context) =
57+
val bindings = List.newBuilder[ValDef]
58+
val vparams = ddef.vparamss.iterator.flatten.toList
59+
val argSyms =
60+
for (arg, param) <- args.zip(vparams) yield
61+
arg.tpe.dealias match
62+
case ref @ TermRef(NoPrefix, _) if isPurePath(arg) =>
63+
ref.symbol
64+
case _ =>
65+
if noBindings then // TODO always generate bindings
66+
NoSymbol
67+
else
68+
val binding = SyntheticValDef(param.name, arg)
69+
bindings += binding
70+
binding.symbol
71+
72+
if argSyms.forall(_.exists) && argSyms.hasSameLengthAs(vparams) then // TODO assert rather than fail silently
73+
seq(
74+
bindings.result(),
75+
TreeTypeMap(
76+
oldOwners = ddef.symbol :: Nil,
77+
newOwners = ctx.owner :: Nil,
78+
substFrom = vparams.map(_.symbol),
79+
substTo = argSyms
80+
).transform(ddef.rhs)
81+
)
82+
else
83+
tree

compiler/src/dotty/tools/dotc/transform/InlinePatterns.scala

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class InlinePatterns extends MiniPhase:
3131

3232
def phaseName: String = "inlinePatterns"
3333

34+
// This phase needs to run after because it need to transform trees that are generated
35+
// by the pattern matcher but are still not visible in that group of phases.
3436
override def runsAfterGroupsOf: Set[String] = Set(PatternMatcher.name)
3537

3638
override def transformApply(app: Apply)(using ctx: Context): Tree =
@@ -52,29 +54,8 @@ class InlinePatterns extends MiniPhase:
5254

5355
private def betaReduce(tree: Apply, fn: Tree, name: Name, args: List[Tree])(using ctx: Context): Tree =
5456
fn match
55-
case Block(Nil, expr) => betaReduce(tree, expr, name, args)
5657
case Block(TypeDef(_, template: Template) :: Nil, Apply(Select(New(_),_), Nil)) if template.constr.rhs.isEmpty =>
5758
template.body match
58-
case List(ddef @ DefDef(`name`, _, _, _, _)) =>
59-
val bindings = List.newBuilder[ValDef]
60-
val vparams = ddef.vparamss.flatten
61-
val argSyms =
62-
for (arg, param) <- args.zip(vparams) yield
63-
arg.tpe.dealias match
64-
case ref @ TermRef(NoPrefix, _) if isPurePath(arg) =>
65-
ref.symbol
66-
case _ =>
67-
val binding = SyntheticValDef(param.name, arg)
68-
bindings += binding
69-
binding.symbol
70-
seq(
71-
bindings.result(),
72-
TreeTypeMap(
73-
oldOwners = ddef.symbol :: Nil,
74-
newOwners = ctx.owner :: Nil,
75-
substFrom = vparams.map(_.symbol),
76-
substTo = argSyms).transform(ddef.rhs)
77-
)
78-
59+
case List(ddef @ DefDef(`name`, _, _, _, _)) => BetaReduce(tree)(ddef, args, false)
7960
case _ => tree
8061
case _ => tree

0 commit comments

Comments
 (0)