// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/tint/transform/promote_initializers_to_let.h"

#include <utility>

#include "src/tint/ast/traverse_expressions.h"
#include "src/tint/program_builder.h"
#include "src/tint/sem/call.h"
#include "src/tint/sem/statement.h"
#include "src/tint/sem/type_initializer.h"
#include "src/tint/transform/utils/hoist_to_decl_before.h"
#include "src/tint/type/struct.h"
#include "src/tint/utils/hashset.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::PromoteInitializersToLet);

namespace tint::transform {

PromoteInitializersToLet::PromoteInitializersToLet() = default;

PromoteInitializersToLet::~PromoteInitializersToLet() = default;

Transform::ApplyResult PromoteInitializersToLet::Apply(const Program* src,
                                                       const DataMap&,
                                                       DataMap&) const {
    ProgramBuilder b;
    CloneContext ctx{&b, src, /* auto_clone_symbols */ true};

    // Returns true if the expression should be hoisted to a new let statement before the
    // expression's statement.
    auto should_hoist = [&](const sem::ValueExpression* expr) {
        if (!expr->Type()->IsAnyOf<type::Array, type::Struct>()) {
            // We only care about array and struct initializers
            return false;
        }

        // Check whether the expression is an array or structure constructor
        {
            // Follow const-chains
            auto* root_expr = expr;
            if (expr->Stage() == sem::EvaluationStage::kConstant) {
                while (auto* user = root_expr->UnwrapMaterialize()->As<sem::VariableUser>()) {
                    root_expr = user->Variable()->Initializer();
                }
            }

            auto* ctor = root_expr->UnwrapMaterialize()->As<sem::Call>();
            if (!ctor || !ctor->Target()->Is<sem::TypeInitializer>()) {
                // Root expression is not a type constructor. Not interested in this.
                return false;
            }
        }

        if (auto* src_var_decl = expr->Stmt()->Declaration()->As<ast::VariableDeclStatement>()) {
            if (src_var_decl->variable->initializer == expr->Declaration()) {
                // This statement is just a variable declaration with the initializer as the
                // initializer value. This is what we're attempting to transform to, and so
                // ignore.
                return false;
            }
        }

        return true;
    };

    // A list of expressions that should be hoisted.
    utils::Vector<const sem::ValueExpression*, 32> to_hoist;
    // A set of expressions that are constant, which _may_ need to be hoisted.
    utils::Hashset<const ast::Expression*, 32> const_chains;

    // Walk the AST nodes. This order guarantees that leaf-expressions are visited first.
    for (auto* node : src->ASTNodes().Objects()) {
        if (auto* sem = src->Sem().GetVal(node)) {
            auto* stmt = sem->Stmt();
            if (!stmt) {
                // Expression is outside of a statement. This usually means the expression is part
                // of a global (module-scope) constant declaration. These must be constexpr, and so
                // cannot contain the type of expressions that must be sanitized.
                continue;
            }

            if (sem->Stage() == sem::EvaluationStage::kConstant) {
                // Expression is constant. We only need to hoist expressions if they're the
                // outermost constant expression in a chain. Remove the immediate child nodes of the
                // expression from const_chains, and add this expression to the const_chains. As we
                // visit leaf-expressions first, this means the content of const_chains only
                // contains the outer-most constant expressions.
                auto* expr = sem->Declaration();
                bool ok = ast::TraverseExpressions(
                    expr, b.Diagnostics(), [&](const ast::Expression* child) {
                        const_chains.Remove(child);
                        return child == expr ? ast::TraverseAction::Descend
                                             : ast::TraverseAction::Skip;
                    });
                if (!ok) {
                    return Program(std::move(b));
                }
                const_chains.Add(expr);
            } else if (should_hoist(sem)) {
                to_hoist.Push(sem);
            }
        }
    }

    // After walking the full AST, const_chains only contains the outer-most constant expressions.
    // Check if any of these need hoisting, and append those to to_hoist.
    for (auto* expr : const_chains) {
        if (auto* sem = src->Sem().GetVal(expr); should_hoist(sem)) {
            to_hoist.Push(sem);
        }
    }

    if (to_hoist.IsEmpty()) {
        // Nothing to do. Skip.
        return SkipTransform;
    }

    // The order of to_hoist is currently undefined. Sort by AST node id, which will make this
    // deterministic.
    to_hoist.Sort([&](auto* expr_a, auto* expr_b) {
        return expr_a->Declaration()->node_id < expr_b->Declaration()->node_id;
    });

    // Hoist all the expression in to_hoist  to a constant variable, declared just before the
    // statement of usage.
    HoistToDeclBefore hoist_to_decl_before(ctx);
    for (auto* expr : to_hoist) {
        if (!hoist_to_decl_before.Add(expr, expr->Declaration(),
                                      HoistToDeclBefore::VariableKind::kLet)) {
            return Program(std::move(b));
        }
    }

    ctx.Clone();
    return Program(std::move(b));
}

}  // namespace tint::transform
