import java.io.*;
import java.util.*;

import codegen.*;
import controlflow.*;
import irgeneration.*;
import optimization.*;
import semanticanalysis.*;
import symboltable.*;
import syntaxtree.*;
import visitor.*;
import regalloc.*;

public class MiniJavaCompiler
{
    private static boolean _optimize = false;

    public static void main(String[] args) throws Exception
    {
        if (args.length < 2)
        {
            System.err.println("usage: java NameAnalysisTest <input-file> <output-file>");
            System.exit(1);
        }

        args = parseFlags(args);

        // parse the program
        Program program = parseProgram(args[0]);

        // build symbol table and check for semantic errors
        List<ErrorChecker> errorCheckers = new ArrayList<ErrorChecker>();
        ISymbolTable symbolTable = buildSymbolTableAndCheckErrors(program, errorCheckers);

        // loop over error checkers, printing out each error
        boolean failed = false;
        for (ErrorChecker checker : errorCheckers)
        {
            if (checker.hasErrors())
            {
                failed = true;
                for (String error : checker.getErrors())
                {
                    System.out.println(error);
                }
            }

        }
        // exit if errors are encountered.
        if (failed)
        {
            System.out.println("Errors encountered, cannot generate IR.");
            return;
        }

        // generate IR (3-address code)
        IRGenVisitor irGenerator = new IRGenVisitor((SymbolTable)symbolTable);
        irGenerator.visit(program);
        irGenerator.printIRList();

        // optimizations!
        List<IRQuadruple> irList = irGenerator.getIRList();
        if (_optimize)
        {
            irList = runOptimizations(irList);
            System.out.println("----- OPTIMIZED IR -----");
            for (IRQuadruple irq : irList)
            {
                System.out.println(irq);
            }
        }

        for(ControlFlowGraph cfg : cfgBuilder.getControlFlowGraphs())
        {
          LivenessAnalysis la = new LivenessAnalysis(cfg);
          System.out.println(la);

          InterferenceGraph ig = new InterferenceGraph(la, cfg);
          System.out.println(ig);

          RegisterAllocator regAlloc = new RegisterAllocator(ig, 9);
          System.out.println(regAlloc);
        }

        CodeGenerator codeGenerator = new CodeGenerator(irList);
        codeGenerator.generateCode();
        //codeGenerator.printCode();
        String outputFileName = args[1];
        System.out.println("----- OUTPUTTING ASSEMBLY TO: " + outputFileName + " -----");
        codeGenerator.outputMIPSFile(outputFileName); //TODO: make this an argument
    }

    private static String[] parseFlags(String[] args)
    {
        List<String> argsList = new ArrayList<String>(Arrays.asList(args));

        if (argsList.contains("-O1"))
        {
            _optimize = true;
            argsList.remove("-O1");
        }
        return argsList.toArray(new String[0]);
    }

    private static List<IRQuadruple> runOptimizations(List<IRQuadruple> irList)
    {
        IROptimizer optimizer = new IROptimizer(irList);
        optimizer.optimize();
        return optimizer.getOptimizedIR();
    }

    private static Program parseProgram(String sourceFileName) throws Exception
    {
        MiniJavaParser parser = new MiniJavaParser(new MiniJavaLexer(new FileReader(sourceFileName)));
        return (Program)parser.parse().value;
    }

    private static ISymbolTable buildSymbolTableAndCheckErrors(Program program, List<ErrorChecker> errorCheckers)
    {
        // build symbol table
        BuildSymbolTableVisitor symbolTableBuilder = new BuildSymbolTableVisitor();
        symbolTableBuilder.visit(program);

        ISymbolTable symbolTable = symbolTableBuilder.getSymbolTable();

        // do name analysis (undefined references)
        NameAnalysisVisitor nameAnalysis = new NameAnalysisVisitor(symbolTable);
        nameAnalysis.visit(program);

        // do type checking
        TypeCheckVisitor typeChecker = new TypeCheckVisitor(symbolTable);
        typeChecker.visit(program);

        // aggregate our error checkers
        errorCheckers.add(symbolTableBuilder);
        errorCheckers.add(nameAnalysis);
        errorCheckers.add(typeChecker);

        return symbolTable;
    }

}

@@ -1991,32 +1991,115 @@
    %7D%0A        %7D%0A%0A
+        ControlFlowGraphBuilder cfgBuilder = new ControlFlowGraphBuilder(irList);%0A%0A
         for(Cont

Fix one last merge issue, basic RegisterAllocation works in testing (not yet used in codegen)