// Copyright 2021 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/resolver/resolver.h"

#include "src/tint/sem/constant.h"
#include "src/tint/sem/type_constructor.h"
#include "src/tint/utils/map.h"

namespace tint::resolver {
namespace {

using i32 = ProgramBuilder::i32;
using u32 = ProgramBuilder::u32;
using f32 = ProgramBuilder::f32;

}  // namespace

sem::Constant Resolver::EvaluateConstantValue(const ast::Expression* expr, const sem::Type* type) {
    if (auto* e = expr->As<ast::LiteralExpression>()) {
        return EvaluateConstantValue(e, type);
    }
    if (auto* e = expr->As<ast::CallExpression>()) {
        return EvaluateConstantValue(e, type);
    }
    return {};
}

sem::Constant Resolver::EvaluateConstantValue(const ast::LiteralExpression* literal,
                                              const sem::Type* type) {
    return Switch(
        literal,
        [&](const ast::IntLiteralExpression* lit) {
            if (lit->suffix == ast::IntLiteralExpression::Suffix::kU) {
                return sem::Constant{type, {static_cast<uint32_t>(lit->value)}};
            }
            return sem::Constant{type, {static_cast<int32_t>(lit->value)}};
        },
        [&](const ast::FloatLiteralExpression* lit) {
            return sem::Constant{type, {lit->value}};
        },
        [&](const ast::BoolLiteralExpression* lit) {
            return sem::Constant{type, {lit->value}};
        });
}

sem::Constant Resolver::EvaluateConstantValue(const ast::CallExpression* call,
                                              const sem::Type* type) {
    auto* vec = type->As<sem::Vector>();

    // For now, only fold scalars and vectors
    if (!type->is_scalar() && !vec) {
        return {};
    }

    auto* elem_type = vec ? vec->type() : type;
    int result_size = vec ? static_cast<int>(vec->Width()) : 1;

    // For zero value init, return 0s
    if (call->args.empty()) {
        if (elem_type->Is<sem::I32>()) {
            return sem::Constant(type, sem::Constant::Scalars(result_size, 0));
        }
        if (elem_type->Is<sem::U32>()) {
            return sem::Constant(type, sem::Constant::Scalars(result_size, 0u));
        }
        if (elem_type->Is<sem::F32>()) {
            return sem::Constant(type, sem::Constant::Scalars(result_size, 0.f));
        }
        if (elem_type->Is<sem::Bool>()) {
            return sem::Constant(type, sem::Constant::Scalars(result_size, false));
        }
    }

    // Build value for type_ctor from each child value by casting to
    // type_ctor's type.
    sem::Constant::Scalars elems;
    for (auto* expr : call->args) {
        auto* arg = builder_->Sem().Get(expr);
        if (!arg || !arg->ConstantValue()) {
            return {};
        }
        auto cast = ConstantCast(arg->ConstantValue(), elem_type);
        elems.insert(elems.end(), cast.Elements().begin(), cast.Elements().end());
    }

    // Splat single-value initializers
    if (elems.size() == 1) {
        for (int i = 0; i < result_size - 1; ++i) {
            elems.emplace_back(elems[0]);
        }
    }

    return sem::Constant(type, std::move(elems));
}

sem::Constant Resolver::ConstantCast(const sem::Constant& value,
                                     const sem::Type* target_elem_type) {
    if (value.ElementType() == target_elem_type) {
        return value;
    }

    sem::Constant::Scalars elems;
    for (size_t i = 0; i < value.Elements().size(); ++i) {
        if (target_elem_type->Is<sem::I32>()) {
            elems.emplace_back(value.WithScalarAt(i, [](auto&& s) { return static_cast<i32>(s); }));
        } else if (target_elem_type->Is<sem::U32>()) {
            elems.emplace_back(value.WithScalarAt(i, [](auto&& s) { return static_cast<u32>(s); }));
        } else if (target_elem_type->Is<sem::F32>()) {
            elems.emplace_back(value.WithScalarAt(i, [](auto&& s) { return static_cast<f32>(s); }));
        } else if (target_elem_type->Is<sem::Bool>()) {
            elems.emplace_back(
                value.WithScalarAt(i, [](auto&& s) { return static_cast<bool>(s); }));
        }
    }

    auto* target_type =
        value.Type()->Is<sem::Vector>()
            ? builder_->create<sem::Vector>(target_elem_type, static_cast<uint32_t>(elems.size()))
            : target_elem_type;

    return sem::Constant(target_type, elems);
}

}  // namespace tint::resolver
