StatementPtr StatementList::postOptimize(AnalysisResultConstPtr ar) {
    for (unsigned int i = 0; i < m_stmts.size(); i++) {
        StatementPtr &s = m_stmts[i];
        if (s->is(KindOfExpStatement) && !s->hasEffect()) {
            ExpressionPtr e =
                dynamic_pointer_cast<ExpStatement>(s)->getExpression();
            if (e->isNoRemove()) continue;
            if (Option::EliminateDeadCode ||
                    static_pointer_cast<ExpStatement>(s)->getExpression()->isScalar()) {
                removeElement(i--);
                getScope()->addUpdates(BlockScope::UseKindCaller);
                continue;
            }
        } else if (s->is(KindOfBlockStatement) &&
                   !static_pointer_cast<BlockStatement>(s)->getStmts()) {
            removeElement(i--);
            getScope()->addUpdates(BlockScope::UseKindCaller);
            continue;
        }
    }
    return StatementPtr();
}
StatementPtr StatementList::preOptimize(AnalysisResultConstPtr ar) {
    bool del = false;
    bool changed = false;
    for (unsigned int i = 0; i < m_stmts.size(); i++) {
        StatementPtr &s = m_stmts[i];
        if (del) {
            if (s->hasReachableLabel()) {
                del = false;
            } else {
                switch (s->getKindOf()) {
                case Statement::KindOfBlockStatement:
                case Statement::KindOfIfBranchStatement:
                case Statement::KindOfIfStatement:
                case Statement::KindOfWhileStatement:
                case Statement::KindOfDoStatement:
                case Statement::KindOfForStatement:
                case Statement::KindOfSwitchStatement:
                case Statement::KindOfCaseStatement:
                case Statement::KindOfBreakStatement:
                case Statement::KindOfContinueStatement:
                case Statement::KindOfReturnStatement:
                case Statement::KindOfGlobalStatement:
                case Statement::KindOfStaticStatement:
                case Statement::KindOfEchoStatement:
                case Statement::KindOfUnsetStatement:
                case Statement::KindOfExpStatement:
                case Statement::KindOfForEachStatement:
                case Statement::KindOfCatchStatement:
                case Statement::KindOfTryStatement:
                case Statement::KindOfThrowStatement:
                    removeElement(i--);
                    changed = true;
                    continue;
                default:
                    break;
                }
            }
        }

        if (s) {
            if (s->is(KindOfStatementList) && !s->hasDecl()) {
                StatementListPtr stmts(static_pointer_cast<StatementList>(s));
                removeElement(i);
                m_stmts.insert(m_stmts.begin() + i,
                               stmts->m_stmts.begin(), stmts->m_stmts.end());
                i--;
                changed = true;
                continue;
            } else if (s->is(KindOfBlockStatement)) {
                BlockStatementPtr bs(static_pointer_cast<BlockStatement>(s));
                StatementListPtr stmts(bs->getStmts());
                if (!stmts) {
                    removeElement(i--);
                    changed = true;
                    continue;
                } else {
                    FunctionScopePtr fs(getFunctionScope());
                    if (fs && (!fs->inPseudoMain() || !stmts->hasDecl())) {
                        removeElement(i);
                        m_stmts.insert(m_stmts.begin() + i,
                                       stmts->m_stmts.begin(), stmts->m_stmts.end());
                        i--;
                        changed = true;
                        continue;
                    }
                }
            } else if (Option::EliminateDeadCode) {
                if (s->is(KindOfBreakStatement) ||
                        s->is(KindOfContinueStatement) ||
                        s->is(KindOfReturnStatement) ||
                        s->is(KindOfThrowStatement)) {
                    del = true;
                } else if (s->is(KindOfExpStatement)) {
                    ExpressionPtr e =
                        dynamic_pointer_cast<ExpStatement>(s)->getExpression();
                    if (!e->hasEffect() && !e->isNoRemove()) {
                        removeElement(i--);
                        changed = true;
                    }
                }
            }
        }
    }

    if (mergeConcatAssign()) changed = true;
    return changed ? static_pointer_cast<Statement>(shared_from_this())
           : StatementPtr();
}