package org.jruby.ir.passes;

import org.jruby.ir.instructions.CopyInstr;
import org.jruby.ir.instructions.Instr;
import org.jruby.ir.interpreter.FullInterpreterContext;
import org.jruby.ir.operands.Nil;
import org.jruby.ir.operands.TemporaryVariable;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.representations.BasicBlock;
import org.jruby.ir.representations.CFG;

import java.util.HashSet;
import java.util.Set;

public class EnsureTempsAssigned extends CompilerPass {
    @Override
    public String getLabel() {
        return "Ensure Temporary Variables Assigned";
    }

    @Override
    public Object execute(FullInterpreterContext fic, Object... data) {
        processCFG(fic.getCFG());

        return null;
    }

    private void processCFG(CFG cfg) {
        Set<TemporaryVariable> names = new HashSet<TemporaryVariable>();
        for (BasicBlock b : cfg.getBasicBlocks()) {
            for (Instr i : b.getInstrs()) {
                for (Variable v : i.getUsedVariables()) {
                    if (v instanceof TemporaryVariable) {
                        names.add((TemporaryVariable)v);
                    }
                }
            }
        }

        BasicBlock bb = cfg.getEntryBB();
        int index = 0;
        TemporaryVariable first = null;
        for (TemporaryVariable name : names) {
            if (first == null) {
                bb.getInstrs().add(index++, new CopyInstr(name, new Nil()));
                first = name;
            } else {
                bb.getInstrs().add(index++, new CopyInstr(name, first));
            }
        }
    }
}