// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/torque/type-inference.h"

namespace v8 {
namespace internal {
namespace torque {

TypeArgumentInference::TypeArgumentInference(
    const GenericParameters& type_parameters,
    const TypeVector& explicit_type_arguments,
    const std::vector<TypeExpression*>& term_parameters,
    const std::vector<base::Optional<const Type*>>& term_argument_types)
    : num_explicit_(explicit_type_arguments.size()),
      type_parameter_from_name_(type_parameters.size()),
      inferred_(type_parameters.size()) {
  if (num_explicit_ > type_parameters.size()) {
    Fail("more explicit type arguments than expected");
    return;
  }
  if (term_argument_types.size() > term_parameters.size()) {
    Fail("more arguments than expected");
    return;
  }

  for (size_t i = 0; i < type_parameters.size(); i++) {
    type_parameter_from_name_[type_parameters[i].name->value] = i;
  }
  for (size_t i = 0; i < num_explicit_; i++) {
    inferred_[i] = {explicit_type_arguments[i]};
  }

  for (size_t i = 0; i < term_argument_types.size(); i++) {
    if (term_argument_types[i])
      Match(term_parameters[i], *term_argument_types[i]);
    if (HasFailed()) return;
  }

  for (size_t i = 0; i < type_parameters.size(); i++) {
    if (!inferred_[i]) {
      Fail("failed to infer arguments for all type parameters");
      return;
    }
  }
}

TypeVector TypeArgumentInference::GetResult() const {
  CHECK(!HasFailed());
  TypeVector result(inferred_.size());
  std::transform(
      inferred_.begin(), inferred_.end(), result.begin(),
      [](base::Optional<const Type*> maybe_type) { return *maybe_type; });
  return result;
}

void TypeArgumentInference::Match(TypeExpression* parameter,
                                  const Type* argument_type) {
  if (BasicTypeExpression* basic =
          BasicTypeExpression::DynamicCast(parameter)) {
    // If the parameter is referring to one of the type parameters, substitute
    if (basic->namespace_qualification.empty() && !basic->is_constexpr) {
      auto result = type_parameter_from_name_.find(basic->name);
      if (result != type_parameter_from_name_.end()) {
        size_t type_parameter_index = result->second;
        if (type_parameter_index < num_explicit_) {
          return;
        }
        base::Optional<const Type*>& maybe_inferred =
            inferred_[type_parameter_index];
        if (maybe_inferred && *maybe_inferred != argument_type) {
          Fail("found conflicting types for generic parameter");
        } else {
          inferred_[type_parameter_index] = {argument_type};
        }
        return;
      }
    }
    // Try to recurse in case of generic types
    if (!basic->generic_arguments.empty()) {
      MatchGeneric(basic, argument_type);
    }
    // NOTE: We could also check whether ground parameter types match the
    // argument types, but we are only interested in inferring type arguments
    // here
  } else {
    // TODO(gsps): Perform inference on function and union types
  }
}

void TypeArgumentInference::MatchGeneric(BasicTypeExpression* parameter,
                                         const Type* argument_type) {
  QualifiedName qualified_name{parameter->namespace_qualification,
                               parameter->name};
  GenericType* generic_type =
      Declarations::LookupUniqueGenericType(qualified_name);
  auto& specialized_from = argument_type->GetSpecializedFrom();
  if (!specialized_from || specialized_from->generic != generic_type) {
    return Fail("found conflicting generic type constructors");
  }
  auto& parameters = parameter->generic_arguments;
  auto& argument_types = specialized_from->specialized_types;
  if (parameters.size() != argument_types.size()) {
    Error(
        "cannot infer types from generic-struct-typed parameter with "
        "incompatible number of arguments")
        .Position(parameter->pos)
        .Throw();
  }
  for (size_t i = 0; i < parameters.size(); i++) {
    Match(parameters[i], argument_types[i]);
    if (HasFailed()) return;
  }
}

}  // namespace torque
}  // namespace internal
}  // namespace v8
