package accrue.analysis.goals;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import polyglot.ast.Node;
import polyglot.frontend.CyclicDependencyException;
import polyglot.frontend.ExtensionInfo;
import polyglot.frontend.Job;
import polyglot.frontend.Scheduler;
import polyglot.frontend.goals.Barrier;
import polyglot.frontend.goals.Goal;
import polyglot.frontend.goals.VisitorGoal;
import polyglot.util.InternalCompilerError;
import accrue.AccrueScheduler;
import accrue.analysis.visit.RegisterExpressions;

public class RegisterExpressionsGoal extends Barrier {
    protected Map<Node, Node> enclosingStmt;
    protected Map<Node, Set<Node>> enclosedExprs;

    protected RegisterExpressionsGoal(Scheduler scheduler) {
        super(scheduler);
        this.enclosingStmt = new HashMap<Node, Node>();
        this.enclosedExprs = new HashMap<Node, Set<Node>>();
    }

    public Map<Node, Node> enclosingStmt() {
        return enclosingStmt;
    }

    @Override
    public Goal goalForJob(Job job) {
        Goal g =
                scheduler.internGoal(new VisitorGoal(job,
                                                     new RegisterExpressions(enclosingStmt,
                                                                             enclosedExprs)));
        AccrueScheduler sched = (AccrueScheduler) scheduler;
        try {
            g.addPrerequisiteGoal(sched.helper().RegisterPointerStmts(job),
                                  scheduler);
        }
        catch (CyclicDependencyException e) {
            throw new InternalCompilerError(e);
        }
        return g;
    }

    public static RegisterExpressionsGoal singleton(ExtensionInfo extInfo) {
        Scheduler scheduler = extInfo.scheduler();
        return (RegisterExpressionsGoal) scheduler.internGoal(new RegisterExpressionsGoal(scheduler));
    }

}
