From 24638b7ec9a2412611f5265e4b5c589369f86ddd Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Mon, 27 Jan 2025 18:33:39 +0100 Subject: [PATCH] NestedPatternMatchTest uses IRComparator --- .../compiler/test/ircompare/IRComparator.java | 44 ++++++++-- .../pass/desugar/NestedPatternMatchTest.scala | 88 ++++++++++++++++++- 2 files changed, 125 insertions(+), 7 deletions(-) diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/compiler/test/ircompare/IRComparator.java b/engine/runtime-integration-tests/src/test/java/org/enso/compiler/test/ircompare/IRComparator.java index 1b79e82c7eb9..18fe6e6bec17 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/compiler/test/ircompare/IRComparator.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/compiler/test/ircompare/IRComparator.java @@ -5,13 +5,18 @@ import java.util.List; import java.util.Objects; import org.enso.compiler.core.IR; +import org.enso.compiler.core.ir.Empty; +import org.enso.compiler.core.ir.Expression; import org.enso.compiler.core.ir.Name; import org.enso.test.utils.IRDumperTestWrapper; +import scala.jdk.javaapi.CollectionConverters; public final class IRComparator { private final String name; private final boolean compareMeta; private final IRDumperTestWrapper dumper = new IRDumperTestWrapper(); + private IR expectedRoot; + private IR actualRoot; private IRComparator(String name, boolean compareMeta) { this.name = name; @@ -24,8 +29,8 @@ public static Builder builder() { /** * Compares IRs and dumps the diff the {@code actualIR} IR does not match the {@code expectedIR} - * one. IRs are compared recursively. {@code expectedIR} IR can have {@link SkipIR} nodes. When - * the {@link IRComparator} encounters {@link SkipIR} node in the {@code expectedIR} IR, the + * one. IRs are compared recursively. {@code expectedIR} IR can have {@link org.enso.compiler.core.ir.Empty} nodes. When + * the {@link IRComparator} encounters {@link org.enso.compiler.core.ir.Empty} node in the {@code expectedIR} IR, the * corresponding subtree in the {@code actualIR} IR is skipped. * *

Traverses the IRs in the BFS order. @@ -37,13 +42,15 @@ public static Builder builder() { * @param actualIR */ public void compare(IR expectedIR, IR actualIR) throws IRComparisonFailure { + expectedRoot = expectedIR; + actualRoot = actualIR; var nodesToProcess = new ArrayDeque(); nodesToProcess.add(new NodePair(expectedIR, actualIR)); while (!nodesToProcess.isEmpty()) { var nodePairToProcess = nodesToProcess.poll(); var expected = nodePairToProcess.expected; var actual = nodePairToProcess.actual; - if (expected instanceof SkipIR) { + if (expected instanceof Empty) { continue; } compareTwoNodes(expected, actual); @@ -106,12 +113,39 @@ private static List zipChildren(IR expected, IR actual) { } private IRComparisonFailure fail(String msg, IR expected, IR actual) { - dumper.dump(expected, name, "expected"); - dumper.dump(actual, name, "actual"); + dumper.dump(expectedRoot, name, "expected"); + dumper.dump(actualRoot, name, "actual"); System.err.println("Dumped expected and actual IRs to IGV with name " + name); return new IRComparisonFailure(msg, expected, actual); } + private IR copyRootWithSwap(IR root, Expression node, Expression replacement) { + var duplRoot = root.duplicate(false, false, false, false); + var nodesToProcess = new ArrayDeque(); + nodesToProcess.add(duplRoot); + while (!nodesToProcess.isEmpty()) { + var nodeToProcess = nodesToProcess.poll(); + if (nodeToProcess == node) { + + } + } + } + + private IR replaceChild(IR node, int childIdx, IR replacement) { + var children = node.children(); + var newChildren = new ArrayList(); + for (var i = 0; i < children.size(); i++) { + if (childIdx == i) { + newChildren.add(replacement); + } else { + newChildren.add(children.apply(i)); + } + } + // Replace via reflection + var newChildrenList = CollectionConverters.asScala(newChildren).toList(); + throw new UnsupportedOperationException("unimplemented"); + } + private record NodePair(IR expected, IR actual) {} public static final class Builder { diff --git a/engine/runtime-integration-tests/src/test/scala/org/enso/compiler/test/pass/desugar/NestedPatternMatchTest.scala b/engine/runtime-integration-tests/src/test/scala/org/enso/compiler/test/pass/desugar/NestedPatternMatchTest.scala index 8afc10b451eb..36670afabf03 100644 --- a/engine/runtime-integration-tests/src/test/scala/org/enso/compiler/test/pass/desugar/NestedPatternMatchTest.scala +++ b/engine/runtime-integration-tests/src/test/scala/org/enso/compiler/test/pass/desugar/NestedPatternMatchTest.scala @@ -3,10 +3,11 @@ package org.enso.compiler.test.pass.desugar import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} import org.enso.compiler.core.ir.expression.Case -import org.enso.compiler.core.ir.{Expression, Literal, Module, Name, Pattern} +import org.enso.compiler.core.ir.{Empty, Expression, Literal, Module, Name, Pattern} import org.enso.compiler.pass.desugar.NestedPatternMatch import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} -import org.enso.compiler.test.CompilerTest +import org.enso.compiler.test.ircompare.{IRComparator} +import org.enso.compiler.test.{CompilerTest} class NestedPatternMatchTest extends CompilerTest { @@ -342,4 +343,87 @@ class NestedPatternMatchTest extends CompilerTest { consANilBranch2Expr.branches.head.terminalBranch shouldBe true } } + + "Simple nested pattern desugaring" should { + implicit val ctx: InlineContext = mkInlineContext + + // IGV graph: https://github.com/user-attachments/assets/b5387e61-e577-4b03-8a4a-ca05e27f2462 + "One nested pattern" in { + val ir = + """ + |case x of + | Cons (Nested a) -> num + |""".stripMargin.preprocessExpression.get + val processed = ir.desugar + + val expectedIR = Expression.Block( + expressions = List( + Expression.Binding( + name = lit(""), + expression = emptyIR(), + identifiedLocation = null + ) + ), + returnValue = Case.Expr( + scrutinee = lit(""), + branches = List( + Case.Branch( + pattern = Pattern.Constructor( + constructor = lit("Cons"), + fields = List( + Pattern.Name(lit(""), identifiedLocation = null) + ), + identifiedLocation = null + ), + expression = Expression.Block( + expressions = List( + Expression.Binding( + name = lit(""), + expression = emptyIR(), + identifiedLocation = null + ), + ), + returnValue = Case.Expr( + scrutinee = lit(""), + branches = List( + Case.Branch( + pattern = Pattern.Constructor( + constructor = lit("Nested"), + fields = List( + Pattern.Name(lit("a"), identifiedLocation = null) + ), + identifiedLocation = null + ), + expression = lit("num"), + terminalBranch = true, + identifiedLocation = null + ) + ), + isNested = true, + identifiedLocation = null + ), + identifiedLocation = null + ), + identifiedLocation = null, + terminalBranch = false + ), + ), + isNested = false, + identifiedLocation = null + ), + identifiedLocation = null + ) + + val comparator = IRComparator.builder().name("One nested pattern").build() + comparator.compare(expectedIR, processed) + } + } + + private def lit(name: String): Name.Literal = { + Name.Literal(name = name, isMethod = false, identifiedLocation = null) + } + + private def emptyIR(): Empty = { + new Empty(null) + } }