// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:kernel/ast.dart' as ir;

import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
import '../ir/element_map.dart';
import 'util.dart' show recordShapeOfRecordType;

/// Visitor that converts string literals and concatenations of string literals
/// into the string value.
class Stringifier extends ir.ExpressionVisitor<String?>
    with ir.ExpressionVisitorDefaultMixin<String?> {
  @override
  String visitStringLiteral(ir.StringLiteral node) => node.value;

  @override
  String? visitStringConcatenation(ir.StringConcatenation node) {
    StringBuffer sb = StringBuffer();
    for (ir.Expression expression in node.expressions) {
      String? value = expression.accept(this);
      if (value == null) return null;
      sb.write(value);
    }
    return sb.toString();
  }

  @override
  String? visitConstantExpression(ir.ConstantExpression node) {
    ir.Constant constant = node.constant;
    if (constant is ir.StringConstant) {
      return constant.value;
    }
    return null;
  }

  @override
  String? defaultExpression(ir.Expression node) => null;
}

/// Visitor that converts kernel dart types into [DartType].
class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
  final IrToElementMap elementMap;
  final Map<ir.StructuralParameter, DartType> currentFunctionTypeParameters =
      <ir.StructuralParameter, DartType>{};

  DartTypeConverter(this.elementMap);

  DartTypes get _dartTypes => elementMap.commonElements.dartTypes;

  DartType _convertNullability(
    DartType baseType,
    ir.DartType nullabilitySource,
  ) {
    final nullability = nullabilitySource.declaredNullability;
    switch (nullability) {
      case ir.Nullability.nonNullable:
        return baseType;
      case ir.Nullability.nullable:
        return _dartTypes.nullableType(baseType);
      case ir.Nullability.undetermined:
        // Type parameters may have undetermined nullability since it is derived
        // from the intersection of the declared nullability with the
        // nullability of the bound. We don't need a nullability wrapper in this
        // case.
        if (nullabilitySource is ir.TypeParameterType ||
            nullabilitySource is ir.StructuralParameterType ||
            nullabilitySource is ir.ExtensionType) {
          return baseType;
        }

        // Iff `T` has undetermined nullability, then so will `FutureOr<T>`
        // since it's the union of `T`, which has undetermined nullability, and
        // `Future<T>`, which does not. We can treat the `Future`/`FutureOr` as
        // non-nullable and rely on the conversion of the type argument to
        // produce the right nullability.
        if (nullabilitySource is ir.FutureOrType &&
            nullabilitySource.typeArgument.nullability ==
                ir.Nullability.undetermined) {
          return baseType;
        }

        throw UnsupportedError(
          'Undetermined nullability on $nullabilitySource',
        );
    }
  }

  DartType visitType(ir.DartType type) {
    return type.accept(this);
  }

  InterfaceType visitSupertype(ir.Supertype node) =>
      visitInterfaceType(node.asInterfaceType).withoutNullability
          as InterfaceType;

  List<DartType> visitTypes(List<ir.DartType> types) {
    return List.generate(
      types.length,
      (int index) => types[index].accept(this),
    );
  }

  @override
  DartType visitTypeParameterType(ir.TypeParameterType node) {
    if (node.parameter.declaration is ir.Typedef) {
      // Typedefs are only used in type literals so we never need their type
      // variables.
      return _dartTypes.dynamicType();
    }
    return _convertNullability(
      _dartTypes.typeVariableType(elementMap.getTypeVariable(node.parameter)),
      node,
    );
  }

  @override
  DartType visitStructuralParameterType(ir.StructuralParameterType node) {
    DartType typeParameter = currentFunctionTypeParameters[node.parameter]!;
    return _convertNullability(typeParameter, node);
  }

  @override
  DartType visitIntersectionType(ir.IntersectionType node) {
    return node.left.accept(this);
  }

  @override
  DartType visitFunctionType(ir.FunctionType node) {
    int index = 0;
    List<FunctionTypeVariable>? typeVariables;
    for (ir.StructuralParameter typeParameter in node.typeParameters) {
      FunctionTypeVariable typeVariable = _dartTypes.functionTypeVariable(
        index,
      );
      currentFunctionTypeParameters[typeParameter] = typeVariable;
      typeVariables ??= <FunctionTypeVariable>[];
      typeVariables.add(typeVariable);
      index++;
    }
    if (typeVariables != null) {
      for (int index = 0; index < typeVariables.length; index++) {
        typeVariables[index].bound = node.typeParameters[index].bound.accept(
          this,
        );
      }
    }

    FunctionType functionType = _dartTypes.functionType(
      visitType(node.returnType),
      visitTypes(
        node.positionalParameters.take(node.requiredParameterCount).toList(),
      ),
      visitTypes(
        node.positionalParameters.skip(node.requiredParameterCount).toList(),
      ),
      node.namedParameters.map((n) => n.name).toList(),
      node.namedParameters
          .where((n) => n.isRequired)
          .map((n) => n.name)
          .toSet(),
      node.namedParameters.map((n) => visitType(n.type)).toList(),
      typeVariables ?? const <FunctionTypeVariable>[],
    );
    DartType type = _convertNullability(functionType, node);
    for (ir.StructuralParameter typeParameter in node.typeParameters) {
      currentFunctionTypeParameters.remove(typeParameter);
    }
    return type;
  }

  @override
  DartType visitInterfaceType(ir.InterfaceType node) {
    ClassEntity cls = elementMap.getClass(node.classNode);
    return _convertNullability(
      _dartTypes.interfaceType(cls, visitTypes(node.typeArguments)),
      node,
    );
  }

  @override
  DartType visitRecordType(ir.RecordType node) {
    final shape = recordShapeOfRecordType(node);
    List<DartType> fields = [
      for (final type in node.positional) visitType(type),
      for (final namedType in node.named) visitType(namedType.type),
    ].toList(growable: false);
    return _convertNullability(_dartTypes.recordType(shape, fields), node);
  }

  @override
  DartType visitFutureOrType(ir.FutureOrType node) {
    return _convertNullability(
      _dartTypes.futureOrType(visitType(node.typeArgument)),
      node,
    );
  }

  @override
  DartType visitVoidType(ir.VoidType node) {
    return _dartTypes.voidType();
  }

  @override
  DartType visitDynamicType(ir.DynamicType node) {
    return _dartTypes.dynamicType();
  }

  @override
  DartType visitInvalidType(ir.InvalidType node) {
    // Root uses such a `o is Unresolved` and `o as Unresolved` must be special
    // cased in the builder, nested invalid types are treated as `dynamic`.
    return _dartTypes.dynamicType();
  }

  @override
  DartType visitNeverType(ir.NeverType node) {
    return _convertNullability(_dartTypes.neverType(), node);
  }

  @override
  DartType visitNullType(ir.NullType node) {
    return elementMap.commonElements.nullType;
  }

  @override
  DartType visitExtensionType(ir.ExtensionType node) {
    return node.extensionTypeErasure.accept(this);
  }

  @override
  DartType visitAuxiliaryType(ir.AuxiliaryType node) {
    throw UnsupportedError(
      'Unsupported auxiliary type $node (${node.runtimeType}).',
    );
  }

  @override
  DartType visitTypedefType(ir.TypedefType node) {
    throw UnsupportedError('Unsupported type $node (${node.runtimeType})');
  }
}

