/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package Processors;

import API.CodeProcessorInterface;
import common.Block;
import common.Code;
import common.Instruction;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.regex.Pattern;

/**
 *
 * @author EUGENIO CARVALHO
 */
public class DeadInstructionsProcessor implements CodeProcessorInterface {

    public static Pattern varPattern = Pattern.compile("\\_[VT].*", Pattern.CASE_INSENSITIVE);

    public DeadInstructionsProcessor() {
    }

    @Override
    public void Exec(Code c, LinkedHashMap<String, CodeProcessorInterface> cp) throws Exception {
        String dst;
        Instruction instruction;
        Block block = c.Block();
        HashMap<String, Boolean> referenced = new HashMap<>();
        LinkedList<Instruction> instructions = block.Instructions();

//        System.out.println("instruction:" + instructions.get(2));
//        throw new Exception("xxxxx");

        String[] params = new String[]{"p1", "p2"};
        Iterator<Instruction> interator = instructions.descendingIterator();
        // Remove instrucoes mortas 
        while (interator.hasNext()) {
            instruction = interator.next();

//            System.out.println("ClearCode:" + instruction);
            dst = instruction.G("dst");
            // Remove a instrucao se:
            // * A instrucao não esta dentro de um loop
            // * Tem destino
            // * É uma variavel local (Variavel ou temporaria)
            // * E não foi referenciada por instruções seguintes

            if (!instruction.eq("inloop", "true")
                    && !dst.equals("")
                    && varPattern.matcher(dst).matches()
                    && !referenced.containsKey(dst)) {

                interator.remove();
                continue;
            }

            for (String param : params) {
                if (!instruction.eq(param + "value", "true")) {
                    referenced.put(instruction.G(param), Boolean.TRUE);
                }
            }
        }
    }

}
