<commit_before>package natlab.toolkits.rewrite;

import java.util.*;
import java.lang.reflect.*;

import ast.*;
import natlab.toolkits.rewrite.simplification.*;
import natlab.toolkits.analysis.varorfun.*;

/**
 * Performs simplifications. Takes care of dependencies and any needed
 * book keeping.
 *
 * Dependencies are assumed to form a tree. Dependencies are built
 * from a start set and recorded in post order, avoiding repetition. 
 *
 * @author <NAME>
 */
public class Simplifier
{

    //List of simplifications. If applied in list order, then all
    //dependencies should be met.
    LinkedList<AbstractSimplification> simplifications;

    ASTNode tree;
    VFPreorderAnalysis kind;

    /**
     * Constructs a simplifier for a given set of simplification
     * classes. 
     */
    public Simplifier( ASTNode tree, Set<Class<? extends AbstractSimplification>> todo )
    {
        this( tree, todo, new VFPreorderAnalysis(tree) );
    }
    public Simplifier( ASTNode tree, 
                       Set<Class<? extends AbstractSimplification>> todo, 
                       VFPreorderAnalysis kindAna )
    {
        simplifications = new LinkedList();
        kind = kindAna;
        if( !kind.isAnalyzed() )
            kind.analyze();

        this.tree = tree;
        for( Class<? extends AbstractSimplification> simpClass : todo ){
            AbstractSimplification simpInst = constrSimp( simpClass );
            buildDependencies( simpInst, todo );
            simplifications.add( simpInst );
        }
    }

    /**
     * Runs the simplifications in a correct order.
     */
    public ASTNode simplify()
    {
        ASTNode currentTree = tree;
        for( AbstractSimplification simp : simplifications ){
            simp.setTree( currentTree );
            currentTree = simp.transform();
        }
        return currentTree;
    }

    /**
     * Builds the dependencies for a given simplification, puts them
     * in the list of simplifications. Ensures that if the
     * simplifications in the list are executed in order, then all
     * dependencies will be met.
     *
     * Dependencies are assumed to form a tree. If a dependency is in
     * the startSet then we stop recursing on that branch.
     */
    protected void buildDependencies( AbstractSimplification base, Set startSet )
    {
        for( Class<? extends AbstractSimplification> depClass : base.getDependencies() ){
            if( !startSet.contains(depClass) ){
                AbstractSimplification depInst = constrSimp( depClass );
                buildDependencies( depInst, startSet );
                simplifications.add( depInst );
            }
        }
    }

    /**
     * Construct a given simplification class. No recovery is
     * attempted if an exception or error occurs. No error should
     * occur.
     */
    protected AbstractSimplification constrSimp( Class<? extends AbstractSimplification> simpClass )
    {
        AbstractSimplification simpInst;
        Constructor<? extends AbstractSimplification> constructor;
        <commit_msg>Modified the simplifier to perform the dependency fulfilment correctly. It also operates on a DAG now.<commit_after>package natlab.toolkits.rewrite;

import java.util.*;
import java.lang.reflect.*;

import ast.*;
import natlab.toolkits.rewrite.simplification.*;
import natlab.toolkits.analysis.varorfun.*;

/**
 * Performs simplifications. Takes care of dependencies and any needed
 * book keeping.
 *
 * Dependencies are assumed to form a tree. Dependencies are built
 * from a start set and recorded in post order, avoiding repetition. 
 *
 * @author <NAME>
 */
public class Simplifier
{

    //List of simplifications. If applied in list order, then all
    //dependencies should be met.
    protected LinkedList<AbstractSimplification> simplifications;

    public String simpsToStr()
    {
        return simplifications.toString();
    }

    protected ASTNode tree;
    protected VFPreorderAnalysis kind;

    /**
     * Constructs a simplifier for a given set of simplification
     * classes. 
     */
    public Simplifier( ASTNode tree, Set<Class<? extends AbstractSimplification>> todo )
    {
        this( tree, todo, new VFPreorderAnalysis(tree) );
    }
    public Simplifier( ASTNode tree, 
                       Set<Class<? extends AbstractSimplification>> todo, 
                       VFPreorderAnalysis kindAna )
    {
        simplifications = new LinkedList();
        kind = kindAna;
        if( !kind.isAnalyzed() )
            kind.analyze();

        this.tree = tree;
        buildDependencies( todo );
        /*for( Class<? extends AbstractSimplification> simpClass : todo ){
            AbstractSimplification simpInst = constrSimp( simpClass );
            buildDependencies( simpInst, todo );
            simplifications.add( simpInst );
            }*/
    }

    /**
     * Runs the simplifications in a correct order.
     */
    public ASTNode simplify()
    {
        ASTNode currentTree = tree;
        for( AbstractSimplification simp : simplifications ){
            System.out.println( simp );
            simp.setTree( currentTree );
            currentTree = simp.transform();
        }
        return currentTree;
    }

    /**
     * Builds the dependencies for a given start set.
     */
    protected void buildDependencies( Set<Class<? extends AbstractSimplification>> startSet )
    {
        Set<Class<? extends AbstractSimplification>> seenStartSet = new HashSet();
        while( !startSet.isEmpty() ){
            Iterator<Class<? extends AbstractSimplification>> iter = startSet.iterator();
            Class<? extends AbstractSimplification> simpClass = iter.next();

            AbstractSimplification simp = constrSimp(simpClass);
            seenStartSet.add( simpClass );
            iter.remove();
            buildDependencies( simp, startSet, seenStartSet );
        }
    }
    /**
     * Builds the dependencies for a given simplification, puts them
     * in the list of simplifications. Ensures that if the
     * simplifications in the list are executed in order, then all
     * dependencies will be met.
     *
     * Dependencies are assumed to form a tree. If a dependency is in
     * the seenStartSet then we stop recursing on that branch.
     */
    protected void buildDependencies( AbstractSimplification base, 
                                      Set<Class<? extends AbstractSimplification>> startSet,
                                      Set<Class<? extends AbstractSimplification>> seenStartSet)
    {
        for( Class<? extends AbstractSimplification> depClass : base.getDependencies() ){
            if( !seenStartSet.contains( depClass )){
                startSet.remove( depClass );
                seenStartSet.add( depClass );
                
                AbstractSimplification depInst = constrSimp( depClass );
                buildDependencies( depInst, startSet, seenStartSet );
            }
        }
        simplifications.add( base );
    }

    /**
     * Construct a given simplification class. No recovery is
     * attempted if an exception or error occurs. No error should
     * occur.
     */
    protected AbstractSimplification constrSimp( Class<? extends AbstractSimplification> simpClass )
    {
        AbstractSimplification simpInst;
        Constructor<? extends AbstractSimplification> constructor;
        
{'fraction_non_alphanumeric': 0.08022690437601297, 'fraction_numerical': 0.0, 'mean_word_length': 2.355233348436792, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4151937', 'n_tokens_mistral': 1933, 'n_tokens_neox': 1861, 'n_words': 600}