class ConstantValuefier extends ir.ComputeOnceConstantVisitor<ConstantValue> {
  final IrToElementMap elementMap;

  ConstantValuefier(this.elementMap);

  static Never _unexpectedConstant(ir.Constant node) {
    throw UnsupportedError("Unexpected constant $node (${node.runtimeType}).");
  }

  @override
  ConstantValue visitUnevaluatedConstant(ir.UnevaluatedConstant node) {
    throw UnsupportedError("Unexpected unevaluated constant $node.");
  }

  @override
  ConstantValue visitTypeLiteralConstant(ir.TypeLiteralConstant node) {
    DartType type = elementMap.getDartType(node.type);
    return constant_system.createType(elementMap.commonElements, type);
  }

  @override
  ConstantValue visitStaticTearOffConstant(ir.StaticTearOffConstant node) {
    ir.Procedure member = node.target;
    FunctionEntity function = elementMap.getMethod(member);
    final type = elementMap.getFunctionType(member.function);
    return FunctionConstantValue(function, type);
  }

  @override
  ConstantValue visitInstantiationConstant(ir.InstantiationConstant node) {
    List<DartType> typeArguments = [];
    for (ir.DartType type in node.types) {
      typeArguments.add(elementMap.getDartType(type));
    }
    final function =
        visitConstant(node.tearOffConstant) as FunctionConstantValue;
    return InstantiationConstantValue(typeArguments, function);
  }

