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

#include <utility>
#include <vector>

#include "src/sem/call.h"
#include "src/sem/expression.h"
#include "src/sem/type_constructor.h"
#include "src/sem/type_conversion.h"
#include "src/utils/transform.h"

namespace tint {
namespace writer {

namespace {

struct VectorConstructorInfo {
  const sem::Call* call = nullptr;
  const sem::TypeConstructor* ctor = nullptr;
  operator bool() const { return call != nullptr; }
};
VectorConstructorInfo AsVectorConstructor(const sem::Expression* expr) {
  if (auto* call = expr->As<sem::Call>()) {
    if (auto* ctor = call->Target()->As<sem::TypeConstructor>()) {
      if (ctor->ReturnType()->Is<sem::Vector>()) {
        return {call, ctor};
      }
    }
  }
  return {};
}

const sem::Expression* Zero(ProgramBuilder& b,
                            const sem::Type* ty,
                            const sem::Statement* stmt) {
  const ast::Expression* expr = nullptr;
  if (ty->Is<sem::I32>()) {
    expr = b.Expr(0);
  } else if (ty->Is<sem::U32>()) {
    expr = b.Expr(0u);
  } else if (ty->Is<sem::F32>()) {
    expr = b.Expr(0.0f);
  } else if (ty->Is<sem::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::Expression>(expr, ty, stmt, sem::Constant{});
  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 sem::Type* packed_el_sem_ty;
  auto* vector_sem = b->Sem().Get(vector_ast);
  auto* scalar_sem = b->Sem().Get(scalar_ast);
  auto* vector_ty = vector_sem->Type()->UnwrapRef();
  if (auto* vec = vector_ty->As<sem::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 = nullptr;
  if (packed_el_sem_ty->Is<sem::I32>()) {
    packed_el_ast_ty = b->create<ast::I32>();
  } else if (packed_el_sem_ty->Is<sem::U32>()) {
    packed_el_ast_ty = b->create<ast::U32>();
  } else if (packed_el_sem_ty->Is<sem::F32>()) {
    packed_el_ast_ty = b->create<ast::F32>();
  } else if (packed_el_sem_ty->Is<sem::Bool>()) {
    packed_el_ast_ty = b->create<ast::Bool>();
  } else {
    TINT_UNREACHABLE(Writer, b->Diagnostics())
        << "unsupported vector element type: "
        << packed_el_sem_ty->TypeInfo().name;
  }

  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<sem::Vector>(packed_el_sem_ty, packed_size);

  // If the coordinates are already passed in a vector constructor, 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-constructor of the vector, then expand that
  // to scalar zeros.
  // The other cases for a nested vector constructor 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.

  std::vector<const sem::Expression*> packed;
  if (auto vc = AsVectorConstructor(vector_sem)) {
    const auto num_supplied = vc.call->Arguments().size();
    if (num_supplied == 0) {
      // Zero-value vector constructor. Populate with zeros
      for (uint32_t i = 0; i < packed_size - 1; i++) {
        auto* zero = Zero(*b, packed_el_sem_ty, statement);
        packed.emplace_back(zero);
      }
    } else if (num_supplied + 1 == packed_size) {
      // All vector components were supplied as scalars.  Pass them through.
      packed = vc.call->Arguments();
    }
  }
  if (packed.empty()) {
    // The special cases didn't occur. Use the vector argument as-is.
    packed.emplace_back(vector_sem);
  }

  if (packed_el_sem_ty != scalar_sem->Type()->UnwrapRef()) {
    // Cast scalar to the vector element type
    auto* scalar_cast_ast = b->Construct(packed_el_ast_ty, scalar_ast);
    auto* scalar_cast_target = b->create<sem::TypeConversion>(
        packed_el_sem_ty,
        b->create<sem::Parameter>(nullptr, 0, scalar_sem->Type()->UnwrapRef(),
                                  ast::StorageClass::kNone,
                                  ast::Access::kUndefined));
    auto* scalar_cast_sem =
        b->create<sem::Call>(scalar_cast_ast, scalar_cast_target,
                             std::vector<const sem::Expression*>{scalar_sem},
                             statement, sem::Constant{});
    b->Sem().Add(scalar_cast_ast, scalar_cast_sem);
    packed.emplace_back(scalar_cast_sem);
  } else {
    packed.emplace_back(scalar_sem);
  }

  auto* constructor_ast = b->Construct(
      packed_ast_ty, utils::Transform(packed, [&](const sem::Expression* expr) {
        return expr->Declaration();
      }));
  auto* constructor_target = b->create<sem::TypeConstructor>(
      packed_sem_ty, utils::Transform(packed,
                                      [&](const tint::sem::Expression* arg,
                                          size_t i) -> const sem::Parameter* {
                                        return b->create<sem::Parameter>(
                                            nullptr, static_cast<uint32_t>(i),
                                            arg->Type()->UnwrapRef(),
                                            ast::StorageClass::kNone,
                                            ast::Access::kUndefined);
                                      }));
  auto* constructor_sem = b->create<sem::Call>(
      constructor_ast, constructor_target, packed, statement, sem::Constant{});
  b->Sem().Add(constructor_ast, constructor_sem);
  return constructor_sem;
}

}  // namespace writer
}  // namespace tint
