package org.jruby.ir.passes;

import java.util.Set;

import org.jruby.ir.interpreter.FullInterpreterContext;
import org.jruby.ir.operands.Nil;
import org.jruby.ir.operands.LocalVariable;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.representations.BasicBlock;
import org.jruby.ir.instructions.CopyInstr;
import org.jruby.ir.dataflow.analyses.DefinedVariablesProblem;

public class AddMissingInitsPass extends CompilerPass {
    @Override
    public String getLabel() {
        return "Add Missing Initialization";
    }

    @Override
    public String getShortLabel() {
        return "Add Missing Init.";
    }

    @Override
    public Object execute(FullInterpreterContext fic, Object... data) {
        // Find undefined vars
        DefinedVariablesProblem p = new DefinedVariablesProblem(fic);
        p.compute_MOP_Solution();
        Set<Variable> undefinedVars = p.findUndefinedVars();

        // Add inits to entry
        BasicBlock bb = fic.getCFG().getEntryBB();
        for (Variable v : undefinedVars) {
            // System.out.println("Adding missing init for " + v + " in " + scope);

            // Add lvar inits to the end of the BB
            //   (so that scopes are pushed before its vars are updated)
            // and tmpvar inits to the beginning of the BB
            //   (so that if a bad analysis causes an already initialized tmp
            //    to be found uninitialized, this unnecessary init doesn't
            //    clobber an already updated tmp. The entryBB will not have
            //    any loads of lvars, so lvars aren't subject to this problem).
            if (v instanceof LocalVariable) {
                bb.getInstrs().add(new CopyInstr(v, new Nil()));
            } else {
                bb.getInstrs().add(0, new CopyInstr(v, new Nil()));
            }
        }

        return null;
    }
}