// Copyright 2020 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/writer/append_vector.h"

#include <utility>
#include <vector>

#include "src/tint/sem/call.h"
#include "src/tint/sem/type_conversion.h"
#include "src/tint/sem/type_initializer.h"
#include "src/tint/sem/value_expression.h"
#include "src/tint/utils/transform.h"

using namespace tint::number_suffixes;  // NOLINT

namespace tint::writer {
namespace {

struct VectorInitializerInfo {
    const sem::Call* call = nullptr;
    const sem::TypeInitializer* ctor = nullptr;
    operator bool() const { return call != nullptr; }
};
VectorInitializerInfo AsVectorInitializer(const sem::ValueExpression* expr) {
    if (auto* call = expr->As<sem::Call>()) {
        if (auto* ctor = call->Target()->As<sem::TypeInitializer>()) {
            if (ctor->ReturnType()->Is<type::Vector>()) {
                return {call, ctor};
            }
        }
    }
    return {};
}

const sem::ValueExpression* Zero(ProgramBuilder& b,
                                 const type::Type* ty,
                                 const sem::Statement* stmt) {
    const ast::Expression* expr = nullptr;
    if (ty->Is<type::I32>()) {
        expr = b.Expr(0_i);
    } else if (ty->Is<type::U32>()) {
        expr = b.Expr(0_u);
    } else if (ty->Is<type::F32>()) {
        expr = b.Expr(0_f);
    } else if (ty->Is<type::Bool>()) {
        expr = b.Expr(false);
    } else {
        TINT_UNREACHABLE(Writer, b.Diagnostics())
            << "unsupported vector element type: " << ty->TypeInfo().name;
        return nullptr;
    }
    auto* sem = b.create<sem::ValueExpression>(expr, ty, sem::EvaluationStage::kRuntime, stmt,
                                               /* constant_value */ nullptr,
                                               /* has_side_effects */ false);
    b.Sem().Add(expr, sem);
    return sem;
}

}  // namespace

const sem::Call* AppendVector(ProgramBuilder* b,
                              const ast::Expression* vector_ast,
                              const ast::Expression* scalar_ast) {
    uint32_t packed_size;
    const type::Type* packed_el_sem_ty;
    auto* vector_sem = b->Sem().GetVal(vector_ast);
    auto* scalar_sem = b->Sem().GetVal(scalar_ast);
    auto* vector_ty = vector_sem->Type()->UnwrapRef();
    if (auto* vec = vector_ty->As<type::Vector>()) {
        packed_size = vec->Width() + 1;
        packed_el_sem_ty = vec->type();
    } else {
        packed_size = 2;
        packed_el_sem_ty = vector_ty;
    }

    const ast::Type* packed_el_ast_ty = Switch(
        packed_el_sem_ty,  //
        [&](const type::I32*) { return b->ty.i32(); },
        [&](const type::U32*) { return b->ty.u32(); },
        [&](const type::F32*) { return b->ty.f32(); },
        [&](const type::Bool*) { return b->ty.bool_(); },
        [&](Default) {
            TINT_UNREACHABLE(Writer, b->Diagnostics())
                << "unsupported vector element type: " << packed_el_sem_ty->TypeInfo().name;
            return nullptr;
        });

    auto* statement = vector_sem->Stmt();

    auto* packed_ast_ty = b->create<ast::Vector>(packed_el_ast_ty, packed_size);
    auto* packed_sem_ty = b->create<type::Vector>(packed_el_sem_ty, packed_size);

    // If the coordinates are already passed in a vector initializer, with only
    // scalar components supplied, extract the elements into the new vector
    // instead of nesting a vector-in-vector.
    // If the coordinates are a zero-initializer of the vector, then expand that
    // to scalar zeros.
    // The other cases for a nested vector initializer are when it is used
    // to convert a vector of a different type, e.g. vec2<i32>(vec2<u32>()).
    // In that case, preserve the original argument, or you'll get a type error.

    utils::Vector<const sem::ValueExpression*, 4> packed;
    if (auto vc = AsVectorInitializer(vector_sem)) {
        const auto num_supplied = vc.call->Arguments().Length();
        if (num_supplied == 0) {
            // Zero-value vector initializer. Populate with zeros
            for (uint32_t i = 0; i < packed_size - 1; i++) {
                auto* zero = Zero(*b, packed_el_sem_ty, statement);
                packed.Push(zero);
            }
        } else if (num_supplied + 1 == packed_size) {
            // All vector components were supplied as scalars.  Pass them through.
            packed = vc.call->Arguments();
        }
    }
    if (packed.IsEmpty()) {
        // The special cases didn't occur. Use the vector argument as-is.
        packed.Push(vector_sem);
    }

    if (packed_el_sem_ty != scalar_sem->Type()->UnwrapRef()) {
        // Cast scalar to the vector element type
        auto* scalar_cast_ast = b->Call(packed_el_ast_ty, scalar_ast);
        auto* scalar_cast_target = b->create<sem::TypeConversion>(
            packed_el_sem_ty,
            b->create<sem::Parameter>(nullptr, 0u, scalar_sem->Type()->UnwrapRef(),
                                      type::AddressSpace::kNone, type::Access::kUndefined),
            sem::EvaluationStage::kRuntime);
        auto* scalar_cast_sem = b->create<sem::Call>(
            scalar_cast_ast, scalar_cast_target, sem::EvaluationStage::kRuntime,
            utils::Vector<const sem::ValueExpression*, 1>{scalar_sem}, statement,
            /* constant_value */ nullptr, /* has_side_effects */ false);
        b->Sem().Add(scalar_cast_ast, scalar_cast_sem);
        packed.Push(scalar_cast_sem);
    } else {
        packed.Push(scalar_sem);
    }

    auto* initializer_ast =
        b->Call(packed_ast_ty, utils::Transform(packed, [&](const sem::ValueExpression* expr) {
                    return expr->Declaration();
                }));
    auto* initializer_target = b->create<sem::TypeInitializer>(
        packed_sem_ty,
        utils::Transform(
            packed,
            [&](const tint::sem::ValueExpression* arg, size_t i) -> const sem::Parameter* {
                return b->create<sem::Parameter>(
                    nullptr, static_cast<uint32_t>(i), arg->Type()->UnwrapRef(),
                    type::AddressSpace::kNone, type::Access::kUndefined);
            }),
        sem::EvaluationStage::kRuntime);
    auto* initializer_sem =
        b->create<sem::Call>(initializer_ast, initializer_target, sem::EvaluationStage::kRuntime,
                             std::move(packed), statement,
                             /* constant_value */ nullptr,
                             /* has_side_effects */ false);
    b->Sem().Add(initializer_ast, initializer_sem);
    return initializer_sem;
}

}  // namespace tint::writer
