/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/sksl/SkSLAnalysis.h"
#include "src/sksl/SkSLConstantFolder.h"
#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/ir/SkSLExpressionStatement.h"
#include "src/sksl/ir/SkSLIfStatement.h"
#include "src/sksl/ir/SkSLLiteral.h"
#include "src/sksl/ir/SkSLNop.h"
#include "src/sksl/ir/SkSLType.h"

namespace SkSL {

std::unique_ptr<Statement> IfStatement::clone() const {
    return std::make_unique<IfStatement>(fPosition, this->isStatic(), this->test()->clone(),
                                         this->ifTrue()->clone(),
                                         this->ifFalse() ? this->ifFalse()->clone() : nullptr);
}

std::string IfStatement::description() const {
    std::string result;
    if (this->isStatic()) {
        result += "@";
    }
    result += "if (" + this->test()->description() + ") " + this->ifTrue()->description();
    if (this->ifFalse()) {
        result += " else " + this->ifFalse()->description();
    }
    return result;
}

std::unique_ptr<Statement> IfStatement::Convert(const Context& context, Position pos,
        bool isStatic, std::unique_ptr<Expression> test, std::unique_ptr<Statement> ifTrue,
        std::unique_ptr<Statement> ifFalse) {
    test = context.fTypes.fBool->coerceExpression(std::move(test), context);
    if (!test) {
        return nullptr;
    }
    SkASSERT(ifTrue);
    if (Analysis::DetectVarDeclarationWithoutScope(*ifTrue, context.fErrors)) {
        return nullptr;
    }
    if (ifFalse && Analysis::DetectVarDeclarationWithoutScope(*ifFalse, context.fErrors)) {
        return nullptr;
    }
    return IfStatement::Make(context, pos, isStatic, std::move(test),
                             std::move(ifTrue), std::move(ifFalse));
}

static std::unique_ptr<Statement> replace_empty_with_nop(std::unique_ptr<Statement> stmt,
                                                         bool isEmpty) {
    return (stmt && (!isEmpty || stmt->is<Nop>())) ? std::move(stmt)
                                                   : Nop::Make();
}

std::unique_ptr<Statement> IfStatement::Make(const Context& context, Position pos, bool isStatic,
        std::unique_ptr<Expression> test, std::unique_ptr<Statement> ifTrue,
        std::unique_ptr<Statement> ifFalse) {
    SkASSERT(test->type().matches(*context.fTypes.fBool));
    SkASSERT(!Analysis::DetectVarDeclarationWithoutScope(*ifTrue));
    SkASSERT(!ifFalse || !Analysis::DetectVarDeclarationWithoutScope(*ifFalse));

    const bool optimize = context.fConfig->fSettings.fOptimize;
    bool trueIsEmpty = false;
    bool falseIsEmpty = false;

    if (optimize) {
        // If both sides are empty, the if statement can be reduced to its test expression.
        trueIsEmpty = ifTrue->isEmpty();
        falseIsEmpty = !ifFalse || ifFalse->isEmpty();
        if (trueIsEmpty && falseIsEmpty) {
            return ExpressionStatement::Make(context, std::move(test));
        }
    }

    if (isStatic || optimize) {
        // Static Boolean values can fold down to a single branch.
        const Expression* testValue = ConstantFolder::GetConstantValueForVariable(*test);
        if (testValue->isBoolLiteral()) {
            if (testValue->as<Literal>().boolValue()) {
                return replace_empty_with_nop(std::move(ifTrue), trueIsEmpty);
            } else {
                return replace_empty_with_nop(std::move(ifFalse), falseIsEmpty);
            }
        }
    }

    if (optimize) {
        // Replace an empty if-true branches with Nop; eliminate empty if-false branches entirely.
        ifTrue = replace_empty_with_nop(std::move(ifTrue), trueIsEmpty);
        if (falseIsEmpty) {
            ifFalse = nullptr;
        }
    }

    return std::make_unique<IfStatement>(pos, isStatic, std::move(test),
                                         std::move(ifTrue), std::move(ifFalse));
}

}  // namespace SkSL
