Skip to content
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

Migrate some passes to Mini passes #11191

Merged
merged 90 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
c9ef2c3
Implement skeleton of mini pass framework
Akirathan Sep 26, 2024
43eafae
Rename MiniPassManager to MiniPassChainer
Akirathan Sep 26, 2024
4a0fd85
Implement default IR.withNewChildren
Akirathan Sep 26, 2024
1bbf991
Add MiniPassTester and MiniPassTraverser
Akirathan Sep 26, 2024
70f0a1a
Add tests for OperatorToFunction mini pass
Akirathan Sep 26, 2024
808dbd8
Add necessary withNewChildren implementations
Akirathan Sep 26, 2024
1abc70d
Add necessary withNewChildren implementations
Akirathan Sep 26, 2024
cdf1d87
MiniIRPass has metadata type argument
Akirathan Sep 27, 2024
d7b6016
Add mini pass version of LambdaShorthandToLambda
Akirathan Sep 27, 2024
1bd2b40
Add tests of mini pass version of LambdaShorthandToLambda
Akirathan Sep 27, 2024
61fed92
Implement Prefix.withNewChildren
Akirathan Sep 27, 2024
40252a2
Add IRTest to test children and withNewChildren API
Akirathan Sep 30, 2024
76dbc23
Update default IR.withNewChildren
Akirathan Sep 30, 2024
4a66460
Copy of children of DefinitionArgument.Specified is handled specifica…
Akirathan Sep 30, 2024
be2724d
Add necessary withNewChildren implementations
Akirathan Sep 30, 2024
fd3a727
LambdaToShorthandMini ignores blank fn
Akirathan Sep 30, 2024
8a5c435
Tests that have different internal naming are handled in different te…
Akirathan Sep 30, 2024
995dea5
DefinitionArgument.Specified implements withNewChildren
Akirathan Oct 1, 2024
985b8c2
Change prepare API
Akirathan Oct 1, 2024
28edccb
MiniIRPass is not parametrized based on metadata type
Akirathan Oct 1, 2024
6121750
Dummy implementation of minipass chaining
Akirathan Oct 1, 2024
54e5bd0
Add test for BinaryOperator.newChildren
Akirathan Oct 1, 2024
6b4c6b3
IR.withNewChildren must be called with the same length as children
Akirathan Oct 1, 2024
01561a1
MiniIRPass.prepare has parent parameter
Akirathan Oct 1, 2024
dd42554
Remove parent parameter from MiniIRPass.prepare
Akirathan Oct 2, 2024
f85f017
Remove MiniIRPass.runsAfter - it will not be necessary for this PR
Akirathan Oct 2, 2024
a4aaf8e
Add docs to MiniIRPass
Akirathan Oct 2, 2024
836c4c2
Add skeleton of TailCallMini pass
Akirathan Oct 2, 2024
079543a
runtime-compiler depends on org.graalvm.sdk:collections
Akirathan Oct 2, 2024
5d19be4
Implement withNewChildren on Expression via mapExpressions
Akirathan Oct 2, 2024
a369ed8
Fix MatchError in TailCallMini
Akirathan Oct 3, 2024
487003f
Revert "Implement withNewChildren on Expression via mapExpressions"
Akirathan Oct 4, 2024
b2f7053
Revert "runtime-compiler depends on org.graalvm.sdk:collections"
Akirathan Oct 4, 2024
edec03b
Replace org.graalvm.collections.EconomicSet with java.util.IdentityHa…
Akirathan Oct 4, 2024
67ff454
Revert tests that depend on InlineContext config
Akirathan Oct 4, 2024
547e9e6
Add more tests that test consistency with old pass version
Akirathan Oct 4, 2024
925a2de
Add logging to MiniPassTraverser
Akirathan Oct 4, 2024
dc6e7f3
Implement more withNewChildren methods
Akirathan Oct 4, 2024
c56c2be
Add another tail call mini pass test
Akirathan Oct 4, 2024
ea1462a
TailCallMini respect initial isInTailPosition flag
Akirathan Oct 4, 2024
18f4cea
Implement TailCallMini.toString
Akirathan Oct 4, 2024
e2fc538
Using IR.mapExpressions in MiniPassTraverser
JaroslavTulach Oct 8, 2024
a58ecc8
Detect and use MiniPassFactory in PassFactory
JaroslavTulach Oct 8, 2024
1aaa589
Move OperatorToFunction mega pass to test
Akirathan Oct 9, 2024
8604acb
Move LambdaShorthandToLambda mega pass to test
Akirathan Oct 9, 2024
0ddb96b
Use pattern match instead of isInstanceOf check in PassManager
Akirathan Oct 9, 2024
a85679d
Move TailCall mega pass to test
Akirathan Oct 9, 2024
80c4545
Implement MiniPass trait for testing mini and mega passes
Akirathan Oct 9, 2024
9a5dfea
TailCallMegaPass uses metadata from TailCall, not this
Akirathan Oct 9, 2024
d5c6983
Change API of MiniIRPass to accept only Expression
Akirathan Oct 10, 2024
89cde89
OperatorToFunctionMini checks post condition
Akirathan Oct 10, 2024
7c9f370
Add failing test to OperatorToFunctionTest
Akirathan Oct 10, 2024
92ae4fe
Implement IRDumper.dumpWithSvg
Akirathan Oct 10, 2024
65560c4
Ensure MiniPassTraverser returns transformed Module
Akirathan Oct 10, 2024
dfc54db
IRDumper handles SugaredType
Akirathan Oct 10, 2024
8771d58
MiniPassTraverser logs IRs with hash code.
Akirathan Oct 10, 2024
bdff605
Refactor TailCallMini to the new API
Akirathan Oct 10, 2024
ce56abb
typo
Akirathan Oct 10, 2024
d42d3e9
Must preprocess the module even for miniPass
JaroslavTulach Oct 11, 2024
ba7ab9d
Using analyseModuleBinding from TailCallMegaPass
JaroslavTulach Oct 11, 2024
90139e7
Allow for comparing mega and mini IR trees
JaroslavTulach Oct 11, 2024
8558d5b
Merging with develop. 47 failing tests. Mostly because of advanturous…
JaroslavTulach Oct 12, 2024
05fd38a
Making the TailCall pass closer to original mega pass code
JaroslavTulach Oct 12, 2024
367fc9a
Properly annotate withClue sections
JaroslavTulach Oct 12, 2024
36ebf2b
Associate TailCall pass metadata
JaroslavTulach Oct 12, 2024
0a02563
Rewrite using tailCandidates
JaroslavTulach Oct 12, 2024
83f4a57
Removal of notTailMeta
JaroslavTulach Oct 12, 2024
69b3274
Execute megaPass.runExpression at the end of the test
JaroslavTulach Oct 12, 2024
dea6dd6
One TailCallTest failure down to six
JaroslavTulach Oct 12, 2024
6c2b51d
Down to five failing tests in TailCallTest
JaroslavTulach Oct 12, 2024
f27ce6f
Down to three failures
JaroslavTulach Oct 12, 2024
f4077de
Reordering the test and down to two failures
JaroslavTulach Oct 12, 2024
1b021c2
Making all TailCallTest pass on mega as well as mini pass
JaroslavTulach Oct 12, 2024
8ce42e0
No need for TailCallMini
JaroslavTulach Oct 12, 2024
64b013f
Cleaning dead code up
JaroslavTulach Oct 13, 2024
f54ba6d
SectionsToBinOp is mini IR pass
JaroslavTulach Oct 13, 2024
40ef345
Introducing MiniIRPass.combine
JaroslavTulach Oct 13, 2024
8124e1e
Hiding traversal behind MiniIRPass.compile
JaroslavTulach Oct 13, 2024
668fdfd
Not including IRDumper changes in this PR
JaroslavTulach Oct 13, 2024
2af068f
No need for MetadataStorage.size
JaroslavTulach Oct 13, 2024
95b1756
Properly clone ChainedMiniPass when first or second delegates changes
JaroslavTulach Oct 14, 2024
c84e881
Removing duplicated test - mini pass testing is already inside of ass…
JaroslavTulach Oct 14, 2024
0964711
Rewriting MiniIRPass processing to queue - much easier for profiling …
JaroslavTulach Oct 14, 2024
ffd27df
MiniIRPass.prepare(parent, child)
JaroslavTulach Oct 14, 2024
924e404
Keep all IRs in local variables for easier debugging
JaroslavTulach Oct 14, 2024
2736a76
Combining subsequent mini passes
JaroslavTulach Oct 15, 2024
762045a
Both MiniPassFactory and IRPass are on par by extending IRProcessingPass
JaroslavTulach Oct 15, 2024
ef3450c
Only update IR metadata in transform methods
JaroslavTulach Oct 15, 2024
248c0f4
Removing dead code
JaroslavTulach Oct 15, 2024
befef0c
TailCall rewritten to Java
JaroslavTulach Oct 15, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.enso.compiler.pass;