  @override
  ConstantValue visitInstanceConstant(ir.InstanceConstant node) {
    InterfaceType type = elementMap.createInterfaceType(
      node.classNode,
      node.typeArguments,
    );
    Map<FieldEntity, ConstantValue> fields = {};
    node.fieldValues.forEach((ir.Reference reference, ir.Constant value) {
      FieldEntity field = elementMap.getField(reference.asField);
      fields[field] = visitConstant(value);
    });
    return ConstructedConstantValue(type, fields);
  }

  @override
  ConstantValue visitListConstant(ir.ListConstant node) {
    List<ConstantValue> elements = [];
    for (ir.Constant element in node.entries) {
      elements.add(visitConstant(element));
    }
    final type = elementMap.commonElements.listType(
      elementMap.getDartType(node.typeArgument),
    );
    return constant_system.createList(
      elementMap.commonElements,
      type,
      elements,
    );
  }

  @override
  ConstantValue visitSetConstant(ir.SetConstant node) {
    List<ConstantValue> elements = [];
    for (ir.Constant element in node.entries) {
      elements.add(visitConstant(element));
    }
    final type = elementMap.commonElements.setType(
      elementMap.getDartType(node.typeArgument),
    );
    return constant_system.createSet(elementMap.commonElements, type, elements);
  }

  @override
  ConstantValue visitMapConstant(ir.MapConstant node) {
    List<ConstantValue> keys = [];
    List<ConstantValue> values = [];
    for (ir.ConstantMapEntry element in node.entries) {
      keys.add(visitConstant(element.key));
      values.add(visitConstant(element.value));
    }
    final type = elementMap.commonElements.mapType(
      elementMap.getDartType(node.keyType),
      elementMap.getDartType(node.valueType),
    );
    return constant_system.createMap(
      elementMap.commonElements,
      type,
      keys,
      values,
    );
  }

  @override
  ConstantValue visitRecordConstant(ir.RecordConstant node) {
    final shape = recordShapeOfRecordType(node.recordType);
    final fieldValues = [
      for (final value in node.positional) visitConstant(value),
      for (final value in node.named.values) visitConstant(value),
    ];
    return RecordConstantValue(shape, fieldValues);
  }

  @override
  ConstantValue visitSymbolConstant(ir.SymbolConstant node) {
    return constant_system.createSymbol(elementMap.commonElements, node.name);
  }

  @override
  ConstantValue visitStringConstant(ir.StringConstant node) {
    return constant_system.createString(node.value);
  }

  @override
  ConstantValue visitDoubleConstant(ir.DoubleConstant node) {
    return constant_system.createDouble(node.value);
  }

  @override
  ConstantValue visitIntConstant(ir.IntConstant node) {
    return constant_system.createIntFromInt(node.value);
  }

  @override
  ConstantValue visitBoolConstant(ir.BoolConstant node) {
    return constant_system.createBool(node.value);
  }

  @override
  ConstantValue visitNullConstant(ir.NullConstant node) {
    return constant_system.createNull();
  }

  @override
  Never visitConstructorTearOffConstant(ir.ConstructorTearOffConstant node) =>
      _unexpectedConstant(node);

  @override
  Never visitRedirectingFactoryTearOffConstant(
    ir.RedirectingFactoryTearOffConstant node,
  ) => _unexpectedConstant(node);

  @override
  Never visitTypedefTearOffConstant(ir.TypedefTearOffConstant node) =>
      _unexpectedConstant(node);

  @override
  Never visitAuxiliaryConstant(ir.AuxiliaryConstant node) =>
      _unexpectedConstant(node);
}
