|
2 | 2 |
|
3 | 3 | import org.apache.commons.lang3.NotImplementedException; |
4 | 4 | import org.apache.commons.lang3.function.TriFunction; |
| 5 | +import org.apache.commons.lang3.mutable.MutableObject; |
5 | 6 | import scala.Tuple2; |
6 | 7 |
|
7 | 8 | import java.util.ArrayList; |
@@ -279,14 +280,14 @@ public void updateAssertionContents(Function<RewriterStatement, RewriterStatemen |
279 | 280 | // TODO: What about backRef? |
280 | 281 | } |
281 | 282 |
|
282 | | - public Stream<RewriterStatement> streamOfContents() { |
| 283 | + public Stream<Tuple2<RewriterStatement, RewriterStatement.RewriterPredecessor>> streamOfContents() { |
283 | 284 | return allAssertions.stream().flatMap(assertion -> { |
284 | 285 | if (assertion.stmt != null) { |
285 | 286 | if (assertion.backRef != null) |
286 | | - return Stream.of(assertion.stmt, assertion.backRef); |
287 | | - return Stream.of(assertion.stmt); |
| 287 | + return Stream.of(new Tuple2<>(assertion.stmt, new RewriterStatement.RewriterPredecessor(this, assertion)), new Tuple2<>(assertion.backRef, new RewriterStatement.RewriterPredecessor(this, assertion))); |
| 288 | + return Stream.of(new Tuple2<>(assertion.stmt, new RewriterStatement.RewriterPredecessor(this, assertion))); |
288 | 289 | } else { |
289 | | - return assertion.set.stream(); |
| 290 | + return assertion.set.stream().map(stmt -> new Tuple2<>(stmt, new RewriterStatement.RewriterPredecessor(this, assertion))); |
290 | 291 | } |
291 | 292 | }); |
292 | 293 | } |
@@ -585,6 +586,72 @@ else if (root.getMeta("_assertions") != null) |
585 | 586 | return eClass; |
586 | 587 | } |
587 | 588 |
|
| 589 | + // This removes E-Classes that are not actually E-Classes like _EClass(argList(nrow(A), nrow(A))), or _EClass(argList(nrow(A), _backRef.INT())) |
| 590 | + public RewriterStatement cleanupEClasses(RewriterStatement expressionRoot) { |
| 591 | + Set<RewriterAssertion> toRemoveList = new HashSet<>(); |
| 592 | + Map<RewriterStatement, RewriterStatement> toRemove = new HashMap<>(); |
| 593 | + |
| 594 | + for (RewriterAssertion assertion : allAssertions) { |
| 595 | + int previousSize = assertion.set.size(); |
| 596 | + if (assertion.stmt != null) { |
| 597 | + // Eliminate top-level back-refs |
| 598 | + assertion.set.removeIf(el -> el.isInstruction() && el.trueInstruction().startsWith("_backRef") && el.getMeta("_backRef").equals(assertion.stmt)); |
| 599 | + } |
| 600 | + |
| 601 | + if (assertion.set.size() < 2) { |
| 602 | + toRemoveList.add(assertion); |
| 603 | + |
| 604 | + if (assertion.stmt != null) |
| 605 | + toRemove.put(assertion.stmt, assertion.set.stream().findFirst().get()); |
| 606 | + } |
| 607 | + |
| 608 | + if (previousSize != assertion.set.size() && assertion.stmt != null) { |
| 609 | + // Then we need to update the EClass |
| 610 | + assertion.stmt.getChild(0).getOperands().removeIf(el -> !assertion.set.contains(el)); |
| 611 | + |
| 612 | + if (assertion.stmt.getChild(0).getOperands().size() != assertion.set.size()) { |
| 613 | + // Then there are still duplicates which we need to rule out |
| 614 | + Set<RewriterStatement> visited = new HashSet<>(); |
| 615 | + List<RewriterStatement> eItems = assertion.stmt.getChild(0).getOperands(); |
| 616 | + for (int i = 0; i < eItems.size(); i++) { |
| 617 | + if (!visited.add(eItems.get(i))) |
| 618 | + eItems.remove(i--); |
| 619 | + } |
| 620 | + } |
| 621 | + } |
| 622 | + } |
| 623 | + |
| 624 | + if (!toRemoveList.isEmpty()) { |
| 625 | + allAssertions.removeAll(toRemoveList); |
| 626 | + |
| 627 | + if (!toRemove.isEmpty()) { |
| 628 | + if (expressionRoot.isEClass()) { |
| 629 | + RewriterStatement mNew = toRemove.get(expressionRoot); |
| 630 | + |
| 631 | + if (mNew != null) |
| 632 | + expressionRoot = mNew; |
| 633 | + } |
| 634 | + |
| 635 | + expressionRoot.forEachPostOrder((cur, pred) -> { |
| 636 | + cur.allChildren().forEach(t -> { |
| 637 | + if (t._1.isEClass()) { |
| 638 | + RewriterStatement mNew = toRemove.get(t._1); |
| 639 | + if (mNew != null) { |
| 640 | + if (t._2.isOperand()) { |
| 641 | + cur.getOperands().set(t._2.getIndex(), mNew); |
| 642 | + } else if (t._2.isMetaObject()) { |
| 643 | + cur.unsafePutMeta(t._2.getMetaKey(), mNew); |
| 644 | + } |
| 645 | + } |
| 646 | + } |
| 647 | + }); |
| 648 | + }, true); |
| 649 | + } |
| 650 | + } |
| 651 | + |
| 652 | + return expressionRoot; |
| 653 | + } |
| 654 | + |
588 | 655 | private void updateRecursively(RewriterStatement cur) { |
589 | 656 | for (int i = 0; i < cur.getOperands().size(); i++) { |
590 | 657 | RewriterStatement child = cur.getChild(i); |
|
0 commit comments