import java.util.Set;
import org.enso.compiler.core.IR;
import org.enso.compiler.core.ir.ProcessingPass;

/**
* Mini IR pass operates on a single IR element at a time. The {@link org.enso.compiler.Compiler}
* traverses the whole IR tree bottom-up from leaves to the root. For each IR element:
*
* <ol>
* <li>The {@link #prepare(IR)} method is called to prepare the pass for the current IR element.
* This method is called when the {@link org.enso.compiler.Compiler} traverses the element
* from top to bottom. This is useful for mini passes that need to build some information
* about the current IR element before transforming it.
* <li>The {@link #transformIr(IR)} method is called to transform the current IR element. This
* method is called when the {@link org.enso.compiler.Compiler} traverses the element from
* bottom to top. All the children of the current IR element are already transformed when this
* method is called.
* </ol>
*
* <p>Inspired by: <a href="https://dl.acm.org/doi/10.1145/3140587.3062346">Miniphases: compilation
* using modular and efficient tree transformations</a>. PDF available at <a
* href="https://infoscience.epfl.ch/server/api/core/bitstreams/8ab72c0a-8aa6-4dee-a704-3504938dc316/content">infoscience.epfl.ch</a>
*/
public abstract class MiniIRPass<T extends IRPass.IRMetadata> implements ProcessingPass {

/** Set of mini passes that should run before this mini pass. */
public Set<MiniIRPass> runsAfter() {
return Set.of();
}

/**
* Prepare the pass for the provided IR element. This method is called when the {@link
* org.enso.compiler.Compiler} traverses the IR element from top to bottom.
*
* @param ir IR element to be prepared for transformation.
*/
public void prepare(IR ir) {
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
// nop
}

/**
* Transform the provided IR element. Children of the IR element are already transformed when this
* method is called. This method is called when the {@link org.enso.compiler.Compiler} traverses
* the IR element from bottom to top.
*
* <p>The pass should not do any traversal in this method.
*
* @param ir IR element to be transformed by this pass.
* @return The transformed IR, or the same IR if no transformation is needed. Must not return
* null.
*/
public abstract IR transformIr(IR ir);

public boolean checkPostCondition(IR ir) {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.enso.compiler.pass;

import java.util.List;
import org.enso.compiler.core.IR;

/** Utility class for chaining mini passes together. */
public final class MiniPassChainer {
private MiniPassChainer() {}

/**
* Chains a list of mini passes into a single pass that applies them in order.
*
* @param passes Ordered list of mini passes.
* @return Chained mini pass that applies all the provided mini passes in the given order.
*/
public static MiniIRPass chain(List<MiniIRPass> passes) {
return new MiniIRPass() {
@Override
public void prepare(IR ir) {
for (var miniPass : passes) {
miniPass.prepare(ir);
}
}

@Override
public IR transformIr(IR ir) {
IR transformedIr = ir;
for (var miniPass : passes) {
transformedIr = miniPass.transformIr(transformedIr);
}
return transformedIr;
}

@Override
public boolean checkPostCondition(IR ir) {
return passes.stream().allMatch(pass -> pass.checkPostCondition(ir));
}
};
}

public static MiniIRPass chain(MiniIRPass firstPass, MiniIRPass secondPass) {
return new MiniIRPass() {
@Override
public void prepare(IR ir) {
firstPass.prepare(ir);
secondPass.prepare(ir);
}

@Override
public IR transformIr(IR ir) {
IR firstResult = firstPass.transformIr(ir);
return secondPass.transformIr(firstResult);
}

@Override
public boolean checkPostCondition(IR ir) {
return firstPass.checkPostCondition(ir) && secondPass.checkPostCondition(ir);
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.enso.compiler.pass;

import org.enso.compiler.context.InlineContext;
import org.enso.compiler.context.ModuleContext;

/**
* A collection of factory methods for {@link MiniIRPass IR mini passes}. If a mini pass supports
* only inline compilation, its {@link #createForModuleCompilation(ModuleContext)} method should
* return null.
*/
public interface MiniPassFactory<T extends MiniIRPass> {
/**
* Creates an instance of mini pass that is capable of transforming IR elements in the context of
* a module.
*
* @param moduleContext A mini pass can optionally save reference to this module context.
* @return May return null if module compilation is not supported.
*/
T createForModuleCompilation(ModuleContext moduleContext);
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved

/**
* Creates an instance of mini pass that is capable of transforming IR elements in the context of
* an inline compilation.
*
* @param inlineContext A mini pass can optionally save reference to this inline context.
* @return Must not return null. Inline compilation should always be supported.
*/
T createForInlineCompilation(InlineContext inlineContext);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package org.enso.compiler.pass;

import org.enso.compiler.context.ModuleContext;
import org.enso.compiler.core.CompilerError;
import org.enso.compiler.core.IR;
import org.enso.compiler.core.ir.DefinitionArgument;
import org.enso.compiler.core.ir.Expression;
import org.enso.compiler.core.ir.Module;
import org.enso.compiler.core.ir.Name;
import scala.Option;

public final class MiniPassTraverser {
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
private MiniPassTraverser() {}

/**
* Compiles the whole module with chained {@link MiniIRPass}.
*
* @param miniPass Mini pass that must support module compilation, i.e., should be created with
* {@link MiniPassFactory#createForModuleCompilation(ModuleContext)}.
* @return Transformed module IR.
*/
public static Module compileModuleWithMiniPass(Module moduleIr, MiniIRPass miniPass) {
var newModuleIr = compileRecursively(moduleIr, miniPass);
return (Module) newModuleIr;
}

public static Expression compileInlineWithMiniPass(Expression exprIr, MiniIRPass miniPass) {
miniPass.prepare(exprIr);
var newIr = compileRecursively(exprIr, miniPass);
if (!miniPass.checkPostCondition(newIr)) {
throw new CompilerError("Post condition failed after applying mini pass " + miniPass);
}
return (Expression) newIr;
}

private static IR compileRecursively(IR ir, MiniIRPass miniPass) {
miniPass.prepare(ir);
IR newIr;
if (ir.children().isEmpty()) {
newIr = ir;
} else {
var transformedChildren =
ir.children()
.map(
Copy link
Member

@JaroslavTulach JaroslavTulach Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was looking at ForkJoinPool. They claim the best way to split the work is

As a very rough rule of thumb, a task should perform more than 100 and less than 10000 basic computational steps, and should avoid indefinite looping"

Maybe we should really be traversing only ir.Expression. Maybe the other elements like CallArgument are too small to be processed by own tasks.

Suggested change
.map(
filter(r -> r instanceof Expression).map(

If we traversed only ir.Expression, then the problem of withNewChildren not being 1:1 with mapExpressions (as pointed out here) would be solved ;-)

Even better way to be 1:1

This is 100% guaranteed to be 1:1 with mapExpressions implementations:

var collect = new ArrayList();
ir.mapExpressions(ir -> {
  collect.add(ir);
  return ir;
});
var transformedChildren = collect.stream().filter(....)

Using ir.mapExpressions is necessary to get thru CallArgument.Specified in Application.

By using mapExpressions to collect the children to process and also to replace the children with new ones, we reuse existing infrastructure. Moreover we get better mapping of current IRPass implementations (that use mapExpressions to traverse) to their new mini passes reimplementation.

Benefit

The only hack needed is a special handling for withNewChildren for DefinitionArgument.Specified

We don't need these decomposition methods that disassemble List<IR> pieces trying to find constructor to call.

Copy link
Member

@JaroslavTulach JaroslavTulach Oct 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really believe we can achieve our performance/memory goals with IR.mapExpression. Here is a tag jtulach/MiniPassTraverserWithMapChildren that demonstrates it. I'll put the commit e2fc538 into this branch as well - but feel free to remove it, if we decide we desperately need withNewChildren for some pass.

Tests seem to work. Prior to my commit there were some failures in org.enso.compiler.test.pass.analyse.TailCallTest - after my commit there are also only failures in TailCallTest. Thus I assume all the other mini passes are working fine with the mapExpressions approach.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am struggling with implementing TailCall mini pass with this pattern. TailCall is a pass that traverses the whole IR tree and attaches to every node either TAIL or NOT_TAIL.

Following is a picture of IR tree with numbered prepare and transform steps of MiniIRPassTraverser (implemented with mapExpressions as contributed by @JaroslavTulach on revision ce56abb):

tmp dot

As you can see, the MiniIRPassTraverser basically ignores the whole bindings[1] and bindings[2] subtrees, because they are not Expressions. How am I supposed to transform those? Should I manually recursively traverse all the children of Expression and look for IR elements that are not Expressions and do my transformation of those? If yes, then this is would not be a mini pass at all, it would be a weird monstrosity somewhere between a mega pass and mini pass. I am not even mentioning how ugly (difficult to maintain) and non-intuitive it is to work with this.

In my opinion, this is a proof that the solution with traversing only Expressions with mapExpressions is not sustainable, and we should not continue in this direction.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last Friday we agreed to disagree. This PR is going to work with mapExpressions and the fact it is green is a proof it can work that way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the other hand, while implementing the TailCall pass, I came to an agreement that the prepare method shall get an edge in the IR tree - e.g. its signature should be MiniIRPass prepare(IR parent, IR child). Traversing by edges is however orthogonal to using mapExpressions or withNewChildren question.

Copy link
Contributor

@hubertp hubertp Oct 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't TailCall pass now simplified (d9b3c75) and therefore not a representative case for this problem? Meaning we will likely encounter it in other passes? Note: unlike both of you, I haven't attempted the transformation into mini passes myself so I have an incomplete picture, clearly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't TailCall pass now simplified (d9b3c75)

No, that change has no effect on the traversal. TailCall is as representative as it was and is the main reason why I see that edge traversal as advocated by Pavel is more meaningful than vertex traversal.

likely encounter it in other passes?

It remains to be seen what we will encounter in other passes. However I'd like to highlight following quote: "by using mapExpressions ... we get better mapping of current IRPass implementations" that are already using mapExpressions to traverse!

child -> {
var newChild = compileRecursively(child, miniPass);
if (newChild == null) {
throw new IllegalStateException("Mini pass returned null");
}
if (!miniPass.checkPostCondition(newChild)) {
throw new CompilerError(
"Post condition failed after applying mini pass " + miniPass);
}
return newChild;
});
newIr = copyWithNewChildren(ir, transformedChildren);
}
var transformedIr = miniPass.transformIr(newIr);
if (!miniPass.checkPostCondition(transformedIr)) {
throw new CompilerError("Post condition failed after applying mini pass " + miniPass);
}
return transformedIr;
}

/**
* Special copy handling of IR elements where the type and the order of children is ambiguous. For
* example {@link DefinitionArgument.Specified}.
*
* @param ir Parent IR.
* @param newChildren List of transformed children.
* @return Copy of the parent IR with new children.
*/
private static IR copyWithNewChildren(IR ir, scala.collection.immutable.List<IR> newChildren) {
return switch (ir) {
case DefinitionArgument.Specified defArg -> {
if (newChildren.isEmpty()) {
throw new IllegalArgumentException("Definition argument must have at least one child");
} else if (newChildren.size() == 1) {
var newName = (Name) newChildren.apply(0);
yield defArg.copy(
newName,
defArg.ascribedType(),
defArg.defaultValue(),
defArg.suspended(),
defArg.location(),
defArg.passData(),
defArg.diagnostics(),
defArg.id());
} else if (newChildren.size() == 2) {
var newName = (Name) newChildren.apply(0);
var newAscribedTypeOrDefaultVal = (Expression) newChildren.apply(1);
if (defArg.ascribedType().isDefined()) {
yield defArg.copy(
newName,
Option.apply(newAscribedTypeOrDefaultVal),
defArg.defaultValue(),
defArg.suspended(),
defArg.location(),
defArg.passData(),
defArg.diagnostics(),
defArg.id());
} else if (defArg.defaultValue().isDefined()) {
yield defArg.copy(
newName,
defArg.ascribedType(),
Option.apply(newAscribedTypeOrDefaultVal),
defArg.suspended(),
defArg.location(),
defArg.passData(),
defArg.diagnostics(),
defArg.id());
} else {
throw new IllegalArgumentException(
"Definition argument must have at most two children");
}
} else if (newChildren.size() == 3) {
var newName = (Name) newChildren.apply(0);
var newAscribedType = (Expression) newChildren.apply(1);
var newDefaultValue = (Expression) newChildren.apply(2);
yield defArg.copy(
newName,
Option.apply(newAscribedType),
Option.apply(newDefaultValue),
defArg.suspended(),
defArg.location(),
defArg.passData(),
defArg.diagnostics(),
defArg.id());
} else {
throw new IllegalArgumentException(
"Definition argument must have at most three children");
}
}
default -> ir.withNewChildren(newChildren);
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.enso.compiler.pass.desugar;

import org.enso.compiler.core.IR;
import org.enso.compiler.core.ir.CallArgument;
import org.enso.compiler.core.ir.expression.Application;
import org.enso.compiler.core.ir.expression.Operator;
import org.enso.compiler.pass.MiniIRPass;
import scala.collection.mutable.ListBuffer;

public class OperatorToFunctionMini extends MiniIRPass {
OperatorToFunctionMini() {}

@Override
public IR transformIr(IR ir) {
if (ir instanceof Operator.Binary binOp) {
ListBuffer<CallArgument> args = new ListBuffer<>();
args.addOne(binOp.left());
args.addOne(binOp.right());
return new Application.Prefix(
binOp.operator(),
args.toList(),
false,
binOp.location(),
binOp.passData(),
binOp.diagnostics());
}
return ir;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import org.enso.compiler.core.ir.{
}
import org.enso.compiler.core.CompilerError
import org.enso.compiler.core.ir.expression.{Application, Case, Operator}
import org.enso.compiler.pass.IRPass
import org.enso.compiler.pass.{IRPass, MiniPassFactory}
import org.enso.compiler.pass.analyse.{
AliasAnalysis,
DataflowAnalysis,
Expand All @@ -35,7 +35,9 @@ import org.enso.compiler.pass.resolve.{
*
* - A [[FreshNameSupply]]
*/
case object LambdaShorthandToLambda extends IRPass {
case object LambdaShorthandToLambda
extends IRPass
with MiniPassFactory[LambdaShorthandToLambdaMini] {
override type Metadata = IRPass.Metadata.Empty
override type Config = IRPass.Configuration.Default

Expand Down Expand Up @@ -434,4 +436,28 @@ case object LambdaShorthandToLambda extends IRPass {
)
}
}

override def createForModuleCompilation(
moduleContext: ModuleContext
): LambdaShorthandToLambdaMini = {
val freshNameSupply = moduleContext.freshNameSupply.getOrElse(
throw new CompilerError(
"Desugaring underscore arguments to lambdas requires a fresh name " +
"supply."
)
)
new LambdaShorthandToLambdaMini(freshNameSupply)
}

override def createForInlineCompilation(
inlineContext: InlineContext
): LambdaShorthandToLambdaMini = {
val freshNameSupply = inlineContext.freshNameSupply.getOrElse(
throw new CompilerError(
"Desugaring underscore arguments to lambdas requires a fresh name " +
"supply."
)
)
new LambdaShorthandToLambdaMini(freshNameSupply)
}
}
Loading
Loading