public ASTNode substituteCommonTerms(ASTNode tree, IExpressionContext context) { ASTNode copy = tree.createCopy(true); final Map<Integer, List<ASTNode>> result = new HashMap<>(); final INodeVisitor visitor = new INodeVisitor() { @Override public boolean visit(ASTNode node, int currentDepth) { final Integer hash = node.hashCode(); List<ASTNode> existing = result.get(hash); if (existing == null) { existing = new ArrayList<>(); result.put(hash, existing); } existing.add(node); return true; } }; tree.visitInOrder(visitor); outer: for (Map.Entry<Integer, List<ASTNode>> entry : result.entrySet()) { final int hash = entry.getKey(); if (entry.getValue().size() <= 1) { continue; } for (ASTNode n : entry.getValue()) { if (n instanceof IdentifierNode) { continue outer; } } // create new variable final ASTNode value = entry.getValue().get(0).createCopy(true); final Identifier identifier = context.createIdentifier(value); final boolean substituted = replaceMatchingTermsWithVariable(context, copy, hash, identifier); if (substituted) { debugPrintln( "SUBSTITUTE: " + value + " => " + identifier + " ( " + entry.getValue().size() + " times )"); } else { context.remove(identifier); } } return copy; }
public ASTNode expand(ASTNode term, IExpressionContext context, boolean deleteExpandedVars) { final ASTNode result = term.createCopy(true); final Set<Identifier> expandedIdentifiers = new HashSet<>(); boolean expanded = false; do { expanded = false; final MutatingNodeVisitor visitor = new MutatingNodeVisitor(context) { @Override public void visit(ASTNode node, IExpressionContext context, IIterationContext it) { final ASTNode unwrapped = unwrap(node); if (node.hasParent() && unwrapped instanceof IdentifierNode) { final ASTNode expanded = unwrapped.evaluate(context); if (expanded != null && expanded != unwrapped) { debugPrintln("EXPAND: Expanding " + node + " -> " + expanded); expandedIdentifiers.add(((IdentifierNode) unwrapped).getIdentifier()); node.replaceWith(expanded); it.astMutated(); } } } }; expanded = applyPostOrder(result, visitor); } while (expanded); if (deleteExpandedVars) { for (Identifier id : expandedIdentifiers) { context.remove(id); } } return result; }