//-----------------------------------------------------------------------------
bool AddSubZero::Optimize(AsmCode& code, int index)
{
    if (index == code.Size())
    {
        return false;
    }

    AsmCmd2* cmd = dynamic_cast<AsmCmd2*>(code[index]);
    if (cmd && (*cmd == cmdSUB || *cmd == cmdADD) && *cmd->GetSecond() == "0")
    {
        code.Delete(index);
        return true;
    }

    return false;
}
bool PushPopOptimization::Optimize(AsmCode& code, int index)
{
    if (index + 1 == code.Size())
    {
        return false;
    }

    AsmCmd1* cmd1 = dynamic_cast<AsmCmd1*>(code[index]);
    AsmCmd1* cmd2 = dynamic_cast<AsmCmd1*>(code[index + 1]);

    if (cmd1 && cmd2 && *cmd1 == cmdPUSH  && *cmd2 == cmdPOP)
    {
        if (*cmd1->GetArgument() == cmd2->GetArgument())
        {
            code.Delete(index, index + 1);
            return true;
        }
    }

    return false;
}
bool PushPopToMovOptimization::Optimize(AsmCode& code, int index)
{
    if (index + 1 == code.Size())
    {
        return false;
    }

    AsmCmd1* cmd1 = dynamic_cast<AsmCmd1*>(code[index]);
    AsmCmd1* cmd2 = dynamic_cast<AsmCmd1*>(code[index + 1]);

    if (cmd1 && cmd2
        && *cmd1 == cmdPUSH  && *cmd2 == cmdPOP
        && *cmd1->GetArgument() != cmd2->GetArgument()
        && !IsMemory(cmd1->GetArgument()) && !IsMemory(cmd2->GetArgument()))
    {
            AsmCmd2* optCmd = new AsmCmd2(cmdMOV, cmd2->GetArgument(), cmd1->GetArgument());
            code.Delete(index, index + 1);
            code.Insert(optCmd, index);
            return true;
    }

    return false;
}
bool MovChainOptimization::Optimize(AsmCode& code, int index)
{
    if (index + 1 == code.Size())
    {
        return false;
    }

    AsmCmd2* cmd1 = dynamic_cast<AsmCmd2*>(code[index]);
    AsmCmd2* cmd2 = dynamic_cast<AsmCmd2*>(code[index + 1]);

    if (cmd1 && cmd2
        && *cmd1 == cmdMOV && *cmd2 == cmdMOV
        && *cmd1->GetFirst() != EBP && *cmd1->GetSecond() != ESP
        && *cmd2->GetSecond() == cmd1->GetFirst()
        && !IsMemory(cmd1->GetSecond()) && !IsMemory(cmd2->GetFirst()))
    {
        AsmCmd2* optCmd = new AsmCmd2(cmdMOV, cmd2->GetFirst(), cmd1->GetSecond());
        code.Delete(index, index + 1);
        code.Insert(optCmd, index);
        return true;
    }

    return false;
}